init
|
|
@ -0,0 +1,4 @@
|
||||||
|
VITE_BASE_URL=http://192.168.0.17:8001/
|
||||||
|
VITE_PROXY=/api
|
||||||
|
VITE_FILE_URL=https://file.zcloudchina.com/YTHFile
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
public
|
||||||
|
dist
|
||||||
|
package.json
|
||||||
|
!.prettierrc.cjs
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es2021: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"standard",
|
||||||
|
"@vue/prettier",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
sourceType: "module"
|
||||||
|
},
|
||||||
|
plugins: ["vue"],
|
||||||
|
rules: {
|
||||||
|
"no-console": "warn",
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
camelcase: "off",
|
||||||
|
eqeqeq: "error",
|
||||||
|
"vue/eqeqeq": "error",
|
||||||
|
"no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{ vars: "all", args: "after-used", ignoreRestSiblings: false }
|
||||||
|
],
|
||||||
|
"linebreak-style": ["off",'windows'],
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
BMapGL: "readonly",
|
||||||
|
JSEncrypt: "readonly",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: ["@vue/prettier", "plugin:prettier/recommended"],
|
||||||
|
endOfLine: "crlf",
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Vue 3 + Vite
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>管理平台</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<noscript>
|
||||||
|
<strong>很抱歉,如果没有启用JavaScript,网站无法正常工作,请启用JavaScript使其正常工作。</strong>
|
||||||
|
</noscript>
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OElqFYoKiAH8KFtph8ftLKF5NlNrbCUr"></script>
|
||||||
|
<script type="text/javascript" src="/jsencrypt.min.js"></script>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"name": "vue3_template",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint --ext .js,.vue --fix src .prettierrc.cjs"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
|
"@icon-park/vue-next": "^1.4.2",
|
||||||
|
"@vueuse/core": "^9.13.0",
|
||||||
|
"@vueuse/integrations": "^10.7.0",
|
||||||
|
"animate.css": "^4.1.1",
|
||||||
|
"axios": "^1.6.3",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"element-plus": "^2.4.4",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
|
"qrcode": "^1.5.3",
|
||||||
|
"qs": "^6.11.2",
|
||||||
|
"throttle-debounce": "^5.0.0",
|
||||||
|
"v-viewer": "^3.0.11",
|
||||||
|
"vue": "^3.3.13",
|
||||||
|
"vue-router": "^4.2.5",
|
||||||
|
"vue3-print-nb": "^0.1.4",
|
||||||
|
"vue3-puzzle-vcode": "^1.0.16"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@our-patches/postcss-px-to-viewport": "^1.2.0",
|
||||||
|
"@types/node": "^18.18.4",
|
||||||
|
"@vitejs/plugin-basic-ssl": "^1.0.1",
|
||||||
|
"@vitejs/plugin-vue": "^4.4.0",
|
||||||
|
"@vue/eslint-config-prettier": "^7.1.0",
|
||||||
|
"autoprefixer": "^10.4.16",
|
||||||
|
"eslint": "^8.51.0",
|
||||||
|
"eslint-config-prettier": "^8.10.0",
|
||||||
|
"eslint-config-standard": "^17.1.0",
|
||||||
|
"eslint-plugin-import": "^2.28.1",
|
||||||
|
"eslint-plugin-n": "^15.7.0",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
|
"prettier": "^2.8.8",
|
||||||
|
"sass": "^1.69.0",
|
||||||
|
"unplugin-auto-import": "^0.12.2",
|
||||||
|
"unplugin-vue-components": "^0.22.12",
|
||||||
|
"vite": "^4.4.11",
|
||||||
|
"vite-plugin-enhance-log": "^0.5.2",
|
||||||
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
|
"vite-plugin-remove-console": "^2.1.1",
|
||||||
|
"vue-eslint-parser": "^9.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
const path = require('path')
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
autoprefixer: {
|
||||||
|
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8', '> 1%'],
|
||||||
|
grid: true,
|
||||||
|
},
|
||||||
|
// '@our-patches/postcss-px-to-viewport': {
|
||||||
|
// unitToConvert: 'px',
|
||||||
|
// viewportWidth: 1920,
|
||||||
|
// unitPrecision: 3,
|
||||||
|
// viewportUnit: 'vw',
|
||||||
|
// selectorBlackList: ['.ignore', '.hairlines'],
|
||||||
|
// minPixelValue: 1,
|
||||||
|
// mediaQuery: false,
|
||||||
|
// exclude: [/^node_modules$/],
|
||||||
|
// include: [/BI/],
|
||||||
|
// landscapeUnit: 'vw',
|
||||||
|
// landscapeWidth: 750,
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<suspense>
|
||||||
|
<template #default>
|
||||||
|
<el-config-provider :locale="zhCn">
|
||||||
|
<router-view />
|
||||||
|
</el-config-provider>
|
||||||
|
</template>
|
||||||
|
<template #fallback>
|
||||||
|
<div>加载中...</div>
|
||||||
|
</template>
|
||||||
|
</suspense>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
import router from "./router";
|
||||||
|
import { useRouterStore } from "./pinia/router";
|
||||||
|
import { useMenuStore } from "./pinia/menu";
|
||||||
|
import { useUserStore } from "@/pinia/user";
|
||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
|
import pinia from "./pinia";
|
||||||
|
import children from "@/components/children/index";
|
||||||
|
import { MODEL } from "@/assets/js/constant";
|
||||||
|
import asyncRouter from "@/assets/js/asyncRouter";
|
||||||
|
import { getAsyncRouter } from "@/request/api";
|
||||||
|
// import { getRouteTreeAll } from "@/request/system_management.js";
|
||||||
|
|
||||||
|
const modules = import.meta.glob("./views/**/*.vue"); // 获取到views下所有的vue文件
|
||||||
|
let storageRouter = null; // 用来获取后台拿到的路由
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from, next) => {
|
||||||
|
const routerStore = useRouterStore(pinia);
|
||||||
|
const menuStore = useMenuStore(pinia);
|
||||||
|
const userStore = useUserStore(pinia);
|
||||||
|
// 需要登陆
|
||||||
|
if (to.meta.isLogin !== false) {
|
||||||
|
if (!userStore.getUserInfo.USER_ID) {
|
||||||
|
next("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!storageRouter) {
|
||||||
|
// 变量里没有储存路由
|
||||||
|
// pinia里没有储存路由,去后台获取路由
|
||||||
|
if (routerStore.getRouters.length === 0) {
|
||||||
|
await getAsyncRouter();
|
||||||
|
// const resData = await getRouteTreeAll();
|
||||||
|
// storageRouter = resData.menuList; // 后台请求得到的路由数据
|
||||||
|
storageRouter = asyncRouter; // 死路由
|
||||||
|
routerStore.setRouters(storageRouter); // 存储路由
|
||||||
|
routerGo(to, next); // 执行路由跳转方法
|
||||||
|
} else {
|
||||||
|
// pinia里储存了路由
|
||||||
|
storageRouter = routerStore.getRouters; // 拿到路由
|
||||||
|
routerGo(to, next); // 执行路由跳转方法
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不需要登陆,清空储存路由
|
||||||
|
storageRouter = null;
|
||||||
|
routerStore.$reset();
|
||||||
|
menuStore.$reset();
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function routerGo(to, next) {
|
||||||
|
const menuStore = useMenuStore(pinia);
|
||||||
|
storageRouter = filterAsyncRouter(cloneDeep(storageRouter)); // 过滤路由
|
||||||
|
for (let i = 0; i < storageRouter.length; i++) {
|
||||||
|
router.addRoute("app", storageRouter[i]); // 动态添加路由
|
||||||
|
}
|
||||||
|
router.addRoute({ path: "/:pathMatch(.*)*", redirect: "/404" }); // 将404路由添加到最后
|
||||||
|
for (let i = 0; i < router.options.routes.length; i++) {
|
||||||
|
if (router.options.routes[i].path === "/") {
|
||||||
|
menuStore.setMenus(
|
||||||
|
router.options.routes[i].children.concat(storageRouter)
|
||||||
|
); // 将路由数据存到一个新的pinia里,做菜单渲染
|
||||||
|
if (!menuStore.getModel) {
|
||||||
|
menuStore.setModel(MODEL["1"]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next({ ...to, replace: true }); // 等待addRoute执行完毕跳转路由
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterAsyncRouter(asyncRouterMap) {
|
||||||
|
// 遍历后台传来的路由字符串,转换为组件对象
|
||||||
|
return asyncRouterMap.filter((route) => {
|
||||||
|
if (route.component) {
|
||||||
|
if (route.component === "children") {
|
||||||
|
route.component = children;
|
||||||
|
} else {
|
||||||
|
route.component = modules[`./views/${route.component}.vue`];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果存在children递归
|
||||||
|
if (route.children && route.children.length) {
|
||||||
|
route.children = filterAsyncRouter(route.children);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,324 @@
|
||||||
|
// 文字超出几行隐藏,最多5行
|
||||||
|
// 使用超出1行隐藏,如果使用了flex,则需要给父元素设置min-width: 0;
|
||||||
|
@for $i from 1 through 5 {
|
||||||
|
.line-#{$i} {
|
||||||
|
@if $i == 1 {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
} @else {
|
||||||
|
display: -webkit-box !important;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
-webkit-line-clamp: $i;
|
||||||
|
-webkit-box-orient: vertical !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成1-50的margin和padding(正负)
|
||||||
|
@for $i from 1 through 50 {
|
||||||
|
.m-#{$i} {
|
||||||
|
margin: #{$i}px;
|
||||||
|
}
|
||||||
|
.mt-#{$i} {
|
||||||
|
margin-top: #{$i}px;
|
||||||
|
}
|
||||||
|
.mr-#{$i} {
|
||||||
|
margin-right: #{$i}px;
|
||||||
|
}
|
||||||
|
.mb-#{$i} {
|
||||||
|
margin-bottom: #{$i}px;
|
||||||
|
}
|
||||||
|
.ml-#{$i} {
|
||||||
|
margin-left: #{$i}px;
|
||||||
|
}
|
||||||
|
.mtb-#{$i} {
|
||||||
|
margin-top: #{$i}px;
|
||||||
|
margin-bottom: #{$i}px;
|
||||||
|
}
|
||||||
|
.mlr-#{$i} {
|
||||||
|
margin-left: #{$i}px;
|
||||||
|
margin-right: #{$i}px;
|
||||||
|
}
|
||||||
|
.p-#{$i} {
|
||||||
|
padding: #{$i}px;
|
||||||
|
}
|
||||||
|
.pt-#{$i} {
|
||||||
|
padding-top: #{$i}px;
|
||||||
|
}
|
||||||
|
.pr-#{$i} {
|
||||||
|
padding-right: #{$i}px;
|
||||||
|
}
|
||||||
|
.pb-#{$i} {
|
||||||
|
padding-bottom: #{$i}px;
|
||||||
|
}
|
||||||
|
.pl-#{$i} {
|
||||||
|
padding-left: #{$i}px;
|
||||||
|
}
|
||||||
|
.ptb-#{$i} {
|
||||||
|
padding-top: #{$i}px;
|
||||||
|
padding-bottom: #{$i}px;
|
||||||
|
}
|
||||||
|
.plr-#{$i} {
|
||||||
|
padding-left: #{$i}px;
|
||||||
|
padding-right: #{$i}px;
|
||||||
|
}
|
||||||
|
.m--#{$i} {
|
||||||
|
margin: -#{$i}px;
|
||||||
|
}
|
||||||
|
.mt--#{$i} {
|
||||||
|
margin-top: -#{$i}px;
|
||||||
|
}
|
||||||
|
.mr--#{$i} {
|
||||||
|
margin-right: -#{$i}px;
|
||||||
|
}
|
||||||
|
.mb--#{$i} {
|
||||||
|
margin-bottom: -#{$i}px;
|
||||||
|
}
|
||||||
|
.ml--#{$i} {
|
||||||
|
margin-left: -#{$i}px;
|
||||||
|
}
|
||||||
|
.mtb--#{$i} {
|
||||||
|
margin-top: -#{$i}px;
|
||||||
|
margin-bottom: -#{$i}px;
|
||||||
|
}
|
||||||
|
.mlr--#{$i} {
|
||||||
|
margin-left: -#{$i}px;
|
||||||
|
margin-right: -#{$i}px;
|
||||||
|
}
|
||||||
|
.p--#{$i} {
|
||||||
|
padding: -#{$i}px;
|
||||||
|
}
|
||||||
|
.pt--#{$i} {
|
||||||
|
padding-top: -#{$i}px;
|
||||||
|
}
|
||||||
|
.pr--#{$i} {
|
||||||
|
padding-right: -#{$i}px;
|
||||||
|
}
|
||||||
|
.pb--#{$i} {
|
||||||
|
padding-bottom: -#{$i}px;
|
||||||
|
}
|
||||||
|
.pl--#{$i} {
|
||||||
|
padding-left: -#{$i}px;
|
||||||
|
}
|
||||||
|
.ptb--#{$i} {
|
||||||
|
padding-top: -#{$i}px;
|
||||||
|
padding-bottom: -#{$i}px;
|
||||||
|
}
|
||||||
|
.plr--#{$i} {
|
||||||
|
padding-left: -#{$i}px;
|
||||||
|
padding-right: -#{$i}px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&:not(dd,dl,dt) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-size: revert;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
background-color: #030f2f;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-image: url("/src/assets/images/public/bg.jpg");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.end {
|
||||||
|
.el-form-item__content {
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tc {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tl {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-blue {
|
||||||
|
color: #3b3bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-yellow {
|
||||||
|
color: #bebe05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-orange {
|
||||||
|
color: #de9004;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-red {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-green {
|
||||||
|
color: #0bb20c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print_use {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.ml-10:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:-webkit-autofill,
|
||||||
|
input:-webkit-autofill:hover,
|
||||||
|
input:-webkit-autofill:focus,
|
||||||
|
input:-webkit-autofill:active {
|
||||||
|
-webkit-transition-delay: 99999s;
|
||||||
|
-webkit-transition: color 99999s ease-out, background-color 99999s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
div::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 10px;
|
||||||
|
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||||
|
opacity: 0.2;
|
||||||
|
background-color: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
div::-webkit-scrollbar-track {
|
||||||
|
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer-zoom-in, .viewer-zoom-out, .viewer-one-to-one, .viewer-reset, .viewer-prev, .viewer-play, .viewer-next, .viewer-rotate-left, .viewer-rotate-right, .viewer-flip-horizontal, .viewer-flip-vertical, .viewer-fullscreen, .viewer-fullscreen-exit, .viewer-close {
|
||||||
|
&::before {
|
||||||
|
font-size: unset !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-bar {
|
||||||
|
--w-e-toolbar-bg-color: var(--el-fill-color-blank) !important;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-bottom: none;
|
||||||
|
--w-e-toolbar-border-color: var(--el-border-color);
|
||||||
|
--w-e-toolbar-color: var(--el-text-color-regular) !important;
|
||||||
|
--w-e-toolbar-disabled-color: var(--el-text-color-regular) !important;
|
||||||
|
--w-e-toolbar-active-bg-color: var(--el-fill-color-light);
|
||||||
|
--w-e-toolbar-active-color: var(--el-color-check);
|
||||||
|
|
||||||
|
.w-e-menu-tooltip-v5:before {
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-select-list ul {
|
||||||
|
li:hover, .selected {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-text-container {
|
||||||
|
--w-e-textarea-bg-color: var(--el-fill-color-blank) !important;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
--w-e-textarea-color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-bar-divider {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-toolbar {
|
||||||
|
border-bottom: 1px dashed var(--el-border-color-darker);
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-bar-item:has([data-menu-key="group-video"]) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-e-bar-item-menus-container .w-e-bar-item:has([data-menu-key="insertImage"]) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-auth-box_ {
|
||||||
|
background: #020f3a !important;
|
||||||
|
border: 1px solid #223765 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-puzzle-vcode {
|
||||||
|
background-color: #0000008d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-auth-box_ .auth-control_ .range-box {
|
||||||
|
background-color: #04205f !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-auth-box_ .auth-control_ .range-box .range-slider .range-btn {
|
||||||
|
background: #3266cb !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印时去掉页眉页脚
|
||||||
|
@page {
|
||||||
|
size: auto;
|
||||||
|
margin: 3mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page_break{
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.el-descriptions__label.el-descriptions__cell.is-bordered-label {
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
.el-descriptions {
|
||||||
|
--el-text-color-primary: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-divider__text {
|
||||||
|
--el-text-color-regular: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print_use {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
display: table;
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
padding: 8px;
|
||||||
|
line-height: 1.6;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.print_no_use {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,385 @@
|
||||||
|
:root {
|
||||||
|
--el-header-height: 69px;
|
||||||
|
--el-aside-scrollbar-height: calc(100vh - var(--el-header-height));
|
||||||
|
--el-main-scrollbar-height: calc(100vh - var(--el-header-height) - 60px);
|
||||||
|
--el-border-color: #273868 !important; // 边框颜色
|
||||||
|
--el-text-color-regular: #fff !important;
|
||||||
|
--el-fill-color-light: #0e1d44 !important; //hover背景色
|
||||||
|
--el-color-check: #14affe !important; //hover、选中 文字颜色
|
||||||
|
--el-aside-bg-color: #081e42 !important;
|
||||||
|
--el-input-bg-color: #081435 !important;
|
||||||
|
--el-fill-color-blank: #081435 !important; // 背景色
|
||||||
|
--el-border-color-lighter: var(--el-border-color) !important;
|
||||||
|
--el-bullet-frame-bg-color: #08163b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button:focus, .el-button:hover {
|
||||||
|
--el-button-hover-text-color: var(--el-button-text-color);
|
||||||
|
--el-button-hover-border-color: var(--el-button-border-color);
|
||||||
|
--el-button-hover-bg-color: var(--el-button-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-header {
|
||||||
|
--el-header-padding: 0 !important;
|
||||||
|
--el-header-height: 69px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-main {
|
||||||
|
--el-main-padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-aside {
|
||||||
|
--el-aside-width: 250px;
|
||||||
|
background-color: var(--el-aside-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card {
|
||||||
|
margin: 10px 20px;
|
||||||
|
--el-card-padding: 18px 18px 0 18px !important;
|
||||||
|
--el-card-bg-color: rgba(8, 24, 58, 0.5) !important;
|
||||||
|
--el-card-border-color: var(--el-border-color) !important;
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-popper {
|
||||||
|
--el-bg-color-overlay: var(--el-fill-color-blank) !important;
|
||||||
|
--el-border-color-light: var(--el-border-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-cascader-node:not(.is-disabled):focus, .el-cascader-node:not(.is-disabled):hover {
|
||||||
|
--el-cascader-node-background-hover: var(--el-fill-color-light);
|
||||||
|
color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-cascader {
|
||||||
|
--el-cascader-tag-background: #214082 !important;
|
||||||
|
--el-color-info: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover {
|
||||||
|
color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dropdown-menu__item {
|
||||||
|
&:not(.is-disabled):focus {
|
||||||
|
--el-dropdown-menuItem-hover-fill: var(--el-fill-color-light);
|
||||||
|
--el-dropdown-menuItem-hover-color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu {
|
||||||
|
border-right: none !important;
|
||||||
|
--el-menu-bg-color: var(--el-aside-bg-color);
|
||||||
|
--el-menu-text-color: var(--el-text-color-regular);
|
||||||
|
--el-menu-hover-text-color: var(--el-text-color-regular);
|
||||||
|
--el-menu-active-color: var(--el-text-color-regular);
|
||||||
|
--el-menu-hover-bg-color: transparent;
|
||||||
|
|
||||||
|
span {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-sub-menu__title *, .el-menu-item * {
|
||||||
|
vertical-align: middle !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item {
|
||||||
|
&:hover, &.is-active {
|
||||||
|
background-image: url("/src/assets/images/public/list_on.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//.el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-menu-item {
|
||||||
|
// padding-left: calc(var(--el-menu-base-level-padding) + var(--el-menu-level) * var(--el-menu-level-padding) + 20px) !important;
|
||||||
|
//}
|
||||||
|
|
||||||
|
.el-breadcrumb {
|
||||||
|
margin-left: 10px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px !important;
|
||||||
|
|
||||||
|
.el-breadcrumb__inner {
|
||||||
|
--el-text-color-regular: #cacbce;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: normal;
|
||||||
|
--el-text-color-primary: #cacbce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-breadcrumb__separator {
|
||||||
|
--el-text-color-placeholder: #cacbce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select, .el-cascader, .el-date-editor.el-input, .el-date-editor.el-input__wrapper, .el-input__wrapper, .el-input-number {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
--el-table-bg-color: #071a43 !important;
|
||||||
|
--el-bg-color: #071a43 !important;
|
||||||
|
--el-table-header-bg-color: #0f2049 !important;
|
||||||
|
--el-table-border-color: var(--el-border-color) !important;
|
||||||
|
--el-table-tr-bg-color: #071a43 !important;
|
||||||
|
--el-fill-color-lighter: #111e40 !important;
|
||||||
|
--el-table-text-color: #e0e0e0 !important;
|
||||||
|
--el-table-header-text-color: var(--el-text-color-regular) !important;
|
||||||
|
--el-table-row-hover-bg-color: #0d5aa3 !important;
|
||||||
|
--el-table-current-row-bg-color: #0d5aa3 !important;
|
||||||
|
|
||||||
|
.el-table__cell {
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__empty-text {
|
||||||
|
--el-text-color-secondary: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination {
|
||||||
|
--el-pagination-button-color: var(--el-text-color-regular) !important;
|
||||||
|
--el-pagination-button-disabled-bg-color: var(--el-fill-color-blank) !important;
|
||||||
|
--el-pagination-bg-color: var(--el-fill-color-blank) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio {
|
||||||
|
--el-radio-input-bg-color: #091839 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio__input.is-checked .el-radio__inner {
|
||||||
|
background: var(--el-radio-input-bg-color) !important;
|
||||||
|
border-color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio__inner {
|
||||||
|
&::after {
|
||||||
|
--el-color-white: var(--el-color-check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio__input.is-disabled.is-checked .el-radio__inner {
|
||||||
|
--el-disabled-border-color: var(--el-color-check);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
--el-text-color-placeholder: var(--el-color-check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio__input.is-disabled .el-radio__inner {
|
||||||
|
--el-disabled-bg-color: var(--el-radio-input-bg-color);
|
||||||
|
--el-disabled-border-color: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-checkbox {
|
||||||
|
--el-checkbox-bg-color: #091839 !important;
|
||||||
|
--el-checkbox-checked-bg-color: #091839 !important;
|
||||||
|
--el-checkbox-checked-input-border-color: var(--el-color-check) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-checkbox__input.is-disabled .el-checkbox__inner {
|
||||||
|
--el-checkbox-disabled-input-fill: var(--el-checkbox-bg-color);
|
||||||
|
--el-checkbox-disabled-border-color: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
|
||||||
|
--el-checkbox-disabled-checked-input-fill: var(--el-checkbox-bg-color);
|
||||||
|
--el-checkbox-disabled-checked-input-border-color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-picker__popper, .el-date-picker {
|
||||||
|
--el-datepicker-border-color: var(--el-border-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-time-panel__btn {
|
||||||
|
--el-text-color-primary: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-time-spinner__item:hover:not(.is-disabled):not(.is-active) {
|
||||||
|
color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button.is-plain {
|
||||||
|
--el-fill-color-blank: var(--el-fill-color-blank);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button.is-text:not(.is-disabled):active {
|
||||||
|
background-color: var(--el-fill-color-light) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button.is-text:not(.is-disabled):focus, .el-button.is-text:not(.is-disabled):hover {
|
||||||
|
color: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-time-spinner__item.is-active:not(.is-disabled) {
|
||||||
|
--el-text-color-primary: var(--el-color-check);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-picker-panel__icon-btn {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-date-range-picker {
|
||||||
|
--el-datepicker-border-color: var(--el-fill-color-light) !important;
|
||||||
|
--el-datepicker-inrange-bg-color: var(--el-fill-color-light) !important;
|
||||||
|
--el-datepicker-inrange-hover-bg-color: var(--el-fill-color-light) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-date-editor .el-range-separator {
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input.is-disabled .el-input__wrapper {
|
||||||
|
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select__tags .el-tag--info {
|
||||||
|
background-color: #214082 !important;
|
||||||
|
--el-tag-text-color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tag .el-tag__close:hover {
|
||||||
|
color: var(--el-color-check) !important;
|
||||||
|
background-color: var(--el-fill-color-light) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload--picture-card {
|
||||||
|
--el-fill-color-lighter: var(--el-fill-color-blank) !important;
|
||||||
|
border: 1px solid var(--el-border-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-collapse {
|
||||||
|
--el-collapse-header-text-color: var(--el-text-color-regular) !important;
|
||||||
|
--el-collapse-content-text-color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
color: var(--el-color-primary) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__nav-wrap::after {
|
||||||
|
--el-border-color-light: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-divider__text {
|
||||||
|
font-size: 16px !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog {
|
||||||
|
background: transparent !important;
|
||||||
|
--el-dialog-margin-top: 50px !important;
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
background-image: url("/src/assets/images/public/tctitlebg.png");
|
||||||
|
height: 31px;
|
||||||
|
line-height: 31px;
|
||||||
|
padding-left: 30px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
margin-right: 0 !important;
|
||||||
|
--el-dialog-padding-primary: 0 !important;
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
.el-dialog__title {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
--el-dialog-title-font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
height: 31px;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body, .el-dialog__footer {
|
||||||
|
background-color: var(--el-bullet-frame-bg-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer {
|
||||||
|
--el-drawer-bg-color: var(--el-bullet-frame-bg-color) !important;
|
||||||
|
|
||||||
|
.el-drawer__header {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-popper.is-dark {
|
||||||
|
background: var(--el-fill-color-blank) !important;
|
||||||
|
border: 1px solid var(--el-border-color) !important;
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
|
||||||
|
.el-popper__arrow::before {
|
||||||
|
background: var(--el-fill-color-blank) !important;
|
||||||
|
border: 1px solid var(--el-border-color) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box {
|
||||||
|
background-color: var(--el-fill-color-blank) !important;
|
||||||
|
--el-messagebox-title-color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-divider__text {
|
||||||
|
background-color: var(--el-fill-color-blank) !important;
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-calendar {
|
||||||
|
--el-calendar-selected-bg-color: var(--el-fill-color-light) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-steps {
|
||||||
|
--el-text-color-primary: var(--el-text-color-regular);
|
||||||
|
|
||||||
|
.el-step__icon {
|
||||||
|
background: var(--el-fill-color-blank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-descriptions {
|
||||||
|
--el-text-color-primary: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-descriptions__label {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-descriptions__content {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-descriptions__title {
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 4px;
|
||||||
|
height: 19px;
|
||||||
|
background-color: #04a9f5;
|
||||||
|
margin-right: 10px;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-statistic__content {
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-step__title{
|
||||||
|
font-size: 14px !important;;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
//router-view动画
|
||||||
|
.view-leave-active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scaleY(1);
|
||||||
|
transition: all .5s;
|
||||||
|
transform-origin: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-enter-active .view-leave-active {
|
||||||
|
transform-origin: center bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-enter-from, .view-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//面包屑动画
|
||||||
|
.breadcrumb-enter-active,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-enter,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-move {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1019 B |
|
After Width: | Height: | Size: 1016 B |
|
After Width: | Height: | Size: 1012 B |
|
After Width: | Height: | Size: 999 B |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { MODEL } from "@/assets/js/constant";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: "/enterprise_management",
|
||||||
|
redirect: "/enterprise_management/information",
|
||||||
|
meta: { title: "企业管理", model: MODEL["1"] },
|
||||||
|
component: "children",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information",
|
||||||
|
redirect: "/enterprise_management/information/info",
|
||||||
|
meta: { title: "企业信息" },
|
||||||
|
component: "children",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/info",
|
||||||
|
meta: { title: "企业信息", isSubMenu: false },
|
||||||
|
component: "children",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: "enterprise_management/information/info",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/info/edit",
|
||||||
|
meta: {
|
||||||
|
title: "编辑",
|
||||||
|
activeMenu: "/enterprise_management/information/info",
|
||||||
|
},
|
||||||
|
component: "enterprise_management/information/edit",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/industry_qualifications",
|
||||||
|
meta: { title: "行业资质", isSubMenu: false },
|
||||||
|
component: "children",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component:
|
||||||
|
"enterprise_management/industry_qualifications/index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/industry_qualifications/add",
|
||||||
|
meta: {
|
||||||
|
title: "新增",
|
||||||
|
activeMenu:
|
||||||
|
"/enterprise_management/information/industry_qualifications",
|
||||||
|
},
|
||||||
|
component: "enterprise_management/industry_qualifications/add",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/industry_qualifications/update",
|
||||||
|
meta: {
|
||||||
|
title: "修改",
|
||||||
|
activeMenu:
|
||||||
|
"/enterprise_management/information/industry_qualifications",
|
||||||
|
},
|
||||||
|
component: "enterprise_management/industry_qualifications/add",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/enterprise_management/information/industry_qualifications/view",
|
||||||
|
meta: {
|
||||||
|
title: "查看",
|
||||||
|
activeMenu:
|
||||||
|
"/enterprise_management/information/industry_qualifications",
|
||||||
|
},
|
||||||
|
component: "enterprise_management/industry_qualifications/view",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useUserStore } from "@/pinia/user.js";
|
||||||
|
import pinia from "@/pinia/index.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install: (app) => {
|
||||||
|
app.directive("button", {
|
||||||
|
mounted(el, { value }) {
|
||||||
|
const userStore = useUserStore(pinia);
|
||||||
|
if (value) {
|
||||||
|
if (!userStore.getPermissions.includes(value)) {
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
|
} else ElMessage.error("参数无效,请联系管理员");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 将常用的值储存成常量,防止重复使用写错
|
||||||
|
|
||||||
|
// 头部导航条切换的model
|
||||||
|
export const MODEL = {
|
||||||
|
1: "prevention",
|
||||||
|
2: "educationAndTraining",
|
||||||
|
3: "highRisk",
|
||||||
|
4: "monitor",
|
||||||
|
5: "comprehensive",
|
||||||
|
};
|
||||||
|
// 头部导航条
|
||||||
|
export const MENU = [
|
||||||
|
{ title: "双重预防", model: MODEL["1"] },
|
||||||
|
{ title: "教育培训", model: MODEL["2"] },
|
||||||
|
{ title: "高危作业管理", model: MODEL["3"] },
|
||||||
|
{ title: "监测预警", model: MODEL["4"] },
|
||||||
|
{ title: "综合管理", model: MODEL["5"] },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const styleText =
|
||||||
|
'<style type="text/css" media="print">\n' +
|
||||||
|
" @page { size: landscape; }\n" +
|
||||||
|
"</style>";
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import {
|
||||||
|
getLearningTrainType,
|
||||||
|
getLevels,
|
||||||
|
getLevelsAndChildrenNumber,
|
||||||
|
getRegulatoryType,
|
||||||
|
} from "@/request/data_dictionary.js";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
// 监管类型
|
||||||
|
export const layoutFnGetRegulatoryType = async (params) => {
|
||||||
|
const resData = await getRegulatoryType(params);
|
||||||
|
return ref(JSON.parse(resData.varOList.zTreeNodes));
|
||||||
|
};
|
||||||
|
// 企业状态
|
||||||
|
export const layoutFnGetEnterpriseStatus = async () => {
|
||||||
|
const resData = await getLevels({
|
||||||
|
DICTIONARIES_ID: "4d4862f9863b4b0da67f754c49e67ea3",
|
||||||
|
});
|
||||||
|
return ref(resData.list);
|
||||||
|
};
|
||||||
|
// 隶属关系
|
||||||
|
export const layoutFnGetSubordination = async () => {
|
||||||
|
const resData = await getLevels({
|
||||||
|
DICTIONARIES_ID: "1a13f574d4c44cd2ac2034f8e3259f9b",
|
||||||
|
});
|
||||||
|
return ref(resData.list);
|
||||||
|
};
|
||||||
|
// 企业规模
|
||||||
|
export const layoutFnGetEnterpriseScale = async () => {
|
||||||
|
const resData = await getLevels({
|
||||||
|
DICTIONARIES_ID: "37b045e160c04ddba851073b4e510cc9",
|
||||||
|
});
|
||||||
|
return ref(resData.list);
|
||||||
|
};
|
||||||
|
// 培训行业类型
|
||||||
|
export const layoutFnGetTrainingIndustryType = async () => {
|
||||||
|
const resData = await getLearningTrainType({
|
||||||
|
parentId: "052369aa22d242118236cde52d0c67ea",
|
||||||
|
});
|
||||||
|
return ref(JSON.parse(resData.zTreeNodes));
|
||||||
|
};
|
||||||
|
// 培训岗位类型
|
||||||
|
export const layoutFnGetTrainingPostType = async () => {
|
||||||
|
const resData = await getLearningTrainType({
|
||||||
|
parentId: "f6a7c4f5602f46e291d06b1390a3f820",
|
||||||
|
});
|
||||||
|
return ref(JSON.parse(resData.zTreeNodes));
|
||||||
|
};
|
||||||
|
// 培训板块类型
|
||||||
|
export const layoutFnGetTrainingPlateType = async () => {
|
||||||
|
const resData = await getLearningTrainType({
|
||||||
|
parentId: "d538d11e4eec409ab428f5d2f3c67c24",
|
||||||
|
});
|
||||||
|
return ref(JSON.parse(resData.zTreeNodes));
|
||||||
|
};
|
||||||
|
// 无法确定DICTIONARIES_ID的数据字典
|
||||||
|
export const layoutFnGetLevels = async (DICTIONARIES_ID) => {
|
||||||
|
const resData = await getLevels({ DICTIONARIES_ID });
|
||||||
|
return ref(resData.list);
|
||||||
|
};
|
||||||
|
// 无法确定DICTIONARIES_ID的数据字典包括子级数量
|
||||||
|
export const layoutFnGetLevelsAndChildrenNumber = async (DICTIONARIES_ID) => {
|
||||||
|
const resData = await getLevelsAndChildrenNumber({ DICTIONARIES_ID });
|
||||||
|
return ref(resData.list);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import mitt from "mitt";
|
||||||
|
export default mitt();
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const buttonRef = ref(null);
|
||||||
|
const THEAD_HEIGHT = 81.59;
|
||||||
|
const A4_HEIGHT_MM = 297;
|
||||||
|
const A4_HEIGHT_MM_TO_PX_PROPORTION = 3.78;
|
||||||
|
let A4_HEIGHT_PX = A4_HEIGHT_MM * A4_HEIGHT_MM_TO_PX_PROPORTION - THEAD_HEIGHT;
|
||||||
|
let elements = [];
|
||||||
|
const printObj = {
|
||||||
|
id: "printContent",
|
||||||
|
closeCallback() {
|
||||||
|
document.querySelector("#printContent").style.overflow = "hidden";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const fnPrint = () => {
|
||||||
|
document.querySelector("#printContent").style.overflow = "visible";
|
||||||
|
elements = document.querySelectorAll("#printContent > table > tr");
|
||||||
|
if (!document.querySelector("#printContent > table thead")) {
|
||||||
|
A4_HEIGHT_PX = A4_HEIGHT_PX + THEAD_HEIGHT;
|
||||||
|
}
|
||||||
|
fnIsPaging();
|
||||||
|
buttonRef.value.$el.click();
|
||||||
|
};
|
||||||
|
const fnIsPaging = (index = 0) => {
|
||||||
|
for (let i = index; i < elements.length; i++) {
|
||||||
|
if (
|
||||||
|
elements[i].offsetHeight +
|
||||||
|
elements[i].offsetTop -
|
||||||
|
elements[index].offsetTop >=
|
||||||
|
A4_HEIGHT_PX
|
||||||
|
) {
|
||||||
|
elements[i - 1].setAttribute("class", "page_break");
|
||||||
|
fnIsPaging(i === index ? i + 1 : i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { fnPrint, printObj, buttonRef };
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { post } from "@/request/axios";
|
||||||
|
|
||||||
|
// 按钮权限
|
||||||
|
export const useButtonJurisdiction = async (type) => {
|
||||||
|
const keys = `${type}:add,${type}:del,${type}:edit,toExcel`;
|
||||||
|
const resData = await post("/api/head/hasButton", {
|
||||||
|
loading: false,
|
||||||
|
keys,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
add: resData[`${type}fhadminadd`],
|
||||||
|
del: resData[`${type}fhadmindel`],
|
||||||
|
edit: resData[`${type}fhadminedit`],
|
||||||
|
excel: resData.toExcel,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { getDataType } from "@/assets/js/utils.js";
|
||||||
|
|
||||||
|
export default function (ref, message = "请补全必填项!") {
|
||||||
|
const type = ["Function", "AsyncFunction"];
|
||||||
|
if (!type.includes(getDataType(ref?.value?.validate)))
|
||||||
|
throw new Error("不是有效的Element-Plus Form组件ref!");
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
ref.value.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
resolve(valid);
|
||||||
|
} else {
|
||||||
|
reject(valid);
|
||||||
|
ElMessage.warning(message);
|
||||||
|
setTimeout(() => {
|
||||||
|
const element = document.querySelectorAll(".el-form-item__error")[0];
|
||||||
|
element.scrollIntoView({
|
||||||
|
behavior: "smooth",
|
||||||
|
block: "center",
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
import { getDataType } from "@/assets/js/utils.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param api {Function} 接口函数
|
||||||
|
* @param options {Object?: {callbackFn, otherParams, immediate, usePagination}} 配置项
|
||||||
|
* @param options.callbackFn {Function?} 回调函数
|
||||||
|
* @param options.otherParams {Object?} 其它接口参数
|
||||||
|
* @param options.immediate {Boolean?} 是否立即执行接口函数(默认是)
|
||||||
|
* @param options.usePagination {Boolean?} 是否使用分页(默认是)
|
||||||
|
* @return {Object} 返回对象包含以下属性:list 表格数据,pagination 分页数据,searchForm 搜索表单数据,tableRef 表格实例,fnGetData 获取数据函数,fnResetPagination 重置分页函数
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function useListData(api, options = {}) {
|
||||||
|
if (getDataType(api) !== "Function") throw new Error("api必须是一个函数");
|
||||||
|
if (options.immediate && getDataType(options.immediate) !== "Boolean")
|
||||||
|
throw new Error("options.immediate必须是一个布尔值");
|
||||||
|
if (options.usePagination && getDataType(options.usePagination) !== "Boolean")
|
||||||
|
throw new Error("options.usePagination必须是一个布尔值");
|
||||||
|
const immediate = options.immediate ?? true;
|
||||||
|
const usePagination = options.usePagination ?? true;
|
||||||
|
if (!immediate && options.otherParams)
|
||||||
|
throw new Error("options.otherParams只有在immediate为true时才有效");
|
||||||
|
if (
|
||||||
|
immediate &&
|
||||||
|
options.otherParams &&
|
||||||
|
getDataType(options.otherParams) !== "Object"
|
||||||
|
)
|
||||||
|
throw new Error("options.otherParams必须是一个对象");
|
||||||
|
if (options.callbackFn && getDataType(options.callbackFn) !== "Function")
|
||||||
|
throw new Error("options.callbackFn必须是一个函数");
|
||||||
|
const list = ref([]);
|
||||||
|
const pagination = ref({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
const searchForm = ref({});
|
||||||
|
const tableRef = ref(null);
|
||||||
|
const fnGetData = async (otherParams = {}) => {
|
||||||
|
const resData = await api({
|
||||||
|
...(usePagination
|
||||||
|
? {
|
||||||
|
currentPage: pagination.value.currentPage,
|
||||||
|
showCount: pagination.value.pageSize,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...searchForm.value,
|
||||||
|
...(options.otherParams || {}),
|
||||||
|
...(getDataType(otherParams) === "Object" ? otherParams : {}),
|
||||||
|
});
|
||||||
|
list.value = resData.varList;
|
||||||
|
pagination.value.total = resData.page.totalResult;
|
||||||
|
options.callbackFn && options.callbackFn(list.value);
|
||||||
|
};
|
||||||
|
immediate && fnGetData().then();
|
||||||
|
const fnResetPagination = async (otherParams) => {
|
||||||
|
list.value = [];
|
||||||
|
pagination.value = {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
};
|
||||||
|
await nextTick();
|
||||||
|
await fnGetData(otherParams);
|
||||||
|
tableRef.value && tableRef.value.clearSelection();
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
list,
|
||||||
|
pagination,
|
||||||
|
searchForm,
|
||||||
|
tableRef,
|
||||||
|
fnGetData: async (otherParams) => await fnGetData(otherParams),
|
||||||
|
fnResetPagination: async (otherParams) =>
|
||||||
|
await fnResetPagination(otherParams),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,320 @@
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 计算序号
|
||||||
|
* @param {Object} pagination 分页数据对象
|
||||||
|
* @param {number | string} pagination.currentPage 当前页
|
||||||
|
* @param {number | string} pagination.pageSize 每页条数
|
||||||
|
* @param {number} index 当页数据的索引值
|
||||||
|
* @return {number} 序号
|
||||||
|
**/
|
||||||
|
export function serialNumber(pagination, index) {
|
||||||
|
return (pagination.currentPage - 1) * pagination.pageSize + (index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 字符串数组转数组
|
||||||
|
* @param {string} value 转换的字符串数组
|
||||||
|
* @return {Array} 转换后的数组
|
||||||
|
**/
|
||||||
|
export function toArrayString(value) {
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
|
return value ? eval(value).map(String) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 判断文件后缀名是否符合
|
||||||
|
* @param {string} name 文件名字
|
||||||
|
* @param {string} suffix 文件后缀
|
||||||
|
* @return {boolean} 是否符合
|
||||||
|
**/
|
||||||
|
export function interceptTheSuffix(name, suffix) {
|
||||||
|
return (
|
||||||
|
name.substring(name.lastIndexOf("."), name.length).toLowerCase() ===
|
||||||
|
suffix.toLowerCase()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 图片转base64
|
||||||
|
* @param {string} imgUrl 图片地址
|
||||||
|
* @return {Promise} Promise实例,then包含base64编码
|
||||||
|
**/
|
||||||
|
export function image2Base64(imgUrl) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = imgUrl;
|
||||||
|
img.crossOrigin = "Anonymous";
|
||||||
|
img.onload = function () {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = img.width;
|
||||||
|
canvas.height = img.height;
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(img, 0, 0, img.width, img.height);
|
||||||
|
const ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
|
||||||
|
resolve(canvas.toDataURL("image/" + ext));
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 判断图片是否可访问成功
|
||||||
|
* @param {string} imgUrl 图片地址
|
||||||
|
* @return {Promise} Promise实例
|
||||||
|
**/
|
||||||
|
export function checkImgExists(imgUrl) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const ImgObj = new Image();
|
||||||
|
ImgObj.src = imgUrl;
|
||||||
|
ImgObj.onload = function (res) {
|
||||||
|
resolve(res);
|
||||||
|
};
|
||||||
|
ImgObj.onerror = function (err) {
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取数据类型
|
||||||
|
* @param {any} data 数据
|
||||||
|
* @return {string} 数据类型
|
||||||
|
**/
|
||||||
|
export function getDataType(data) {
|
||||||
|
return Object.prototype.toString.call(data).slice(8, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 数组去重
|
||||||
|
* @param {Array<number,string>} arr 去重的数组
|
||||||
|
* @return {Array} 去重后的数组
|
||||||
|
**/
|
||||||
|
export function ArrayDeduplication(arr) {
|
||||||
|
return [...new Set(arr)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 数组对象去重
|
||||||
|
* @param {Array} arr 去重的数组
|
||||||
|
* @param {string} name 去重的key
|
||||||
|
* @return {Array} 去重后的数组
|
||||||
|
**/
|
||||||
|
export function ArrayObjectDeduplication(arr, name) {
|
||||||
|
const obj = {};
|
||||||
|
arr = arr.reduce(function (previousValue, currentValue) {
|
||||||
|
if (!obj[currentValue[name]]) {
|
||||||
|
obj[currentValue[name]] = true;
|
||||||
|
previousValue.push(currentValue);
|
||||||
|
}
|
||||||
|
return previousValue;
|
||||||
|
}, []);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 查找字符串中指定的值第几次出现的位置
|
||||||
|
* @param {Array} str 查找的字符串数组
|
||||||
|
* @param {string} char 查找的值
|
||||||
|
* @param {number} num 第几次出现
|
||||||
|
* @return {number} 出现的位置
|
||||||
|
**/
|
||||||
|
export function findCharIndex(str, char, num) {
|
||||||
|
let index = str.indexOf(char);
|
||||||
|
for (let i = 0; i < num - 1; i++) {
|
||||||
|
index = str.indexOf(char, index + 1);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 生成指定两个值之间的随机数
|
||||||
|
* @param {number} min 最小值
|
||||||
|
* @param {number} max 最大值
|
||||||
|
* @return {number} 随机数
|
||||||
|
**/
|
||||||
|
export function randoms(min, max) {
|
||||||
|
return Math.random() * (max - min + 1) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 千位分隔符
|
||||||
|
* @param {number | string} num 转换的值
|
||||||
|
* @return {string} 转换后的值
|
||||||
|
**/
|
||||||
|
export function numFormat(num) {
|
||||||
|
if (num) {
|
||||||
|
const numArr = num.toString().split(".");
|
||||||
|
const arr = numArr[0].split("").reverse();
|
||||||
|
let res = [];
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (i % 3 === 0 && i !== 0) {
|
||||||
|
res.push(",");
|
||||||
|
}
|
||||||
|
res.push(arr[i]);
|
||||||
|
}
|
||||||
|
res.reverse();
|
||||||
|
if (numArr[1]) {
|
||||||
|
res = res.join("").concat("." + numArr[1]);
|
||||||
|
} else {
|
||||||
|
res = res.join("");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 验证是否为空
|
||||||
|
* @param {any} value 验证的值
|
||||||
|
* @return {boolean} 是否为空
|
||||||
|
**/
|
||||||
|
export function isEmpty(value) {
|
||||||
|
return (
|
||||||
|
value === undefined ||
|
||||||
|
value === null ||
|
||||||
|
(typeof value === "object" && Object.keys(value).length === 0) ||
|
||||||
|
(typeof value === "string" && value.trim().length === 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取url参数
|
||||||
|
* @param {string} name 获取的key
|
||||||
|
* @return {string} 获取的值
|
||||||
|
**/
|
||||||
|
export function getUrlParam(name) {
|
||||||
|
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
|
||||||
|
const r = window.location.search.substr(1).match(reg);
|
||||||
|
if (r != null) return decodeURI(r[2]);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 数据分页
|
||||||
|
* @param {Array} list 分页的数组
|
||||||
|
* @param {number | string} currentPage 当前页
|
||||||
|
* @param {number | string} pageSize 每页条数
|
||||||
|
* @return {Array} 分页后的数组
|
||||||
|
**/
|
||||||
|
export function paging(list, currentPage, pageSize) {
|
||||||
|
return list.filter((item, index) => {
|
||||||
|
return (
|
||||||
|
index < +currentPage * +pageSize &&
|
||||||
|
index >= (+currentPage - 1) * +pageSize
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取文件后缀
|
||||||
|
* @param {string} name 文件名
|
||||||
|
* @return {string} 文件后缀
|
||||||
|
**/
|
||||||
|
export function getFileSuffix(name) {
|
||||||
|
return name.substring(name.lastIndexOf(".") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取文件名称
|
||||||
|
* @param {string} name 文件地址
|
||||||
|
* @return {string} 文件名称
|
||||||
|
**/
|
||||||
|
export function getFileName(name) {
|
||||||
|
return name.substring(name.lastIndexOf("/") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 读取txt文档
|
||||||
|
* @param {string} filePah 文档路径
|
||||||
|
* @return {resolve,string} 读取后的内容
|
||||||
|
**/
|
||||||
|
export function readTxtDocument(filePah) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||||
|
const file_url = FILE_URL + filePah;
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("get", file_url, true);
|
||||||
|
xhr.responseType = "blob";
|
||||||
|
xhr.onload = function (event) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsText(event.target.response, "GB2312");
|
||||||
|
reader.onload = function () {
|
||||||
|
resolve(reader.result);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将秒转换成时分秒
|
||||||
|
* @param {string,number} second 需要转换的秒数
|
||||||
|
* @return {string} 转换后的时间
|
||||||
|
**/
|
||||||
|
export function secondConversion(second) {
|
||||||
|
if (!second) return 0;
|
||||||
|
const h = parseInt((second / 60 / 60) % 24, 10);
|
||||||
|
const m = parseInt((second / 60) % 60, 10);
|
||||||
|
const s = parseInt(second % 60, 10);
|
||||||
|
if (h) {
|
||||||
|
return h + "小时" + m + "分钟" + s + "秒";
|
||||||
|
} else {
|
||||||
|
if (m) {
|
||||||
|
return m + "分钟" + s + "秒";
|
||||||
|
} else {
|
||||||
|
return s + "秒";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 下载附件
|
||||||
|
* @param {string} filePah 下载路径
|
||||||
|
**/
|
||||||
|
export async function downloadFile(filePah) {
|
||||||
|
const FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||||
|
await ElMessageBox.confirm("确定要下载此文件吗?", { type: "warning" });
|
||||||
|
window.open(FILE_URL + filePah, "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 附件添加前缀
|
||||||
|
* @param {Array} list 附件数组
|
||||||
|
* @return {Array} 添加完的数组
|
||||||
|
**/
|
||||||
|
export function addingPrefixToFile(list) {
|
||||||
|
const FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
list[i].url = FILE_URL + list[i].FILEPATH;
|
||||||
|
list[i].name = getFileName(list[i].FILEPATH);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 验证重复选择
|
||||||
|
* @param {Array} list 验证的数组
|
||||||
|
* @param {number} index 选择的索引
|
||||||
|
* @param {string} key 验证的字段
|
||||||
|
* @param {string} id 验证的值
|
||||||
|
**/
|
||||||
|
export function verifyDuplicateSelection(list, index, key, id) {
|
||||||
|
if (list.some((item) => item[key] === id)) {
|
||||||
|
ElMessage.warning("不能重复选择");
|
||||||
|
} else {
|
||||||
|
list[index][key] = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 翻译状态
|
||||||
|
* @param {number | string} status 状态
|
||||||
|
* @param {Array} list 翻译的数组
|
||||||
|
* @return {string} 翻译后的状态
|
||||||
|
**/
|
||||||
|
export function translationStatus(status, list) {
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (status === list[i].ID) {
|
||||||
|
return list[i].NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<el-card>
|
||||||
|
<div class="top_bg" />
|
||||||
|
<div class="content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div class="bottom_bg" />
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutCard",
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-card {
|
||||||
|
--el-card-padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top_bg {
|
||||||
|
margin: auto;
|
||||||
|
width: 1250px;
|
||||||
|
height: 15px;
|
||||||
|
background-image: url("/src/assets/images/public/topguang.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom_bg {
|
||||||
|
margin: auto;
|
||||||
|
width: 1218px;
|
||||||
|
height: 30px;
|
||||||
|
background-image: url("/src/assets/images/public/bottomguang.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<template>
|
||||||
|
<el-cascader
|
||||||
|
ref="cascaderRef"
|
||||||
|
v-model="modelValue"
|
||||||
|
:props="cascaderProps"
|
||||||
|
:show-all-levels="showAllLevels"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import {
|
||||||
|
layoutFnGetLevels,
|
||||||
|
layoutFnGetLevelsAndChildrenNumber,
|
||||||
|
} from "@/assets/js/data_dictionary.js";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutCascader",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
level: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 3,
|
||||||
|
},
|
||||||
|
checkStrictly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showAllLevels: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: "DICTIONARIES_ID",
|
||||||
|
},
|
||||||
|
joinSeparator: {
|
||||||
|
type: String,
|
||||||
|
default: "/",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const cascaderRef = ref(null);
|
||||||
|
const cascaderProps = {
|
||||||
|
lazy: true,
|
||||||
|
lazyLoad: async (node, resolve) => {
|
||||||
|
let resData;
|
||||||
|
if (props.checkStrictly)
|
||||||
|
resData = await layoutFnGetLevels(node.data.DICTIONARIES_ID || props.id);
|
||||||
|
else
|
||||||
|
resData = await layoutFnGetLevelsAndChildrenNumber(
|
||||||
|
node.data.DICTIONARIES_ID || props.id
|
||||||
|
);
|
||||||
|
resolve(
|
||||||
|
resData.value.map((item) => {
|
||||||
|
return {
|
||||||
|
DICTIONARIES_ID: item.DICTIONARIES_ID,
|
||||||
|
BIANMA: item.BIANMA,
|
||||||
|
NAME: item.NAME,
|
||||||
|
leaf: props.checkStrictly
|
||||||
|
? node.level >= props.level
|
||||||
|
: item.zcount === 0,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
value: props.value,
|
||||||
|
id: "DICTIONARIES_ID",
|
||||||
|
label: "NAME",
|
||||||
|
children: "children",
|
||||||
|
checkStrictly: props.checkStrictly,
|
||||||
|
};
|
||||||
|
const getCheckedNodes = () => {
|
||||||
|
return cascaderRef.value
|
||||||
|
.getCheckedNodes()[0]
|
||||||
|
.pathLabels.join(props.joinSeparator);
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getCheckedNodes,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<template>
|
||||||
|
<router-view />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineOptions({
|
||||||
|
name: "children",
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<layout-cascader
|
||||||
|
id="688d2cf1c6cd4dab999a0106e09aec83"
|
||||||
|
v-model="modelValue"
|
||||||
|
ref="cascaderRef"
|
||||||
|
:check-strictly="false"
|
||||||
|
:show-all-levels="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
import LayoutCascader from "@/components/cascader/index.vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutEconomicType",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const cascaderRef = ref(null);
|
||||||
|
const getCheckedNodes = () => {
|
||||||
|
return cascaderRef.value.getCheckedNodes();
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getCheckedNodes,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<layout-cascader
|
||||||
|
id="f2598ba72e864eadabf0ca4b664d26b9"
|
||||||
|
v-model="modelValue"
|
||||||
|
ref="cascaderRef"
|
||||||
|
:check-strictly="false"
|
||||||
|
:show-all-levels="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
import LayoutCascader from "@/components/cascader/index.vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutIndustry",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const cascaderRef = ref(null);
|
||||||
|
const getCheckedNodes = () => {
|
||||||
|
return cascaderRef.value.getCheckedNodes();
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getCheckedNodes,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
style="display: flex; justify-content: space-between; align-items: center"
|
||||||
|
>
|
||||||
|
<div class="breadcrumb">
|
||||||
|
<icon-local theme="filled" size="22" fill="#10a7e5" :strokeWidth="3" />
|
||||||
|
<el-breadcrumb class="app-breadcrumb" separator=">">
|
||||||
|
<transition-group name="breadcrumb">
|
||||||
|
<el-breadcrumb-item
|
||||||
|
v-for="(item, index) in data.breadcrumbList"
|
||||||
|
:key="item.path"
|
||||||
|
>
|
||||||
|
<router-link v-if="index === 0" :to="item.path">
|
||||||
|
{{ item.meta.title }}
|
||||||
|
</router-link>
|
||||||
|
<span v-else-if="index !== data.breadcrumbList.length - 1">
|
||||||
|
{{ item.meta.title }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="no-redirect">{{ item.meta.title }}</span>
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</transition-group>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</div>
|
||||||
|
<div class="return">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
link
|
||||||
|
@click="$router.back()"
|
||||||
|
v-if="
|
||||||
|
route.meta?.activeMenu &&
|
||||||
|
route.path &&
|
||||||
|
route.meta?.activeMenu !== route.path
|
||||||
|
"
|
||||||
|
>
|
||||||
|
返回上一页
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, watch } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutBreadcrumb",
|
||||||
|
});
|
||||||
|
const route = useRoute();
|
||||||
|
const data = reactive({
|
||||||
|
breadcrumbList: [],
|
||||||
|
});
|
||||||
|
const fnGetBreadcrumb = () => {
|
||||||
|
const matched = route.matched.filter((item) => item.meta?.title);
|
||||||
|
data.breadcrumbList = matched.filter(
|
||||||
|
(item) => item.meta?.title && item.meta?.breadcrumb !== false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
fnGetBreadcrumb();
|
||||||
|
watch(
|
||||||
|
() => route,
|
||||||
|
() => fnGetBreadcrumb(),
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.breadcrumb {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.no-redirect {
|
||||||
|
color: #ffffff;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.return {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
title="修改头像"
|
||||||
|
width="600px"
|
||||||
|
:before-close="fnClose"
|
||||||
|
>
|
||||||
|
<el-form :model="form" :rules="rules" label-width="100px" ref="formRef">
|
||||||
|
<el-form-item label="头像" prop="file">
|
||||||
|
<layout-upload
|
||||||
|
v-model:file-list="form.file"
|
||||||
|
accept=".jpg,.jpeg,.png"
|
||||||
|
list-type="picture-card"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button type="primary" @click="fnSubmit">确认</el-button>
|
||||||
|
<el-button @click="fnClose">关闭</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import LayoutUpload from "@/components/upload/index.vue";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||||
|
import { setAvatar } from "@/request/api.js";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useVModels } from "@vueuse/core";
|
||||||
|
import { useUserStore } from "@/pinia/user.js";
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:visible", "update:form"]);
|
||||||
|
const { visible, form } = useVModels(props, emits);
|
||||||
|
const formRef = ref(null);
|
||||||
|
const rules = {
|
||||||
|
file: [{ required: true, message: "请上传头像", trigger: "change" }],
|
||||||
|
};
|
||||||
|
const fnSubmit = debounce(
|
||||||
|
1000,
|
||||||
|
async () => {
|
||||||
|
await useFormValidate(formRef);
|
||||||
|
if (!form.value.file[0].raw) {
|
||||||
|
ElMessage.warning("没有修改图片,不需要保存");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("FFILE", form.value.file[0].raw);
|
||||||
|
const resData = await setAvatar(formData);
|
||||||
|
fnClose();
|
||||||
|
ElMessage.success("修改成功");
|
||||||
|
userStore.setUserInfo({
|
||||||
|
...userStore.getUserInfo,
|
||||||
|
userPhoto: resData.userPhoto,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
const fnClose = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
title="修改信息"
|
||||||
|
width="600px"
|
||||||
|
:before-close="fnClose"
|
||||||
|
>
|
||||||
|
<el-form :model="form" :rules="rules" label-width="100px" ref="formRef">
|
||||||
|
<el-form-item label="用户名" prop="USERNAME">
|
||||||
|
<el-input
|
||||||
|
v-model="form.USERNAME"
|
||||||
|
disabled
|
||||||
|
placeholder="默认用户手机号码..."
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码" prop="newpwd">
|
||||||
|
<el-input v-model="form.newpwd" type="password" autocomplete="off" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认密码" prop="newpassword1">
|
||||||
|
<el-input
|
||||||
|
v-model="form.newpassword1"
|
||||||
|
type="password"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名" prop="NAME">
|
||||||
|
<el-input v-model="form.NAME" placeholder="这里输入姓名..." />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="邮箱" prop="EMAIL">
|
||||||
|
<el-input v-model="form.EMAIL" placeholder="这里输入邮箱..." />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="BZ">
|
||||||
|
<el-input
|
||||||
|
:rows="3"
|
||||||
|
v-model="form.BZ"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="这里输入备注..."
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button type="primary" @click="fnSubmit"> 确认修改 </el-button>
|
||||||
|
<el-button @click="fnClose">关闭</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { getVerifyDuplicateEmail, setUserInfo } from "@/request/api.js";
|
||||||
|
import { useVModels } from "@vueuse/core";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useUserStore } from "@/pinia/user.js";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:visible", "update:form"]);
|
||||||
|
const { visible, form } = useVModels(props, emits);
|
||||||
|
const formRef = ref(null);
|
||||||
|
const validatePass = (rule, value, callback) => {
|
||||||
|
if (form.value.newpwd && !value) {
|
||||||
|
callback(new Error("请再次输入新密码"));
|
||||||
|
} else if (form.value.newpwd && value && value !== form.value.newpwd) {
|
||||||
|
callback(new Error("两次输入密码不一致!"));
|
||||||
|
} else callback();
|
||||||
|
};
|
||||||
|
const validateEmail = async (rule, value, callback) => {
|
||||||
|
if (value) {
|
||||||
|
try {
|
||||||
|
await getVerifyDuplicateEmail({
|
||||||
|
EMAIL: value,
|
||||||
|
USERNAME: form.value.USERNAME,
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
} catch {
|
||||||
|
callback(new Error("邮箱重复"));
|
||||||
|
}
|
||||||
|
} else callback();
|
||||||
|
};
|
||||||
|
const rules = {
|
||||||
|
NAME: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
|
||||||
|
EMAIL: [
|
||||||
|
{ required: false, message: "请输入邮箱", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,
|
||||||
|
message: "请输入正确的邮箱",
|
||||||
|
},
|
||||||
|
{ validator: validateEmail, trigger: "blur" },
|
||||||
|
],
|
||||||
|
newpwd: [
|
||||||
|
{ required: false, message: "请输入新密码", trigger: "blur" },
|
||||||
|
{ min: 6, max: 18, message: "密码长度为6-18位", trigger: "blur" },
|
||||||
|
],
|
||||||
|
newpassword1: [{ required: false, validator: validatePass, trigger: "blur" }],
|
||||||
|
};
|
||||||
|
const fnSubmit = debounce(
|
||||||
|
1000,
|
||||||
|
async () => {
|
||||||
|
await useFormValidate(formRef);
|
||||||
|
await setUserInfo({
|
||||||
|
USER_ID: userStore.getUserInfo.USER_ID,
|
||||||
|
OPERATIONTYPE: "1",
|
||||||
|
...form.value,
|
||||||
|
PASSWORD: form.value.newpwd,
|
||||||
|
});
|
||||||
|
fnClose();
|
||||||
|
ElMessage.success("修改成功");
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
const fnClose = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
<template>
|
||||||
|
<div class="header">
|
||||||
|
<div class="left">
|
||||||
|
<div class="logo">管理平台</div>
|
||||||
|
<div class="menu">
|
||||||
|
<ul>
|
||||||
|
<template v-for="(item, index) in MENU" :key="index">
|
||||||
|
<li
|
||||||
|
@click="switchMenu(item.model)"
|
||||||
|
:class="{ active: item.model === menuStore.getModel }"
|
||||||
|
>
|
||||||
|
<div v-for="item1 in 4" :key="item1" :class="'horn' + item1" />
|
||||||
|
<div class="title">{{ item.title }}</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user">
|
||||||
|
<el-dropdown
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom-end"
|
||||||
|
@command="dropdownCommand"
|
||||||
|
>
|
||||||
|
<div class="user_info">
|
||||||
|
<el-avatar :size="23" fit="fill" :src="data.avatar" />
|
||||||
|
<span>{{ userStore.getUserInfo.NAME }}</span>
|
||||||
|
<icon-down theme="filled" size="16" fill="#a2c2d3" :strokeWidth="3" />
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item command="modifyInformation">
|
||||||
|
修改信息
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="modifyAvatar">
|
||||||
|
修改头像
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="signOut">退出</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
<update-info
|
||||||
|
v-model:visible="data.userDialog.visible"
|
||||||
|
v-model:form="data.userDialog.form"
|
||||||
|
/>
|
||||||
|
<update-avatar
|
||||||
|
v-model:visible="data.avatarDialog.visible"
|
||||||
|
v-model:form="data.avatarDialog.form"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onBeforeUnmount, reactive } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useMenuStore } from "@/pinia/menu";
|
||||||
|
import { useUserStore } from "@/pinia/user";
|
||||||
|
import { MENU } from "@/assets/js/constant";
|
||||||
|
import { getInfo, getUserInfo, logout } from "@/request/api";
|
||||||
|
import { useMiscellaneousStore } from "@/pinia/miscellaneous.js";
|
||||||
|
import UpdateInfo from "./components/update_info.vue";
|
||||||
|
import UpdateAvatar from "./components/update_avatar.vue";
|
||||||
|
import { checkImgExists, addingPrefixToFile } from "@/assets/js/utils.js";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutHeader",
|
||||||
|
});
|
||||||
|
const FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||||
|
let webSocket;
|
||||||
|
const router = useRouter();
|
||||||
|
const menuStore = useMenuStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const miscellaneousStore = useMiscellaneousStore();
|
||||||
|
const data = reactive({
|
||||||
|
avatar: "",
|
||||||
|
userDialog: {
|
||||||
|
visible: false,
|
||||||
|
form: {},
|
||||||
|
},
|
||||||
|
avatarDialog: {
|
||||||
|
visible: false,
|
||||||
|
form: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const dropdownCommand = async (command) => {
|
||||||
|
if (command === "signOut") {
|
||||||
|
await fnSignOut();
|
||||||
|
}
|
||||||
|
if (command === "modifyInformation") {
|
||||||
|
await fnGetUserInfo();
|
||||||
|
}
|
||||||
|
if (command === "modifyAvatar") {
|
||||||
|
data.avatarDialog.visible = true;
|
||||||
|
data.avatarDialog.form.file = addingPrefixToFile([
|
||||||
|
{ FILEPATH: userStore.getUserInfo.userPhoto },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const fnGetUserInfo = async () => {
|
||||||
|
const resData = await getUserInfo({
|
||||||
|
USER_ID: userStore.getUserInfo.USER_ID,
|
||||||
|
});
|
||||||
|
data.userDialog.visible = true;
|
||||||
|
data.userDialog.form = resData.pd;
|
||||||
|
};
|
||||||
|
const switchMenu = (model) => {
|
||||||
|
menuStore.setModel(model);
|
||||||
|
};
|
||||||
|
const fnGetInfo = async () => {
|
||||||
|
const resData = await getInfo();
|
||||||
|
try {
|
||||||
|
await checkImgExists(FILE_URL + resData.userPhoto);
|
||||||
|
data.avatar = FILE_URL + resData.userPhoto;
|
||||||
|
} catch {
|
||||||
|
data.avatar = new URL(
|
||||||
|
"../../../assets/images/public/tx.png",
|
||||||
|
import.meta.url
|
||||||
|
).href;
|
||||||
|
}
|
||||||
|
userStore.setUserInfo({
|
||||||
|
...userStore.getUserInfo,
|
||||||
|
...resData,
|
||||||
|
});
|
||||||
|
miscellaneousStore.setOnlineAddress(resData.onlineAdress);
|
||||||
|
webSocket = new WebSocket(encodeURI("ws://" + resData.onlineAdress));
|
||||||
|
webSocket.onopen = () => {
|
||||||
|
webSocket.send("[join]" + resData.USERNAME);
|
||||||
|
};
|
||||||
|
webSocket.onmessage = (message) => {
|
||||||
|
const messageMsg = JSON.parse(message.data);
|
||||||
|
if (messageMsg.type === "goOut") {
|
||||||
|
fnSignOut();
|
||||||
|
} else if (messageMsg.type === "thegoout") {
|
||||||
|
fnSignOut();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
fnGetInfo();
|
||||||
|
const fnSignOut = async () => {
|
||||||
|
await logout();
|
||||||
|
webSocket && webSocket.close();
|
||||||
|
userStore.$reset();
|
||||||
|
await router.replace("/login");
|
||||||
|
};
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
webSocket && webSocket.close();
|
||||||
|
webSocket = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header {
|
||||||
|
background-image: url("/src/assets/images/public/headerbg.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 660px 70px;
|
||||||
|
background-color: #030f2f;
|
||||||
|
border-bottom: 1px solid #1f3869;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 99;
|
||||||
|
width: max-content;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 500px;
|
||||||
|
height: var(--el-header-height);
|
||||||
|
line-height: var(--el-header-height);
|
||||||
|
padding-left: 20px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: cursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
li {
|
||||||
|
width: 120px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #051748;
|
||||||
|
clip-path: polygon(0% 0%, 80% 0%, 100% 100%, 20% 100%);
|
||||||
|
position: relative;
|
||||||
|
box-shadow: rgba(11, 62, 110, 0.7) 0 0 13px inset;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-image: url("/src/assets/images/public/tguang.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@for $i from 1 through 4 {
|
||||||
|
.horn#{$i} {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-image: url("/src/assets/images/public/menu_horn#{$i}.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
@if $i == 1 {
|
||||||
|
top: 0;
|
||||||
|
left: 2px;
|
||||||
|
}
|
||||||
|
@if $i == 2 {
|
||||||
|
top: 0;
|
||||||
|
right: 21px;
|
||||||
|
}
|
||||||
|
@if $i == 3 {
|
||||||
|
bottom: 0;
|
||||||
|
left: 21px;
|
||||||
|
}
|
||||||
|
@if $i == 4 {
|
||||||
|
bottom: 0;
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
width: 500px;
|
||||||
|
height: 70px;
|
||||||
|
background-image: url("/src/assets/images/public/userbg.jpg");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
border-bottom: 1px solid #1f3869;
|
||||||
|
|
||||||
|
.el-dropdown {
|
||||||
|
margin-right: 55px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user_info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span:nth-child(2) {
|
||||||
|
color: #ece8e8;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-header>
|
||||||
|
<layout-header />
|
||||||
|
</el-header>
|
||||||
|
<el-container>
|
||||||
|
<el-aside>
|
||||||
|
<el-scrollbar style="height: var(--el-aside-scrollbar-height)">
|
||||||
|
<el-menu
|
||||||
|
router
|
||||||
|
unique-opened
|
||||||
|
:default-active="$route.meta.activeMenu || $route.path"
|
||||||
|
>
|
||||||
|
<layout-menu :menus="routes" />
|
||||||
|
</el-menu>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-aside>
|
||||||
|
<el-main>
|
||||||
|
<layout-breadcrumb v-if="route.meta.isBreadcrumb !== false" />
|
||||||
|
<el-scrollbar style="height: var(--el-main-scrollbar-height)">
|
||||||
|
<router-view v-slot="{ Component }">
|
||||||
|
<transition name="view" mode="out-in">
|
||||||
|
<div :key="$route.path">
|
||||||
|
<component :is="Component"></component>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</router-view>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import LayoutBreadcrumb from "@/components/layout/breadcrumb/index";
|
||||||
|
import LayoutHeader from "@/components/layout/header/index";
|
||||||
|
import LayoutMenu from "@/components/layout/menu/index";
|
||||||
|
import { computed } from "vue";
|
||||||
|
import { useMenuStore } from "@/pinia/menu";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "layout",
|
||||||
|
});
|
||||||
|
const menuStore = useMenuStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const routes = computed(() => menuStore.getMenus);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<template>
|
||||||
|
<template v-for="menu in props.menus" :key="menu.path">
|
||||||
|
<!-- 没有二级导航-->
|
||||||
|
<el-menu-item
|
||||||
|
v-if="fnIsShowMenuItem(menu)"
|
||||||
|
:index="menu.path"
|
||||||
|
:route="{ path: menu.path }"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="'icon-application-menu'"
|
||||||
|
theme="filled"
|
||||||
|
fill="#a5b2c2"
|
||||||
|
size="18"
|
||||||
|
:strokeWidth="3"
|
||||||
|
style="margin-right: 15px"
|
||||||
|
/>
|
||||||
|
<span>{{ menu.meta?.title }}</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<!-- 有二级导航-->
|
||||||
|
<el-sub-menu v-else-if="fnIsShowSubmenu(menu)" :index="menu.path">
|
||||||
|
<template #title>
|
||||||
|
<component
|
||||||
|
:is="'icon-application-menu'"
|
||||||
|
theme="filled"
|
||||||
|
fill="#a5b2c2"
|
||||||
|
size="18"
|
||||||
|
:strokeWidth="3"
|
||||||
|
style="margin-right: 15px"
|
||||||
|
/>
|
||||||
|
<span>{{ menu.meta?.title }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- 递归调用当前组件生成导航-->
|
||||||
|
<layout-menu :menus="menu.children" />
|
||||||
|
</el-sub-menu>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutMenu",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
menus: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const fnIsShowMenuItem = (menu) => {
|
||||||
|
if (menu.meta?.isMenu === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (menu.meta?.isSubMenu === false) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return !menu.children || menu.children.length === 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const fnIsShowSubmenu = (menu) => {
|
||||||
|
if (menu.meta?.isMenu === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (menu.meta?.isSubMenu === false) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return menu.children && menu.children.length > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<template>
|
||||||
|
<el-tree-select
|
||||||
|
ref="treeSelectRef"
|
||||||
|
v-model="modelValue"
|
||||||
|
:data="data"
|
||||||
|
:props="{
|
||||||
|
value: 'id',
|
||||||
|
children: 'nodes',
|
||||||
|
label: 'name',
|
||||||
|
}"
|
||||||
|
node-key="id"
|
||||||
|
:render-after-expand="false"
|
||||||
|
accordion
|
||||||
|
check-strictly
|
||||||
|
:clearable="true"
|
||||||
|
:disabled="disabled"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
layoutFnGetTrainingIndustryType,
|
||||||
|
layoutFnGetTrainingPlateType,
|
||||||
|
layoutFnGetTrainingPostType,
|
||||||
|
} from "@/assets/js/data_dictionary";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutLearningTrainType",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
validator: (value) => {
|
||||||
|
if (["industry", "post", "plate"].includes(value)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error("type必须是industry、post、plate之一");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const treeSelectRef = ref(null);
|
||||||
|
const getCurrentNode = () => {
|
||||||
|
return treeSelectRef.value.getCurrentNode();
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getCurrentNode,
|
||||||
|
});
|
||||||
|
let data = [];
|
||||||
|
if (props.type === "industry") data = await layoutFnGetTrainingIndustryType();
|
||||||
|
if (props.type === "post") data = await layoutFnGetTrainingPostType();
|
||||||
|
if (props.type === "plate") data = await layoutFnGetTrainingPlateType();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<el-tree-select
|
||||||
|
ref="treeSelectRef"
|
||||||
|
v-model="modelValue"
|
||||||
|
:data="data"
|
||||||
|
node-key="id"
|
||||||
|
:props="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'NAME',
|
||||||
|
}"
|
||||||
|
:render-after-expand="false"
|
||||||
|
accordion
|
||||||
|
check-strictly
|
||||||
|
:clearable="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { layoutFnGetRegulatoryType } from "@/assets/js/data_dictionary";
|
||||||
|
import { ref, watchEffect } from "vue";
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutRegulatoryType",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
territory: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const treeSelectRef = ref(null);
|
||||||
|
const data = ref([]);
|
||||||
|
const fnGetData = async () => {
|
||||||
|
const { value } = await layoutFnGetRegulatoryType({
|
||||||
|
PROVINCE: props.territory[0],
|
||||||
|
CITY: props.territory[1],
|
||||||
|
COUNTY: props.territory[2],
|
||||||
|
});
|
||||||
|
data.value = value;
|
||||||
|
};
|
||||||
|
watchEffect(() => {
|
||||||
|
if (props.territory.length > 0) fnGetData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
size="small"
|
||||||
|
:data="props.data"
|
||||||
|
:border="border"
|
||||||
|
:stripe="stripe"
|
||||||
|
:height="height"
|
||||||
|
:max-height="maxHeight"
|
||||||
|
:highlight-current-row="highlightCurrentRow"
|
||||||
|
:row-key="rowKey"
|
||||||
|
:row-class-name="rowClassName"
|
||||||
|
:show-header="showHeader"
|
||||||
|
:show-summary="showSummary"
|
||||||
|
:summary-method="summaryMethod"
|
||||||
|
@row-click="rowClick"
|
||||||
|
@row-dblclick="rowDblclick"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</el-table>
|
||||||
|
<div class="table_footer">
|
||||||
|
<div>
|
||||||
|
<slot name="button"></slot>
|
||||||
|
</div>
|
||||||
|
<el-pagination
|
||||||
|
v-if="props.showPagination"
|
||||||
|
small
|
||||||
|
:current-page="props.pagination.currentPage || 1"
|
||||||
|
:page-size="props.pagination.pageSize || 10"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="props.pagination.total || 0"
|
||||||
|
@update:current-page="handleCurrentChange"
|
||||||
|
@update:page-size="handleSizeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutTable",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
showPagination: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
stripe: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showHeader: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
highlightCurrentRow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
showSummary: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
rowKey: {
|
||||||
|
type: [String, Function],
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
type: [String, Number],
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: [String, Number],
|
||||||
|
},
|
||||||
|
rowClassName: {
|
||||||
|
type: Function,
|
||||||
|
},
|
||||||
|
summaryMethod: {
|
||||||
|
type: Function,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits([
|
||||||
|
"update:pagination",
|
||||||
|
"get-data",
|
||||||
|
"row-click",
|
||||||
|
"row-dblclick",
|
||||||
|
]);
|
||||||
|
const tableRef = ref(null);
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
emits("update:pagination", {
|
||||||
|
currentPage: val,
|
||||||
|
pageSize: props.pagination.pageSize,
|
||||||
|
total: props.pagination.total,
|
||||||
|
});
|
||||||
|
emits("get-data");
|
||||||
|
};
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
emits("update:pagination", {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: val,
|
||||||
|
total: props.pagination.total,
|
||||||
|
});
|
||||||
|
emits("get-data");
|
||||||
|
};
|
||||||
|
const rowClick = (row, column, event) => {
|
||||||
|
emits("row-click", row, column, event);
|
||||||
|
};
|
||||||
|
const rowDblclick = (row, column, event) => {
|
||||||
|
emits("row-dblclick", row, column, event);
|
||||||
|
};
|
||||||
|
const getSelectionRows = () => {
|
||||||
|
return tableRef.value.getSelectionRows();
|
||||||
|
};
|
||||||
|
const clearSelection = () => {
|
||||||
|
return tableRef.value.clearSelection();
|
||||||
|
};
|
||||||
|
const toggleRowSelection = (id, selected) => {
|
||||||
|
for (let i = 0; i < props.data.length; i++) {
|
||||||
|
if (props.data[i][props.rowKey] === id) {
|
||||||
|
tableRef.value.toggleRowSelection(props.data[i], selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getSelectionRows,
|
||||||
|
clearSelection,
|
||||||
|
toggleRowSelection,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.table_footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<layout-cascader
|
||||||
|
id="e725d2a91b8248f4b8f49889038df7de"
|
||||||
|
v-model="modelValue"
|
||||||
|
ref="cascaderRef"
|
||||||
|
:check-strictly="checkStrictly"
|
||||||
|
:level="level"
|
||||||
|
value="BIANMA"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useVModel } from "@vueuse/core";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import LayoutCascader from "@/components/cascader/index.vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutTerritory",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
level: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 3,
|
||||||
|
},
|
||||||
|
checkStrictly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
const modelValue = useVModel(props, "modelValue", emits);
|
||||||
|
const cascaderRef = ref(null);
|
||||||
|
const getCheckedNodes = () => {
|
||||||
|
return cascaderRef.value.getCheckedNodes();
|
||||||
|
};
|
||||||
|
defineExpose({
|
||||||
|
getCheckedNodes,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
<template>
|
||||||
|
<el-upload
|
||||||
|
style="width: 100%"
|
||||||
|
ref="uploadRef"
|
||||||
|
:file-list="fileList"
|
||||||
|
:action="action"
|
||||||
|
multiple
|
||||||
|
:limit="limit"
|
||||||
|
:list-type="listType"
|
||||||
|
:auto-upload="autoUpload"
|
||||||
|
:disabled="disabled"
|
||||||
|
:accept="accept"
|
||||||
|
:on-remove="onRemove"
|
||||||
|
:before-remove="beforeRemove"
|
||||||
|
:on-change="onChange"
|
||||||
|
:on-exceed="onExceed"
|
||||||
|
:on-preview="onPreview"
|
||||||
|
:http-request="httpRequest"
|
||||||
|
:show-file-list="showFileList"
|
||||||
|
:class="{ hide: fileList.length === limit }"
|
||||||
|
>
|
||||||
|
<icon-plus
|
||||||
|
v-if="listType === 'picture-card'"
|
||||||
|
theme="filled"
|
||||||
|
size="32"
|
||||||
|
fill="#fff"
|
||||||
|
:strokeWidth="3"
|
||||||
|
/>
|
||||||
|
<el-button v-else type="primary">点击选择文件上传</el-button>
|
||||||
|
<template #tip>
|
||||||
|
<div class="ml text-red"><slot name="tip"></slot></div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
<el-dialog v-model="visible" title="查看图片">
|
||||||
|
<img
|
||||||
|
:src="imageUrl"
|
||||||
|
alt="Preview Image"
|
||||||
|
style="width: 100%; object-fit: scale-down"
|
||||||
|
/>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import { setDeleteImg } from "@/request/api";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutUpload",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
fileList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
autoUpload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
listType: {
|
||||||
|
type: String,
|
||||||
|
default: "text",
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
ratio: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
deleteToServer: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
showFileList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
httpRequest: {
|
||||||
|
type: Function,
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const visible = ref(false);
|
||||||
|
const imageUrl = ref("");
|
||||||
|
const emits = defineEmits(["update:file-list", "preview"]);
|
||||||
|
const uploadRef = ref(null);
|
||||||
|
const onExceed = () => {
|
||||||
|
ElMessage.warning(`最多上传${props.limit}个文件`);
|
||||||
|
};
|
||||||
|
const beforeRemove = async (uploadFile) => {
|
||||||
|
if (props.deleteToServer && uploadFile.IMGFILES_ID) {
|
||||||
|
await ElMessageBox.confirm("确定要删除吗?", {
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
await setDeleteImg({
|
||||||
|
IMGFILES_ID: uploadFile.IMGFILES_ID,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onRemove = (uploadFile, uploadFiles) => {
|
||||||
|
emits("update:file-list", uploadFiles);
|
||||||
|
};
|
||||||
|
const onChange = (uploadFile, uploadFiles) => {
|
||||||
|
const accept = props.accept && props.accept.split(",");
|
||||||
|
const ratio = props.ratio && props.ratio.split("*");
|
||||||
|
const suffix = uploadFile.raw.name.substring(
|
||||||
|
uploadFile.raw.name.lastIndexOf("."),
|
||||||
|
uploadFile.raw.name.length
|
||||||
|
);
|
||||||
|
const size = props.size * 1024 * 1024;
|
||||||
|
if (ratio) {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = uploadFile.url;
|
||||||
|
img.onload = () => {
|
||||||
|
if (img.width !== +ratio[0] && img.height !== +ratio[1]) {
|
||||||
|
ElMessage.warning(`只能上传${props.ratio}分辨率的图片`);
|
||||||
|
uploadRef.value.handleRemove(uploadFile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (size) {
|
||||||
|
if (uploadFile.size > size) {
|
||||||
|
ElMessage.warning(`文件大小不能超过${props.size}M`);
|
||||||
|
uploadRef.value.handleRemove(uploadFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (accept) {
|
||||||
|
if (accept.includes(suffix)) {
|
||||||
|
emits("update:file-list", uploadFiles);
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(`只能上传${props.accept}格式的文件`);
|
||||||
|
uploadRef.value.handleRemove(uploadFile);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emits("update:file-list", uploadFiles);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onPreview = (uploadFile) => {
|
||||||
|
if (props.listType === "picture-card") {
|
||||||
|
visible.value = true;
|
||||||
|
imageUrl.value = uploadFile.url;
|
||||||
|
} else {
|
||||||
|
emits("preview", uploadFile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.hide :deep(.el-upload--picture-card) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
<template>
|
||||||
|
<div class="mi-captcha">
|
||||||
|
<div class="mi-captcha-content">
|
||||||
|
<!-- 没有进行验证-->
|
||||||
|
<div
|
||||||
|
class="mi-captcha-radar"
|
||||||
|
v-if="!verificationPass"
|
||||||
|
@click="verificationShow = true"
|
||||||
|
>
|
||||||
|
<div class="mi-captcha-radar-ready">
|
||||||
|
<div class="mi-captcha-radar-ring" />
|
||||||
|
<div class="mi-captcha-radar-dot" />
|
||||||
|
</div>
|
||||||
|
<div class="mi-captcha-radar-tip">点击按钮进行验证</div>
|
||||||
|
</div>
|
||||||
|
<!-- 验证通过-->
|
||||||
|
<div
|
||||||
|
class="mi-captcha-radar mi-captcha-radar-pass"
|
||||||
|
v-if="verificationPass"
|
||||||
|
>
|
||||||
|
<div class="mi-captcha-radar-success mi-captcha-radar-success-icon">
|
||||||
|
<span role="img" aria-label="verified">
|
||||||
|
<svg
|
||||||
|
focusable="false"
|
||||||
|
class=""
|
||||||
|
data-icon="verified"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
fill="currentColor"
|
||||||
|
aria-hidden="true"
|
||||||
|
viewBox="64 64 896 896"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M447.8 588.8l-7.3-32.5c-.2-1-.6-1.9-1.1-2.7a7.94 7.94 0 00-11.1-2.2L405 567V411c0-4.4-3.6-8-8-8h-81c-4.4 0-8 3.6-8 8v36c0 4.4 3.6 8 8 8h37v192.4a8 8 0 0012.7 6.5l79-56.8c2.6-1.9 3.8-5.1 3.1-8.3zm-56.7-216.6l.2.2c3.2 3 8.3 2.8 11.3-.5l24.1-26.2a8.1 8.1 0 00-.3-11.2l-53.7-52.1a8 8 0 00-11.2.1l-24.7 24.7c-3.1 3.1-3.1 8.2.1 11.3l54.2 53.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M866.9 169.9L527.1 54.1C523 52.7 517.5 52 512 52s-11 .7-15.1 2.1L157.1 169.9c-8.3 2.8-15.1 12.4-15.1 21.2v482.4c0 8.8 5.7 20.4 12.6 25.9L499.3 968c3.5 2.7 8 4.1 12.6 4.1s9.2-1.4 12.6-4.1l344.7-268.6c6.9-5.4 12.6-17 12.6-25.9V191.1c.2-8.8-6.6-18.3-14.9-21.2zM810 654.3L512 886.5 214 654.3V226.7l298-101.6 298 101.6v427.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M452 297v36c0 4.4 3.6 8 8 8h108v274h-38V405c0-4.4-3.6-8-8-8h-35c-4.4 0-8 3.6-8 8v210h-31c-4.4 0-8 3.6-8 8v37c0 4.4 3.6 8 8 8h244c4.4 0 8-3.6 8-8v-37c0-4.4-3.6-8-8-8h-72V493h58c4.4 0 8-3.6 8-8v-35c0-4.4-3.6-8-8-8h-58V341h63c4.4 0 8-3.6 8-8v-36c0-4.4-3.6-8-8-8H460c-4.4 0-8 3.6-8 8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="mi-captcha-radar-tip">通过验证</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<verification
|
||||||
|
:show="verificationShow"
|
||||||
|
@success="verificationSuccess"
|
||||||
|
@close="verificationClose"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Verification from "vue3-puzzle-vcode";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "LayoutVerification",
|
||||||
|
});
|
||||||
|
defineProps({
|
||||||
|
verificationPass: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(["update:verificationPass"]);
|
||||||
|
const verificationShow = ref(false);
|
||||||
|
const verificationClose = () => {
|
||||||
|
verificationShow.value = false;
|
||||||
|
};
|
||||||
|
const verificationSuccess = () => {
|
||||||
|
emits("update:verificationPass", true);
|
||||||
|
verificationClose();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.mi-captcha {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
height: 2.625rem;
|
||||||
|
font-family: "Pingfang SC", "Microsoft YaHei", "Monospaced Number",
|
||||||
|
"Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
|
"PingFang SC", "Hiragino Sans GB", "Helvetica Neue", Helvetica, Arial,
|
||||||
|
sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #1d1e23;
|
||||||
|
background-image: linear-gradient(315deg, #2e63d8 0%, #21438e 74%);
|
||||||
|
border: 1px solid #2056cf;
|
||||||
|
cursor: pointer;
|
||||||
|
min-width: 10rem;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-ready,
|
||||||
|
.mi-captcha-radar-success {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
width: 1.875rem;
|
||||||
|
height: 1.875rem;
|
||||||
|
margin: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-ring,
|
||||||
|
.mi-captcha-radar-dot {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: scale(0.4);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-shadow: inset 0 0 0 1px #2c67ec;
|
||||||
|
background-image: linear-gradient(0, rgba(0, 0, 0, 0) 50%, #fff 50%),
|
||||||
|
linear-gradient(0, #fff 50%, rgba(0, 0, 0, 0) 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-dot {
|
||||||
|
background: #2c67ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-ring {
|
||||||
|
animation: mi-anim-wait 1s infinite;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-success {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: row;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-success-icon {
|
||||||
|
color: #f6ca9d;
|
||||||
|
animation-name: mi-captcha-success;
|
||||||
|
animation-timing-function: ease;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
animation-delay: 0.5s;
|
||||||
|
animation-duration: 0.4s;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-tip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 2.625rem;
|
||||||
|
padding-left: 0.125rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mi-captcha-radar-pass .mi-captcha-radar-tip {
|
||||||
|
color: #f6ca9d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mi-captcha-success {
|
||||||
|
25% {
|
||||||
|
transform: rotate(25deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(-360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mi-anim-wait {
|
||||||
|
60% {
|
||||||
|
transform: scale(0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep {
|
||||||
|
.vue-auth-box_ {
|
||||||
|
background: #2e63d8 !important;
|
||||||
|
border: 1px solid #2752b3 !important;
|
||||||
|
}
|
||||||
|
.mi-captcha-radar-pass .mi-captcha-radar-tip {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
.mi-captcha-radar-success-icon {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { createApp } from "vue";
|
||||||
|
import "@/assets/css/common.scss";
|
||||||
|
import "@/assets/css/transition.scss";
|
||||||
|
import "@/assets/css/element.scss";
|
||||||
|
import "dayjs/locale/zh-cn";
|
||||||
|
import App from "./App";
|
||||||
|
import pinia from "./pinia";
|
||||||
|
import router from "./router";
|
||||||
|
import "normalize.css";
|
||||||
|
import "animate.css";
|
||||||
|
import "viewerjs/dist/viewer.css";
|
||||||
|
import VueViewer from "v-viewer";
|
||||||
|
import print from "vue3-print-nb";
|
||||||
|
import button from "@/assets/js/button";
|
||||||
|
import "./addRouters";
|
||||||
|
import "element-plus/es/components/loading/style/css";
|
||||||
|
import "element-plus/es/components/message/style/css";
|
||||||
|
import "element-plus/es/components/message-box/style/css";
|
||||||
|
import "element-plus/es/components/notification/style/css";
|
||||||
|
import { install } from "@icon-park/vue-next/es/all";
|
||||||
|
import LayoutTable from "@/components/table/index.vue";
|
||||||
|
import LayoutCard from "@/components/card/index.vue";
|
||||||
|
import ElDialog from "element-plus/es/components/dialog/index";
|
||||||
|
|
||||||
|
ElDialog.props.closeOnClickModal.default = false;
|
||||||
|
ElDialog.props.closeOnPressEscape.default = false;
|
||||||
|
const app = createApp(App);
|
||||||
|
app.component("layout-table", LayoutTable);
|
||||||
|
app.component("layout-card", LayoutCard);
|
||||||
|
install(app, "icon");
|
||||||
|
app
|
||||||
|
.use(pinia)
|
||||||
|
.use(router)
|
||||||
|
.use(VueViewer, {
|
||||||
|
defaultOptions: {
|
||||||
|
zIndex: 9999,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.use(print)
|
||||||
|
.use(button)
|
||||||
|
.mount("#app");
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { createPinia } from "pinia";
|
||||||
|
import piniaPersistedstate from "pinia-plugin-persistedstate";
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
|
pinia.use(piniaPersistedstate);
|
||||||
|
|
||||||
|
export default pinia;
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useMenuStore = defineStore("menuStore", {
|
||||||
|
state: () => ({
|
||||||
|
menusAll: [],
|
||||||
|
menus: [],
|
||||||
|
model: "",
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
getMenus: (state) => state.menus,
|
||||||
|
getModel: (state) => state.model,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setMenus(menus) {
|
||||||
|
this.menusAll = menus;
|
||||||
|
},
|
||||||
|
setModel(model) {
|
||||||
|
this.model = model;
|
||||||
|
this.menus = [];
|
||||||
|
for (let i = 0; i < this.menusAll.length; i++) {
|
||||||
|
if (this.menusAll[i].meta.model === model) {
|
||||||
|
this.menus.push(this.menusAll[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
persist: {
|
||||||
|
storage: window.sessionStorage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useMiscellaneousStore = defineStore("miscellaneousStore", {
|
||||||
|
state: () => ({
|
||||||
|
onlineAddress: false,
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
getOnlineAddress: (state) => state.onlineAddress,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setOnlineAddress(onlineAddress) {
|
||||||
|
this.onlineAddress = onlineAddress;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
persist: {
|
||||||
|
storage: window.sessionStorage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useRouterStore = defineStore("routerStore", {
|
||||||
|
state: () => ({
|
||||||
|
routers: [],
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
getRouters: (state) => state.routers,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setRouters(routers) {
|
||||||
|
this.routers = routers;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
persist: {
|
||||||
|
storage: window.sessionStorage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useUserStore = defineStore("userStore", {
|
||||||
|
state: () => ({
|
||||||
|
userInfo: {},
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
getUserInfo: (state) => state.userInfo,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setUserInfo(userInfo) {
|
||||||
|
this.userInfo = userInfo;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
persist: {
|
||||||
|
storage: window.sessionStorage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { post, upload } from "./axios";
|
||||||
|
|
||||||
|
export const Login = (params) => post("/admin/check", params); // 登录
|
||||||
|
export const logout = (params) => post("/main/logout", params); // 退出登录
|
||||||
|
export const getAsyncRouter = (params) => post("/main/index", params); // 获取动态路由
|
||||||
|
export const getUserInfo = (params) => post("/user/goEditMyInfo", params); // 获取用户信息
|
||||||
|
export const setUserInfo = (params) => post("/user/editUserOwn", params); // 修改用户信息
|
||||||
|
export const getVerifyDuplicateEmail = (params) =>
|
||||||
|
post("/user/hasEmail", params); // 验证邮箱重复
|
||||||
|
export const getVerifyDeduplicationUser = (params) =>
|
||||||
|
post("/user/hasUser", params); // 用户名去重
|
||||||
|
export const setAvatar = (params) => upload("/photo/saveNew", params); // 修改头像
|
||||||
|
export const getInfo = (params) =>
|
||||||
|
post("/head/getInfo", { loading: false, ...params }); // 获取用户信息
|
||||||
|
export const setUploadImg = (params) => upload("/imgfiles/add", params); // 上传附件
|
||||||
|
export const setDeleteImg = (params) => post("/imgfiles/delete", params); // 删除附件
|
||||||
|
export const getViewImg = (params) => post("/imgfiles/listImgs", params); // 查看图片
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import { ElLoading, ElMessage } from "element-plus";
|
||||||
|
import router from "../router";
|
||||||
|
import QS from "qs";
|
||||||
|
|
||||||
|
let loading = null;
|
||||||
|
|
||||||
|
function startLoading() {
|
||||||
|
loading = ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: "加载中...",
|
||||||
|
background: "rgba(0, 0, 0, 0.5)",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function endLoading() {
|
||||||
|
loading && loading.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.defaults.baseURL = import.meta.env[
|
||||||
|
import.meta.env.DEV ? "VITE_PROXY" : "VITE_BASE_URL"
|
||||||
|
];
|
||||||
|
axios.defaults.timeout = 1000 * 60 * 10;
|
||||||
|
// axios.defaults.withCredentials = true;
|
||||||
|
axios.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
if (config.method === "get" || config.method === "GET") {
|
||||||
|
if (QS.parse(config.params)?.loading !== "false") startLoading();
|
||||||
|
}
|
||||||
|
if (config.method === "post" || config.method === "POST") {
|
||||||
|
if (QS.parse(config.data)?.loading !== "false") startLoading();
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => Promise.reject(error)
|
||||||
|
);
|
||||||
|
|
||||||
|
axios.interceptors.response.use(
|
||||||
|
(config) => {
|
||||||
|
if (config.config.method === "get" || config.config.method === "GET") {
|
||||||
|
if (QS.parse(config.config.params)?.loading !== "false") endLoading();
|
||||||
|
}
|
||||||
|
if (config.config.method === "post" || config.config.method === "POST") {
|
||||||
|
if (QS.parse(config.config.data)?.loading !== "false") endLoading();
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.log(error);
|
||||||
|
if (error && error.response) {
|
||||||
|
switch (error.response.status) {
|
||||||
|
case 0:
|
||||||
|
case 302:
|
||||||
|
endLoading();
|
||||||
|
ElMessage.error("登录失效,请重新登陆");
|
||||||
|
router.push("/login").then();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error.message = `连接错误${error.response.status}`;
|
||||||
|
import.meta.env.DEV &&
|
||||||
|
ElMessage.error(`连接错误${error.response.status}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error.message = "连接到服务器失败";
|
||||||
|
endLoading();
|
||||||
|
ElMessage.error("登录失效,请重新登陆");
|
||||||
|
router.push("/login").then();
|
||||||
|
}
|
||||||
|
return Promise.reject(error.message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export function post(url, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.post(url, QS.stringify(params), {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.result === "success") {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
ElMessage.error(
|
||||||
|
res.data.msg ||
|
||||||
|
res.data.resMsg ||
|
||||||
|
res.data.resultStr ||
|
||||||
|
"系统开小差了"
|
||||||
|
);
|
||||||
|
reject(res.data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function get(url, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.get(url, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
params: QS.stringify(params),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.result === "success") {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
ElMessage.error(
|
||||||
|
res.data.msg ||
|
||||||
|
res.data.resMsg ||
|
||||||
|
res.data.resultStr ||
|
||||||
|
"系统开小差了"
|
||||||
|
);
|
||||||
|
reject(res.data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function upload(url, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.post(url, params, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.result === "success") {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
ElMessage.error(
|
||||||
|
res.data.msg ||
|
||||||
|
res.data.resMsg ||
|
||||||
|
res.data.resultStr ||
|
||||||
|
"系统开小差了"
|
||||||
|
);
|
||||||
|
reject(res.data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { post } from "@/request/axios.js";
|
||||||
|
|
||||||
|
// 获取数据字典
|
||||||
|
export const getLevels = (params) =>
|
||||||
|
post("/dictionaries/getLevels", {
|
||||||
|
loading: false,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
// 获取数据字典包括子级数量
|
||||||
|
export const getLevelsAndChildrenNumber = (params) =>
|
||||||
|
post("/dictionaries/getLevelsAndSCount", {
|
||||||
|
loading: false,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
// 监管类型
|
||||||
|
export const getRegulatoryType = (params) =>
|
||||||
|
post("/corptype/corptypelist", {
|
||||||
|
loading: false,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
// 获取在线学习培训类型
|
||||||
|
export const getLearningTrainType = (params) =>
|
||||||
|
post("/dictionaries/listDictToParId", {
|
||||||
|
loading: false,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { post, upload } from "@/request/axios.js";
|
||||||
|
|
||||||
|
export const getEnterpriseInfo = (params) => post("/corpinfo/goEdit", params); // 获取企业信息
|
||||||
|
export const setEnterpriseInfo = (params) => upload("/corpinfo/edit", params); // 修改企业信息
|
||||||
|
export const getIndustryQualificationsList = (params) =>
|
||||||
|
post("/qualifications/list", params); // 行业资质列表
|
||||||
|
export const setIndustryQualificationsDelete = (params) =>
|
||||||
|
post("/qualifications/delete", params); // 行业资质删除
|
||||||
|
export const getIndustryQualificationsView = (params) =>
|
||||||
|
post("/qualifications/goEdit", params); // 行业资质查看
|
||||||
|
export const setIndustryQualificationsAdd = (params) =>
|
||||||
|
post("/qualifications/add", params); // 行业资质添加
|
||||||
|
export const setIndustryQualificationsEdit = (params) =>
|
||||||
|
post("/qualifications/edit", params); // 行业资质修改
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { createRouter, createWebHashHistory } from "vue-router";
|
||||||
|
import layout from "../components/layout/index.vue";
|
||||||
|
// import children from "../components/children/index.vue";
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
path: "/login",
|
||||||
|
name: "/login",
|
||||||
|
meta: { title: "登录", isLogin: false },
|
||||||
|
component: () => import("@/views/login/index"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
name: "app",
|
||||||
|
redirect: "/index",
|
||||||
|
meta: { title: "首页" },
|
||||||
|
component: layout,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/index",
|
||||||
|
name: "/index",
|
||||||
|
meta: {
|
||||||
|
title: "首页",
|
||||||
|
breadcrumb: false,
|
||||||
|
isMenu: false,
|
||||||
|
isSubMenu: false,
|
||||||
|
},
|
||||||
|
component: () => import("@/views/index/index"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/404",
|
||||||
|
name: "/404",
|
||||||
|
meta: { title: "404", isBreadcrumb: false, isMenu: false },
|
||||||
|
component: () => import("@/views/404"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHashHistory(import.meta.env.BASE_URL),
|
||||||
|
routes,
|
||||||
|
scrollBehavior(to, from, savedPosition) {
|
||||||
|
if (savedPosition) {
|
||||||
|
return savedPosition;
|
||||||
|
} else {
|
||||||
|
return { left: 0, top: 0 };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
|
@ -0,0 +1,565 @@
|
||||||
|
<template>
|
||||||
|
<div class="containerer">
|
||||||
|
<div class="container container-star">
|
||||||
|
<div class="star-1" v-for="item in 30" :key="item"></div>
|
||||||
|
<div class="star-2" v-for="item in 30" :key="item"></div>
|
||||||
|
</div>
|
||||||
|
<div class="container container-bird">
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bird bird-anim">
|
||||||
|
<div class="bird-container">
|
||||||
|
<div class="wing wing-left">
|
||||||
|
<div class="wing-left-top"></div>
|
||||||
|
</div>
|
||||||
|
<div class="wing wing-right">
|
||||||
|
<div class="wing-right-top"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-title">
|
||||||
|
<div class="title">
|
||||||
|
<div class="number">4</div>
|
||||||
|
<div class="moon">
|
||||||
|
<div class="face">
|
||||||
|
<div class="mouth"></div>
|
||||||
|
<div class="eyes">
|
||||||
|
<div class="eye-left"></div>
|
||||||
|
<div class="eye-right"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="number">4</div>
|
||||||
|
</div>
|
||||||
|
<div class="subtitle">抱歉,您访问的页面不存在!</div>
|
||||||
|
<button class="backbtn" @click="router.push({ name: '/index' })">
|
||||||
|
返回首页
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Lato|Russo+One");
|
||||||
|
*,
|
||||||
|
*:after,
|
||||||
|
*:before {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stars
|
||||||
|
.container-star {
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
#04112b 0%,
|
||||||
|
#474c88 70%,
|
||||||
|
#a871d6 100%
|
||||||
|
);
|
||||||
|
&:after {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse at center,
|
||||||
|
rgba(255, 255, 255, 0) 0%,
|
||||||
|
rgba(255, 255, 255, 0) 40%,
|
||||||
|
rgba(15, 10, 38, 0.2) 100%
|
||||||
|
);
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.star-1 {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
animation: twinkle 5s infinite ease-in-out;
|
||||||
|
&:after {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse at center,
|
||||||
|
rgba(255, 255, 255, 0.5) 0%,
|
||||||
|
rgba(255, 255, 255, 0) 60%,
|
||||||
|
rgba(255, 255, 255, 0) 100%
|
||||||
|
);
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
content: "";
|
||||||
|
top: -20%;
|
||||||
|
left: -50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for $i from 1 through (30) {
|
||||||
|
$top: random(100) + vh;
|
||||||
|
$left: random(100) + vw;
|
||||||
|
$size: random(6) + 3px;
|
||||||
|
.star-1:nth-of-type(#{$i}) {
|
||||||
|
top: $top;
|
||||||
|
left: $left;
|
||||||
|
width: $size;
|
||||||
|
height: calc($size / 3);
|
||||||
|
animation-delay: random(5) + s;
|
||||||
|
&:before {
|
||||||
|
width: $size * 2;
|
||||||
|
height: $size * 2;
|
||||||
|
top: -250%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.star-2 {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
animation: twinkle 5s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
@for $i from 31 through (60) {
|
||||||
|
$top: random(100) + vh;
|
||||||
|
$left: random(100) + vw;
|
||||||
|
$size: random(3) + 1px;
|
||||||
|
.star-2:nth-of-type(#{$i}) {
|
||||||
|
top: $top;
|
||||||
|
left: $left;
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
animation-delay: random(5) + s;
|
||||||
|
&:before {
|
||||||
|
width: $size * 2;
|
||||||
|
height: $size * 2;
|
||||||
|
top: -250%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//text and moon
|
||||||
|
.container-title {
|
||||||
|
width: 600px;
|
||||||
|
height: 450px;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.title > * {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 200px;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
text-shadow: 20px 20px 20px rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 0 0.2em;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-top: 3em;
|
||||||
|
text-shadow: 4px 4px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 2em;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 999;
|
||||||
|
border: 1px solid white;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-shadow: 4px 4px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.moon {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #fff,
|
||||||
|
0 0 70px #fff, 0 0 80px #fff, 0 0 100px #ff1177;
|
||||||
|
animation: rotate 5s ease-in-out infinite;
|
||||||
|
.face {
|
||||||
|
top: 60%;
|
||||||
|
left: 47%;
|
||||||
|
position: absolute;
|
||||||
|
.mouth {
|
||||||
|
border-top-left-radius: 50%;
|
||||||
|
border-bottom-right-radius: 50%;
|
||||||
|
border-top-right-radius: 50%;
|
||||||
|
background-color: #5c3191;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
position: absolute;
|
||||||
|
animation: snore 5s ease-in-out infinite;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
box-shadow: inset -4px -4px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
.eyes {
|
||||||
|
position: absolute;
|
||||||
|
top: -30px;
|
||||||
|
left: -30px;
|
||||||
|
.eye-left,
|
||||||
|
.eye-right {
|
||||||
|
border: 4px solid #5c3191;
|
||||||
|
width: 30px;
|
||||||
|
height: 15px;
|
||||||
|
border-bottom-left-radius: 100px;
|
||||||
|
border-bottom-right-radius: 100px;
|
||||||
|
border-top: 0;
|
||||||
|
position: absolute;
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: #5c3191;
|
||||||
|
top: -2px;
|
||||||
|
left: -4px;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
left: auto;
|
||||||
|
right: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.eye-right {
|
||||||
|
left: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//birds
|
||||||
|
.container-bird {
|
||||||
|
perspective: 2000px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.bird {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
height: 40px;
|
||||||
|
width: 50px;
|
||||||
|
transform: translate3d(-100vw, 0, 0) rotateY(90deg);
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
.bird-container {
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
transform: translate3d(50px, 30px, -300px);
|
||||||
|
}
|
||||||
|
.wing {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
transform-origin: center bottom;
|
||||||
|
z-index: 300;
|
||||||
|
}
|
||||||
|
.wing-left {
|
||||||
|
background: linear-gradient(to bottom, #a58dc4 0%, #7979a8 100%);
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(-30deg);
|
||||||
|
animation: wingLeft 1.3s cubic-bezier(0.45, 0, 0.5, 0.95) infinite;
|
||||||
|
}
|
||||||
|
.wing-right {
|
||||||
|
background: linear-gradient(to bottom, #d9d3e2 0%, #b8a5d1 100%);
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(-30deg);
|
||||||
|
animation: wingRight 1.3s cubic-bezier(0.45, 0, 0.5, 0.95) infinite;
|
||||||
|
}
|
||||||
|
.wing-right-top,
|
||||||
|
.wing-left-top {
|
||||||
|
border-right: 25px solid transparent;
|
||||||
|
border-left: 25px solid transparent;
|
||||||
|
top: -20px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
transform-origin: 100% 100%;
|
||||||
|
}
|
||||||
|
.wing-right-top {
|
||||||
|
border-bottom: 20px solid #b8a5d1;
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(60deg);
|
||||||
|
animation: wingRightTop 1.3s cubic-bezier(0.45, 0, 0.5, 0.95) infinite;
|
||||||
|
}
|
||||||
|
.wing-left-top {
|
||||||
|
border-bottom: 20px solid #7979a8;
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(-60deg);
|
||||||
|
animation: wingLeftTop 1.3s cubic-bezier(0.45, 0, 0.5, 0.95) infinite;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(1) {
|
||||||
|
animation: bird1 30s linear infinite forwards;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(2) {
|
||||||
|
animation: bird2 30s linear infinite forwards;
|
||||||
|
animation-delay: 3s;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(3) {
|
||||||
|
animation: bird3 30s linear infinite forwards;
|
||||||
|
animation-delay: 5s;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(4) {
|
||||||
|
animation: bird4 30s linear infinite forwards;
|
||||||
|
animation-delay: 7s;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(5) {
|
||||||
|
animation: bird5 30s linear infinite forwards;
|
||||||
|
animation-delay: 14s;
|
||||||
|
}
|
||||||
|
.bird-anim:nth-child(6) {
|
||||||
|
animation: bird6 30s linear infinite forwards;
|
||||||
|
animation-delay: 10s;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//keyframes
|
||||||
|
@keyframes rotate {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: rotate(-8deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes snore {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: scale(1) rotate(30deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(0.5) rotate(30deg);
|
||||||
|
border-bottom-left-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes twinkle {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wingLeft {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(-50deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate3d(0, -20px, 0) rotateX(-130deg);
|
||||||
|
background: linear-gradient(to bottom, #d9d3e2 0%, #b8a5d1 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wingLeftTop {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(-10deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate3d(0px, 0px, 0) rotateX(-40deg);
|
||||||
|
border-bottom: 20px solid #b8a5d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wingRight {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(50deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate3d(0, -20px, 0) rotateX(130deg);
|
||||||
|
background: linear-gradient(to bottom, #a58dc4 0%, #7979a8 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wingRightTop {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) rotateX(10deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate3d(0px, 0px, 0px) rotateX(40deg);
|
||||||
|
border-bottom: 20px solid #7979a8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird1 {
|
||||||
|
0% {
|
||||||
|
transform: translate3d(-120vw, -20px, -1000px) rotateY(-40deg) rotateX(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(100vw, -40vh, 1000px) rotateY(-40deg) rotateX(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird2 {
|
||||||
|
0%,
|
||||||
|
15% {
|
||||||
|
transform: translate3d(100vw, -300px, -1000px) rotateY(10deg) rotateX(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(-100vw, -20px, -1000px) rotateY(10deg) rotateX(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird3 {
|
||||||
|
0% {
|
||||||
|
transform: translate3d(100vw, -50vh, 100px) rotateY(-5deg) rotateX(-20deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(-100vw, -10vh, 100px) rotateY(-5deg) rotateX(-20deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird4 {
|
||||||
|
0% {
|
||||||
|
transform: translate3d(100vw, 30vh, 200px) rotateY(-5deg) rotateX(10deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(-100vw, -30vh, 200px) rotateY(-5deg) rotateX(10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird5 {
|
||||||
|
0%,
|
||||||
|
5% {
|
||||||
|
transform: translate3d(100vw, 30vh, 400px) rotateY(-15deg) rotateX(-10deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(-100vw, 10vh, 400px) rotateY(-15deg) rotateX(-10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bird6 {
|
||||||
|
0%,
|
||||||
|
10% {
|
||||||
|
transform: translate3d(-100vw, 20vh, -500px) rotateY(15deg) rotateX(10deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate3d(100vw, 40vh, -800px) rotateY(5deg) rotateX(10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 580px) {
|
||||||
|
.container-404 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
font-size: 100px;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
.moon {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.face {
|
||||||
|
transform: scale(0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<layout-card>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:rules="data.rules"
|
||||||
|
:model="data.form"
|
||||||
|
label-width="110px"
|
||||||
|
>
|
||||||
|
<el-form-item label="证书名称" prop="NAME">
|
||||||
|
<el-input v-model="data.form.NAME" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="证书有效期" prop="VALIDITYTIME">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="data.form.VALIDITYTIME"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="证书编号" prop="NUMBER">
|
||||||
|
<el-input v-model="data.form.NUMBER" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="DESCR">
|
||||||
|
<el-input autosize v-model="data.form.DESCR" type="textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="证书图片" prop="file">
|
||||||
|
<layout-upload
|
||||||
|
v-model:file-list="data.form.file"
|
||||||
|
accept=".jpg,.jpeg,.png"
|
||||||
|
list-type="picture-card"
|
||||||
|
delete-to-server
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="tc mt">
|
||||||
|
<el-button type="primary" @click="fnSubmit">提交</el-button>
|
||||||
|
</div>
|
||||||
|
</layout-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import LayoutCard from "@/components/card/index.vue";
|
||||||
|
import LayoutUpload from "@/components/upload/index.vue";
|
||||||
|
import { reactive, ref } from "vue";
|
||||||
|
import {
|
||||||
|
getIndustryQualificationsView,
|
||||||
|
setIndustryQualificationsAdd,
|
||||||
|
setIndustryQualificationsEdit,
|
||||||
|
} from "@/request/prevention/enterprise_management.js";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { setUploadImg } from "@/request/api.js";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
import { addingPrefixToFile } from "@/assets/js/utils.js";
|
||||||
|
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const { QUALIFICATIONS_ID } = route.query;
|
||||||
|
const formRef = ref(null);
|
||||||
|
const data = reactive({
|
||||||
|
form: {
|
||||||
|
NAME: "",
|
||||||
|
VALIDITYTIME: "",
|
||||||
|
NUMBER: "",
|
||||||
|
DESCR: "",
|
||||||
|
file: [],
|
||||||
|
verifyFileUrl: "12",
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
NAME: [{ required: true, message: "名称不能为空", trigger: "blur" }],
|
||||||
|
VALIDITYTIME: [
|
||||||
|
{ required: true, message: "证书有效期不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
NUMBER: [{ required: true, message: "证书编号不能为空", trigger: "blur" }],
|
||||||
|
file: [{ required: true, message: "证书图片不能为空", trigger: "blur" }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const fnGetData = async () => {
|
||||||
|
if (!QUALIFICATIONS_ID) return;
|
||||||
|
const resData = await getIndustryQualificationsView({ QUALIFICATIONS_ID });
|
||||||
|
data.form = resData.pd;
|
||||||
|
data.form.file = addingPrefixToFile(resData.hImgs);
|
||||||
|
};
|
||||||
|
fnGetData();
|
||||||
|
const fnSubmit = debounce(
|
||||||
|
1000,
|
||||||
|
async () => {
|
||||||
|
await useFormValidate(formRef);
|
||||||
|
const resData = !QUALIFICATIONS_ID
|
||||||
|
? await setIndustryQualificationsAdd({ ...data.form })
|
||||||
|
: await setIndustryQualificationsEdit({ ...data.form });
|
||||||
|
const formData = new FormData();
|
||||||
|
for (let i = 0; i < data.form.file.length; i++) {
|
||||||
|
if (data.form.file[i].raw)
|
||||||
|
formData.append("FFILE", data.form.file[i].raw);
|
||||||
|
}
|
||||||
|
formData.append("FOREIGN_KEY", resData.pd.QUALIFICATIONS_ID);
|
||||||
|
formData.append("TYPE", 6);
|
||||||
|
await setUploadImg(formData);
|
||||||
|
ElMessage.success("保存成功");
|
||||||
|
router.back();
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card>
|
||||||
|
<el-form
|
||||||
|
:model="searchForm"
|
||||||
|
label-width="130px"
|
||||||
|
@submit.prevent="fnResetPaginationTransfer"
|
||||||
|
>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="证书名称/证书编号" prop="KEYWORDS">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.KEYWORDS"
|
||||||
|
placeholder="请输入关键字"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="证书有效期" prop="dates">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchForm.dates"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label-width="10px">
|
||||||
|
<el-button type="primary" native-type="submit">搜索</el-button>
|
||||||
|
<el-button native-type="reset" @click="fnResetPagination">
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
<layout-card>
|
||||||
|
<layout-table
|
||||||
|
:data="list"
|
||||||
|
v-model:pagination="pagination"
|
||||||
|
@get-data="fnGetDataTransfer"
|
||||||
|
>
|
||||||
|
<el-table-column label="序号" width="70">
|
||||||
|
<template v-slot="{ $index }">
|
||||||
|
{{ serialNumber(pagination, $index) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="证书名称" prop="NAME" />
|
||||||
|
<el-table-column label="证书有效期" prop="VALIDITYTIME" />
|
||||||
|
<el-table-column label="证书编号" prop="NUMBER" />
|
||||||
|
<el-table-column label="照片">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-tooltip placement="top">
|
||||||
|
<template #content>
|
||||||
|
<template v-if="row.imgs.length > 0">
|
||||||
|
<img
|
||||||
|
v-for="item in row.imgs"
|
||||||
|
:key="item.IMGFILES_ID"
|
||||||
|
:src="FILE_URL + item.FILEPATH"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span v-else>暂无图片</span>
|
||||||
|
</template>
|
||||||
|
<el-tag>预览</el-tag>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="150">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
link
|
||||||
|
@click="
|
||||||
|
router.push({
|
||||||
|
path: '/enterprise_management/information/industry_qualifications/view',
|
||||||
|
query: { QUALIFICATIONS_ID: row.QUALIFICATIONS_ID },
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
link
|
||||||
|
@click="
|
||||||
|
router.push({
|
||||||
|
path: '/enterprise_management/information/industry_qualifications/update',
|
||||||
|
query: { QUALIFICATIONS_ID: row.QUALIFICATIONS_ID },
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
link
|
||||||
|
@click="fnDelete(row.QUALIFICATIONS_ID)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<template #button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
router.push({
|
||||||
|
path: '/enterprise_management/information/industry_qualifications/add',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</layout-table>
|
||||||
|
</layout-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { serialNumber } from "@/assets/js/utils.js";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import {
|
||||||
|
getIndustryQualificationsList,
|
||||||
|
setIndustryQualificationsDelete,
|
||||||
|
} from "@/request/prevention/enterprise_management.js";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import useListData from "@/assets/js/useListData.js";
|
||||||
|
|
||||||
|
const FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||||
|
const router = useRouter();
|
||||||
|
const listData = useListData(getIndustryQualificationsList);
|
||||||
|
const { list, pagination, searchForm, fnGetData, fnResetPagination } = listData;
|
||||||
|
const fnGetDataTransfer = async () => {
|
||||||
|
await fnGetData({
|
||||||
|
STARTTIME: searchForm.value.dates?.[0],
|
||||||
|
ENDTIME: searchForm.value.dates?.[1],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const fnResetPaginationTransfer = async () => {
|
||||||
|
await fnResetPagination({
|
||||||
|
STARTTIME: searchForm.value.dates?.[0],
|
||||||
|
ENDTIME: searchForm.value.dates?.[1],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const fnDelete = debounce(
|
||||||
|
1000,
|
||||||
|
async (QUALIFICATIONS_ID) => {
|
||||||
|
await ElMessageBox.confirm("确定要删除吗?", { type: "warning" });
|
||||||
|
await setIndustryQualificationsDelete({ QUALIFICATIONS_ID });
|
||||||
|
ElMessage.success("删除成功");
|
||||||
|
await fnResetPaginationTransfer();
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<layout-card>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="证书名称">
|
||||||
|
{{ data.info.NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="证书有效期">
|
||||||
|
{{ data.info.VALIDITYTIME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="证书编号">
|
||||||
|
{{ data.info.NUMBER }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="备注">
|
||||||
|
{{ data.info.DESCR }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="证书图片">
|
||||||
|
<img
|
||||||
|
v-viewer
|
||||||
|
v-for="item in data.info.file"
|
||||||
|
:key="item.FILEPATH"
|
||||||
|
:src="item.url"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
class="ml"
|
||||||
|
/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</layout-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import LayoutCard from "@/components/card/index.vue";
|
||||||
|
import { getIndustryQualificationsView } from "@/request/prevention/enterprise_management.js";
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { addingPrefixToFile } from "@/assets/js/utils.js";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { QUALIFICATIONS_ID } = route.query;
|
||||||
|
const data = reactive({
|
||||||
|
info: {},
|
||||||
|
});
|
||||||
|
const fnGetData = async () => {
|
||||||
|
const resData = await getIndustryQualificationsView({ QUALIFICATIONS_ID });
|
||||||
|
data.info = resData.pd;
|
||||||
|
data.info.file = addingPrefixToFile(resData.hImgs);
|
||||||
|
};
|
||||||
|
fnGetData();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,721 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<layout-card>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="data.form"
|
||||||
|
:rules="data.rules"
|
||||||
|
label-width="210px"
|
||||||
|
>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-divider content-position="left">基本信息</el-divider>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="企业名称" prop="CORP_NAME">
|
||||||
|
<el-input v-model="data.form.CORP_NAME" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="邮政编码">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.POSTAL_CODE"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="统一社会信用代码" prop="CODE">
|
||||||
|
<el-input v-model="data.form.CODE" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="市行业监管部门" prop="INDUSTRY_DEPARTMENTName">
|
||||||
|
<el-input
|
||||||
|
disabled
|
||||||
|
v-model="data.form.INDUSTRY_DEPARTMENTName"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="属地" prop="POSSESSION">
|
||||||
|
<layout-territory
|
||||||
|
ref="territoryCascaderRef"
|
||||||
|
v-model="data.form.POSSESSION"
|
||||||
|
:level="4"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="监管类型" prop="REGULARTYPE">
|
||||||
|
<layout-regulatory-type
|
||||||
|
v-model="data.form.REGULARTYPE"
|
||||||
|
:territory="data.form.POSSESSION"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="所属行业" prop="INDUSTRYALL">
|
||||||
|
<layout-industry
|
||||||
|
ref="industryCascaderRef"
|
||||||
|
v-model="data.form.INDUSTRYALL"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="经济类型" prop="ECO_TYPEALL">
|
||||||
|
<layout-economic-type
|
||||||
|
ref="economicTypeCascaderRef"
|
||||||
|
v-model="data.form.ECO_TYPEALL"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="企事业单位经营地址" prop="ADDRESS_BUSINESS">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.ADDRESS_BUSINESS"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="企业状态" prop="CORP_STATE">
|
||||||
|
<el-select v-model="data.form.CORP_STATE">
|
||||||
|
<el-option
|
||||||
|
v-for="item in enterpriseStatus"
|
||||||
|
:key="item.DICTIONARIES_ID"
|
||||||
|
:label="item.NAME"
|
||||||
|
:value="item.DICTIONARIES_ID"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="经度/纬度" prop="LONGITUDE">
|
||||||
|
<div style="flex: 1; display: flex">
|
||||||
|
<el-input
|
||||||
|
:model-value="
|
||||||
|
(data.form.LONGITUDE ?? '') +
|
||||||
|
'-' +
|
||||||
|
(data.form.LATITUDE ?? '')
|
||||||
|
"
|
||||||
|
disabled
|
||||||
|
style="flex: 1"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="ml-10"
|
||||||
|
@click="fnMapDialogVisible"
|
||||||
|
>
|
||||||
|
地图定位
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="主要负责人" prop="CONTACTS">
|
||||||
|
<el-input v-model="data.form.CONTACTS" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="主要负责人电话" prop="CONTACTS_PHONE">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.CONTACTS_PHONE"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="法定代表人">
|
||||||
|
<el-input v-model="data.form.LR_NAME" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="法人手机号" prop="LR_MOBILE">
|
||||||
|
<el-input v-model="data.form.LR_PHONE" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="占地面积(㎡)">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.AREA_COVERED"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="职工人数(人)">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.EMPLOYEES"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="成立时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="data.form.CREATE_DATE"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
type="date"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="注册资金(万元)">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.REGCAPITAL"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="资产总额(万元)">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.TOTALASSETS"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="隶属关系">
|
||||||
|
<el-select v-model="data.form.SUBORDINATION">
|
||||||
|
<el-option
|
||||||
|
v-for="item in subordination"
|
||||||
|
:key="item.DICTIONARIES_ID"
|
||||||
|
:label="item.NAME"
|
||||||
|
:value="item.DICTIONARIES_ID"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="规模" prop="SCALE">
|
||||||
|
<el-select v-model="data.form.SCALE" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in enterpriseScale"
|
||||||
|
:key="item.DICTIONARIES_ID"
|
||||||
|
:label="item.NAME"
|
||||||
|
:value="item.DICTIONARIES_ID"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否规模以上" prop="SCALE_TYPE">
|
||||||
|
<el-radio-group v-model="data.form.SCALE_TYPE">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训行业类型" prop="TRAINTYPE">
|
||||||
|
<layout-learning-train-type
|
||||||
|
v-model="data.form.TRAINTYPE"
|
||||||
|
type="industry"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="企业可新建用户数量" prop="USERS_NUM">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.USERS_NUM"
|
||||||
|
disabled
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="四色图类型">
|
||||||
|
<el-radio v-model="data.form.FOURTYPE" :label="1">
|
||||||
|
平面四色图
|
||||||
|
</el-radio>
|
||||||
|
<el-radio
|
||||||
|
v-model="data.form.FOURTYPE"
|
||||||
|
:label="2"
|
||||||
|
@change="fnProhibitSelect"
|
||||||
|
>
|
||||||
|
3D图
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="data.form.FOURTYPE === 1">
|
||||||
|
<el-form-item label="四色图" prop="four_images">
|
||||||
|
<layout-upload
|
||||||
|
v-model:file-list="data.form.four_images"
|
||||||
|
accept=".jpg,.jpeg,.png"
|
||||||
|
list-type="picture-card"
|
||||||
|
ratio="1480*640"
|
||||||
|
delete-to-server
|
||||||
|
>
|
||||||
|
<template #tip> 四色图:请上传1480*640分辨率的图片 </template>
|
||||||
|
</layout-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="营业执照" prop="bus_images">
|
||||||
|
<layout-upload
|
||||||
|
v-model:file-list="data.form.bus_images"
|
||||||
|
accept=".jpg,.jpeg,.png"
|
||||||
|
list-type="picture-card"
|
||||||
|
:limit="99"
|
||||||
|
delete-to-server
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-divider content-position="left">安全负责人信息</el-divider>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="姓名" prop="SAFETY_NAME">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.SAFETY_NAME"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="职务" prop="SAFETY_POST">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.SAFETY_POST"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="单位电话" prop="SAFETY_NUMBER">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.SAFETY_NUMBER"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="手机号码" prop="SAFETY_PHONE">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.SAFETY_PHONE"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-divider content-position="left">企业相关属性</el-divider>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="有无职业卫生信息" prop="WHETHER_HYGIENE">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_HYGIENE">
|
||||||
|
<el-radio :label="0">无</el-radio>
|
||||||
|
<el-radio :label="1">有</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="有无重大危险源" prop="WHETHER_HAZARDS">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_HAZARDS">
|
||||||
|
<el-radio :label="0">无</el-radio>
|
||||||
|
<el-radio :label="1">有</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item
|
||||||
|
label="是否有稀缺大型应急物资或设施"
|
||||||
|
prop="WHETHER_SCARCE"
|
||||||
|
>
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_SCARCE">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否涉及危化品" prop="WHETHER_CHEMICALS">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_CHEMICALS">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="有无特种设备" prop="WHETHER_SPECIALEQUIPMENT">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_SPECIALEQUIPMENT">
|
||||||
|
<el-radio :label="0">无</el-radio>
|
||||||
|
<el-radio :label="1">有</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="有无特种作业人员" prop="WHETHER_SPECIALPEOPLE">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_SPECIALPEOPLE">
|
||||||
|
<el-radio :label="0">无</el-radio>
|
||||||
|
<el-radio :label="1">有</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否涉及煤气" prop="WHETHER_COALGAS">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_COALGAS">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否属于消防重点单位" prop="WHETHER_FIRE">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_FIRE">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否在受限空间作业" prop="WHETHER_CONFINED">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_CONFINED">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否存在涉爆粉尘作业" prop="WHETHER_POWDER">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_POWDER">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否涉及防雷防静电" prop="WHETHER_LIGHTNING">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_LIGHTNING">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否持有放射源" prop="WHETHER_ACTINOGEN">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_ACTINOGEN">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否涉及液氨制冷" prop="WHETHER_LIQUIDAMMONIA">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_LIQUIDAMMONIA">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否涉及危化品管道" prop="WHETHER_PIPELINE">
|
||||||
|
<el-radio-group v-model="data.form.WHETHER_PIPELINE">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div class="tc mt-10">
|
||||||
|
<el-button @click="back">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="fnSubmit">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</layout-card>
|
||||||
|
<el-dialog title="请选择位置" v-model="data.mapDialog.visible">
|
||||||
|
<el-form label-position="right" label-width="50px">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="坐标">
|
||||||
|
<el-input disabled v-model="data.mapDialog.lng" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label-width="10px">
|
||||||
|
<el-input disabled v-model="data.mapDialog.lat" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div
|
||||||
|
v-loading="data.mapDialog.loading"
|
||||||
|
element-loading-text="地图正在加载中..."
|
||||||
|
element-loading-background="rgba(0, 0, 0, 0.5)"
|
||||||
|
>
|
||||||
|
<div style="width: 100%; height: 500px" id="map_container" />
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="fnMapDialogVisible">取消</el-button>
|
||||||
|
<el-button type="primary" @click="fnMapDialogConfirm">确定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { nextTick, onBeforeUnmount, reactive, ref } from "vue";
|
||||||
|
import LayoutTerritory from "@/components/territory/index.vue";
|
||||||
|
import LayoutRegulatoryType from "@/components/regulatory_type/index.vue";
|
||||||
|
import LayoutIndustry from "@/components/industry/index.vue";
|
||||||
|
import LayoutEconomicType from "@/components/economic_type/index.vue";
|
||||||
|
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||||
|
import LayoutUpload from "@/components/upload/index.vue";
|
||||||
|
import {
|
||||||
|
layoutFnGetEnterpriseScale,
|
||||||
|
layoutFnGetEnterpriseStatus,
|
||||||
|
layoutFnGetSubordination,
|
||||||
|
} from "@/assets/js/data_dictionary.js";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||||
|
import {
|
||||||
|
getEnterpriseInfo,
|
||||||
|
setEnterpriseInfo,
|
||||||
|
} from "@/request/prevention/enterprise_management.js";
|
||||||
|
import { addingPrefixToFile } from "@/assets/js/utils.js";
|
||||||
|
|
||||||
|
let mapInstance;
|
||||||
|
const router = useRouter();
|
||||||
|
const formRef = ref(null);
|
||||||
|
const territoryCascaderRef = ref(null);
|
||||||
|
const industryCascaderRef = ref(null);
|
||||||
|
const economicTypeCascaderRef = ref(null);
|
||||||
|
const data = reactive({
|
||||||
|
form: {
|
||||||
|
CORP_NAME: "",
|
||||||
|
POSTAL_CODE: "",
|
||||||
|
CODE: "",
|
||||||
|
INDUSTRY_DEPARTMENTName: "",
|
||||||
|
INDUSTRY_DEPARTMENT: "",
|
||||||
|
POSSESSION: [],
|
||||||
|
REGULARTYPE: "",
|
||||||
|
INDUSTRYALL: [],
|
||||||
|
ECO_TYPEALL: [],
|
||||||
|
ADDRESS_BUSINESS: "",
|
||||||
|
CORP_STATE: "",
|
||||||
|
LONGITUDE: "",
|
||||||
|
LATITUDE: "",
|
||||||
|
CONTACTS: "",
|
||||||
|
CONTACTS_PHONE: "",
|
||||||
|
LR_NAME: "",
|
||||||
|
LR_MOBILE: "",
|
||||||
|
AREA_COVERED: "",
|
||||||
|
EMPLOYEES: "",
|
||||||
|
CREATE_DATE: "",
|
||||||
|
REGCAPITAL: "",
|
||||||
|
TOTALASSETS: "",
|
||||||
|
SUBORDINATION: "",
|
||||||
|
SCALE: "",
|
||||||
|
SCALE_TYPE: "",
|
||||||
|
TRAINTYPE: [],
|
||||||
|
USERS_NUM: "",
|
||||||
|
FOURTYPE: "",
|
||||||
|
four_images: [],
|
||||||
|
bus_images: [],
|
||||||
|
SAFETY_NAME: "",
|
||||||
|
SAFETY_POST: "",
|
||||||
|
SAFETY_NUMBER: "",
|
||||||
|
SAFETY_PHONE: "",
|
||||||
|
WHETHER_HYGIENE: "",
|
||||||
|
WHETHER_HAZARDS: "",
|
||||||
|
WHETHER_SCARCE: "",
|
||||||
|
WHETHER_CHEMICALS: "",
|
||||||
|
WHETHER_SPECIALEQUIPMENT: "",
|
||||||
|
WHETHER_SPECIALPEOPLE: "",
|
||||||
|
WHETHER_COALGAS: "",
|
||||||
|
WHETHER_FIRE: "",
|
||||||
|
WHETHER_CONFINED: "",
|
||||||
|
WHETHER_POWDER: "",
|
||||||
|
WHETHER_LIGHTNING: "",
|
||||||
|
WHETHER_ACTINOGEN: "",
|
||||||
|
WHETHER_LIQUIDAMMONIA: "",
|
||||||
|
WHETHER_PIPELINE: "",
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
CORP_NAME: [
|
||||||
|
{ required: true, message: "企业名称不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
CODE: [
|
||||||
|
{ required: true, message: "统一社会信用代码不能为空", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern: /^[^_IOZSVa-z\W]{2}\d{6}[^_IOZSVa-z\W]{10}$/,
|
||||||
|
message: "请输入正确的统一社会信用代码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
POSSESSION: [{ required: true, message: "属地不能为空", trigger: "blur" }],
|
||||||
|
INDUSTRYALL: [
|
||||||
|
{ required: true, message: "所属行业不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
ECO_TYPEALL: [
|
||||||
|
{ required: true, message: "经济类型不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
ADDRESS_BUSINESS: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "企事业单位经营地址不能为空",
|
||||||
|
trigger: "blur",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
CORP_STATE: [
|
||||||
|
{ required: true, message: "企业状态不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
LONGITUDE: [{ required: true, message: "经度不能为空", trigger: "blur" }],
|
||||||
|
LATITUDE: [{ required: true, message: "纬度不能为空", trigger: "blur" }],
|
||||||
|
CONTACTS: [
|
||||||
|
{ required: true, message: "主要负责人不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
CONTACTS_PHONE: [
|
||||||
|
{ required: true, message: "主要负责人电话不能为空", trigger: "blur" },
|
||||||
|
{ min: 11, max: 11, message: "请输入11位手机号码", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TRAINTYPE: [
|
||||||
|
{ required: true, message: "培训行业类型不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
bus_images: [
|
||||||
|
{ required: true, message: "营业执照不能为空", trigger: "blur" },
|
||||||
|
],
|
||||||
|
LR_MOBILE: [
|
||||||
|
{ min: 11, max: 11, message: "请输入11位手机号码", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
SAFETY_PHONE: [
|
||||||
|
{ min: 11, max: 11, message: "请输入11位手机号码", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
SAFETY_NUMBER: [
|
||||||
|
{ min: 11, max: 11, message: "请输入11位手机号码", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern:
|
||||||
|
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
mapDialog: {
|
||||||
|
visible: false,
|
||||||
|
loading: true,
|
||||||
|
lat: "",
|
||||||
|
lng: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const fnGetData = async () => {
|
||||||
|
const resData = await getEnterpriseInfo();
|
||||||
|
data.form = resData.pd;
|
||||||
|
data.form.bus_images = addingPrefixToFile(resData.busImgs);
|
||||||
|
data.form.four_images = addingPrefixToFile(resData.fourImgs);
|
||||||
|
data.form.OLDFOURTYPE = resData.pd.FOURTYPE;
|
||||||
|
data.form.FOURTYPE = resData.pd.FOURTYPE || 1;
|
||||||
|
};
|
||||||
|
fnGetData();
|
||||||
|
const enterpriseStatus = await layoutFnGetEnterpriseStatus();
|
||||||
|
const subordination = await layoutFnGetSubordination();
|
||||||
|
const enterpriseScale = await layoutFnGetEnterpriseScale();
|
||||||
|
const fnMapInit = () => {
|
||||||
|
mapInstance = new window.BMapGL.Map("map_container");
|
||||||
|
mapInstance.centerAndZoom(
|
||||||
|
new window.BMapGL.Point(
|
||||||
|
data.form.LONGITUDE || "116.3972282409668",
|
||||||
|
data.form.LATITUDE || "39.90960456049752"
|
||||||
|
),
|
||||||
|
16
|
||||||
|
);
|
||||||
|
mapInstance.enableScrollWheelZoom(true);
|
||||||
|
mapInstance.setMapStyleV2({
|
||||||
|
styleId: "6f501abeb2a0cc0d961d110b9407b127",
|
||||||
|
});
|
||||||
|
data.mapDialog.loading = false;
|
||||||
|
mapInstance.addEventListener("click", function (event) {
|
||||||
|
data.mapDialog.lat = event.latlng.lat;
|
||||||
|
data.mapDialog.lng = event.latlng.lng;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const fnMapDialogVisible = async () => {
|
||||||
|
data.mapDialog.visible = !data.mapDialog.visible;
|
||||||
|
data.mapDialog.lat = data.form.LATITUDE;
|
||||||
|
data.mapDialog.lng = data.form.LONGITUDE;
|
||||||
|
if (!mapInstance) {
|
||||||
|
await nextTick();
|
||||||
|
fnMapInit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const fnMapDialogConfirm = () => {
|
||||||
|
data.form.LATITUDE = data.mapDialog.lat;
|
||||||
|
data.form.LONGITUDE = data.mapDialog.lng;
|
||||||
|
fnMapDialogVisible();
|
||||||
|
};
|
||||||
|
const fnProhibitSelect = () => {
|
||||||
|
ElMessage.error("请联系管理员制作3D图");
|
||||||
|
data.form.FOURTYPE = 1;
|
||||||
|
};
|
||||||
|
const back = () => {
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
const fnSubmit = debounce(
|
||||||
|
1000,
|
||||||
|
async () => {
|
||||||
|
await useFormValidate(formRef);
|
||||||
|
data.form.PROVINCE = data.form.POSSESSION[0] || "";
|
||||||
|
data.form.CITY = data.form.POSSESSION[1] || "";
|
||||||
|
data.form.COUNTY = data.form.POSSESSION[2] || "";
|
||||||
|
data.form.VILLAGE = data.form.POSSESSION[3] || "";
|
||||||
|
data.form.STREET = data.form.POSSESSION[4] || "";
|
||||||
|
data.form.COMPANY_AREA = territoryCascaderRef.value.getCheckedNodes();
|
||||||
|
data.form.SMALL = "2";
|
||||||
|
data.form.ECO_TYPE = data.form.ECO_TYPEALL[0] || "";
|
||||||
|
data.form.ECO_TYPE2 = data.form.ECO_TYPEALL[1] || "";
|
||||||
|
data.form.ECO_TYPE_NAME =
|
||||||
|
economicTypeCascaderRef.value.getCheckedNodes()[0];
|
||||||
|
data.form.CORP_TYPE = data.form.INDUSTRYALL[0] || "";
|
||||||
|
data.form.CORP_TYPE2 = data.form.INDUSTRYALL[1] || "";
|
||||||
|
data.form.CORP_TYPE3 = data.form.INDUSTRYALL[2] || "";
|
||||||
|
data.form.CORP_TYPE4 = data.form.INDUSTRYALL[3] || "";
|
||||||
|
data.form.CORP_TYPE_NAME = industryCascaderRef.value.getCheckedNodes()[0];
|
||||||
|
const formData = new FormData();
|
||||||
|
Object.keys(data.form).forEach((key) => {
|
||||||
|
formData.append(key, data.form[key]);
|
||||||
|
});
|
||||||
|
for (let i = 0; i < data.form.bus_images.length; i++) {
|
||||||
|
data.form.bus_images[i].raw &&
|
||||||
|
formData.append("imgFiles", data.form.bus_images[i].raw);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < data.form.four_images.length; i++) {
|
||||||
|
data.form.four_images[i].raw &&
|
||||||
|
formData.append("fourFiles", data.form.four_images[i].raw);
|
||||||
|
}
|
||||||
|
formData.append(
|
||||||
|
"EDITFOURTYPE",
|
||||||
|
data.form.FOURTYPE === data.form.OLDFOURTYPE
|
||||||
|
);
|
||||||
|
await setEnterpriseInfo(formData);
|
||||||
|
back();
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (mapInstance) {
|
||||||
|
mapInstance.destroy();
|
||||||
|
mapInstance = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,259 @@
|
||||||
|
<template>
|
||||||
|
<layout-card>
|
||||||
|
<el-divider content-position="left">基本信息</el-divider>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="企业名称">
|
||||||
|
{{ data.info.CORP_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="邮政编码">
|
||||||
|
{{ data.info.POSTAL_CODE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="统一社会信用代码">
|
||||||
|
{{ data.info.CODE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="市行业监管部门">
|
||||||
|
{{ data.info.INDUSTRY_DEPARTMENTName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="属地">
|
||||||
|
{{ data.info.COMPANY_AREA }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="监管类型">
|
||||||
|
{{ data.info.REGULARTYPE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="经济类型">
|
||||||
|
{{ data.info.ECO_TYPE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="所属行业">
|
||||||
|
{{ data.info.CORP_TYPE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="企事业单位经营地址">
|
||||||
|
{{ data.info.ADDRESS_BUSINESS }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="企业状态">
|
||||||
|
{{ data.info.CORP_STATE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="经度">
|
||||||
|
{{ data.info.LONGITUDE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="纬度">
|
||||||
|
{{ data.info.LATITUDE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="主要负责人">
|
||||||
|
{{ data.info.CONTACTS }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="主要负责人电话">
|
||||||
|
{{ data.info.CONTACTS_PHONE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="法定代表人">
|
||||||
|
{{ data.info.LR_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="法人手机号">
|
||||||
|
{{ data.info.LR_PHONE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="占地面积(㎡)">
|
||||||
|
{{ data.info.AREA_COVERED }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="职工人数(人)">
|
||||||
|
{{ data.info.EMPLOYEES }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成立时间">
|
||||||
|
{{ data.info.CREATE_DATE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="注册资金(万元)">
|
||||||
|
{{ data.info.REGCAPITAL }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="资产总额(万元)">
|
||||||
|
{{ data.info.TOTALASSETS }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="隶属关系">
|
||||||
|
{{ data.info.SUBORDINATIONNAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="规模">
|
||||||
|
{{ data.info.SCALE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否规模以上">
|
||||||
|
<template v-if="data.info.SCALE_TYPE === 0">否</template>
|
||||||
|
<template v-if="data.info.SCALE_TYPE === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训行业类型">
|
||||||
|
{{ data.info.TRAINTYPE_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="企业可新建用户数量">
|
||||||
|
{{ data.info.USERS_NUM }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item
|
||||||
|
label="四色图"
|
||||||
|
v-if="data.info.FOURTYPE === 1"
|
||||||
|
:span="2"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-viewer
|
||||||
|
v-for="item in data.four_images"
|
||||||
|
:src="item.url"
|
||||||
|
:key="item.IMGFILES_ID"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
class="ml-10"
|
||||||
|
/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="营业执照" :span="2">
|
||||||
|
<img
|
||||||
|
v-viewer
|
||||||
|
v-for="item in data.bus_images"
|
||||||
|
:src="item.url"
|
||||||
|
:key="item.IMGFILES_ID"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
class="ml-10"
|
||||||
|
/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<el-divider content-position="left">安全负责人信息</el-divider>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="姓名">
|
||||||
|
{{ data.info.SAFETY_NAME }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="职务">
|
||||||
|
{{ data.info.SAFETY_POST }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="单位电话">
|
||||||
|
{{ data.info.SAFETY_NUMBER }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="手机号码">
|
||||||
|
{{ data.info.SAFETY_PHONE }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<el-divider content-position="left">企业相关属性</el-divider>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="有无职业卫生信息">
|
||||||
|
<template v-if="data.info.WHETHER_HYGIENE === 0">无</template>
|
||||||
|
<template v-if="data.info.WHETHER_HYGIENE === 1">有</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="有无重大危险源">
|
||||||
|
<template v-if="data.info.WHETHER_HAZARDS === 0">无</template>
|
||||||
|
<template v-if="data.info.WHETHER_HAZARDS === 1">有</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否有稀缺大型应急物资或设施">
|
||||||
|
<template v-if="data.info.WHETHER_SCARCE === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_SCARCE === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否涉及危化品">
|
||||||
|
<template v-if="data.info.WHETHER_CHEMICALS === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_CHEMICALS === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="有无特种设备">
|
||||||
|
<template v-if="data.info.WHETHER_SPECIALEQUIPMENT === 0">无</template>
|
||||||
|
<template v-if="data.info.WHETHER_SPECIALEQUIPMENT === 1">有</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="有无特种作业人员">
|
||||||
|
<template v-if="data.info.WHETHER_SPECIALPEOPLE === 0">无</template>
|
||||||
|
<template v-if="data.info.WHETHER_SPECIALPEOPLE === 1">有</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否涉及煤气">
|
||||||
|
<template v-if="data.info.WHETHER_COALGAS === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_COALGAS === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否属于消防重点单位">
|
||||||
|
<template v-if="data.info.WHETHER_FIRE === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_FIRE === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否在受限空间作业">
|
||||||
|
<template v-if="data.info.WHETHER_CONFINED === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_CONFINED === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否存在涉爆粉尘作业">
|
||||||
|
<template v-if="data.info.WHETHER_POWDER === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_POWDER === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否涉及防雷防静电">
|
||||||
|
<template v-if="data.info.WHETHER_LIGHTNING === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_LIGHTNING === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否持有放射源">
|
||||||
|
<template v-if="data.info.WHETHER_ACTINOGEN === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_ACTINOGEN === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否涉及液氨制冷">
|
||||||
|
<template v-if="data.info.WHETHER_LIQUIDAMMONIA === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_LIQUIDAMMONIA === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否涉及危化品管道">
|
||||||
|
<template v-if="data.info.WHETHER_PIPELINE === 0">否</template>
|
||||||
|
<template v-if="data.info.WHETHER_PIPELINE === 1">是</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<div class="tc mt-10">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
router.push({ path: '/enterprise_management/information/info/edit' })
|
||||||
|
"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="fnQrCode">二维码</el-button>
|
||||||
|
</div>
|
||||||
|
<el-dialog
|
||||||
|
v-model="data.qrCodeDialog.visible"
|
||||||
|
title="查看二维码"
|
||||||
|
width="600px"
|
||||||
|
>
|
||||||
|
<div id="printContainer" style="border: 1px dashed #ccc">
|
||||||
|
<div class="tc mt-20">
|
||||||
|
<h1>{{ data.info.CORP_NAME }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="tc mt-20 mb-20">
|
||||||
|
<img :src="data.qrCodeDialog.src" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="fnQrCodeDialogChangeShow">关 闭</el-button>
|
||||||
|
<el-button v-print="'#printContainer'" type="primary">打 印</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</layout-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { getEnterpriseInfo } from "@/request/prevention/enterprise_management.js";
|
||||||
|
import { addingPrefixToFile } from "@/assets/js/utils.js";
|
||||||
|
import { reactive } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useQRCode } from "@vueuse/integrations/useQRCode";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const data = reactive({
|
||||||
|
info: {},
|
||||||
|
bus_images: [],
|
||||||
|
four_images: [],
|
||||||
|
qrCodeDialog: {
|
||||||
|
visible: false,
|
||||||
|
src: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const fnGetData = async () => {
|
||||||
|
const resData = await getEnterpriseInfo();
|
||||||
|
data.info = resData.pd;
|
||||||
|
data.bus_images = addingPrefixToFile(resData.busImgs);
|
||||||
|
data.four_images = addingPrefixToFile(resData.fourImgs);
|
||||||
|
};
|
||||||
|
fnGetData();
|
||||||
|
const fnQrCodeDialogChangeShow = () => {
|
||||||
|
data.qrCodeDialog.visible = !data.qrCodeDialog.visible;
|
||||||
|
};
|
||||||
|
const fnQrCode = () => {
|
||||||
|
if (data.info.CORPINFO_ID) {
|
||||||
|
fnQrCodeDialogChangeShow();
|
||||||
|
// TODO: 扫码跳转到企业信息页面
|
||||||
|
data.qrCodeDialog.src = useQRCode("https://vueuse.org", {
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
margin: 1,
|
||||||
|
correctLevel: "H",
|
||||||
|
});
|
||||||
|
} else ElMessage.error("请重新获取二维码");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
<template>
|
||||||
|
<div class="login">
|
||||||
|
<div class="main">
|
||||||
|
<div class="title">管理平台</div>
|
||||||
|
<div class="form">
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="data.form"
|
||||||
|
:rules="data.rules"
|
||||||
|
@submit.prevent="fnLogin"
|
||||||
|
>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input
|
||||||
|
v-model="data.form.username"
|
||||||
|
placeholder="请输入用户名"
|
||||||
|
tabindex="1"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<icon-people theme="filled" size="16" fill="#909399" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
v-model="data.form.password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
tabindex="2"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<icon-lock
|
||||||
|
theme="filled"
|
||||||
|
size="16"
|
||||||
|
fill="#909399"
|
||||||
|
:strokeWidth="3"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<verification v-model:verification-pass="verificationPass" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="button">
|
||||||
|
<el-button native-type="submit">登录</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import Verification from "@/components/verification/index";
|
||||||
|
import { useUserStore } from "@/pinia/user";
|
||||||
|
import { Login } from "@/request/api";
|
||||||
|
import { debounce } from "throttle-debounce";
|
||||||
|
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const formRef = ref(null);
|
||||||
|
const verificationPass = ref(false);
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const data = reactive({
|
||||||
|
form: {
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||||
|
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fnLogin = debounce(
|
||||||
|
1000,
|
||||||
|
() => {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
fnSubmitLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (verificationPass.value) {
|
||||||
|
fnSubmitLogin();
|
||||||
|
} else {
|
||||||
|
ElMessage.warning("请进行登录验证");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ atBegin: true }
|
||||||
|
);
|
||||||
|
const fnSubmitLogin = async () => {
|
||||||
|
await useFormValidate(formRef, "请输入用户名密码");
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const jsencrypt = new JSEncrypt();
|
||||||
|
jsencrypt.setPublicKey(
|
||||||
|
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUoHAavCikaZxjlDM6Km8cX+ye78F4oF39AcEfnE1p2Yn9pJ9WFxYZ4Vkh6F8SKMi7k4nYsKceqB1RwG996SvHQ5C3pM3nbXCP4K15ad6QhN4a7lzlbLhiJcyIKszvvK8ncUDw8mVQ0j/2mwxv05yH6LN9OKU6Hzm1ninpWeE+awIDAQAB"
|
||||||
|
);
|
||||||
|
const KEYDATA = jsencrypt.encrypt(
|
||||||
|
"zcloudchina" + data.form.username + ",zy," + data.form.password
|
||||||
|
);
|
||||||
|
|
||||||
|
const resData = await Login({
|
||||||
|
KEYDATA,
|
||||||
|
SOURCE: 1,
|
||||||
|
});
|
||||||
|
await userStore.setUserInfo({
|
||||||
|
...userStore.getUserInfo,
|
||||||
|
...resData,
|
||||||
|
});
|
||||||
|
await router.replace("/index");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.login {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1920px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
background: url("../../assets/images/public/loginbg.jpg") no-repeat top center;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
|
||||||
|
.main {
|
||||||
|
width: 600px;
|
||||||
|
padding-top: 280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36px;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 478px;
|
||||||
|
min-height: 290px;
|
||||||
|
padding: 20px 40px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: rgba(8, 22, 59, 0.36);
|
||||||
|
border: 1px solid rgba(31, 58, 136, 0.9);
|
||||||
|
margin: 60px auto 0;
|
||||||
|
box-shadow: 0 0 20px rgba(47, 85, 124, 0.2) inset;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item {
|
||||||
|
width: 325px;
|
||||||
|
margin: 20px auto;
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
.el-button {
|
||||||
|
background: #0948d5;
|
||||||
|
border: 1px solid #276aff;
|
||||||
|
height: 45px;
|
||||||
|
width: 100%;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep {
|
||||||
|
.el-input-group__prepend {
|
||||||
|
padding-top: 5px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { defineConfig, loadEnv } from "vite";
|
||||||
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
import eslintPlugin from "vite-plugin-eslint";
|
||||||
|
import AutoImport from "unplugin-auto-import/vite";
|
||||||
|
import Components from "unplugin-vue-components/vite";
|
||||||
|
import {
|
||||||
|
ElementPlusResolver,
|
||||||
|
VantResolver,
|
||||||
|
} from "unplugin-vue-components/resolvers";
|
||||||
|
// import basicSsl from "@vitejs/plugin-basic-ssl";
|
||||||
|
import removeConsole from "vite-plugin-remove-console";
|
||||||
|
import EnhanceLog from "vite-plugin-enhance-log";
|
||||||
|
|
||||||
|
export default ({ mode }) => {
|
||||||
|
return defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
eslintPlugin(),
|
||||||
|
removeConsole({
|
||||||
|
includes: [
|
||||||
|
"assert",
|
||||||
|
"clear",
|
||||||
|
"count",
|
||||||
|
"countReset",
|
||||||
|
"createTask",
|
||||||
|
"debug",
|
||||||
|
"dir",
|
||||||
|
"dirxml",
|
||||||
|
"error",
|
||||||
|
"group",
|
||||||
|
"groupCollapsed",
|
||||||
|
"groupEnd",
|
||||||
|
"info",
|
||||||
|
"log",
|
||||||
|
"profile",
|
||||||
|
"profileEnd",
|
||||||
|
"table",
|
||||||
|
"time",
|
||||||
|
"timeEnd",
|
||||||
|
"timeLog",
|
||||||
|
"timeStamp",
|
||||||
|
"trace",
|
||||||
|
"warn",
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
AutoImport({
|
||||||
|
resolvers: [ElementPlusResolver()],
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [ElementPlusResolver(), VantResolver()],
|
||||||
|
}),
|
||||||
|
EnhanceLog({
|
||||||
|
preTip: "🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀",
|
||||||
|
}),
|
||||||
|
// basicSsl(),
|
||||||
|
],
|
||||||
|
server: {
|
||||||
|
// https: true,
|
||||||
|
host: true, // 本机的局域网IP,不然其他人无法通过IP访问到,0.0.0.0或true会自动获取本机的IP
|
||||||
|
port: 8099, // 端口号
|
||||||
|
open: true, // 是否自动打开浏览器
|
||||||
|
proxy: {
|
||||||
|
[loadEnv(mode, process.cwd()).VITE_PROXY]: {
|
||||||
|
target: loadEnv(mode, process.cwd()).VITE_BASE_URL,
|
||||||
|
changeOrigin: true,
|
||||||
|
ws: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": "/src", // 别名,@代表src目录
|
||||||
|
},
|
||||||
|
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"], // 引入文件时哪些后缀名可以不写
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
// 打包多个入口文件
|
||||||
|
// input: {
|
||||||
|
// admin: path.resolve(__dirname, "index.html"),
|
||||||
|
// 其它入口文件路径需要为src/views/*/index.html
|
||||||
|
// },
|
||||||
|
output: {
|
||||||
|
chunkFileNames: "static/js/[name]-[hash].js",
|
||||||
|
entryFileNames: "static/js/[name]-[hash].js",
|
||||||
|
assetFileNames: "static/[ext]/name-[hash].[ext]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||