Merge remote-tracking branch 'origin/main' into main

test
HuangHuiKang 2 weeks ago
commit 576a9fa5e6

@ -1,34 +1,22 @@
# 开发环境本地只启动前端项目依赖开发环境后端、APP
NODE_ENV=production
VITE_DEV=true
# 请求路径
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
VITE_BASE_URL=' '
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=server
VITE_UPLOAD_URL='/admin-api/infra/file/upload'
# 接口地址
VITE_API_URL=/admin-api
# 是否删除debugger
VITE_DROP_DEBUGGER=false
# 是否删除console.log
VITE_DROP_CONSOLE=false
# 是否sourcemap
VITE_SOURCEMAP=true
# 打包路径
VITE_BASE_PATH=/
# 输出路径
VITE_OUT_DIR=dist
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true
VITE_APP_CAPTCHA_ENABLE=false

@ -8,8 +8,9 @@ VITE_DEV=true
# 线上环境
# VITE_BASE_URL='https://besure.ngsk.tech:7001'
# 本地联调
# VITE_BASE_URL='http://192.168.5.107:48081'
VITE_BASE_URL='http://localhost:48081'
VITE_BASE_URL='http://192.168.5.106:48081'
# VITE_BASE_URL='http://192.168.5.164:48081'
# VITE_BASE_URL='http://192.168.5.5:48081'
# 文件上传类型server - 后端上传, client - 前端直连上传,仅支持 S3 服务

4
.gitignore vendored

@ -9,3 +9,7 @@ auto-*.d.ts
.history
pnpm-lock.yaml
/.vscode
.env.cklocal
.vscode/*
.vscode/settings.json
launch.json

@ -1,144 +0,0 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"npm.packageManager": "pnpm",
"editor.tabSize": 2,
"prettier.printWidth": 100, //
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.eol": "\n",
"search.exclude": {
"**/node_modules": true,
"**/*.log": true,
"**/*.log*": true,
"**/bower_components": true,
"**/dist": true,
"**/elehukouben": true,
"**/.git": true,
"**/.gitignore": true,
"**/.svn": true,
"**/.DS_Store": true,
"**/.idea": true,
"**/.vscode": false,
"**/yarn.lock": true,
"**/tmp": true,
"out": true,
"dist": true,
"node_modules": true,
"CHANGELOG.md": true,
"examples": true,
"res": true,
"screenshots": true,
"yarn-error.log": true,
"**/.yarn": true
},
"files.exclude": {
"**/.cache": true,
"**/.editorconfig": true,
"**/.eslintcache": true,
"**/bower_components": true,
"**/.idea": true,
"**/tmp": true,
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true
},
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/.vscode/**": true,
"**/node_modules/**": true,
"**/tmp/**": true,
"**/bower_components/**": true,
"**/dist/**": true,
"**/yarn.lock": true
},
"stylelint.enable": true,
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
"path-intellisense.mappings": {
"@/": "${workspaceRoot}/src"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
},
"i18n-ally.localesPaths": ["src/locales"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": false,
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue", "react"],
"cSpell.words": [
"brotli",
"browserslist",
"codemirror",
"commitlint",
"cropperjs",
"echart",
"echarts",
"esnext",
"esno",
"iconify",
"INTLIFY",
"lintstagedrc",
"logicflow",
"nprogress",
"pinia",
"pnpm",
"qrcode",
"sider",
"sortablejs",
"stylelint",
"svgs",
"unocss",
"unplugin",
"unref",
"videojs",
"VITE",
"vitejs",
"vueuse",
"wangeditor",
"xingyu",
"yudao",
"zxcvbn"
],
//
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.expand": false,
"explorer.fileNesting.patterns": {
"*.ts": "$(capture).test.ts, $(capture).test.tsx",
"*.tsx": "$(capture).test.ts, $(capture).test.tsx",
"*.env": "$(capture).env.*",
"package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
},
"terminal.integrated.scrollback": 10000,
"nuxt.isNuxtApp": false
}

@ -1,16 +1,16 @@
# 使用轻量级的 Nginx 镜像
FROM nginx:alpine
# 复制自定义 Nginx 配置(如果有)
ARG NGINX_CONF=nginx.conf
RUN rm -f /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY ${NGINX_CONF} /etc/nginx/conf.d/default.conf
# 将本地 dist 目录复制到容器中
COPY dist /usr/share/nginx/html
# 暴露 8088 端口
EXPOSE 8088
# 创建启动脚本
RUN echo -e '#!/bin/sh\n\
echo "Waiting for MySQL/Redis/MinIO to start..."\n\

@ -0,0 +1,130 @@
server {
listen 8088;
server_name localhost;
# 允许上传最大100MB
client_max_body_size 100m;
# =========================
# 后端接口代理DEV
# =========================
location /admin-api/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /jmreport/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /v3/api-docs/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /doc.html {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /swagger-ui/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /webjars/ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ~ /v3/api-docs/.*\.json$ {
proxy_pass http://besure_server_dev:48081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# =========================
# 前端静态页面
# =========================
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# =========================
# 错误页
# =========================
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# =========================
# FRP / 转发代理
# =========================
server {
listen 39002;
server_name localhost;
location /besure/ {
proxy_pass http://ngsk.tech:39001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_buffering off;
}
}

@ -10,11 +10,11 @@
"pro": "vite --mode env.prod",
"dev-server": "vite --mode dev",
"ts:check": "vue-tsc --noEmit",
"build:local": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build",
"build:dev": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode dev",
"build:test": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode test",
"build:stage": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode stage",
"build:prod": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode prod",
"build:local": "node --max_old_space_size=6144 ./node_modules/vite/bin/vite.js build",
"build:dev": "node --max_old_space_size=6144 ./node_modules/vite/bin/vite.js build --mode dev",
"build:test": "node --max_old_space_size=6144 ./node_modules/vite/bin/vite.js build --mode test",
"build:stage": "node --max_old_space_size=6144 ./node_modules/vite/bin/vite.js build --mode stage",
"build:prod": "node --max_old_space_size=6144 ./node_modules/vite/bin/vite.js build --mode prod",
"serve:dev": "vite preview --mode dev",
"serve:prod": "vite preview --mode prod",
"preview": "pnpm build:local && vite preview",
@ -44,6 +44,7 @@
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"dhtmlx-gantt": "^9.1.3",
"diagram-js": "^12.8.0",
"driver.js": "^1.3.1",
"echarts": "^5.5.0",
@ -72,6 +73,7 @@
"vue": "3.5.12",
"vue-dompurify-html": "^4.1.4",
"vue-i18n": "9.10.2",
"vue-plugin-hiprint": "^0.0.60",
"vue-router": "4.4.5",
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",

@ -62,6 +62,9 @@ importers:
dayjs:
specifier: ^1.11.10
version: 1.11.19
dhtmlx-gantt:
specifier: ^9.1.3
version: 9.1.3
diagram-js:
specifier: ^12.8.0
version: 12.8.1
@ -146,6 +149,9 @@ importers:
vue-i18n:
specifier: 9.10.2
version: 9.10.2(vue@3.5.12(typescript@5.3.3))
vue-plugin-hiprint:
specifier: ^0.0.60
version: 0.0.60
vue-router:
specifier: 4.4.5
version: 4.4.5(vue@3.5.12(typescript@5.3.3))
@ -911,6 +917,11 @@ packages:
'@carbon/icons@11.71.0':
resolution: {integrity: sha512-PwOJ7C2MNQbHvaOsPhiKHNikJ9flGtyVeGIsOHIkyNndcxAUOleppHcGofOo4NvCeIUZwnr+EN8fMaU+ZdsH9w==}
'@claviska/jquery-minicolors@2.3.6':
resolution: {integrity: sha512-8Ro6D4GCrmOl41+6w4NFhEOpx8vjxwVRI69bulXsFDt49uVRKhLU5TnzEV7AmOJrylkVq+ugnYNMiGHBieeKUQ==}
peerDependencies:
jquery: '>= 1.7.x'
'@codemirror/autocomplete@6.20.0':
resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==}
@ -1658,6 +1669,9 @@ packages:
'@sinclair/typebox@0.27.8':
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
'@socket.io/component-emitter@3.1.2':
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
'@swc/core-darwin-arm64@1.15.7':
resolution: {integrity: sha512-+hNVUfezUid7LeSHqnhoC6Gh3BROABxjlDNInuZ/fie1RUxaEX4qzDwdTgozJELgHhvYxyPIg1ro8ibnKtgO4g==}
engines: {node: '>=10'}
@ -1882,6 +1896,9 @@ packages:
'@types/qs@6.14.0':
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
'@types/raf@3.4.3':
resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==}
'@types/semver@7.7.1':
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
@ -2342,6 +2359,10 @@ packages:
slate: ^0.72.0
snabbdom: ^3.1.0
'@wtto00/html2canvas@1.4.3':
resolution: {integrity: sha512-jwsb+xL8N+gjrSNABSaFdxmWtE4c7RNFjP20lo1G7gs63Qqo1phhxVBTzxc/apDVh6LgXsU2l5bwKtXd9uz65w==}
engines: {node: '>=8.0.0'}
'@xmldom/xmldom@0.8.11':
resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
engines: {node: '>=10.0.0'}
@ -2523,6 +2544,10 @@ packages:
balanced-match@2.0.0:
resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
base64-arraybuffer@1.0.2:
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
engines: {node: '>= 0.6.0'}
base@0.11.2:
resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==}
engines: {node: '>=0.10.0'}
@ -2593,9 +2618,18 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
btoa@1.2.1:
resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==}
engines: {node: '>= 0.4.0'}
hasBin: true
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
bwip-js@4.8.0:
resolution: {integrity: sha512-gUDkDHSTv8/DJhomSIbO0fX/Dx0MO/sgllLxJyJfu4WixCQe9nfGJzmHm64ZCbxo+gUYQEsQcRmqcwcwPRwUkg==}
hasBin: true
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@ -2640,6 +2674,10 @@ packages:
caniuse-lite@1.0.30001761:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
canvg@3.0.11:
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
engines: {node: '>=10.0.0'}
chalk@1.1.3:
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
engines: {node: '>=0.10.0'}
@ -2867,6 +2905,9 @@ packages:
resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==}
engines: {node: '>=12 || >=16'}
css-line-break@2.1.0:
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
css-select@4.3.0:
resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
@ -3126,6 +3167,9 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
dhtmlx-gantt@9.1.3:
resolution: {integrity: sha512-3FjvcsGVLFgpZgQKjzKnw1vZh2dIKwLt1Zm6G9Oo/bW2Ogm6/PeQ2cNHO033MWicuxJZn2mpLmg6yssUK3RAiQ==}
diagram-js-direct-editing@3.2.0:
resolution: {integrity: sha512-+pyxeQGBSdLiZX0/tmmsm2qZSvm9YtVzod5W3RMHSTR7VrkUMD6E7EX/W9JQv3ebxO7oIdqFmytmNDDpSHnYEw==}
peerDependencies:
@ -3197,6 +3241,9 @@ packages:
resolution: {integrity: sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==}
engines: {node: '>=18'}
dompurify@2.5.9:
resolution: {integrity: sha512-i6mvVmWN4xo9LrhCOZrDgSs9noW6nOahbrmzjRbPF36YPyj5Ue5lgok0MHDWkG7xzpWFO2OYttXdzM7rJxHvNA==}
dompurify@3.3.1:
resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==}
@ -3270,6 +3317,13 @@ packages:
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
engines: {node: '>= 4'}
engine.io-client@6.6.4:
resolution: {integrity: sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==}
engine.io-parser@5.2.3:
resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
engines: {node: '>=10.0.0'}
entities@1.1.2:
resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==}
@ -3518,6 +3572,9 @@ packages:
feelin@3.2.0:
resolution: {integrity: sha512-GFDbHsTYk7YXO1tyw1dOjb7IODeAZvNIosdGZThUwPx5XcD/XhO0hnPZXsIbAzSsIdrgGlTEEdby9fZ2gixysA==}
fflate@0.8.2:
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
file-entry-cache@11.1.1:
resolution: {integrity: sha512-TPVFSDE7q91Dlk1xpFLvFllf8r0HyOMOlnWy7Z2HBku5H3KhIeOGInexrIeg2D64DosVB/JXkrrk6N/7Wriq4A==}
@ -3803,6 +3860,10 @@ packages:
html-void-elements@2.0.1:
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
html2canvas@1.4.1:
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
engines: {node: '>=8.0.0'}
htmlparser2@3.10.1:
resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==}
@ -4109,6 +4170,9 @@ packages:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
jquery@3.7.1:
resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==}
js-base64@2.6.4:
resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
@ -4131,6 +4195,9 @@ packages:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
jsbarcode@3.12.3:
resolution: {integrity: sha512-CuHU9hC6dPsHF5oVFMo8NW76uQVjH4L22CsP4hW+dNnGywJHC/B0ThA1CTDVLnxKLrrpYdicBLnd2xsgTfRnvg==}
jsencrypt@3.5.4:
resolution: {integrity: sha512-kNjfYEMNASxrDGsmcSQh/rUTmcoRfSUkxnAz+MMywM8jtGu+fFEZ3nJjHM58zscVnwR0fYmG9sGkTDjqUdpiwA==}
@ -4174,6 +4241,9 @@ packages:
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
engines: {'0': node >= 0.2.0}
jspdf@2.5.2:
resolution: {integrity: sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==}
katex@0.16.27:
resolution: {integrity: sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==}
hasBin: true
@ -4603,6 +4673,9 @@ packages:
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
nzh@1.0.14:
resolution: {integrity: sha512-wKgaqCSZdrySvB4RWop5g+v6IDv2IErsT6rjq06Bg0yiT9hiHYZO12GMGx/xweGVLcO2lDjX5RqWD0S/Jy9z5Q==}
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@ -4764,6 +4837,9 @@ packages:
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
performance-now@2.1.0:
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -4971,6 +5047,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
raf@3.4.1:
resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
rd@2.0.1:
resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==}
@ -5000,6 +5079,9 @@ packages:
regenerate@1.4.2:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
@ -5084,6 +5166,10 @@ packages:
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rgbcolor@1.0.1:
resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==}
engines: {node: '>= 0.8.15'}
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
@ -5263,6 +5349,14 @@ packages:
resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==}
engines: {node: '>=0.10.0'}
socket.io-client@4.8.3:
resolution: {integrity: sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==}
engines: {node: '>=10.0.0'}
socket.io-parser@4.2.6:
resolution: {integrity: sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==}
engines: {node: '>=10.0.0'}
sortablejs@1.14.0:
resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
@ -5310,6 +5404,10 @@ packages:
resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
stackblur-canvas@2.7.0:
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
engines: {node: '>=0.1.14'}
static-extend@0.1.2:
resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
engines: {node: '>=0.10.0'}
@ -5438,6 +5536,10 @@ packages:
svg-baker@1.7.0:
resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==}
svg-pathdata@6.0.3:
resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==}
engines: {node: '>=12.0.0'}
svg-tags@1.0.0:
resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
@ -5476,6 +5578,9 @@ packages:
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
engines: {node: '>=8'}
text-segmentation@1.0.3:
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@ -5690,6 +5795,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
utrie@1.0.2:
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
uuid@10.0.0:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
hasBin: true
@ -5801,6 +5909,10 @@ packages:
peerDependencies:
vue: ^3.0.0
vue-plugin-hiprint@0.0.60:
resolution: {integrity: sha512-a5uOMn6Nr4qlYYaVNbQKwRZJa8UcNMTflfi6J430/NDtySJB+5ArE8I8+NLjgVV56x3/qdUBs/GWuZCX5Umv1w==}
engines: {node: '>=16'}
vue-router@4.4.5:
resolution: {integrity: sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==}
peerDependencies:
@ -5913,6 +6025,18 @@ packages:
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
ws@8.18.3:
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
xml-js@1.6.11:
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
hasBin: true
@ -5921,6 +6045,10 @@ packages:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}
xmlhttprequest-ssl@2.1.2:
resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==}
engines: {node: '>=0.4.0'}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
@ -6757,6 +6885,10 @@ snapshots:
dependencies:
'@ibm/telemetry-js': 1.10.2
'@claviska/jquery-minicolors@2.3.6(jquery@3.7.1)':
dependencies:
jquery: 3.7.1
'@codemirror/autocomplete@6.20.0':
dependencies:
'@codemirror/language': 6.12.1
@ -7459,6 +7591,8 @@ snapshots:
'@sinclair/typebox@0.27.8': {}
'@socket.io/component-emitter@3.1.2': {}
'@swc/core-darwin-arm64@1.15.7':
optional: true
@ -7673,6 +7807,8 @@ snapshots:
'@types/qs@6.14.0': {}
'@types/raf@3.4.3': {}
'@types/semver@7.7.1': {}
'@types/svgo@2.6.4':
@ -8383,6 +8519,11 @@ snapshots:
slate: 0.72.8
snabbdom: 3.6.3
'@wtto00/html2canvas@1.4.3':
dependencies:
css-line-break: 2.1.0
text-segmentation: 1.0.3
'@xmldom/xmldom@0.8.11': {}
'@zxcvbn-ts/core@3.0.4':
@ -8558,6 +8699,8 @@ snapshots:
balanced-match@2.0.0: {}
base64-arraybuffer@1.0.2: {}
base@0.11.2:
dependencies:
cache-base: 1.0.1
@ -8660,8 +8803,12 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
btoa@1.2.1: {}
buffer-from@1.1.2: {}
bwip-js@4.8.0: {}
cac@6.7.14: {}
cache-base@1.0.1:
@ -8717,6 +8864,17 @@ snapshots:
caniuse-lite@1.0.30001761: {}
canvg@3.0.11:
dependencies:
'@babel/runtime': 7.28.4
'@types/raf': 3.4.3
core-js: 3.47.0
raf: 3.4.1
regenerator-runtime: 0.13.11
rgbcolor: 1.0.1
stackblur-canvas: 2.7.0
svg-pathdata: 6.0.3
chalk@1.1.3:
dependencies:
ansi-styles: 2.2.1
@ -8952,6 +9110,10 @@ snapshots:
css-functions-list@3.2.3: {}
css-line-break@2.1.0:
dependencies:
utrie: 1.0.2
css-select@4.3.0:
dependencies:
boolbase: 1.0.0
@ -9232,6 +9394,8 @@ snapshots:
detect-libc@1.0.3:
optional: true
dhtmlx-gantt@9.1.3: {}
diagram-js-direct-editing@3.2.0(diagram-js@14.11.3):
dependencies:
diagram-js: 14.11.3
@ -9322,6 +9486,9 @@ snapshots:
domify@2.0.0: {}
dompurify@2.5.9:
optional: true
dompurify@3.3.1:
optionalDependencies:
'@types/trusted-types': 2.0.7
@ -9430,6 +9597,20 @@ snapshots:
emojis-list@3.0.0: {}
engine.io-client@6.6.4:
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.4.3
engine.io-parser: 5.2.3
ws: 8.18.3
xmlhttprequest-ssl: 2.1.2
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
engine.io-parser@5.2.3: {}
entities@1.1.2: {}
entities@2.2.0: {}
@ -9816,6 +9997,8 @@ snapshots:
lezer-feel: 1.9.0
luxon: 3.7.2
fflate@0.8.2: {}
file-entry-cache@11.1.1:
dependencies:
flat-cache: 6.1.19
@ -10112,6 +10295,12 @@ snapshots:
html-void-elements@2.0.1: {}
html2canvas@1.4.1:
dependencies:
css-line-break: 2.1.0
text-segmentation: 1.0.3
optional: true
htmlparser2@3.10.1:
dependencies:
domelementtype: 1.3.1
@ -10390,6 +10579,8 @@ snapshots:
jiti@2.6.1: {}
jquery@3.7.1: {}
js-base64@2.6.4: {}
js-beautify@1.15.4:
@ -10410,6 +10601,8 @@ snapshots:
dependencies:
argparse: 2.0.1
jsbarcode@3.12.3: {}
jsencrypt@3.5.4: {}
jsesc@3.1.0: {}
@ -10445,6 +10638,18 @@ snapshots:
jsonparse@1.3.1: {}
jspdf@2.5.2:
dependencies:
'@babel/runtime': 7.28.4
atob: 2.1.2
btoa: 1.2.1
fflate: 0.8.2
optionalDependencies:
canvg: 3.0.11
core-js: 3.47.0
dompurify: 2.5.9
html2canvas: 1.4.1
katex@0.16.27:
dependencies:
commander: 8.3.0
@ -10896,6 +11101,8 @@ snapshots:
dependencies:
boolbase: 1.0.0
nzh@1.0.14: {}
object-assign@4.1.1: {}
object-copy@0.1.0:
@ -11047,6 +11254,8 @@ snapshots:
perfect-debounce@1.0.0: {}
performance-now@2.1.0: {}
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@ -11241,6 +11450,10 @@ snapshots:
queue-microtask@1.2.3: {}
raf@3.4.1:
dependencies:
performance-now: 2.1.0
rd@2.0.1:
dependencies:
'@types/node': 10.17.60
@ -11276,6 +11489,8 @@ snapshots:
regenerate@1.4.2: {}
regenerator-runtime@0.13.11: {}
regenerator-runtime@0.14.1: {}
regex-not@1.0.2:
@ -11349,6 +11564,8 @@ snapshots:
rfdc@1.4.1: {}
rgbcolor@1.0.1: {}
rimraf@3.0.2:
dependencies:
glob: 7.2.3
@ -11591,6 +11808,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
socket.io-client@4.8.3:
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.4.3
engine.io-client: 6.6.4
socket.io-parser: 4.2.6
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
socket.io-parser@4.2.6:
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.4.3
transitivePeerDependencies:
- supports-color
sortablejs@1.14.0: {}
sortablejs@1.15.6: {}
@ -11628,6 +11863,8 @@ snapshots:
stable@0.1.8: {}
stackblur-canvas@2.7.0: {}
static-extend@0.1.2:
dependencies:
define-property: 0.2.5
@ -11813,6 +12050,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
svg-pathdata@6.0.3: {}
svg-tags@1.0.0: {}
svg.js@2.7.1: {}
@ -11857,6 +12096,10 @@ snapshots:
text-extensions@2.4.0: {}
text-segmentation@1.0.3:
dependencies:
utrie: 1.0.2
text-table@0.2.0: {}
through@2.3.8: {}
@ -12124,6 +12367,10 @@ snapshots:
util-deprecate@1.0.2: {}
utrie@1.0.2:
dependencies:
base64-arraybuffer: 1.0.2
uuid@10.0.0: {}
vary@1.1.2: {}
@ -12257,6 +12504,23 @@ snapshots:
'@vue/devtools-api': 6.6.4
vue: 3.5.12(typescript@5.3.3)
vue-plugin-hiprint@0.0.60:
dependencies:
'@claviska/jquery-minicolors': 2.3.6(jquery@3.7.1)
'@wtto00/html2canvas': 1.4.3
bwip-js: 4.8.0
canvg: 3.0.11
jquery: 3.7.1
jsbarcode: 3.12.3
jspdf: 2.5.2
lodash: 4.17.21
nzh: 1.0.14
socket.io-client: 4.8.3
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
vue-router@4.4.5(vue@3.5.12(typescript@5.3.3)):
dependencies:
'@vue/devtools-api': 6.6.4
@ -12400,12 +12664,16 @@ snapshots:
imurmurhash: 0.1.4
signal-exit: 4.1.0
ws@8.18.3: {}
xml-js@1.6.11:
dependencies:
sax: 1.4.3
xml-name-validator@4.0.0: {}
xmlhttprequest-ssl@2.1.2: {}
y18n@4.0.3: {}
y18n@5.0.8: {}

@ -52,6 +52,8 @@ export interface AutocodeRuleVO {
id: number // ID
ruleCode: string // 规则编码
ruleName: string // 规则名称
barcodeType?: number | string
barCodeType?: number | string
ruleDesc: string // 描述
maxLength: number // 最大长度
isPadded: string // 是否补齐
@ -102,4 +104,4 @@ getTestCode: async (ruleCode: string) => {
getAutocodePartListByRuleId: async (ruleId) => {
return await request.get({ url: `/erp/autocode-rule/autocode-part/list-by-rule-id?ruleId=` + ruleId })
}
}
}

@ -26,6 +26,7 @@ export interface MoldBrandTreeVO extends MoldBrandVO {
export interface MoldVO {
id: number // ID
code: string // 模具编码
isCode?: boolean
name: string // 模具名称
unitId: number // 单位ID
machineId: number // 机台ID
@ -33,6 +34,8 @@ export interface MoldVO {
inTime: Date // 入库时间
status: number // 状态
images: string // 模具图片
qrcodeUrl?: string
templateJson?: string | any
fileUrl?: string
remark: string // 备注
isEnable: boolean // 是否启用
@ -124,6 +127,9 @@ export const MoldBrandApi = {
// 获得模具
getMold: async (id: number) => {
return await request.get({ url: `/erp/mold-brand/mold/get?id=` + id })
},
regenerateCode: async (id: number, code: string) => {
return await request.post({ url: `/erp/mold-brand/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` })
},
// 根据状态获得模具
getMoldListByStatus: async (status: number) => {

@ -5,6 +5,9 @@ export interface ProductVO {
id: number // 产品编号
name: string // 产品名称
barCode: string // 产品条码
isCode?: boolean
qrcodeUrl?: string
templateJson?: string | any
categoryId: number // 产品类型编号
subCategoryId: number // 产品类型子类编号
subCategoryName: string // 产品类型子类名称
@ -18,6 +21,12 @@ export interface ProductVO {
purchasePrice: number // 采购价格,单位:元
salePrice: number // 销售价格,单位:元
minPrice: number // 最低价格,单位:元
deviceIds?: string // 关联设备ID列表
moldIds?: string // 关联模具ID列表
devices?: { id: number; name: string }[] // 关联设备列表
molds?: { id: number; name: string }[] // 关联模具列表
deviceList?: any[]
moldList?: any[]
}
// ERP 产品 API
@ -63,6 +72,13 @@ export const ProductApi = {
return await request.put({ url: `/erp/product/update`, data })
},
// 刷新产品二维码
regenerateCode: async (id: number, code: string) => {
return await request.post({
url: `/erp/product/regenerate-code?id=${id}&code=${encodeURIComponent(code)}`
})
},
// 删除产品
deleteProduct: async (id: number) => {
return await request.delete({ url: `/erp/product/delete?id=` + id })

@ -56,4 +56,9 @@ export const ProductUnitApi = {
getProductUnitListByFlag: async () => {
return await request.get({ url: `/erp/product-unit/flag-list`})
},
// 下载用户导入模板
importUserTemplate: async () => {
return await request.download({ url: '/erp/product-unit/get-import-template' })
}
}

@ -12,6 +12,33 @@ export interface WarehouseVO {
truckagePrice: number // 搬运费,单位:元
status: number // 开启状态
defaultStatus: boolean // 是否默认
warehouseId:number
areaList?: Array<{
id: number
warehouseId: number
areaCode: string
areaName: string
areaSize: number
description: string
status: number
createTime: number
}>
locationList?: Array<{
id: number
warehouseId: number
areaId: number
code: string
name: string
areaSize: number
maxLoadWeight: number
positionX: number
positionY: number
positionZ: number
allowProductMix: boolean
allowBatchMix: boolean
status: number
createTime: number
}>
}
// ERP 仓库 API

@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface WarehouseAreaVO {
id: number
warehouseId: number
areaCode: string
areaName: string
areaSize: number
description: string
status: number
createTime: string
}
export const WarehouseAreaApi = {
getWarehouseAreaPage: async (params: any) => {
return await request.get({ url: `/erp/warehouse-area/page`, params })
},
getWarehouseArea: async (id: number) => {
return await request.get({ url: `/erp/warehouse-area/get?id=` + id })
},
createWarehouseArea: async (data: WarehouseAreaVO) => {
return await request.post({ url: `/erp/warehouse-area/create`, data })
},
updateWarehouseArea: async (data: WarehouseAreaVO) => {
return await request.put({ url: `/erp/warehouse-area/update`, data })
},
deleteWarehouseArea: async (id: number) => {
return await request.delete({ url: `/erp/warehouse-area/delete?id=` + id })
}
}

@ -0,0 +1,40 @@
import request from '@/config/axios'
export interface WarehouseLocationVO {
id: number
warehouseId: number
areaId: number
code: string
name: string
areaSize: number
maxLoadWeight: number
positionX: number
positionY: number
positionZ: number
allowProductMix: boolean
allowBatchMix: boolean
status: number
createTime: string
}
export const WarehouseLocationApi = {
getWarehouseLocationPage: async (params: any) => {
return await request.get({ url: `/erp/warehouse-location/page`, params })
},
getWarehouseLocation: async (id: number) => {
return await request.get({ url: `/erp/warehouse-location/get?id=` + id })
},
createWarehouseLocation: async (data: WarehouseLocationVO) => {
return await request.post({ url: `/erp/warehouse-location/create`, data })
},
updateWarehouseLocation: async (data: WarehouseLocationVO) => {
return await request.put({ url: `/erp/warehouse-location/update`, data })
},
deleteWarehouseLocation: async (id: number) => {
return await request.delete({ url: `/erp/warehouse-location/delete?id=` + id })
}
}

@ -1,4 +1,5 @@
import request from '@/config/axios'
import qs from 'qs'
// 物联设备 VO
export interface DeviceVO {
@ -26,6 +27,7 @@ export interface DeviceVO {
certificate?: string // 证书
secretKey?: string // 秘钥
collectionTime?: string | number
images: string,//图片
}
export interface DeviceConnectParams {
@ -65,6 +67,7 @@ export interface HistoryRecordParams {
deviceId: string | number
collectionStartTime?: string
collectionEndTime?: string
attributeCodes?: string[]
}
export interface DeviceContactModelVO {
@ -84,8 +87,8 @@ export const DeviceApi = {
return await request.get({ url: `/iot/device/page`, params })
},
// 查询物联设备
getDeviceList: async () => {
return await request.get({ url: `/iot/device/deviceList` })
getDeviceList: async (params?: any) => {
return await request.get({ url: `/iot/device/deviceList`, params })
},
// 查询物联设备详情
getDevice: async (id: number) => {
@ -97,6 +100,12 @@ export const DeviceApi = {
getDeviceList2ByNoUsed: async (id: number) => {
return await request.get({ url: `/iot/device/noUsedlist2?id=` + id })
},
getAvailableList: async () => {
return await request.get({ url: `/iot/device/available-list` })
},
getAvailableListPage: async (params: any) => {
return await request.get({ url: `/iot/device/available-page` , params})
},
// 新增物联设备
createDevice: async (data: DeviceVO) => {
return await request.post({ url: `/iot/device/create`, data })
@ -142,8 +151,25 @@ export const DeviceApi = {
return await request.get({ url: `/iot/device/singleDevice`, params })
},
getSingleDeviceFrom: async (params: SingleDeviceParams) => {
return await request.get({ url: `/iot/device/singleDeviceFrom`, params })
},
getHistoryRecord: async (params: HistoryRecordParams) => {
return await request.get({ url: `/iot/device/historyRecord`, params })
return await request.get({
url: `/iot/device/historyRecord`,
params,
paramsSerializer: (p) => qs.stringify(p, { allowDots: true, arrayFormat: 'repeat' })
})
},
getHistoryAnalyse: async (params: HistoryRecordParams) => {
return await request.get({
url: `/iot/device/historyAnalyse`,
params,
paramsSerializer: (p) => qs.stringify(p, { allowDots: true, arrayFormat: 'repeat' })
})
},
devicePointList: async () => {
@ -161,8 +187,12 @@ export const DeviceApi = {
getDeviceAttributePage: async (params) => {
return await request.get({ url: `/iot/device/device-attribute/page`, params })
},
// 获得设备属性按类型分租
getDeviceAttributeGroupList: async (params) => {
return await request.get({ url: `/iot/device/device-attribute/groupList`, params })
},
// 获得设备属性列表
getDeviceAttributeList: async (deviceId: number) => {
getDeviceAttributeList: async (deviceId: number | string) => {
return await request.get({ url: `/iot/device/device-attribute/list?deviceId=` + deviceId })
},

@ -0,0 +1,62 @@
import request from '@/config/axios'
export interface DeviceOperationOverviewParams {
ids?: string
startTime?: string
endTime?: string
timelinePageNo?: number
timelinePageSize?: number
}
export interface DeviceOperationOverviewMetricVO {
key: string
icon: string
value: number
unit: string
change: number
}
export interface DeviceOperationOverviewHourlyStatusVO {
hour: string
running: number
standby: number
fault: number
offline: number
}
export interface DeviceOperationOverviewSummaryVO {
status: 'running' | 'standby' | 'fault' | 'offline'
percent: number
hours: number
}
export interface DeviceOperationOverviewTimelineSegmentVO {
status: 'running' | 'standby' | 'fault' | 'offline'
startHour: number
endHour: number
}
export interface DeviceOperationOverviewTimelineRowVO {
id: string
name: string
utilizationRate: number
segments: DeviceOperationOverviewTimelineSegmentVO[]
}
export interface DeviceOperationOverviewRespVO {
metrics: DeviceOperationOverviewMetricVO[]
hourlyStatus: DeviceOperationOverviewHourlyStatusVO[]
summary: DeviceOperationOverviewSummaryVO[]
summaryTotalHours: number
timelineRows: DeviceOperationOverviewTimelineRowVO[]
totalDevices: number
}
export const DeviceOperationOverviewApi = {
getRunOverview: async (params: DeviceOperationOverviewParams) => {
return await request.get<DeviceOperationOverviewRespVO>({
url: `/iot/device-operation-record/runOverview`,
params
})
}
}

@ -8,8 +8,14 @@ export interface DeviceOperationRecordVO {
totalStandbyTime: number
totalFaultTime: number
totalWarningTime: number
totalOfflineTime?: number
utilizationRate: string
powerOnRate?: string
startTime?: string
endTime?: string
lineCode?: string
lineName?: string
deviceId?: number
}
export interface DeviceOperationRecordPageParams {
@ -22,10 +28,23 @@ export interface DeviceOperationRecordPageParams {
ids?: string
}
export interface DeviceOperationListParams {
deviceCode?: string
deviceName?: string
startTime?: string
endTime?: string
lineCode?: string
lineName?: string
deviceId?: number | string
}
export const DeviceOperationRecordApi = {
getDeviceOperationRecordPage: async (params: DeviceOperationRecordPageParams) => {
return await request.get({ url: `/iot/device-operation-record/deviceOperationPage`, params })
},
getDeviceOperationList: async (params?: DeviceOperationListParams) => {
return await request.get({ url: `/iot/device-operation-record/deviceOperationList`, params })
},
exportDeviceOperationReport: async (params: DeviceOperationRecordPageParams) => {
return await request.download({ url: `/iot/device-operation-record/export-device-operation-report`, params })
}

@ -42,6 +42,10 @@ export const DeviceAttributeTypeApi = {
},
// 获得采集点分类列表
importTemplate: async () => {
return await request.download({ url: `/iot/device-attribute-type/get-import-template` })
},
getDeviceAttributeTypeList: async () => {
return await request.get({ url: `/iot/device-attribute-type/list` })
},

@ -14,6 +14,11 @@ export interface RecipePlanDetailVO {
isEnable?: string | number | boolean
}
export interface CollectLatestTimeResult {
timeAbnormal?: boolean
latestTime?: string | number
}
export const RecipePlanDetailApi = {
getRecipePlanDetailPage: async (params: any) => {
return await request.get({ url: `/iot/recipe-plan-detail/page`, params })
@ -39,5 +44,8 @@ export const RecipePlanDetailApi = {
return await request.post({ url: `/iot/recipe-plan-detail/batch-create?id=` + id })
},
getCollectLatestTime: async (params: { id?: number | string; recipeId?: number | string }) => {
return await request.get({ url: `/iot/recipe-plan-detail/getCollectLatestTime`, params })
}
}

@ -12,10 +12,27 @@ export interface RecipePointRecordVO {
export const RecipePointRecordApi = {
// 新增记录
createRecipePointRecord: async (data: RecipePointRecordVO) => {
return await request.post({ url: `/iot/recipe-point-record/create`, data })
},
// 批量新增记录
createRecipePointRecordBatch: async (data: RecipePointRecordVO[]) => {
return await request.post({ url: `/iot/recipe-point-record/batch-create`, data })
},
getRecipePointRecordPage: async (params: any) => {
return await request.get({ url: `/iot/recipe-point-record/page`, params })
}
}
},
updateRecipePointRecord: async (params: {
id: string | number
recipeId?: string | number
name?: string
max?: string | number
min?: string | number
dataType?: string | number
dataUnit?: string | number
remark?: string
refer?: string
}) => {
return await request.put({ url: `/iot/recipe-point-record/update`, data:params })
}
}

@ -3,11 +3,28 @@ import request from '@/config/axios'
// 报工 VO
export interface BaogongRecordVO {
id: number // id
planId: number // 关联计划id
planId: number // 关联计划 id
num: number // 派工数量
baogongTime: Date // 派工时间
}
// 报工统计 VO
export interface BaogongRecordStatVO {
id: number // ID
taskCode: string // 任务单编码
planCode: string // 计划单编码
employeeId: string // 员工 ID
employeeName: string // 员工姓名
productName: string // 产品名称
productCode: string // 产品编码
baogongNum: number // 报工数量
passNum: number // 合格数量
noPassNum: number // 不合格数量
passRate: number // 合格率 (%)
reason: string // 原因
baogongTime: Date // 报工时间
}
// 报工 API
export const BaogongRecordApi = {
// 查询报工分页
@ -15,6 +32,11 @@ export const BaogongRecordApi = {
return await request.get({ url: `/mes/baogong-record/page`, params })
},
// 查询报工统计分页
getBaogongRecordStatPage: async (params: any) => {
return await request.get({ url: `/mes/baogong-record/stat-page`, params })
},
// 查询报工详情
getBaogongRecord: async (id: number) => {
return await request.get({ url: `/mes/baogong-record/get?id=` + id })
@ -40,4 +62,13 @@ export const BaogongRecordApi = {
return await request.download({ url: `/mes/baogong-record/export-excel`, params })
},
// 导出报工统计 Excel
exportBaogongRecordStat: async (params) => {
return await request.download({ url: `/mes/baogong-record/export-stat-excel`, params })
},
// 导出报工统计 Excel (新)
statExportExcel: async (params) => {
return await request.download({ url: `/mes/baogong-record/stat-export-excel`, params })
},
}

@ -49,5 +49,9 @@ export const BomApi = {
// 获得产品BOM明细列表
getBomDetailListByBomId: async (bomId) => {
return await request.get({ url: `/mes/bom/bom-detail/list-by-bom-id?bomId=` + bomId })
},
getBomByProductId: async (productId: number) => {
return await request.get({ url: `/mes/bom/getByProductId`, params: { productId } })
}
}

@ -0,0 +1,55 @@
import request from '@/config/axios'
// 节假日设置 VO
export interface CalHolidayVO {
holidayId: number // 流水号
theDay: Date // 日期
holidayType: string // 日期类型
startTime: Date // 开始时间
endTime: Date // 结束时间
remark: string // 备注
attr1: string // 预留字段1
attr2: string // 预留字段2
attr3: number // 预留字段3
attr4: number // 预留字段4
createBy: string // 创建者
updateBy: string // 更新者
}
// 节假日设置 API
export const CalHolidayApi = {
// 查询节假日设置分页
getCalHolidayPage: async (params: any) => {
return await request.get({ url: `/mes/cal-holiday/page`, params })
},
// 查询节假日设置详情
getCalHoliday: async (id: number) => {
return await request.get({ url: `/mes/cal-holiday/get?id=` + id })
},
// 新增节假日设置
createCalHoliday: async (data: CalHolidayVO) => {
return await request.post({ url: `/mes/cal-holiday/create`, data })
},
// 修改节假日设置
updateCalHoliday: async (data: CalHolidayVO) => {
return await request.put({ url: `/mes/cal-holiday/update`, data })
},
// 删除节假日设置
deleteCalHoliday: async (id: number) => {
return await request.delete({ url: `/mes/cal-holiday/delete?id=` + id })
},
// 导出节假日设置 Excel
exportCalHoliday: async (params) => {
return await request.download({ url: `/mes/cal-holiday/export-excel`, params })
},
// 删除节假日设置
deleteCalHolidayByDay: async (theDay: String) => {
return await request.delete({ url: `/mes/cal-holiday/deleteByDay?theDay=` + theDay })
},
}

@ -3,11 +3,15 @@ import request from '@/config/axios'
export interface CriticalComponentVO {
id: number
code: string
isCode?: boolean
name: string
description?: string
count?: number
remark?: string
qrcodeUrl?: string
templateJson?: string | any
createTime?: string
images?: string
}
export const CriticalComponentApi = {
@ -17,6 +21,9 @@ export const CriticalComponentApi = {
getCriticalComponentList: async () => {
return await request.get({ url: `/mes/critical-component/list`, })
},
getCriticalComponent: async (id: number) => {
return await request.get({ url: `/mes/critical-component/get?id=` + id })
},
createCriticalComponent: async (data: Partial<CriticalComponentVO>) => {
return await request.post({ url: `/mes/critical-component/create`, data })
},
@ -25,6 +32,12 @@ export const CriticalComponentApi = {
return await request.put({ url: `/mes/critical-component/update`, data })
},
regenerateCode: async (id: number, code: string) => {
return await request.post({
url: `/mes/critical-component/regenerate-code?id=${id}&code=${encodeURIComponent(code)}`
})
},
deleteCriticalComponent: async (ids: string) => {
return await request.delete({ url: `/mes/critical-component/delete?ids=` + ids })
},

@ -0,0 +1,47 @@
import request from '@/config/axios'
export interface CapacityReportVO {
id: number
deviceCode: string
deviceName: string
typeName: string
deviceStatus: number
ratedCapacity: number
reportCapacity: number
actualCapacity: number
workshopName: string
}
export interface CapacityReportQuery {
pageNo: number
pageSize: number
deviceCode?: string
deviceName?: string
deviceType?: string
deviceStatus?: string
workshop?: string
ids?: string
}
export const DeviceLedgerApi = {
/**
*
*/
getCapacityReportPage: async (params: CapacityReportQuery) => {
return await request.get({ url: '/mes/device-ledger/capacity-report/page', params })
},
/**
*
*/
exportCapacityReport: async (params: { ids?: string }) => {
return await request.download({ url: '/mes/device-ledger/capacity-report/export-excel', params })
},
/**
*
*/
updateDeviceLedger: async (data: { id: number; deviceStatus: number }) => {
return await request.put({ url: '/mes/device-ledger/update', data })
}
}

@ -6,12 +6,14 @@ import { MoldVO } from '@/api/erp/mold'
export interface DeviceLedgerVO {
id: number // id
deviceCode: string // 设备编号
isCode?: boolean
deviceName: string // 设备名称
deviceStatus: number // 设备状态 (0-正常, 1-停用, 2-维修, 3-报废)
deviceBrand: string // 设备品牌
deviceModel: string // 设备型号
deviceSpec: string // 设备规格
deviceType: string | number // 设备类型
deviceLine?: string | number // 设备产线
deviceTypeName?: string // 设备类型名称
supplier: string // 供应商
workshop: string // 所属车间
@ -24,6 +26,11 @@ export interface DeviceLedgerVO {
deviceRemark: string // 设备备注
remark: string // 备注
fileUrl?: string // 附件下载
qrcodeUrl?: string
templateJson?: string | any
isSchedueld?: number
isScheduled?: number
ratedCapacity?: number
componentId?: string // 关键件ids集合
componentList?: CriticalComponentVO[]
beijianId?: string // 备件ids集合
@ -37,6 +44,7 @@ export interface DeviceLedgerVO {
createTime?: string | number | Date
updateTime?: string | number | Date
sort: number // 排序
images?: string // 图片
}
// 设备类型 API
@ -73,6 +81,10 @@ export const DeviceLedgerApi = {
return await request.put({ url: `/mes/device-ledger/update`, data })
},
regenerateCode: async (id: number, code: string) => {
return await request.post({ url: `/mes/device-ledger/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` })
},
// 删除设备类型
deleteDeviceLedger: async (ids: string) => {
return await request.delete({ url: `/mes/device-ledger/delete?ids=` + ids })

@ -0,0 +1,45 @@
import request from '@/config/axios'
export interface DeviceLineVO {
id: number
code: string
isCode?: boolean
qrcodeUrl?: string
name: string
remark: string
sort: number
parentId: number
parentChain: string
createTime?: string
}
export interface DeviceLineTreeVO extends DeviceLineVO {
children?: DeviceLineTreeVO[]
leaf?: boolean
}
export const DeviceLineApi = {
getDeviceLine: async (id: number) => {
return await request.get({ url: `/mes/device-line/get?id=` + id })
},
getDeviceLineTree: async () => {
return await request.get({ url: `/mes/device-line/tree` })
},
regenerateCode: async (id: number, code: string) => {
return await request.post({ url: `/mes/device-line/regenerate-code?id=${id}&code=${encodeURIComponent(code)}` })
},
createDeviceLine: async (data: DeviceLineVO) => {
return await request.post({ url: `/mes/device-line/create`, data })
},
updateDeviceLine: async (data: DeviceLineVO) => {
return await request.put({ url: `/mes/device-line/update`, data })
},
deleteDeviceLine: async (id: number) => {
return await request.delete({ url: `/mes/device-line/delete?id=` + id })
}
}

@ -11,6 +11,7 @@ export interface DvSubjectVO {
isEnable: string // 是否启用
inspectionMethod: string // 检验方式
valueType: string // 值类型
jobType:string // 作业类型
judgmentCriteria: string // 判定基准
creator?: string // 创建人
createTime?: string | number | Date // 创建时间

@ -42,6 +42,61 @@ export interface EnergyDeviceDataRecordVO {
latestDataTime?: string
}
export interface EnergyOverviewMetricVO {
key: string
label: string
value: string
unit?: string
subLabel?: string
subValue?: string
change?: string
down?: boolean
}
export interface EnergyOverviewTrendVO {
unit?: string
xAxis: string[]
data: string[]
}
export interface EnergyOverviewRegionItemVO {
name: string
value: string
percent: string
}
export interface EnergyOverviewRegionVO {
unit?: string
totalValue: string
items: EnergyOverviewRegionItemVO[]
}
export interface EnergyOverviewRankVO {
id: number
name: string
region: string
value: string
}
export interface EnergyOverviewDetailVO {
id: number
name: string
energyType: string
region: string
value: string
startTime: string
endTime: string
}
export interface EnergyOverviewRespVO {
metrics: EnergyOverviewMetricVO[]
trendChart: EnergyOverviewTrendVO
regionChart: EnergyOverviewRegionVO
rankList: EnergyOverviewRankVO[]
total: number
detailList: EnergyOverviewDetailVO[]
}
// 能源设备 API
export const EnergyDeviceApi = {
// 查询能源设备分页
@ -66,6 +121,10 @@ export const EnergyDeviceApi = {
return await request.get({ url: `/mes/energy-device/queryDataRecords`, params })
},
queryOverviewData: async (params: any) => {
return await request.get({ url: `/mes/energy-device/queryOverviewData`, params })
},
exportQueryDataRecords: async (params: any) => {
return await request.download({ url: `/mes/energy-device/record-export-excel`, params })
},

@ -0,0 +1,85 @@
import request from '@/config/axios'
// esop文件表库 VO
export interface FileVO {
id: number // id
configId: number // 配置编号
code: string // 文件编码
name: string // 文件名
path: string // 文件路径
url: string // 文件 URL
type: string // 文件类型
class: string // 文件分类
status: number // 文件状态
size: number // 文件大小
}
// 文件预签名地址 Response VO
export interface FilePresignedUrlRespVO {
// 文件配置编号
configId: number
// 文件上传 URL
uploadUrl: string
// 文件 URL
url: string
}
export enum ApiUrl{
'/admin-api/mes/esop/file/create'
}
// esop文件表库 API
export const FileApi = {
// 查询esop文件表库分页
getFilePage: async (params: any) => {
return await request.get({ url: `/esop/file/page`, params })
},
// 查询esop文件表库详情
getFile: async (id: number) => {
return await request.get({ url: `/esop/file/get?id=` + id })
},
// 新增esop文件表库
createFile: async (data: FileVO) => {
return await request.post({ url: `/esop/file/create`, data })
},
// 修改esop文件表库
updateFile: async (data: FileVO) => {
return await request.put({ url: `/esop/file/update`, data })
},
// 删除esop文件表库
deleteFile: async (id: number) => {
return await request.delete({ url: `/esop/file/delete?id=` + id })
},
// 导出esop文件表库 Excel
exportFile: async (params) => {
return await request.download({ url: `/esop/file/export-excel`, params })
},
// 获取文件编码
generateCode: async () => {
return await request.get({ url: `/esop/file/generate`})
},
}
// 获取文件预签名地址
export const getFilePresignedUrl = (path: string) => {
return request.get<FilePresignedUrlRespVO>({
url: '/infra/file/presigned-url',
params: { path }
})
}
// 创建文件
export const createFile = (data: any) => {
return request.post({ url: '/esop/file/create', data })
}
// 上传文件
export const updateFile = (data: any) => {
return request.upload({ url: '/esop/file/create', data })
}

@ -1,6 +1,36 @@
import request from '@/config/axios'
import {ItemRequisitionVO} from "@/api/mes/itemrequisition";
// 计划记录状态枚举
export enum OperateStatusEnum {
SCHEDULED = '1', // 已排产
PAUSED = '3', // 暂停
PENDING_WAREHOUSE = '4', // 待入库
WAREHOUSED = '5', // 已入库
STARTED = '8' // 已开工
}
// 计划记录状态映射
export const OPERATE_STATUS_MAP: Record<string, string> = {
'1': '已排产',
'3': '暂停',
'4': '待入库',
'5': '已入库',
'8': '已开工'
}
// 计划记录 VO
export interface PlanRecordVO {
id: number // ID
taskId: number // 任务ID
planId: number // 计划ID
operateStatus: string // 操作状态 ('1' | '3' | '4' | '5' | '8')
operateTime: number // 操作时间戳(毫秒)
remark: string // 备注
isEnable: boolean // 是否启用
createTime: number // 创建时间戳
}
// 生产计划 VO
export interface PlanVO {
id: number // ID
@ -26,6 +56,27 @@ export interface PlanVO {
feedingPipelineName: string
wangongNumber: number
passRate: number
passNumber?: number // 合格数量
noPassNumber?: number // 不合格数量
deviceName?: string // 设备名称
planRecordList?: PlanRecordVO[] // 计划记录列表
}
export interface DevicePlanGanttPlanVO {
planId: number
planStartTime: string
planEndTime: string
latestStartTime: string
planNumber: number
productName: string
deviceName: string
}
export interface DevicePlanGanttRespVO {
deviceId: number
deviceName: string
deviceCode: string
plans: DevicePlanGanttPlanVO[]
}
// 生产计划 API
@ -63,6 +114,9 @@ export const PlanApi = {
saveBatchPlan: async (data: any) => {
return await request.post({ url: `/mes/plan/saveBatchPlan`, data })
},
createBatch: async (data:any) => {
return await request.post({ url: `/mes/plan/create-batch`, data })
},
// 派工生产计划
arrangePlan: async (data: ItemRequisitionVO) => {
return await request.put({ url: `/mes/plan/paigong`, data })
@ -116,5 +170,16 @@ export const PlanApi = {
},
getLastSevenDaysCompletedCount: async (params?: any) => {
return await request.get({ url: `/mes/plan/getLastSevenDaysCompletedCount`, params })
},
getGanttByDevice: async (params: { startTime: string; endTime: string }) => {
return await request.get<DevicePlanGanttRespVO[]>({ url: `/mes/plan/gantt-by-device`, params })
},
getPlanPageByTask: async (params: any) => {
return await request.get({ url: `/mes/plan/page-by-task`, params })
},
getProductCapacityPage: async (params: any) => {
return await request.get({ url: `/mes/plan/product-capacity-page`, params })
}
}

@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface PrintTemplateVO {
id: number
templateCode: string
templateName: string
templateType: number
templateBizType: number
templateJson: string
remark: string
isEnable: boolean
createTime: string
}
export const PrintTemplateApi = {
getPrintTemplatePage: async (params: any) => {
return await request.get({ url: `/mes/print-template/page`, params })
},
getPrintTemplate: async (id: number) => {
return await request.get({ url: `/mes/print-template/get?id=` + id })
},
createPrintTemplate: async (data: PrintTemplateVO) => {
return await request.post({ url: `/mes/print-template/create`, data })
},
updatePrintTemplate: async (data: PrintTemplateVO) => {
return await request.put({ url: `/mes/print-template/update`, data })
},
deletePrintTemplate: async (id: number) => {
return await request.delete({ url: `/mes/print-template/delete?id=` + id })
},
exportPrintTemplate: async (params) => {
return await request.download({ url: `/mes/print-template/export-excel`, params })
},
}

@ -6,6 +6,7 @@ export interface TaskVO {
code: string // 编码
orderDate: Date // 下达日期
deliveryDate: Date // 交货日期
isUrgent: string // 是否急单0-否 1-是
status: number // 状态
processInstanceId: string // 流程实例的编号
remark: string // 备注
@ -155,4 +156,8 @@ export const TaskApi = {
generatePlanByTaskDetail: async (params) => {
return await request.get({ url: `/mes/task/generate-plan/byTaskDetail`, params })
},
// 一键排产
oneClickSchedule: async (data: any) => {
return await request.post({ url: `/mes/task/one-click-schedule`, data })
},
}

@ -5,7 +5,7 @@ export interface WorkTeamVO {
id: number // ID
teamName: string // 班组名称
teamLeaderId: number // 组长ID
teamType: string // 工序类型
teamType?: string // 工序类型
startTime: Date
endTime: Date
remark: string // 备注

@ -44,6 +44,10 @@ export const ZjTaskApi = {
return await request.get({ url: `/mes/zj-task/list`, params })
},
getZjTaskPageByTicket: async (params: any) => {
return await request.get({ url: `/mes/zj-task/page-by-ticket`, params })
},
createZjTask: async (data: ZjTaskVO) => {
return await request.post({ url: `/mes/zj-task/create`, data })
},

@ -4,6 +4,7 @@ export type DictDataVO = {
id: number | undefined
sort: number | undefined
label: string
labelEn?: string
value: string
dictType: string
status: number

@ -16,12 +16,14 @@ export interface MenuVO {
visible: boolean
keepAlive: boolean
alwaysShow?: boolean
clientType?: number
terminalType?: number
createTime: Date
}
// 查询菜单(精简)列表
export const getSimpleMenusList = () => {
return request.get({ url: '/system/menu/simple-list' })
export const getSimpleMenusList = (clientType?: number) => {
return request.get({ url: '/system/menu/simple-list', params: { clientType } })
}
// 查询菜单列表

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -9,13 +9,14 @@ const props = defineProps({
modelValue: propTypes.bool.def(false),
title: propTypes.string.def('Dialog'),
fullscreen: propTypes.bool.def(true),
initialFullscreen: propTypes.bool.def(false),
width: propTypes.oneOfType([String, Number]).def('40%'),
scroll: propTypes.bool.def(false), // maxHeight
scroll: propTypes.bool.def(false),
maxHeight: propTypes.oneOfType([String, Number]).def('400px')
})
const getBindValue = computed(() => {
const delArr: string[] = ['fullscreen', 'title', 'maxHeight', 'appendToBody']
const delArr: string[] = ['fullscreen', 'initialFullscreen', 'title', 'maxHeight', 'appendToBody']
const attrs = useAttrs()
const obj = { ...attrs, ...props }
for (const key in obj) {
@ -26,7 +27,7 @@ const getBindValue = computed(() => {
return obj
})
const isFullscreen = ref(false)
const isFullscreen = ref(props.initialFullscreen)
const toggleFull = () => {
isFullscreen.value = !unref(isFullscreen)

@ -4,7 +4,8 @@ import { isHexColor } from '@/utils/color'
import { ElTag } from 'element-plus'
import { DictDataType, getDictOptions } from '@/utils/dict'
import { isArray, isBoolean, isNumber, isString } from '@/utils/is'
import {useLocaleStoreWithOut} from "@/store/modules/locale";
const localeStore = useLocaleStoreWithOut()
export default defineComponent({
name: 'DictTag',
props: {
@ -68,6 +69,7 @@ export default defineComponent({
if (dict.colorType + '' === 'primary' || dict.colorType + '' === 'default') {
dict.colorType = ''
}
const label = localeStore.getCurrentLocale?.lang === 'en' ? (dict.labelEn || dict.label) : dict.label
return (
//
<ElTag
@ -76,7 +78,7 @@ export default defineComponent({
color={dict?.cssClass && isHexColor(dict?.cssClass) ? dict?.cssClass : ''}
disableTransitions={true}
>
{dict?.label}
{label}
</ElTag>
)
}

@ -0,0 +1,397 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="92%" :fullscreen="false" top="4vh">
<div class="hiprint-preview">
<div class="hiprint-toolbar">
<div class="hiprint-paper">
<el-button
v-for="(value, type) in paperTypes"
:key="type"
size="small"
:type="curPaperType === type ? 'primary' : 'default'"
@click="setPaper(type, value)"
>
{{ type }}
</el-button>
<el-popover placement="bottom-start" :width="260" trigger="click" v-model:visible="paperPopVisible">
<template #reference>
<el-button size="small" :type="curPaperType === 'other' ? 'primary' : 'default'">自定义纸张</el-button>
</template>
<div class="paper-pop">
<div class="paper-pop-title">设置纸张宽高(mm)</div>
<div class="paper-pop-form">
<el-input-number v-model="paperWidth" :precision="1" :min="1" controls-position="right" />
<span>x</span>
<el-input-number v-model="paperHeight" :precision="1" :min="1" controls-position="right" />
</div>
<el-button class="mt-8px" size="small" type="primary" @click="setPaperOther"></el-button>
</div>
</el-popover>
</div>
<div class="hiprint-zoom">
<el-button size="small" @click="changeScale(false)">
<Icon icon="ep:zoom-out" />
</el-button>
<div class="zoom-value">{{ (scaleValue * 100).toFixed(0) }}%</div>
<el-button size="small" @click="changeScale(true)">
<Icon icon="ep:zoom-in" />
</el-button>
</div>
<el-button type="primary" size="small" @click="handlePrint">
<Icon icon="ep:printer" class="mr-4px" />
浏览器打印
</el-button>
</div>
<div class="hiprint-body">
<div class="hiprint-left">
<div class="hiprint-title">基础元素</div>
<div :id="dragContainerId" class="hiprint-drag-wrap">
<div v-for="item in baseElements" :key="item.tid" class="ep-draggable-item hiprint-item" :tid="item.tid">
<span>{{ item.label }}</span>
</div>
</div>
</div>
<div class="hiprint-center">
<div :id="designerContainerId"></div>
</div>
<div class="hiprint-right">
<div :id="settingContainerId"></div>
</div>
</div>
</div>
</Dialog>
</template>
<script setup lang="ts">
import { defaultElementTypeProvider, hiprint } from 'vue-plugin-hiprint'
interface HiprintPreviewOpenOptions {
title?: string
printData?: Record<string, any> | Record<string, any>[]
withDefaultQrcodeLayout?: boolean
templateJson?: Record<string, any>
paperSize?: {
width: number
height: number
}
}
const message = useMessage()
const baseElements = [
{ tid: 'defaultModule.text', label: '文本' },
{ tid: 'defaultModule.image', label: '图片' },
{ tid: 'defaultModule.longText', label: '长文' },
{ tid: 'defaultModule.table', label: '表格' },
{ tid: 'defaultModule.html', label: 'HTML' },
{ tid: 'defaultModule.hline', label: '横线' },
{ tid: 'defaultModule.vline', label: '竖线' },
{ tid: 'defaultModule.rect', label: '矩形' },
{ tid: 'defaultModule.oval', label: '圆形' }
]
const dialogVisible = ref(false)
const dialogTitle = ref('打印预览')
const currentPrintData = ref<Record<string, any> | Record<string, any>[]>({})
const withDefaultQrcodeLayout = ref(false)
const currentTemplateJson = ref<Record<string, any> | undefined>(undefined)
const instanceId = `hiprint-preview-${Math.random().toString(36).slice(2)}`
const dragContainerId = `${instanceId}-drag`
const designerContainerId = `${instanceId}-designer`
const settingContainerId = `${instanceId}-setting`
const paperTypes = {
A3: { width: 420, height: 296.6 },
A4: { width: 210, height: 296.6 },
A5: { width: 210, height: 147.6 },
B3: { width: 500, height: 352.6 },
B4: { width: 250, height: 352.6 },
B5: { width: 250, height: 175.6 }
}
const curPaper = ref({
type: 'A4',
width: 210,
height: 296.6
})
const paperPopVisible = ref(false)
const paperWidth = ref(220)
const paperHeight = ref(80)
const curPaperType = computed(() => {
let type = 'other'
for (const [key, value] of Object.entries(paperTypes)) {
if (value.width === curPaper.value.width && value.height === curPaper.value.height) {
type = key
break
}
}
return type
})
const scaleValue = ref(1)
const scaleMax = 5
const scaleMin = 0.5
let hiprintInited = false
let hiprintTemplate: any
const ensureInit = () => {
if (hiprintInited) {
return
}
hiprint.init({
providers: [defaultElementTypeProvider()]
})
hiprintInited = true
}
const buildLeftElement = () => {
const jquery = (window as any).$
if (!jquery) {
message.warning('未检测到 jQuery无法加载拖拽元素')
return
}
hiprint.PrintElementTypeManager.buildByHtml(jquery(`#${dragContainerId} .ep-draggable-item`))
}
const buildDesigner = () => {
const jquery = (window as any).$
if (!jquery) {
message.warning('未检测到 jQuery无法初始化打印设计器')
return
}
jquery(`#${designerContainerId}`).empty()
const template =
currentTemplateJson.value || (withDefaultQrcodeLayout.value ? buildDefaultQrcodeTemplateJson() : undefined)
hiprintTemplate = new hiprint.PrintTemplate({
template,
settingContainer: `#${settingContainerId}`
})
hiprintTemplate.design(`#${designerContainerId}`)
setPaper(curPaperType.value, { width: curPaper.value.width, height: curPaper.value.height })
hiprintTemplate.zoom(scaleValue.value)
}
const buildDefaultQrcodeTemplateJson = () => ({
panels: [
{
index: 0,
name: 1,
width: 80,
height: 60,
paperHeader: 0,
paperFooter: 170.07874015748033,
printElements: [
{
options: {
left: 20,
top: 6,
height: 36,
width: 36,
textType: 'qrcode',
title: '二维码',
field: 'qrcodeContent',
testData: 'XS888888888'
},
printElementType: {
title: '二维码',
type: 'text'
}
},
{
options: {
left: 8,
top: 46,
height: 8,
width: 60,
title: 'ID',
field: 'printId',
testData: 'ID: 1001',
textAlign: 'center',
fontSize: 10
},
printElementType: {
title: '文本',
type: 'text'
}
}
],
paperNumberLeft: 196,
paperNumberTop: 148,
paperNumberDisabled: true,
paperNumberContinue: true,
watermarkOptions: {},
panelLayoutOptions: {}
}
]
})
const setPaper = (type: string, value: { width: number; height: number }) => {
if (!hiprintTemplate) {
return
}
const width = Number(value.width)
const height = Number(value.height)
curPaper.value = { type, width, height }
hiprintTemplate.setPaper(width, height)
}
const setPaperOther = () => {
paperPopVisible.value = false
setPaper('other', { width: Number(paperWidth.value), height: Number(paperHeight.value) })
}
const changeScale = (isZoomIn: boolean) => {
if (!hiprintTemplate) {
return
}
let nextScale = scaleValue.value
if (isZoomIn) {
nextScale += 0.1
if (nextScale > scaleMax) nextScale = scaleMax
} else {
nextScale -= 0.1
if (nextScale < scaleMin) nextScale = scaleMin
}
scaleValue.value = nextScale
hiprintTemplate.zoom(nextScale)
}
const handlePrint = () => {
if (!hiprintTemplate) {
return
}
hiprintTemplate.print(currentPrintData.value, { leftOffset: -1, topOffset: -1 })
}
const resetState = () => {
scaleValue.value = 1
curPaper.value = {
type: 'A4',
width: 210,
height: 296.6
}
paperWidth.value = 220
paperHeight.value = 80
paperPopVisible.value = false
}
const open = async (options: HiprintPreviewOpenOptions = {}) => {
dialogTitle.value = options.title || '打印预览'
currentPrintData.value = options.printData || {}
withDefaultQrcodeLayout.value = !!options.withDefaultQrcodeLayout
currentTemplateJson.value = options.templateJson
resetState()
if (options.paperSize?.width && options.paperSize?.height) {
const width = Number(options.paperSize.width)
const height = Number(options.paperSize.height)
curPaper.value = {
type: 'other',
width,
height
}
paperWidth.value = width
paperHeight.value = height
}
dialogVisible.value = true
await nextTick()
ensureInit()
buildLeftElement()
buildDesigner()
}
defineExpose({ open })
</script>
<style scoped lang="scss">
.hiprint-preview {
width: 100%;
}
.hiprint-toolbar {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.hiprint-paper {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.hiprint-zoom {
display: flex;
align-items: center;
gap: 4px;
}
.zoom-value {
width: 56px;
text-align: center;
font-size: 13px;
color: var(--el-text-color-regular);
}
.paper-pop-title {
font-size: 14px;
font-weight: 600;
}
.paper-pop-form {
margin-top: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.hiprint-body {
height: 75vh;
display: grid;
grid-template-columns: 220px 1fr 300px;
gap: 12px;
}
.hiprint-left,
.hiprint-center,
.hiprint-right {
background: var(--el-bg-color);
border: 1px solid var(--el-border-color-light);
border-radius: 8px;
overflow: auto;
}
.hiprint-center {
padding: 16px;
}
.hiprint-right {
padding: 12px;
}
.hiprint-title {
padding: 10px 10px 0;
font-weight: 600;
}
.hiprint-drag-wrap {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
padding: 10px;
}
.hiprint-item {
min-height: 56px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
border: 1px solid var(--el-border-color);
background: var(--el-fill-color-light);
color: var(--el-text-color-primary);
cursor: grab;
}
</style>

@ -1,4 +1,5 @@
import Icon from './src/Icon.vue'
import IconSelect from './src/IconSelect.vue'
import AppIconSelect from './src/AppIconSelect.vue'
export { Icon, IconSelect }
export { Icon, IconSelect, AppIconSelect }

@ -0,0 +1,280 @@
<script lang="ts" setup>
import { uniIconsList, uviewIconsList, uniIconsUnicodeMap, uviewIconsUnicodeMap } from './appIconData'
defineOptions({ name: 'AppIconSelect' })
const props = defineProps({
modelValue: {
require: false,
type: String
},
clearable: {
require: false,
type: Boolean
}
})
const emit = defineEmits<{ (e: 'update:modelValue', v: string) }>()
const visible = ref(false)
const inputValue = toRef(props, 'modelValue')
const currentActiveType = ref('uni-icons')
const filterValue = ref('')
const iconDataMap: Record<string, string[]> = {
'uni-icons': uniIconsList,
'uview-plus': uviewIconsList
}
const unicodeMapMap: Record<string, Record<string, string>> = {
'uni-icons': uniIconsUnicodeMap,
'uview-plus': uviewIconsUnicodeMap
}
const fontFamilyMap: Record<string, string> = {
'uni-icons': 'UniIconsFontFamily',
'uview-plus': 'uview-iconfont'
}
const tabsList = [
{ label: 'uni-icons', name: 'uni-icons' },
{ label: 'uview-plus', name: 'uview-plus' }
]
const pageSize = ref(96)
const currentPage = ref(1)
const currentIconList = computed(() => {
return iconDataMap[currentActiveType.value] || []
})
const currentUnicodeMap = computed(() => {
return unicodeMapMap[currentActiveType.value] || {}
})
const currentFontFamily = computed(() => {
return fontFamilyMap[currentActiveType.value] || 'UniIconsFontFamily'
})
const filteredList = computed(() => {
return currentIconList.value.filter((v) =>
v.toLowerCase().includes(filterValue.value.toLowerCase())
)
})
const pageList = computed(() => {
if (currentPage.value === 1) {
return filteredList.value.slice(0, pageSize.value)
}
return filteredList.value.slice(
pageSize.value * (currentPage.value - 1),
pageSize.value * (currentPage.value - 1) + pageSize.value
)
})
const iconCount = computed(() => filteredList.value.length)
function parseIconValue(value: string): { prefix: string; name: string } | null {
if (!value || value.indexOf(':') < 0) return null
const idx = value.indexOf(':')
return {
prefix: value.substring(0, idx),
name: value.substring(idx + 1)
}
}
function getUnicode(name: string): string {
return currentUnicodeMap.value[name] || ''
}
function getSelectedFontFamily(fullValue: string): string {
const parsed = parseIconValue(fullValue)
if (!parsed) return 'UniIconsFontFamily'
return fontFamilyMap[parsed.prefix] || 'UniIconsFontFamily'
}
function getSelectedUnicode(fullValue: string): string {
const parsed = parseIconValue(fullValue)
if (!parsed) return ''
const map = unicodeMapMap[parsed.prefix]
return map ? map[parsed.name] || '' : ''
}
function handleClick({ props }: any) {
currentPage.value = 1
currentActiveType.value = props.name
}
function onChangeIcon(item: string) {
emit('update:modelValue', currentActiveType.value + ':' + item)
visible.value = false
}
function onCurrentChange(page: number) {
currentPage.value = page
}
function clearIcon() {
emit('update:modelValue', '')
visible.value = false
}
watch(
() => props.modelValue,
(val) => {
if (val) {
const parsed = parseIconValue(val)
if (parsed && fontFamilyMap[parsed.prefix]) {
currentActiveType.value = parsed.prefix
}
}
}
)
watch(
() => filterValue.value,
() => {
currentPage.value = 1
}
)
</script>
<template>
<div class="selector">
<ElInput v-model="inputValue" @click="visible = !visible" :clearable="props.clearable" @clear="clearIcon">
<template #append>
<ElPopover
:visible="visible"
:width="355"
popper-class="pure-popper"
trigger="click"
>
<template #reference>
<div
class="h-32px w-40px flex cursor-pointer items-center justify-center"
@click="visible = !visible"
>
<span
v-if="inputValue && getSelectedUnicode(inputValue)"
class="app-icon-font"
:style="{ fontFamily: getSelectedFontFamily(inputValue), fontSize: '18px' }"
>{{ getSelectedUnicode(inputValue) }}</span>
<span v-else class="text-12px color-gray-500">选择</span>
</div>
</template>
<ElInput v-model="filterValue" class="p-2" clearable placeholder="搜索图标" />
<ElDivider border-style="dashed" />
<ElTabs v-model="currentActiveType" @tab-click="handleClick">
<ElTabPane
v-for="(pane, index) in tabsList"
:key="index"
:label="pane.label"
:name="pane.name"
>
<ElDivider border-style="dashed" class="tab-divider" />
<ElScrollbar height="220px">
<ul class="ml-2 flex flex-wrap">
<li
v-for="(item, key) in pageList"
:key="key"
:style="inputValue === currentActiveType + ':' + item ? { borderColor: 'var(--el-color-primary)', color: 'var(--el-color-primary)' } : {}"
:title="item"
class="icon-item mr-2 mt-1 w-1/10 flex cursor-pointer items-center justify-center border border-solid p-2"
@click="onChangeIcon(item)"
>
<span
class="app-icon-font"
:style="{ fontFamily: currentFontFamily }"
>{{ getUnicode(item) }}</span>
</li>
</ul>
</ElScrollbar>
</ElTabPane>
</ElTabs>
<ElDivider border-style="dashed" />
<ElPagination
:current-page="currentPage"
:page-size="pageSize"
:total="iconCount"
background
class="h-10 flex items-center justify-center"
layout="prev, pager, next"
size="small"
@current-change="onCurrentChange"
/>
</ElPopover>
</template>
</ElInput>
</div>
</template>
<style lang="scss">
@font-face {
font-family: 'UniIconsFontFamily';
src: url('@/assets/fonts/uniicons.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'uview-iconfont';
src: url('@/assets/fonts/uview-icons.ttf') format('truetype');
font-display: swap;
}
</style>
<style lang="scss" scoped>
.app-icon-font {
font-style: normal;
font-size: 20px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-divider--horizontal {
margin: 1px auto !important;
}
.tab-divider.el-divider--horizontal {
margin: 0 !important;
}
.icon-item {
&:hover {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
transform: scaleX(1.05);
transition: all 0.4s;
}
}
:deep(.el-tabs__nav-next) {
font-size: 15px;
line-height: 32px;
box-shadow: -5px 0 5px -6px #ccc;
}
:deep(.el-tabs__nav-prev) {
font-size: 15px;
line-height: 32px;
box-shadow: 5px 0 5px -6px #ccc;
}
:deep(.el-input-group__append) {
padding: 0;
}
:deep(.el-tabs__item) {
height: 30px;
font-size: 12px;
font-weight: normal;
line-height: 30px;
}
:deep(.el-tabs__header),
:deep(.el-tabs__nav-wrap) {
position: static;
margin: 0;
}
</style>

@ -0,0 +1,382 @@
const uniIconsUnicodeMap: Record<string, string> = {
'arrow-down': '\ue6be',
'arrow-left': '\ue6bc',
'arrow-right': '\ue6bb',
'arrow-up': '\ue6bd',
'auth': '\ue6ab',
'auth-filled': '\ue6cc',
'back': '\ue6b9',
'bars': '\ue627',
'calendar': '\ue6a0',
'calendar-filled': '\ue6c0',
'camera': '\ue65a',
'camera-filled': '\ue658',
'cart': '\ue631',
'cart-filled': '\ue6d0',
'chat': '\ue65d',
'chat-filled': '\ue659',
'chatboxes': '\ue696',
'chatboxes-filled': '\ue692',
'chatbubble': '\ue697',
'chatbubble-filled': '\ue694',
'checkbox': '\ue62b',
'checkbox-filled': '\ue62c',
'checkmarkempty': '\ue65c',
'circle': '\ue65b',
'circle-filled': '\ue65e',
'clear': '\ue66d',
'close': '\ue673',
'closeempty': '\ue66c',
'cloud-download': '\ue647',
'cloud-download-filled': '\ue646',
'cloud-upload': '\ue645',
'cloud-upload-filled': '\ue648',
'color': '\ue6cf',
'color-filled': '\ue6c9',
'compose': '\ue67f',
'contact': '\ue693',
'contact-filled': '\ue695',
'down': '\ue6b8',
'bottom': '\ue6b8',
'download': '\ue68d',
'download-filled': '\ue681',
'email': '\ue69e',
'email-filled': '\ue69a',
'eye': '\ue651',
'eye-filled': '\ue66a',
'eye-slash': '\ue6b3',
'eye-slash-filled': '\ue6b4',
'fire': '\ue6a1',
'fire-filled': '\ue6c5',
'flag': '\ue65f',
'flag-filled': '\ue660',
'folder-add': '\ue6a9',
'folder-add-filled': '\ue6c8',
'font': '\ue6a3',
'forward': '\ue6ba',
'gear': '\ue664',
'gear-filled': '\ue661',
'gift': '\ue6a4',
'gift-filled': '\ue6c4',
'hand-down': '\ue63d',
'hand-down-filled': '\ue63c',
'hand-up': '\ue63f',
'hand-up-filled': '\ue63e',
'headphones': '\ue630',
'heart': '\ue639',
'heart-filled': '\ue641',
'help': '\ue679',
'help-filled': '\ue674',
'home': '\ue662',
'home-filled': '\ue663',
'image': '\ue670',
'image-filled': '\ue678',
'images': '\ue650',
'images-filled': '\ue64b',
'info': '\ue669',
'info-filled': '\ue649',
'left': '\ue6b7',
'link': '\ue6a5',
'list': '\ue644',
'location': '\ue6ae',
'location-filled': '\ue6af',
'locked': '\ue66b',
'locked-filled': '\ue668',
'loop': '\ue633',
'mail-open': '\ue643',
'mail-open-filled': '\ue63a',
'map': '\ue667',
'map-filled': '\ue666',
'map-pin': '\ue6ad',
'map-pin-ellipse': '\ue6ac',
'medal': '\ue6a2',
'medal-filled': '\ue6c3',
'mic': '\ue671',
'mic-filled': '\ue677',
'micoff': '\ue67e',
'micoff-filled': '\ue6b0',
'minus': '\ue66f',
'minus-filled': '\ue67d',
'more': '\ue64d',
'more-filled': '\ue64e',
'navigate': '\ue66e',
'navigate-filled': '\ue67a',
'notification': '\ue6a6',
'notification-filled': '\ue6c1',
'paperclip': '\ue652',
'paperplane': '\ue672',
'paperplane-filled': '\ue675',
'person': '\ue699',
'person-filled': '\ue69d',
'personadd': '\ue69f',
'personadd-filled': '\ue698',
'phone': '\ue69c',
'phone-filled': '\ue69b',
'plus': '\ue676',
'plus-filled': '\ue6c7',
'plusempty': '\ue67b',
'pulldown': '\ue632',
'pyq': '\ue682',
'qq': '\ue680',
'redo': '\ue64a',
'redo-filled': '\ue655',
'refresh': '\ue657',
'refresh-filled': '\ue656',
'refreshempty': '\ue6bf',
'reload': '\ue6b2',
'right': '\ue6b5',
'scan': '\ue62a',
'search': '\ue654',
'settings': '\ue653',
'settings-filled': '\ue6ce',
'shop': '\ue62f',
'shop-filled': '\ue6cd',
'smallcircle': '\ue67c',
'smallcircle-filled': '\ue665',
'sound': '\ue684',
'sound-filled': '\ue686',
'spinner-cycle': '\ue68a',
'staff': '\ue6a7',
'staff-filled': '\ue6cb',
'star': '\ue688',
'star-filled': '\ue68f',
'starhalf': '\ue683',
'trash': '\ue687',
'trash-filled': '\ue685',
'tune': '\ue6aa',
'tune-filled': '\ue6ca',
'undo': '\ue64f',
'undo-filled': '\ue64c',
'up': '\ue6b6',
'top': '\ue6b6',
'upload': '\ue690',
'upload-filled': '\ue68e',
'videocam': '\ue68c',
'videocam-filled': '\ue689',
'vip': '\ue6a8',
'vip-filled': '\ue6c6',
'wallet': '\ue6b1',
'wallet-filled': '\ue6c2',
'weibo': '\ue68b',
'weixin': '\ue691'
}
const uviewIconsUnicodeMap: Record<string, string> = {
'level': '\ue693',
'column-line': '\ue68e',
'checkbox-mark': '\ue807',
'folder': '\ue7f5',
'movie': '\ue7f6',
'star-fill': '\ue669',
'star': '\ue65f',
'phone-fill': '\ue64f',
'phone': '\ue622',
'apple-fill': '\ue881',
'chrome-circle-fill': '\ue885',
'backspace': '\ue67b',
'attach': '\ue632',
'cut': '\ue948',
'empty-car': '\ue602',
'empty-coupon': '\ue682',
'empty-address': '\ue646',
'empty-favor': '\ue67c',
'empty-permission': '\ue686',
'empty-news': '\ue687',
'empty-search': '\ue664',
'github-circle-fill': '\ue887',
'rmb': '\ue608',
'person-delete-fill': '\ue66a',
'reload': '\ue788',
'order': '\ue68f',
'server-man': '\ue6bc',
'search': '\ue62a',
'fingerprint': '\ue955',
'more-dot-fill': '\ue630',
'scan': '\ue662',
'share-square': '\ue60b',
'map': '\ue61d',
'map-fill': '\ue64e',
'tags': '\ue629',
'tags-fill': '\ue651',
'bookmark-fill': '\ue63b',
'bookmark': '\ue60a',
'eye': '\ue613',
'eye-fill': '\ue641',
'mic': '\ue64a',
'mic-off': '\ue649',
'calendar': '\ue66e',
'calendar-fill': '\ue634',
'trash': '\ue623',
'trash-fill': '\ue658',
'play-left': '\ue66d',
'play-right': '\ue610',
'minus': '\ue618',
'plus': '\ue62d',
'info': '\ue653',
'info-circle': '\ue7d2',
'info-circle-fill': '\ue64b',
'question': '\ue715',
'error': '\ue6d3',
'close': '\ue685',
'checkmark': '\ue6a8',
'android-circle-fill': '\ue67e',
'android-fill': '\ue67d',
'ie': '\ue87b',
'IE-circle-fill': '\ue889',
'google': '\ue87a',
'google-circle-fill': '\ue88a',
'setting-fill': '\ue872',
'setting': '\ue61f',
'minus-square-fill': '\ue855',
'plus-square-fill': '\ue856',
'heart': '\ue7df',
'heart-fill': '\ue851',
'camera': '\ue7d7',
'camera-fill': '\ue870',
'more-circle': '\ue63e',
'more-circle-fill': '\ue645',
'chat': '\ue620',
'chat-fill': '\ue61e',
'bag-fill': '\ue617',
'bag': '\ue619',
'error-circle-fill': '\ue62c',
'error-circle': '\ue624',
'close-circle': '\ue63f',
'close-circle-fill': '\ue637',
'checkmark-circle': '\ue63d',
'checkmark-circle-fill': '\ue635',
'question-circle-fill': '\ue666',
'question-circle': '\ue625',
'share': '\ue631',
'share-fill': '\ue65e',
'shopping-cart': '\ue621',
'shopping-cart-fill': '\ue65d',
'bell': '\ue609',
'bell-fill': '\ue640',
'list': '\ue650',
'list-dot': '\ue616',
'zhihu': '\ue6ba',
'zhihu-circle-fill': '\ue709',
'zhifubao': '\ue6b9',
'zhifubao-circle-fill': '\ue6b8',
'weixin-circle-fill': '\ue6b1',
'weixin-fill': '\ue6b2',
'twitter-circle-fill': '\ue6ab',
'twitter': '\ue6aa',
'taobao-circle-fill': '\ue6a7',
'taobao': '\ue6a6',
'weibo-circle-fill': '\ue6a5',
'weibo': '\ue6a4',
'qq-fill': '\ue6a1',
'qq-circle-fill': '\ue6a0',
'moments-circel-fill': '\ue69a',
'moments': '\ue69b',
'qzone': '\ue695',
'qzone-circle-fill': '\ue696',
'baidu-circle-fill': '\ue680',
'baidu': '\ue681',
'facebook-circle-fill': '\ue68a',
'facebook': '\ue689',
'car': '\ue60c',
'car-fill': '\ue636',
'warning-fill': '\ue64d',
'warning': '\ue694',
'clock-fill': '\ue638',
'clock': '\ue60f',
'edit-pen': '\ue612',
'edit-pen-fill': '\ue66b',
'email': '\ue611',
'email-fill': '\ue642',
'minus-circle': '\ue61b',
'minus-circle-fill': '\ue652',
'plus-circle': '\ue62e',
'plus-circle-fill': '\ue661',
'file-text': '\ue663',
'file-text-fill': '\ue665',
'pushpin': '\ue7e3',
'pushpin-fill': '\ue86e',
'grid': '\ue673',
'grid-fill': '\ue678',
'play-circle': '\ue647',
'play-circle-fill': '\ue655',
'pause-circle-fill': '\ue654',
'pause': '\ue8fa',
'pause-circle': '\ue643',
'eye-off': '\ue648',
'eye-off-outline': '\ue62b',
'gift-fill': '\ue65c',
'gift': '\ue65b',
'rmb-circle-fill': '\ue657',
'rmb-circle': '\ue677',
'kefu-ermai': '\ue656',
'server-fill': '\ue751',
'coupon-fill': '\ue8c4',
'coupon': '\ue8ae',
'integral': '\ue704',
'integral-fill': '\ue703',
'home-fill': '\ue964',
'home': '\ue965',
'hourglass-half-fill': '\ue966',
'hourglass': '\ue967',
'account': '\ue628',
'plus-people-fill': '\ue626',
'minus-people-fill': '\ue615',
'account-fill': '\ue614',
'thumb-down-fill': '\ue726',
'thumb-down': '\ue727',
'thumb-up': '\ue733',
'thumb-up-fill': '\ue72f',
'lock-fill': '\ue979',
'lock-open': '\ue973',
'lock-opened-fill': '\ue974',
'lock': '\ue97a',
'red-packet-fill': '\ue690',
'photo-fill': '\ue98b',
'photo': '\ue98d',
'volume-off-fill': '\ue659',
'volume-off': '\ue644',
'volume-fill': '\ue670',
'volume': '\ue633',
'red-packet': '\ue691',
'download': '\ue63c',
'arrow-up-fill': '\ue6b0',
'arrow-down-fill': '\ue600',
'play-left-fill': '\ue675',
'play-right-fill': '\ue676',
'rewind-left-fill': '\ue679',
'rewind-right-fill': '\ue67a',
'arrow-downward': '\ue604',
'arrow-leftward': '\ue601',
'arrow-rightward': '\ue603',
'arrow-upward': '\ue607',
'arrow-down': '\ue60d',
'arrow-right': '\ue605',
'arrow-left': '\ue60e',
'arrow-up': '\ue606',
'skip-back-left': '\ue674',
'skip-forward-right': '\ue672',
'rewind-right': '\ue66f',
'rewind-left': '\ue671',
'arrow-right-double': '\ue68d',
'arrow-left-double': '\ue68c',
'wifi-off': '\ue668',
'wifi': '\ue667',
'empty-data': '\ue62f',
'empty-history': '\ue684',
'empty-list': '\ue68b',
'empty-page': '\ue627',
'empty-order': '\ue639',
'man': '\ue697',
'woman': '\ue69c',
'man-add': '\ue61c',
'man-add-fill': '\ue64c',
'man-delete': '\ue61a',
'man-delete-fill': '\ue66a',
'zh': '\ue70a',
'en': '\ue692'
}
const uniIconsList = Object.keys(uniIconsUnicodeMap)
const uviewIconsList = Object.keys(uviewIconsUnicodeMap)
export { uniIconsList, uviewIconsList, uniIconsUnicodeMap, uviewIconsUnicodeMap }

@ -0,0 +1,371 @@
<template>
<div class="qrcode-action-card">
<el-image
v-if="imageUrl"
:src="imageUrl"
:preview-src-list="[imageUrl]"
preview-teleported
fit="cover"
class="qrcode-action-card__img"
>
<template #error>
<div class="qrcode-action-card__error">{{ errorText || emptyText }}</div>
</template>
</el-image>
<div v-else class="qrcode-action-card__error">{{ emptyText }}</div>
<div v-if="showActionMask" class="qrcode-action-card__mask">
<el-button v-if="showPreview" circle :disabled="!imageUrl" @click="handlePreview">
<Icon icon="ep:zoom-in" />
</el-button>
<el-button v-if="showPrint" circle :disabled="!imageUrl || printDisabled" @click="handlePrint">
<Icon icon="ep:printer" />
</el-button>
<el-button
v-if="showRefresh"
circle
:loading="refreshLoading"
:disabled="refreshDisabled || refreshLoading"
@click="handleRefresh"
>
<Icon icon="ep:refresh" />
</el-button>
</div>
</div>
<HiprintPreviewDialog ref="hiprintPreviewDialogRef" />
</template>
<script setup lang="ts">
import request from '@/config/axios'
import HiprintPreviewDialog from '@/components/HiprintPreviewDialog/index.vue'
import { createImageViewer } from '@/components/ImageViewer'
import { ElLoading } from 'element-plus'
const { t } = useI18n()
const message = useMessage()
const props = withDefaults(
defineProps<{
imageUrl?: string
printId?: string | number
printTitle?: string
emptyText?: string
refreshUrl?: string
refreshMethod?: 'post' | 'put' | 'get'
refreshDisabled?: boolean
printDisabled?: boolean
refreshConfirmText?: string
errorText?: string
showPreview?: boolean
showPrint?: boolean
showRefresh?: boolean
printAdaptive?: boolean
printPaperWidth?: number
printPaperHeight?: number
printMaxWidth?: number
printMaxHeight?: number
templateJsonUrl?: string
templateJson?: any
printData?: Record<string, any>
}>(),
{
imageUrl: '',
printId: '',
printTitle: '二维码打印预览',
emptyText: '',
refreshUrl: '',
refreshMethod: 'post',
refreshDisabled: false,
printDisabled: false,
refreshConfirmText: '',
errorText: '',
showPreview: true,
showPrint: true,
showRefresh: true,
printAdaptive: true,
printPaperWidth: 80,
printPaperHeight: 80,
printMaxWidth: 180,
printMaxHeight: 120,
templateJsonUrl: '',
templateJson: undefined,
printData: () => ({})
}
)
const emit = defineEmits<{
(e: 'refresh-success', data: any): void
}>()
const hiprintPreviewDialogRef = ref()
const refreshLoading = ref(false)
const showActionMask = computed(() => props.showPreview || props.showPrint || props.showRefresh)
const buildQrcodeTemplateJson = (
qrcodeUrl: string,
printId: string,
imageWidth: number,
imageHeight: number,
paperHeight: number
) => ({
panels: [
{
index: 0,
name: 1,
width: imageWidth,
height: paperHeight,
paperHeader: 0,
paperFooter: 0,
printElements: [
{
options: {
left: 0,
top: 0,
width: imageWidth,
height: imageHeight,
src: qrcodeUrl,
field: 'qrcodeUrl',
title: '二维码图片',
testData: qrcodeUrl
},
printElementType: {
title: '图片',
type: 'image'
}
},
{
options: {
left: 0,
top: imageHeight + 2,
height: 10,
width: imageWidth,
testData: printId,
title: 'ID',
field: 'printId',
textAlign: 'center',
fontSize: 10
},
printElementType: {
title: '文本',
type: 'text'
}
}
],
paperNumberDisabled: true,
paperNumberContinue: true,
watermarkOptions: {},
panelLayoutOptions: {}
}
]
})
const getImageSize = (src: string) =>
new Promise<{ width: number; height: number }>((resolve, reject) => {
const img = new Image()
img.onload = () => {
const width = img.naturalWidth || img.width
const height = img.naturalHeight || img.height
if (!width || !height) {
reject(new Error('invalid image size'))
return
}
resolve({ width, height })
}
img.onerror = () => reject(new Error('image load failed'))
img.src = src
})
const resolvePrintSize = async (src: string) => {
const fallbackWidth = Math.max(20, Number(props.printPaperWidth) || 80)
const fallbackHeight = Math.max(20, Number(props.printPaperHeight) || 80)
if (!props.printAdaptive) {
return { width: fallbackWidth, height: fallbackHeight }
}
try {
const size = await getImageSize(src)
const ratio = size.width / size.height
if (!Number.isFinite(ratio) || ratio <= 0) {
return { width: fallbackWidth, height: fallbackHeight }
}
if (ratio >= 1) {
const height = fallbackHeight
const width = Math.min(Math.max(fallbackWidth, Math.round(height * ratio)), Number(props.printMaxWidth) || 180)
return { width, height }
}
const width = fallbackWidth
const height = Math.min(Math.max(fallbackHeight, Math.round(width / ratio)), Number(props.printMaxHeight) || 120)
return { width, height }
} catch {
return { width: fallbackWidth, height: fallbackHeight }
}
}
const handlePreview = () => {
if (!props.imageUrl) return
createImageViewer({
zIndex: 9999999,
urlList: [props.imageUrl]
})
}
const replaceTemplateValues = (templateJson: any, printData: Record<string, any>) => {
if (!templateJson?.panels) return templateJson
return {
...templateJson,
panels: templateJson.panels.map((panel: any) => ({
...panel,
printElements: panel.printElements?.map((element: any) => {
if (!element?.options?.qid) return element
const qid = element.options.qid
const value = printData[qid]
if (value === undefined || value === null) return element
const newOptions = { ...element.options }
if (qid === 'qrcodeUrl') {
newOptions.src = value
newOptions.testData = value
} else {
newOptions.field = qid
if (newOptions.testData === undefined || newOptions.testData === '') {
newOptions.testData = String(value)
}
}
return {
...element,
options: newOptions
}
}) || []
}))
}
}
const handlePrint = async () => {
if (!props.imageUrl || !props.showPrint) return
let templateJson: any
let printData: Record<string, any>
printData = {
qrcodeUrl: props.imageUrl,
printId: props.printId === undefined || props.printId === null ? '' : String(props.printId),
...props.printData
}
if (props.templateJson) {
templateJson = replaceTemplateValues(props.templateJson, printData)
} else if (props.templateJsonUrl) {
try {
const response = await request.get({ url: props.templateJsonUrl })
templateJson = typeof response.data === 'string' ? JSON.parse(response.data) : response.data
templateJson = replaceTemplateValues(templateJson, printData)
} catch (error) {
console.error('获取打印模板失败', error)
message.error('获取打印模板失败')
return
}
} else {
const printSize = await resolvePrintSize(props.imageUrl)
const imageWidth = printSize.width
const imageHeight = printSize.height
const printId = props.printId === undefined || props.printId === null ? '' : String(props.printId)
const idAreaHeight = printId ? 14 : 0
const paperHeight = imageHeight + idAreaHeight
templateJson = buildQrcodeTemplateJson(props.imageUrl, printId, imageWidth, imageHeight, paperHeight)
}
const paperSize = templateJson?.panels?.[0] ? {
width: templateJson.panels[0].width,
height: templateJson.panels[0].height
} : { width: 80, height: 80 }
hiprintPreviewDialogRef.value?.open({
title: props.printTitle,
printData,
templateJson,
withDefaultQrcodeLayout: false,
paperSize
})
}
const handleRefresh = async () => {
if (!props.refreshUrl || props.refreshDisabled || !props.showRefresh) return
try {
await message.confirm(props.refreshConfirmText || '确认刷新二维码吗?')
} catch {
return
}
refreshLoading.value = true
const loading = ElLoading.service({
lock: true,
text: t('common.loading'),
background: 'rgba(0, 0, 0, 0.3)'
})
try {
let data
if (props.refreshMethod === 'get') {
data = await request.get({ url: props.refreshUrl })
} else if (props.refreshMethod === 'put') {
data = await request.put({ url: props.refreshUrl })
} else {
data = await request.post({ url: props.refreshUrl })
}
emit('refresh-success', data)
message.success(t('common.updateSuccess'))
} finally {
loading.close()
refreshLoading.value = false
}
}
</script>
<style scoped lang="scss">
.qrcode-action-card {
position: relative;
height: 150px;
width: fit-content;
min-width: 150px;
border-radius: 10px;
overflow: hidden;
border: 1px solid var(--el-border-color-lighter);
background: var(--el-fill-color-blank);
}
.qrcode-action-card__img {
height: 150px;
width: auto;
display: block;
}
.qrcode-action-card__error {
height: 150px;
min-width: 150px;
display: flex;
align-items: center;
justify-content: center;
color: var(--el-text-color-secondary);
font-size: 12px;
padding: 0 12px;
}
.qrcode-action-card__mask {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
background: rgba(0, 0, 0, 0.35);
opacity: 0;
transition: opacity 0.2s ease;
}
.qrcode-action-card:hover .qrcode-action-card__mask {
opacity: 1;
}
</style>

@ -17,9 +17,10 @@
/>
</el-select>
</ElDialog>
<div v-else class="custom-hover" @click.stop="showTopSearch = !showTopSearch">
<div v-else class="custom-hover" @click.stop="toggleTopSearch">
<Icon icon="ep:search" />
<el-select
ref="topSelectRef"
@click.stop
filterable
:reserve-keyword="false"
@ -51,7 +52,8 @@ defineProps({
const router = useRouter() //
const showSearch = ref(false) //
const showTopSearch = ref(false) //
const value: Ref = ref('') //
const value: Ref = ref('')
const topSelectRef = ref<InstanceType<typeof ElSelect>>()
const routers = router.getRoutes() //
const options = computed(() => {
@ -86,6 +88,15 @@ function hiddenTopSearch() {
showTopSearch.value = false
}
function toggleTopSearch() {
showTopSearch.value = !showTopSearch.value
if (showTopSearch.value) {
setTimeout(() => {
topSelectRef.value?.focus()
}, 600)
}
}
onMounted(() => {
window.addEventListener('keydown', listenKey)
window.addEventListener('click', hiddenTopSearch)

@ -0,0 +1,241 @@
<template>
<Dialog :title="title" v-model="dialogVisible" :appendToBody="true" width="1080">
<ContentWrap>
<!-- 新增查询表单区域 -->
<div v-if="$slots.header" class="search-container">
<slot name="header"></slot>
</div>
<el-table
ref="tableRef"
v-loading="loading"
:data="list"
:row-key="resolveRowKey"
:show-overflow-tooltip="true"
:stripe="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column
v-for="column in columns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:width="column.width"
:min-width="column.minWidth"
:align="column.align || 'center'"
/>
</el-table>
<Pagination
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
</ContentWrap>
<template #footer>
<el-button type="primary" @click="submitSelection"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import type { ElTable } from 'element-plus'
defineOptions({ name: 'TableSelectDialog' })
type TableColumn = {
label: string
prop: string
width?: string | number
minWidth?: string | number
align?: 'left' | 'center' | 'right'
}
const props = withDefaults(
defineProps<{
title: string
columns: TableColumn[]
fetchApi: (params: Record<string, any>) => Promise<{ list: any[]; total: number }>
selectionType?: 'single' | 'multiple'
rowKey?: string
pageSize?: number
initialRows?: any[]
queryParams?: Record<string, any> //
/** ✅ 新增 */
defaultSelectedKeys?: (string | number)[]
}>(),
{
selectionType: 'multiple',
rowKey: 'id',
pageSize: 10,
initialRows: () => [],
queryParams: () => ({}), //
defaultSelectedKeys: () => []
}
)
const emit = defineEmits<{
(e: 'confirm', value: { ids: (number | string)[]; rows: any[] }): void
}>()
const dialogVisible = ref(false)
const loading = ref(false)
const list = ref<any[]>([])
const total = ref(0)
const tableRef = ref<InstanceType<typeof ElTable>>()
const queryParams = reactive({
pageNo: 1,
pageSize: props.pageSize
})
const selectedMap = ref(new Map<number | string, any>())
const syncingSelection = ref(false)
const isSingleSelect = computed(() => props.selectionType === 'single')
const resolveRowKey = (row: Record<string, any>) => row[props.rowKey]
const refreshSelectionOnTable = async () => {
await nextTick()
const table = tableRef.value
if (!table) return
syncingSelection.value = true
try {
table.clearSelection()
const selectedIds = selectedMap.value
list.value.forEach((row) => {
const rowId = resolveRowKey(row)
if (selectedIds.has(rowId)) {
table.toggleRowSelection(row, true)
}
})
} finally {
syncingSelection.value = false
}
}
/**
* 新增根据 defaultSelectedKeys 初始化选中状态
*/
const initDefaultSelection = () => {
if (!props.defaultSelectedKeys.length) return
props.defaultSelectedKeys.forEach((key) => {
selectedMap.value.set(key, { [props.rowKey]: key })
})
}
const getList = async () => {
loading.value = true
try {
const params = getQueryParams()
const data = await props.fetchApi(params)
list.value = data.list || []
total.value = data.total || 0
await refreshSelectionOnTable()
} finally {
loading.value = false
}
}
const handleSelectionChange = (rows: any[]) => {
if (syncingSelection.value) return
if (isSingleSelect.value) {
selectedMap.value.clear()
const latestRow = rows.length ? rows[rows.length - 1] : undefined
if (latestRow) {
selectedMap.value.set(resolveRowKey(latestRow), latestRow)
}
void refreshSelectionOnTable()
return
}
const pageIdSet = new Set(list.value.map((item) => resolveRowKey(item)))
pageIdSet.forEach((id) => {
selectedMap.value.delete(id)
})
rows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row)
})
}
const handleRowClick = (row: any) => {
if (!isSingleSelect.value) return
const table = tableRef.value
if (!table) return
syncingSelection.value = true
try {
table.clearSelection()
table.toggleRowSelection(row, true)
} finally {
syncingSelection.value = false
}
selectedMap.value.clear()
selectedMap.value.set(resolveRowKey(row), row)
}
const open = async (rows?: any[]) => {
/* selectedMap.value.clear()
const initialRows = rows || props.initialRows
const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
nextRows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row)
})
queryParams.pageNo = 1
queryParams.pageSize = props.pageSize
dialogVisible.value = true
await getList()*/
selectedMap.value.clear()
// 使 defaultSelectedKeys
if (props.defaultSelectedKeys.length) {
initDefaultSelection()
}
// initialRows / rows
const initialRows = rows || props.initialRows
const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
nextRows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row)
})
queryParams.pageNo = 1
queryParams.pageSize = props.pageSize
dialogVisible.value = true
await getList()
}
const submitSelection = () => {
const rows = Array.from(selectedMap.value.values())
const ids = rows.map((row) => resolveRowKey(row))
emit('confirm', { ids, rows })
dialogVisible.value = false
}
//
const reload =async () => {
loading.value = true
//
await getList()
}
// 3. queryParams
const getQueryParams = () => {
return {
pageNo: queryParams.pageNo || 1,
pageSize: queryParams.pageSize || 10,
...props.queryParams //
}
}
// 4.
watch(() => props.queryParams, async () => {
await getList()
}, { deep: true })
defineExpose({ open, reload })
</script>
<style scoped>
.search-container {
margin-bottom: 10px;
padding: 0 0px;
}
</style>

@ -202,6 +202,35 @@ $prefix-cls: #{$namespace}-menu;
.#{$elNamespace}-menu-item {
padding-right: 0;
}
&:not(.#{$elNamespace}-menu--collapse) {
.#{$elNamespace}-sub-menu__title,
.#{$elNamespace}-menu-item {
display: flex;
align-items: flex-start;
/* min-height: var(--el-menu-item-height);*/
height: auto;
padding-top: 10px;
padding-bottom: 10px;
white-space: normal;
}
/* .#{$elNamespace}-sub-menu__icon-arrow {
margin-top: 8px;
}*/
.#{$prefix-cls}__title {
display: block;
flex: 1;
min-width: 0;
overflow: visible;
text-overflow: initial;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
line-height: 1.4;
}
}
}
}
@ -228,6 +257,10 @@ $prefix-cls: #{$namespace}-menu;
}
.#{$prefix-cls}__title {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* stylelint-disable-next-line */
max-height: calc(var(--top-tool-height) - 2px) !important;
/* stylelint-disable-next-line */

@ -10,14 +10,10 @@ export const useRenderMenuTitle = () => {
return icon ? (
<>
<Icon icon={meta.icon}></Icon>
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
{t(title as string)}
</span>
<span class="v-menu__title">{t(title as string)}</span>
</>
) : (
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
{t(title as string)}
</span>
<span class="v-menu__title">{t(title as string)}</span>
)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -41,6 +41,8 @@ import '@/plugins/tongji' // 百度统计
import Logger from '@/utils/Logger'
import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患
import { hiPrintPlugin } from 'vue-plugin-hiprint'
import 'vue-plugin-hiprint/dist/print-lock.css'
// 创建实例
const setupAll = async () => {
@ -56,6 +58,9 @@ const setupAll = async () => {
setupFormCreate(app)
app.use(hiPrintPlugin, '$hiprint', false)
hiPrintPlugin.disAutoConnect()
setupRouter(app)
// directives 指令

@ -79,7 +79,9 @@ const whiteList = [
'/auth-redirect',
'/bind',
'/register',
'/oauthLogin/gitee'
'/oauthLogin/gitee',
'/iot/report/dashboardPage/Dashboard8',
'/iot/report/dashboardPage/Dashboard1'
]
// 路由加载前

@ -642,6 +642,28 @@ const remainingRouter: AppRouteRecordRaw[] = [
canTo: true
}
},
{
path: '/iot',
component: Layout,
name: 'IotHiddenPages',
meta: {
hidden: true
},
children: [
{
path: 'runoverview',
component: () => import('@/views/iot/runoverview/index.vue'),
name: 'IotRunOverview',
meta: {
title: t('DataCollection.RunOverview.moduleName'),
hidden: true,
noTagsView: false,
canTo: true,
activeMenu: '/iot/runoverview'
}
}
]
},
{
path: '/:pathMatch(.*)*',
@ -672,6 +694,28 @@ const remainingRouter: AppRouteRecordRaw[] = [
activeMenu: '/mes/plan'
},
component: () => import('@/views/mes/plan/index.vue')
},
{
path: 'production-report/detail/:id',
name: 'MesProductionReportDetail',
meta: {
title: '生产报工详情',
noCache: true,
hidden: true,
activeMenu: '/mes/productionReport'
},
component: () => import('@/views/mes/productionReport/detail/index.vue')
},
{
path: 'device-ledger/detail/:id',
name: 'MesDeviceLedgerDetail',
meta: {
title: '设备台账详情',
noCache: true,
hidden: true,
activeMenu: '/mes/deviceledger'
},
component: () => import('@/views/mes/deviceledger/detail/index.vue')
}
]
}

@ -9,6 +9,7 @@ import { getSimpleDictDataList } from '@/api/system/dict/dict.data'
export interface DictValueType {
value: any
label: string
labelEn?: string
clorType?: string
cssClass?: string
}
@ -42,33 +43,41 @@ export const useDictStore = defineStore('dict', {
async setDictMap() {
const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)
if (dictMap) {
this.dictMap = dictMap
this.isSetDict = true
} else {
try {
const res = await getSimpleDictDataList()
const dictDataMap = new Map<string, any>()
res.forEach((dictData: DictDataVO) => {
const enumValueObj = dictDataMap[dictData.dictType]
if (!enumValueObj) {
dictDataMap[dictData.dictType] = []
}
dictDataMap[dictData.dictType].push({
value: dictData.value,
label: dictData.label,
colorType: dictData.colorType,
cssClass: dictData.cssClass
})
})
this.dictMap = dictDataMap
wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 })
} catch (error) {
console.error('加载数据字典失败', error)
this.dictMap = new Map<string, any>()
} finally {
const dictTypes = Object.keys(dictMap || {})
const firstDictType = dictTypes[0]
const firstList = firstDictType ? dictMap[firstDictType] : undefined
const needsUpgrade =
Array.isArray(firstList) && firstList.length > 0 && !('labelEn' in (firstList[0] || {}))
if (!needsUpgrade) {
this.dictMap = dictMap
this.isSetDict = true
return
}
}
try {
const res = await getSimpleDictDataList()
const dictDataMap = new Map<string, any>()
res.forEach((dictData: DictDataVO) => {
const enumValueObj = dictDataMap[dictData.dictType]
if (!enumValueObj) {
dictDataMap[dictData.dictType] = []
}
dictDataMap[dictData.dictType].push({
value: dictData.value,
label: dictData.label,
labelEn: (dictData as any).labelEn,
colorType: dictData.colorType,
cssClass: dictData.cssClass
})
})
this.dictMap = dictDataMap
wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 })
} catch (error) {
console.error('加载数据字典失败', error)
this.dictMap = new Map<string, any>()
} finally {
this.isSetDict = true
}
},
getDictByType(type: string) {
if (!this.isSetDict) {
@ -89,6 +98,7 @@ export const useDictStore = defineStore('dict', {
dictDataMap[dictData.dictType].push({
value: dictData.value,
label: dictData.label,
labelEn: (dictData as any).labelEn,
colorType: dictData.colorType,
cssClass: dictData.cssClass
})

@ -20,3 +20,7 @@
.icon-user-o:before {
content: '\f2c0';
}
.el-table--small .cell {
padding: 0 2px;
}

@ -35,3 +35,19 @@
border-left-color: var(--el-color-primary);
}
}
/* 全局生效,所有表格的悬停色都会改变 */
.el-table--enable-row-hover .el-table__body tr:hover > td {
background-color: #f0f9eb !important;
}
/* 2. 关键补全:针对展开行内的 hover 状态 */
/* 展开行tr.expanded内部的 td 需要单独设置 */
.el-table__body .el-table__expanded-cell:hover > td {
background-color: #f0f9eb !important;
}
/* 3. 针对展开后触发的 hover-row 类(某些版本生效) */
.el-table__body tr.hover-row > td {
background-color: #f0f9eb !important;
}

@ -1,7 +1,7 @@
:root {
--login-bg-color: #293146;
--left-menu-max-width: 200px;
--left-menu-max-width: 220px;
--left-menu-min-width: 64px;

@ -0,0 +1,668 @@
/**
* @1900-2100区间内的公历农历互转
* @charset UTF-8
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hexAttribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
* @Version 1.0.3
* @公历转农历calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
const calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,//1900-1909
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,//1910-1919
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,//1920-1929
0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,//1930-1939
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,//1940-1949
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0,//1950-1959
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,//1960-1969
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6,//1970-1979
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,//1980-1989
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0,//1990-1999
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,//2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,//2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,//2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,//2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0,//2040-2049
/**Add By JJonline@JJonline.Cn**/
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0,//2050-2059
0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4,//2060-2069
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0,//2070-2079
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160,//2080-2089
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099
0x0d520],//2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan: ["\u7532", "\u4e59", "\u4e19", "\u4e01", "\u620a", "\u5df1", "\u5e9a", "\u8f9b", "\u58ec", "\u7678"],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi: ["\u5b50", "\u4e11", "\u5bc5", "\u536f", "\u8fb0", "\u5df3", "\u5348", "\u672a", "\u7533", "\u9149", "\u620c", "\u4ea5"],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals: ["\u9f20", "\u725b", "\u864e", "\u5154", "\u9f99", "\u86c7", "\u9a6c", "\u7f8a", "\u7334", "\u9e21", "\u72d7", "\u732a"],
/**
* 阳历节日
*/
festival: {
'1-1': {title: '元旦节'},
'2-14': {title: '情人节'},
'5-1': {title: '劳动节'},
'5-4': {title: '青年节'},
'6-1': {title: '儿童节'},
'9-10': {title: '教师节'},
'10-1': {title: '国庆节'},
'12-25': {title: '圣诞节'},
'3-8': {title: '妇女节'},
'3-12': {title: '植树节'},
'4-1': {title: '愚人节'},
'5-12': {title: '护士节'},
'7-1': {title: '建党节'},
'8-1': {title: '建军节'},
'12-24': {title: '平安夜'},
},
/**
* 农历节日
*/
lFestival: {
'12-30': {title: '除夕'},
'1-1': {title: '春节'},
'1-15': {title: '元宵节'},
'2-2': {title: '龙抬头'},
'5-5': {title: '端午节'},
'7-7': {title: '七夕节'},
'7-15': {title: '中元节'},
'8-15': {title: '中秋节'},
'9-9': {title: '重阳节'},
'10-1': {title: '寒衣节'},
'10-15': {title: '下元节'},
'12-8': {title: '腊八节'},
'12-23': {title: '北方小年'},
'12-24': {title: '南方小年'},
},
/**
* 返回默认定义的阳历节日
*/
getFestival() {
return this.festival
},
/**
* 返回默认定义的内容里节日
*/
getLunarFestival() {
return this.lFestival
},
/**
*
* @param param {Object} 按照festival的格式输入数据设置阳历节日
*/
setFestival(param = {}) {
this.festival = param
},
/**
*
* @param param {Object} 按照lFestival的格式输入数据设置农历节日
*/
setLunarFestival(param = {}) {
this.lFestival = param
},
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm: ["\u5c0f\u5bd2", "\u5927\u5bd2", "\u7acb\u6625", "\u96e8\u6c34", "\u60ca\u86f0", "\u6625\u5206", "\u6e05\u660e", "\u8c37\u96e8", "\u7acb\u590f", "\u5c0f\u6ee1", "\u8292\u79cd", "\u590f\u81f3", "\u5c0f\u6691", "\u5927\u6691", "\u7acb\u79cb", "\u5904\u6691", "\u767d\u9732", "\u79cb\u5206", "\u5bd2\u9732", "\u971c\u964d", "\u7acb\u51ac", "\u5c0f\u96ea", "\u5927\u96ea", "\u51ac\u81f3"],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1: ["\u65e5", "\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341"],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2: ["\u521d", "\u5341", "\u5eff", "\u5345"],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3: ["\u6b63", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u51ac", "\u814a"],
/**
* 返回农历y年一整年的总天数
* @param y lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays: function (y) {
let i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0;
}
return (sum + this.leapDays(y));
},
/**
* 返回农历y年闰月是哪个月若y年没有闰月 则返回0
* @param y lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth: function (y) { //闰字编码 \u95f0
return (this.lunarInfo[y - 1900] & 0xf);
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param y lunar Year
* @return Number (02930)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays: function (y) {
if (this.leapMonth(y)) {
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29);
}
return (0);
},
/**
* 返回农历y年m月非闰月的总天数计算m为闰月时的天数请使用leapDays方法
* @param y lunar Year
* @param m lunar Month
* @return Number (-12930)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays: function (y, m) {
if (m > 12 || m < 1) {
return -1
}//月份参数从1至12参数错误返回-1
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29);
},
/**
* 返回公历(!)y年m月的天数
* @param y solar Year
* @param m solar Month
* @return Number (-128293031)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays: function (y, m) {
if (m > 12 || m < 1) {
return -1
} //若参数错误 返回-1
const ms = m - 1;
if (ms === 1) { //2月份的闰平规律测算后确认返回28或29
return (((y % 4 === 0) && (y % 100 !== 0) || (y % 400 === 0)) ? 29 : 28);
} else {
return (this.solarMonth[ms]);
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear: function (lYear) {
var ganKey = (lYear - 3) % 10;
var zhiKey = (lYear - 3) % 12;
if (ganKey === 0) ganKey = 10;//如果余数为0则为最后一个天干
if (zhiKey === 0) zhiKey = 12;//如果余数为0则为最后一个地支
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1];
},
/**
* 公历月日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro: function (cMonth, cDay) {
const s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf";
const arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22];
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + "\u5ea7";//座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi: function (offset) {
return this.Gan[offset % 10] + this.Zhi[offset % 12];
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y y公历年(1900-2100)
* @param n n二十四节气中的第几个节气(1~24)从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm: function (y, n) {
if( y < 1900 || y > 2100 || n < 1 || n > 24) {
return -1;
}
const _table = this.sTermInfo[y - 1900];
const _calcDay = []
for (let index = 0; index < _table.length; index += 5) {
const chunk = parseInt('0x' + _table.substr(index, 5)).toString()
_calcDay.push(
chunk[0],
chunk.substr(1, 2),
chunk[3],
chunk.substr(4, 2)
)
}
return parseInt(_calcDay[n - 1]);
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param m lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth: function (m) { // 月 => \u6708
if (m > 12 || m < 1) {
return -1
} //若参数错误 返回-1
let s = this.nStr3[m - 1];
s += "\u6708";//加上月字
return s;
},
/**
* 传入农历日期数字返回汉字表示法
* @param d lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay: function (d) { //日 => \u65e5
let s;
switch (d) {
case 10:
s = '\u521d\u5341';
break;
case 20:
s = '\u4e8c\u5341';
break;
case 30:
s = '\u4e09\u5341';
break;
default :
s = this.nStr2[Math.floor(d / 10)];
s += this.nStr1[d % 10];
}
return (s);
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是立春
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function (y) {
return this.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历农历object信息 <=>JSON
* !important! 公历参数区间1900.1.31~2100.12.31
* @param yPara solar year
* @param mPara solar month
* @param dPara solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar: function (yPara, mPara, dPara) {
let y = parseInt(yPara);
let m = parseInt(mPara);
let d = parseInt(dPara);
//年份限定、上限
if (y < 1900 || y > 2100) {
return -1;// undefined转换为数字变为NaN
}
//公历传参最下限
if (y === 1900 && m === 1 && d < 31) {
return -1;
}
//未传参 获得当天
let objDate;
if (!y) {
objDate = new Date();
} else {
objDate = new Date(y, parseInt(m) - 1, d);
}
let i, leap = 0, temp = 0;
//修正ymd参数
y = objDate.getFullYear();
m = objDate.getMonth() + 1;
d = objDate.getDate();
let offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000;
for (i = 1900; i < 2101 && offset > 0; i++) {
temp = this.lYearDays(i);
offset -= temp;
}
if (offset < 0) {
offset += temp;
i--;
}
//是否今天
let isTodayObj = new Date(),
isToday = false;
if (isTodayObj.getFullYear() === y && isTodayObj.getMonth() + 1 === m && isTodayObj.getDate() === d) {
isToday = true;
}
//星期几
let nWeek = objDate.getDay(),
cWeek = this.nStr1[nWeek];
//数字表示周几顺应天朝周一开始的惯例
if (nWeek === 0) {
nWeek = 7;
}
//农历年
const year = i;
leap = this.leapMonth(i); //闰哪个月
let isLeap = false;
//效验闰月
for (i = 1; i < 13 && offset > 0; i++) {
//闰月
if (leap > 0 && i === (leap + 1) && isLeap === false) {
--i;
isLeap = true;
temp = this.leapDays(year); //计算农历闰月天数
} else {
temp = this.monthDays(year, i);//计算农历普通月天数
}
//解除闰月
if (isLeap === true && i === (leap + 1)) {
isLeap = false;
}
offset -= temp;
}
// 闰月导致数组下标重叠取反
if (offset === 0 && leap > 0 && i === leap + 1) {
if (isLeap) {
isLeap = false;
} else {
isLeap = true;
--i;
}
}
if (offset < 0) {
offset += temp;
--i;
}
//农历月
const month = i;
//农历日
const day = offset + 1;
//天干地支处理
const sm = m - 1;
const gzY = this.toGanZhiYear(year);
// 当月的两个节气
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
const firstNode = this.getTerm(y, (m * 2 - 1));//返回当月「节」为几日开始
const secondNode = this.getTerm(y, (m * 2));//返回当月「节」为几日开始
// 依据12节气修正干支月
let gzM = this.toGanZhi((y - 1900) * 12 + m + 11);
if (d >= firstNode) {
gzM = this.toGanZhi((y - 1900) * 12 + m + 12);
}
//传入的日期的节气与否
let isTerm = false;
let Term = null;
if (firstNode === d) {
isTerm = true;
Term = this.solarTerm[m * 2 - 2];
}
if (secondNode === d) {
isTerm = true;
Term = this.solarTerm[m * 2 - 1];
}
//日柱 当月一日与 1900/1/1 相差天数
const dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10;
const gzD = this.toGanZhi(dayCyclical + d - 1);
//该日期所属的星座
const astro = this.toAstro(m, d);
const solarDate = y + '-' + m + '-' + d;
const lunarDate = year + '-' + month + '-' + day;
const festival = this.festival;
const lFestival = this.lFestival;
const festivalDate = m + '-' + d;
let lunarFestivalDate = month + '-' + day;
// bugfix https://github.com/jjonline/calendar.js/issues/29
// 农历节日修正农历12月小月则29号除夕大月则30号除夕
// 此处取巧修正当前为农历12月29号时增加一次判断并且把lunarFestivalDate设置为12-30以正确取得除夕
// 天朝农历节日遇闰月过前不过后的原则此处取农历12月天数不考虑闰月
// 农历润12月在本工具支持的200年区间内仅1574年出现
if (month === 12 && day === 29 && this.monthDays(year, month) === 29) {
lunarFestivalDate = '12-30';
}
return {
date: solarDate,
lunarDate: lunarDate,
festival: festival[festivalDate] ? festival[festivalDate].title : null,
lunarFestival: lFestival[lunarFestivalDate] ? lFestival[lunarFestivalDate].title : null,
'lYear': year,
'lMonth': month,
'lDay': day,
'Animal': this.getAnimal(year),
'IMonthCn': (isLeap ? "\u95f0" : '') + this.toChinaMonth(month),
'IDayCn': this.toChinaDay(day),
'cYear': y,
'cMonth': m,
'cDay': d,
'gzYear': gzY,
'gzMonth': gzM,
'gzDay': gzD,
'isToday': isToday,
'isLeap': isLeap,
'nWeek': nWeek,
'ncWeek': "\u661f\u671f" + cWeek,
'isTerm': isTerm,
'Term': Term,
'astro': astro
};
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历农历object信息 <=>JSON
* !important! 参数区间1900.1.31~2100.12.1
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar: function (y, m, d, isLeapMonth) {
y = parseInt(y)
m = parseInt(m)
d = parseInt(d)
isLeapMonth = !!isLeapMonth;
const leapOffset = 0;
const leapMonth = this.leapMonth(y);
const leapDay = this.leapDays(y);
if (isLeapMonth && (leapMonth !== m)) {
return -1;
}//传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if (y === 2100 && m === 12 && d > 1 || y === 1900 && m === 1 && d < 31) {
return -1;
}//超出了最大极限值
const day = this.monthDays(y, m);
let _day = day;
//bugFix 2016-9-25
//if month is leap, _day use leapDays method
if (isLeapMonth) {
_day = this.leapDays(y, m);
}
if (y < 1900 || y > 2100 || d > _day) {
return -1;
}//参数合法性效验
//计算农历的时间差
let offset = 0;
let i;
for (i = 1900; i < y; i++) {
offset += this.lYearDays(i);
}
let leap = 0, isAdd = false;
for (i = 1; i < m; i++) {
leap = this.leapMonth(y);
if (!isAdd) {//处理闰月
if (leap <= i && leap > 0) {
offset += this.leapDays(y);
isAdd = true;
}
}
offset += this.monthDays(y, i);
}
//转换闰月农历 需补充该年闰月的前一个月的时差
if (isLeapMonth) {
offset += day;
}
//1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
const strap = Date.UTC(1900, 1, 30, 0, 0, 0);
const calObj = new Date((offset + d - 31) * 86400000 + strap);
const cY = calObj.getUTCFullYear();
const cM = calObj.getUTCMonth() + 1;
const cD = calObj.getUTCDate();
return this.solar2lunar(cY, cM, cD);
}
};
export default calendar;

@ -2,9 +2,11 @@
*
*/
import { useDictStoreWithOut } from '@/store/modules/dict'
import { useLocaleStoreWithOut } from '@/store/modules/locale'
import { ElementPlusInfoType } from '@/types/elementPlus'
const dictStore = useDictStoreWithOut()
const localeStore = useLocaleStoreWithOut()
/**
* dictType
@ -15,6 +17,7 @@ const dictStore = useDictStoreWithOut()
export interface DictDataType {
dictType: string
label: string
labelEn?: string
value: string | number
colorType: ElementPlusInfoType | ''
cssClass: string
@ -39,8 +42,10 @@ export const getIntDictOptions = (dictType: string): NumberDictDataType[] => {
// why 需要特殊转换:避免 IDEA 在 v-for="dict in getIntDictOptions(...)" 时el-option 的 key 会告警
const dictOption: NumberDictDataType[] = []
dictOptions.forEach((dict: DictDataType) => {
const label = localeStore.getCurrentLocale?.lang === 'en' ? (dict.labelEn || dict.label) : dict.label
dictOption.push({
...dict,
label,
value: parseInt(dict.value + '')
})
})
@ -54,8 +59,10 @@ export const getStrDictOptions = (dictType: string) => {
// why 需要特殊转换:避免 IDEA 在 v-for="dict in getStrDictOptions(...)" 时el-option 的 key 会告警
const dictOption: StringDictDataType[] = []
dictOptions.forEach((dict: DictDataType) => {
const label = localeStore.getCurrentLocale?.lang === 'en' ? (dict.labelEn || dict.label) : dict.label
dictOption.push({
...dict,
label,
value: dict.value + ''
})
})
@ -66,8 +73,10 @@ export const getBoolDictOptions = (dictType: string) => {
const dictOption: DictDataType[] = []
const dictOptions: DictDataType[] = getDictOptions(dictType)
dictOptions.forEach((dict: DictDataType) => {
const label = localeStore.getCurrentLocale?.lang === 'en' ? (dict.labelEn || dict.label) : dict.label
dictOption.push({
...dict,
label,
value: dict.value + '' === 'true'
})
})
@ -101,7 +110,8 @@ export const getDictLabel = (dictType: string, value: any): string => {
const dictLabel = ref('')
dictOptions.forEach((dict: DictDataType) => {
if (dict.value === value + '') {
dictLabel.value = dict.label
dictLabel.value =
localeStore.getCurrentLocale?.lang === 'en' ? (dict.labelEn || dict.label) : dict.label
}
})
return dictLabel.value
@ -256,6 +266,9 @@ export enum DICT_TYPE {
MOLD_GET_STATUS = "mold_get_status",
MES_PRE_PRODUCTION = "mes_pre_production",
MES_ZJ_PRODUCT = "mes_zj_product",
FILE_STATUS = "file_status",
Classification = "classification",
MES_JOB_TYPE = "mes_job_type",
//====iot
IOT_SIEMENS_TYPE = "iot_siemens_type",
IOT_MODBUS_TYPE = "iot_modbus_type",
@ -278,7 +291,7 @@ export enum DICT_TYPE {
IOT_ALERT_LEVEL = "iot_alert_level",
IOT_PROTOCOL = "iot_protocol",
IOT_DEVICE_ATTRIBUTE_UNIT = "iot_device_attribute_unit",
IOT_ALARM_REGISTRATION = " alarm_registration",
IOT_ALARM_REGISTRATION = "alarm_registration",
PRIMARY_FLAG = "primary_flag"
}

@ -2,9 +2,9 @@
<div class="home-page">
<div class="home-welcome">
<div class="home-welcome-left">
<div class="home-welcome-title text-white!">欢迎您使用必硕数字化智能中控平台</div>
<div class="home-welcome-title text-white!">{{t("home.welcome")}}</div>
<div class="home-welcome-desc text-white! opacity-80">
必硕数字化智能中控平台以生产运营为核心统一整合生产计划数据采集仓储设备能源模具质量配方及报表分析等关键业务模块实现从计划到执行从设备到制品从数据到决策的全流程数字化管理
{{t("home.message")}}
</div>
</div>
<div class="home-welcome-right">
@ -15,11 +15,11 @@ alt="banner" :src="bannerImg" fit="contain" class="home-welcome-image"
</div>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">整体生产概况</div>
<div class="section-title">{{t("home.productTitle")}}</div>
<div>
<el-date-picker
v-model="productionOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD"
start-placeholder="开始日期" end-placeholder="结束日期" size="small" @change="handleProductionOverviewRangeChange" />
:start-placeholder="t('home.placeholderCreateTimeStart')" :end-placeholder="t('home.placeholderCreateTimeEnd')" size="small" @change="handleProductionOverviewRangeChange" />
</div>
</div>
<el-row class="production-overview-row" :gutter="0">
@ -45,14 +45,14 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-card>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">实时生产进度</div>
<div class="section-title">{{t("home.productionSchedule")}}</div>
</div>
<el-carousel height="190px" arrow="always" indicator-position="none" :interval="15000" class="progress-carousel">
<el-carousel-item v-for="(group, index) in productionProgressGroups" :key="index">
<el-row :gutter="16">
<el-col v-for="item in group" :key="item.id" :xl="8" :lg="8" :md="8" :sm="12" :xs="24">
<div class="progress-card">
<div class="progress-card-header">生产计划 {{ item.code }}
<div class="progress-card-header">{{t("home.productionPlan")}} {{ item.code }}
<el-tag :type="getPlanStatusTagType(item.status)" effect="light">
{{ getPlanStatusLabel(item.status) }}
</el-tag>
@ -60,45 +60,45 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<div class="progress-card-body">
<div class="progress-col">
<div class="progress-row">
<span class="progress-label">产品名称</span>
<span class="progress-label">{{t("home.productionName")}}</span>
<span class="progress-value">{{ item.productName }}</span>
</div>
<div class="progress-row">
<span class="progress-label">计划数量</span>
<span class="progress-label">{{t("home.planNumber")}}</span>
<span class="progress-value">{{ item.planNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">生产线</span>
<span class="progress-label">{{t("home.productionLine")}}</span>
<span class="progress-value">{{ item.feedingPipelineName }}</span>
</div>
<div class="progress-row">
<span class="progress-label">计划开始时间</span>
<span class="progress-label">{{t("home.planStartTime")}}</span>
<span class="progress-value">{{ formatDate(item.planStartTime) }}</span>
</div>
<div class="progress-row">
<span class="progress-label">计划结束时间</span>
<span class="progress-label">{{t("home.planEndTime")}}</span>
<span class="progress-value">{{ formatDate(item.planEndTime) }}</span>
</div>
</div>
<div class="progress-col">
<div class="progress-row">
<span class="progress-label">完工数量</span>
<span class="progress-label">{{t("home.completedQuantity")}}</span>
<span class="progress-value">{{ item.wangongNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">合格数量</span>
<span class="progress-label">{{t("home.qualifiedQuantity")}}</span>
<span class="progress-value">{{ item.passNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">不合格数量</span>
<span class="progress-label">{{t("home.unqualifiedQuantity")}}</span>
<span class="progress-value">{{ item.noPassNumber }}%</span>
</div>
<div class="progress-row">
<span class="progress-label">合格率</span>
<span class="progress-label">{{t("home.yieldRate")}}</span>
<span class="progress-value">{{ item.passRate }}</span>
</div>
<div class="progress-row">
<span class="progress-label">实际结束时间</span>
<span class="progress-label">{{t("home.actualEndTime")}}</span>
<span class="progress-value">{{ formatDate(item.endTime) }}</span>
</div>
</div>
@ -111,7 +111,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-card>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">待办任务</div>
<div class="section-title">{{t("home.gtasks")}}</div>
</div>
<el-carousel height="160px" arrow="always" indicator-position="none" class="todo-carousel" :interval="15000">
<el-carousel-item v-for="(group, index) in todoTaskGroups" :key="index">
@ -119,10 +119,10 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col v-for="item in group" :key="item.id" :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
<div class="todo-card">
<div class="todo-title">{{ item.name }}</div>
<div class="todo-sub">任务编号{{ item.code }}</div>
<div class="todo-sub">任务类型{{ item.type }}</div>
<div class="todo-sub">目标{{ item.deviceName }}</div>
<div class="todo-sub">创建时间{{ formatDate(item.createTime) }}</div>
<div class="todo-sub">{{t("home.missionNumber")}}{{ item.code }}</div>
<div class="todo-sub">{{t("home.taskType")}}{{ item.type }}</div>
<div class="todo-sub">{{t("home.target")}}{{ item.deviceName }}</div>
<div class="todo-sub">{{t("home.creationTime")}}{{ formatDate(item.createTime) }}</div>
</div>
</el-col>
</el-row>
@ -133,7 +133,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col">
<el-card shadow="never" class="device-alarm-card">
<div class="section-header">
<div class="section-title">设备</div>
<div class="section-title">{{t("home.equipment")}}</div>
<!-- <div class="section-actions">
<el-button type="default" size="small">查看文档</el-button>
<el-button type="primary" size="small">添加设备</el-button>
@ -152,7 +152,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col mt-16px xl:mt-0 lg:mt-0">
<el-card shadow="never" class="device-alarm-card">
<div class="section-header">
<div class="section-title">模具</div>
<div class="section-title">{{t("home.mould")}}</div>
</div>
<el-row :gutter="12" class="mt-16px">
<el-col v-for="item in moldStatusCards" :key="item.key" :span="8">
@ -167,7 +167,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-row>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">采集设备整体情况</div>
<div class="section-title">{{t("home.equipmentTile")}}</div>
<!-- <div>
<el-date-picker
v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD"
@ -177,43 +177,43 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-row class="device-overview-row" :gutter="0" v-model = "formData">
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">总设备数</div>
<div class="production-overview-label">{{t("home.equipmentCount")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.totalDevices }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">运行</div>
<div class="production-overview-label">{{t("home.operation")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.runningCount }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">待机中</div>
<div class="production-overview-label">{{t("home.standbyMode")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.standbyCount }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">故障中</div>
<div class="production-overview-label">{{t("home.malfunction")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.faultCount }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">报警中</div>
<div class="production-overview-label">{{t("home.alerting")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.warningCount }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">利用率</div>
<div class="production-overview-label">{{t("home.useRatio")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.utilizationRate }}</div>
</div>
</el-col>
<el-col :span="2">
<div class="device-overview-item">
<div class="production-overview-label">故障率</div>
<div class="production-overview-label">{{t("home.failureRate")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.faultRate }}</div>
</div>
</el-col>
@ -224,7 +224,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never">
<template #header>
<div class="h-3 flex justify-between">
<span>设备维修数量统计</span>
<span>{{t("home.equipmentTitle")}}</span>
</div>
</template>
<Echart :options="deviceRepairLineOptions" :height="260" />
@ -234,7 +234,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never">
<template #header>
<div class="h-3 flex justify-between">
<span>设备分类统计</span>
<span>{{t("home.equipmentClass")}}</span>
</div>
</template>
<Echart :options="deviceCategoryPieOptionsData" :height="260" />
@ -244,7 +244,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never">
<template #header>
<div class="h-3 flex justify-between">
<span>按模具分类统计取模具数量最多的前10项</span>
<span>{{t("home.equipmentMessage")}}</span>
</div>
</template>
<Echart :options="moldTypeBarOptionsData" :height="260" />

@ -72,10 +72,10 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="分类编号" align="center" prop="id" />
<el-table-column label="分类名" align="center" prop="name" />
<el-table-column label="分类标志" align="center" prop="code" />
<el-table-column label="分类名" align="center" prop="name" sortable />
<el-table-column label="分类标志" align="center" prop="code" sortable />
<el-table-column label="分类描述" align="center" prop="description" />
<el-table-column label="分类状态" align="center" prop="status">
<el-table-column label="分类状态" align="center" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
@ -87,7 +87,7 @@
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button

@ -3,15 +3,15 @@
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="定义编号" align="center" prop="id" width="400" />
<el-table-column label="流程名称" align="center" prop="name" width="200">
<el-table-column label="流程名称" align="center" prop="name" width="200" sortable>
<template #default="scope">
<el-button type="primary" link @click="handleBpmnDetail(scope.row)">
<span>{{ scope.row.name }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="定义分类" align="center" prop="categoryName" width="100" />
<el-table-column label="表单信息" align="center" prop="formType" width="200">
<el-table-column label="定义分类" align="center" prop="categoryName" width="100" sortable />
<el-table-column label="表单信息" align="center" prop="formType" width="200" sortable>
<template #default="scope">
<el-button
v-if="scope.row.formType === 10"
@ -44,7 +44,7 @@
prop="deploymentTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<el-table-column
label="定义描述"
align="center"

@ -39,8 +39,8 @@
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="编号" prop="id" />
<el-table-column align="center" label="表单名" prop="name" />
<el-table-column align="center" label="状态" prop="status">
<el-table-column align="center" label="表单名" prop="name" sortable />
<el-table-column align="center" label="状态" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
@ -51,7 +51,7 @@
align="center"
label="创建时间"
prop="createTime"
/>
sortable />
<el-table-column align="center" label="操作">
<template #default="scope">
<el-button

@ -58,7 +58,7 @@
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="组名" align="center" prop="name" />
<el-table-column label="组名" align="center" prop="name" sortable />
<el-table-column label="描述" align="center" prop="description" />
<el-table-column label="成员" align="center">
<template #default="scope">
@ -67,7 +67,7 @@
</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<el-table-column label="状态" align="center" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
@ -77,7 +77,7 @@
align="center"
prop="createTime"
:formatter="dateFormatter"
/>
sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button

@ -76,7 +76,7 @@
:data="modelList"
row-key="id"
>
<el-table-column label="流程名" prop="name" min-width="150">
<el-table-column label="流程名" prop="name" min-width="150" sortable>
<template #default="scope">
<div class="flex items-center">
<el-tooltip content="拖动排序" v-if="isModelSorting">
@ -110,7 +110,7 @@
</el-text>
</template>
</el-table-column>
<el-table-column label="表单信息" prop="formType" min-width="200">
<el-table-column label="表单信息" prop="formType" min-width="200" sortable>
<template #default="scope">
<el-button
v-if="scope.row.formType === BpmModelFormType.NORMAL"
@ -131,7 +131,7 @@
<label v-else></label>
</template>
</el-table-column>
<el-table-column label="最后发布" prop="deploymentTime" min-width="250">
<el-table-column label="最后发布" prop="deploymentTime" min-width="250" sortable>
<template #default="scope">
<div class="flex items-center">
<span v-if="scope.row.processDefinition" class="w-150px">

@ -60,7 +60,7 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="流程名称" align="center" prop="name" min-width="200" />
<el-table-column label="流程名称" align="center" prop="name" min-width="200" sortable />
<el-table-column label="流程图标" align="center" prop="icon" min-width="100">
<template #default="scope">
<el-image :src="scope.row.icon" class="h-32px w-32px" />
@ -86,8 +86,8 @@
</el-text>
</template>
</el-table-column>
<el-table-column label="流程分类" align="center" prop="categoryName" min-width="100" />
<el-table-column label="表单信息" align="center" prop="formType" min-width="200">
<el-table-column label="流程分类" align="center" prop="categoryName" min-width="100" sortable />
<el-table-column label="表单信息" align="center" prop="formType" min-width="200" sortable>
<template #default="scope">
<el-button
v-if="scope.row.formType === 10"
@ -108,7 +108,7 @@
<label v-else></label>
</template>
</el-table-column>
<el-table-column label="最后发布" align="center" prop="deploymentTime" min-width="250">
<el-table-column label="最后发布" align="center" prop="deploymentTime" min-width="250" sortable>
<template #default="scope">
<span v-if="scope.row.processDefinition">
{{ formatDate(scope.row.processDefinition.deploymentTime) }}

@ -80,7 +80,7 @@
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="申请编号" prop="id" />
<el-table-column align="center" label="状态" prop="status">
<el-table-column align="center" label="状态" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
</template>
@ -91,15 +91,15 @@
label="开始时间"
prop="startTime"
width="180"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
width="180"
/>
<el-table-column align="center" label="请假类型" prop="type">
sortable />
<el-table-column align="center" label="请假类型" prop="type" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="scope.row.type" />
</template>
@ -111,7 +111,7 @@
label="申请时间"
prop="createTime"
width="180"
/>
sortable />
<el-table-column align="center" label="操作" width="200">
<template #default="scope">
<el-button

@ -58,8 +58,8 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="状态" align="center" prop="status">
<el-table-column label="名字" align="center" prop="name" sortable />
<el-table-column label="状态" align="center" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
@ -71,7 +71,7 @@
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button

@ -1,6 +1,6 @@
<template>
<el-table :data="tasks" border header-cell-class-name="table-header-gray">
<el-table-column label="审批节点" prop="name" min-width="120" align="center" />
<el-table-column label="审批节点" prop="name" min-width="120" align="center" sortable />
<el-table-column label="审批人" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
@ -12,15 +12,15 @@
label="开始时间"
prop="createTime"
min-width="140"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
min-width="140"
/>
<el-table-column align="center" label="审批状态" prop="status" min-width="90">
sortable />
<el-table-column align="center" label="审批状态" prop="status" min-width="90" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>

@ -128,17 +128,17 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" />
<el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" sortable />
<el-table-column
label="流程分类"
align="center"
prop="categoryName"
min-width="100"
fixed="left"
/>
sortable />
<!-- TODO @芋艿摘要 -->
<!-- TODO tuituiji参考钉钉1审批中时展示审批任务2非审批中展示状态 -->
<el-table-column label="流程状态" prop="status" width="120">
<el-table-column label="流程状态" prop="status" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
</template>
@ -149,14 +149,14 @@
prop="startTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<el-table-column
label="结束时间"
align="center"
prop="endTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<!--<el-table-column align="center" label="耗时" prop="durationInMillis" width="160">
<template #default="scope">
{{ scope.row.durationInMillis > 0 ? formatPast2(scope.row.durationInMillis) : '-' }}

@ -88,17 +88,17 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" />
<el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" sortable />
<el-table-column
label="流程分类"
align="center"
prop="categoryName"
min-width="100"
fixed="left"
/>
<el-table-column label="流程发起人" align="center" prop="startUser.nickname" width="120" />
<el-table-column label="发起部门" align="center" prop="startUser.deptName" width="120" />
<el-table-column label="流程状态" prop="status" width="120">
sortable />
<el-table-column label="流程发起人" align="center" prop="startUser.nickname" width="120" sortable />
<el-table-column label="发起部门" align="center" prop="startUser.deptName" width="120" sortable />
<el-table-column label="流程状态" prop="status" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
</template>
@ -109,14 +109,14 @@
prop="startTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<el-table-column
label="结束时间"
align="center"
prop="endTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<el-table-column align="center" label="耗时" prop="durationInMillis" width="169">
<template #default="scope">
{{ scope.row.durationInMillis > 0 ? formatPast2(scope.row.durationInMillis) : '-' }}

@ -47,19 +47,19 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="类型" align="center" prop="type">
<el-table-column label="名字" align="center" prop="name" sortable />
<el-table-column label="类型" align="center" prop="type" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_LISTENER_TYPE" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<el-table-column label="状态" align="center" prop="status" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="事件" align="center" prop="event" />
<el-table-column label="值类型" align="center" prop="valueType">
<el-table-column label="值类型" align="center" prop="valueType" sortable>
<template #default="scope">
<dict-tag
:type="DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE"
@ -74,7 +74,7 @@
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button

@ -40,21 +40,21 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="流程名" prop="processInstanceName" min-width="180" />
<el-table-column align="center" label="流程名" prop="processInstanceName" min-width="180" sortable />
<el-table-column
align="center"
label="流程发起人"
prop="startUser.nickname"
min-width="100"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="流程发起时间"
prop="processInstanceStartTime"
width="180"
/>
<el-table-column align="center" label="抄送节点" prop="activityName" min-width="180" />
sortable />
<el-table-column align="center" label="抄送节点" prop="activityName" min-width="180" sortable />
<el-table-column align="center" label="抄送人" min-width="100">
<template #default="scope"> {{ scope.row.createUser?.nickname || '系统' }} </template>
</el-table-column>
@ -65,7 +65,7 @@
prop="createTime"
width="180"
:formatter="dateFormatter"
/>
sortable />
<el-table-column align="center" label="操作" fixed="right" width="80">
<template #default="scope">
<el-button link type="primary" @click="handleAudit(scope.row)"></el-button>

@ -114,36 +114,36 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" />
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" sortable />
<el-table-column
align="center"
label="发起人"
prop="processInstance.startUser.nickname"
width="100"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="发起时间"
prop="createTime"
width="180"
/>
<el-table-column align="center" label="当前任务" prop="name" width="180" />
sortable />
<el-table-column align="center" label="当前任务" prop="name" width="180" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务开始时间"
prop="createTime"
width="180"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务结束时间"
prop="endTime"
width="180"
/>
<el-table-column align="center" label="审批状态" prop="status" width="120">
sortable />
<el-table-column align="center" label="审批状态" prop="status" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>

@ -46,37 +46,37 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" />
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" sortable />
<el-table-column
align="center"
label="发起人"
prop="processInstance.startUser.nickname"
width="100"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="发起时间"
prop="createTime"
width="180"
/>
<el-table-column align="center" label="当前任务" prop="name" width="180" />
sortable />
<el-table-column align="center" label="当前任务" prop="name" width="180" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务开始时间"
prop="createTime"
width="180"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务结束时间"
prop="endTime"
width="180"
/>
<el-table-column align="center" label="审批人" prop="assigneeUser.nickname" width="100" />
<el-table-column align="center" label="审批状态" prop="status" width="120">
sortable />
<el-table-column align="center" label="审批人" prop="assigneeUser.nickname" width="100" sortable />
<el-table-column align="center" label="审批状态" prop="status" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>

@ -98,28 +98,28 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" />
<el-table-column align="center" label="流程" prop="processInstance.name" width="180" sortable />
<el-table-column
align="center"
label="发起人"
prop="processInstance.startUser.nickname"
width="100"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="发起时间"
prop="createTime"
width="180"
/>
<el-table-column align="center" label="当前任务" prop="name" width="180" />
sortable />
<el-table-column align="center" label="当前任务" prop="name" width="180" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务时间"
prop="createTime"
width="180"
/>
sortable />
<el-table-column align="center" label="流程编号" prop="id" :show-overflow-tooltip="true" />
<el-table-column align="center" label="任务编号" prop="id" :show-overflow-tooltip="true" />
<el-table-column align="center" label="操作" fixed="right" width="80">

@ -29,7 +29,7 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="160">
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -61,7 +61,7 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column
label="最后跟进时间"
@ -69,25 +69,25 @@
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" sortable />
<el-table-column
label="更新时间"
align="center"
prop="updateTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -30,15 +30,15 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" fixed="left" label="合同编号" prop="no" width="180" />
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="160">
<el-table-column align="center" fixed="left" label="合同编号" prop="no" width="180" sortable />
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="客户名称" prop="customerName" width="120">
<el-table-column align="center" label="客户名称" prop="customerName" width="120" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -49,7 +49,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="商机名称" prop="businessName" width="130">
<el-table-column align="center" label="商机名称" prop="businessName" width="130" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -73,22 +73,22 @@
prop="orderDate"
width="120"
:formatter="dateFormatter2"
/>
sortable />
<el-table-column
align="center"
label="合同开始时间"
prop="startTime"
width="120"
:formatter="dateFormatter2"
/>
sortable />
<el-table-column
align="center"
label="合同结束时间"
prop="endTime"
width="120"
:formatter="dateFormatter2"
/>
<el-table-column align="center" label="客户签约人" prop="contactName" width="130">
sortable />
<el-table-column align="center" label="客户签约人" prop="contactName" width="130" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -99,7 +99,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="公司签约人" prop="signUserName" width="130" />
<el-table-column align="center" label="公司签约人" prop="signUserName" width="130" sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column
align="center"
@ -125,25 +125,25 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
sortable />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="120" />
<el-table-column align="center" fixed="right" label="合同状态" prop="auditStatus" width="120">
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="120" sortable />
<el-table-column align="center" fixed="right" label="合同状态" prop="auditStatus" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
</template>

@ -30,15 +30,15 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" fixed="left" label="合同编号" prop="no" width="180" />
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="160">
<el-table-column align="center" fixed="left" label="合同编号" prop="no" width="180" sortable />
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="客户名称" prop="customerName" width="120">
<el-table-column align="center" label="客户名称" prop="customerName" width="120" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -49,7 +49,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="商机名称" prop="businessName" width="130">
<el-table-column align="center" label="商机名称" prop="businessName" width="130" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -73,22 +73,22 @@
prop="orderDate"
width="120"
:formatter="dateFormatter2"
/>
sortable />
<el-table-column
align="center"
label="合同开始时间"
prop="startTime"
width="120"
:formatter="dateFormatter2"
/>
sortable />
<el-table-column
align="center"
label="合同结束时间"
prop="endTime"
width="120"
:formatter="dateFormatter2"
/>
<el-table-column align="center" label="客户签约人" prop="contactName" width="130">
sortable />
<el-table-column align="center" label="客户签约人" prop="contactName" width="130" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -99,7 +99,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="公司签约人" prop="signUserName" width="130" />
<el-table-column align="center" label="公司签约人" prop="signUserName" width="130" sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column
align="center"
@ -125,25 +125,25 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
sortable />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="120" />
<el-table-column align="center" fixed="right" label="合同状态" prop="auditStatus" width="120">
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="120" sortable />
<el-table-column align="center" fixed="right" label="合同状态" prop="auditStatus" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
</template>

@ -31,7 +31,7 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -62,14 +62,14 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column align="center" label="锁定状态" prop="lockStatus">
<el-table-column align="center" label="锁定状态" prop="lockStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.lockStatus" />
</template>
</el-table-column>
<el-table-column align="center" label="成交状态" prop="dealStatus">
<el-table-column align="center" label="成交状态" prop="dealStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" />
</template>
@ -80,29 +80,29 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
<el-table-column label="地址" align="center" prop="detailAddress" width="180" />
<el-table-column align="center" label="距离进入公海天数" prop="poolDay" width="140">
<template #default="scope"> {{ scope.row.poolDay }} </template>
</el-table-column>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -29,7 +29,7 @@
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -60,14 +60,14 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column align="center" label="锁定状态" prop="lockStatus">
<el-table-column align="center" label="锁定状态" prop="lockStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.lockStatus" />
</template>
</el-table-column>
<el-table-column align="center" label="成交状态" prop="dealStatus">
<el-table-column align="center" label="成交状态" prop="dealStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" />
</template>
@ -78,29 +78,29 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
<el-table-column label="地址" align="center" prop="detailAddress" width="180" />
<el-table-column align="center" label="距离进入公海天数" prop="poolDay" width="140">
<template #default="scope"> {{ scope.row.poolDay }} </template>
</el-table-column>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -43,7 +43,7 @@
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160">
<el-table-column align="center" label="客户名称" fixed="left" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -74,14 +74,14 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column align="center" label="锁定状态" prop="lockStatus">
<el-table-column align="center" label="锁定状态" prop="lockStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.lockStatus" />
</template>
</el-table-column>
<el-table-column align="center" label="成交状态" prop="dealStatus">
<el-table-column align="center" label="成交状态" prop="dealStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" />
</template>
@ -92,29 +92,29 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
<el-table-column label="地址" align="center" prop="detailAddress" width="180" />
<el-table-column align="center" label="距离进入公海天数" prop="poolDay" width="140">
<template #default="scope"> {{ scope.row.poolDay }} </template>
</el-table-column>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -30,14 +30,14 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column align="center" fixed="left" label="回款编号" prop="no" width="180">
<el-table-column align="center" fixed="left" label="回款编号" prop="no" width="180" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.no }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="客户名称" prop="customerName" width="120">
<el-table-column align="center" label="客户名称" prop="customerName" width="120" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -48,7 +48,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="合同编号" prop="contractNo" width="180">
<el-table-column align="center" label="合同编号" prop="contractNo" width="180" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -65,7 +65,7 @@
label="回款日期"
prop="returnTime"
width="150px"
/>
sortable />
<el-table-column
align="center"
label="回款金额(元)"
@ -73,7 +73,7 @@
width="140"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column align="center" label="回款方式" prop="returnType" width="130px">
<el-table-column align="center" label="回款方式" prop="returnType" width="130px" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
</template>
@ -86,24 +86,24 @@
width="140"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="120" />
<el-table-column align="center" fixed="right" label="回款状态" prop="auditStatus" width="120">
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="120" sortable />
<el-table-column align="center" fixed="right" label="回款状态" prop="auditStatus" width="120" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
</template>

@ -30,7 +30,7 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="150">
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="150" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -41,7 +41,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="合同编号" prop="contractNo" width="200px" />
<el-table-column align="center" label="合同编号" prop="contractNo" width="200px" sortable />
<el-table-column align="center" label="期数" prop="period">
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
@ -62,7 +62,7 @@
label="计划回款日期"
prop="returnTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="提前几天提醒" prop="remindDays" width="150" />
<el-table-column
align="center"
@ -70,14 +70,14 @@
prop="remindTime"
width="180px"
:formatter="dateFormatter2"
/>
<el-table-column align="center" label="回款方式" prop="returnType" width="130px">
sortable />
<el-table-column align="center" label="回款方式" prop="returnType" width="130px" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
</template>
</el-table-column>
<el-table-column align="center" label="备注" prop="remark" />
<el-table-column label="负责人" prop="ownerUserName" width="120" />
<el-table-column label="负责人" prop="ownerUserName" width="120" sortable />
<el-table-column
align="center"
label="实际回款金额(元)"
@ -97,7 +97,7 @@
prop="receivable.returnTime"
width="180px"
:formatter="dateFormatter2"
/>
sortable />
<el-table-column
align="center"
label="实际回款金额(元)"
@ -117,15 +117,15 @@
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
<el-table-column align="center" fixed="right" label="操作" width="180px">
<template #default="scope">
<el-button

@ -31,7 +31,7 @@
:show-overflow-tooltip="true"
>
<el-table-column type="selection" width="55" v-if="queryParams.contactId" />
<el-table-column label="商机名称" fixed="left" align="center" prop="name">
<el-table-column label="商机名称" fixed="left" align="center" prop="name" sortable>
<template #default="scope">
<el-link type="primary" :underline="false" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -44,9 +44,9 @@
prop="price"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="客户名称" align="center" prop="customerName" />
<el-table-column label="商机组" align="center" prop="statusTypeName" />
<el-table-column label="商机阶段" align="center" prop="statusName" />
<el-table-column label="客户名称" align="center" prop="customerName" sortable />
<el-table-column label="商机组" align="center" prop="statusTypeName" sortable />
<el-table-column label="商机阶段" align="center" prop="statusName" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -38,7 +38,7 @@
:show-overflow-tooltip="true"
>
<el-table-column type="selection" width="55" />
<el-table-column label="商机名称" fixed="left" align="center" prop="name">
<el-table-column label="商机名称" fixed="left" align="center" prop="name" sortable>
<template #default="scope">
<el-link type="primary" :underline="false" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -51,9 +51,9 @@
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="客户名称" align="center" prop="customerName" />
<el-table-column label="商机组" align="center" prop="statusTypeName" />
<el-table-column label="商机阶段" align="center" prop="statusName" />
<el-table-column label="客户名称" align="center" prop="customerName" sortable />
<el-table-column label="商机组" align="center" prop="statusTypeName" sortable />
<el-table-column label="商机阶段" align="center" prop="statusName" sortable />
</el-table>
<!-- 分页 -->
<Pagination

@ -7,12 +7,12 @@
fixed="left"
prop="productName"
min-width="160"
>
sortable>
<template #default="scope">
{{ scope.row.productName }}
</template>
</el-table-column>
<el-table-column label="产品条码" align="center" prop="productNo" min-width="120" />
<el-table-column label="产品条码" align="center" prop="productNo" min-width="120" sortable />
<el-table-column align="center" label="产品单位" prop="productUnit" min-width="160">
<template #default="{ row }">
<dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />

@ -55,14 +55,14 @@
<el-tab-pane label="下属负责的" name="3" />
</el-tabs>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" fixed="left" label="商机名称" prop="name" width="160">
<el-table-column align="center" fixed="left" label="商机名称" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="120">
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="120" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -86,7 +86,7 @@
label="预计成交日期"
prop="dealTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column
:formatter="dateFormatter"
@ -94,45 +94,45 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
sortable />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
<el-table-column
align="center"
fixed="right"
label="商机状态组"
prop="statusTypeName"
width="140"
/>
sortable />
<el-table-column
align="center"
fixed="right"
label="商机阶段"
prop="statusName"
width="120"
/>
sortable />
<el-table-column align="center" fixed="right" label="操作" width="130px">
<template #default="scope">
<el-button

@ -36,7 +36,7 @@
<el-text v-else></el-text>
</template>
</el-table-column>
<el-table-column align="center" label="阶段名称" width="160" prop="name">
<el-table-column align="center" label="阶段名称" width="160" prop="name" sortable>
<template #default="{ row }">
<el-input v-if="!row.endStatus" v-model="row.name" placeholder="请输入状态名称" />
<el-text v-else>{{ row.name }}</el-text>

@ -25,8 +25,8 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="状态组名" align="center" prop="name" />
<el-table-column label="应用部门" align="center" prop="deptNames">
<el-table-column label="状态组名" align="center" prop="name" sortable />
<el-table-column label="应用部门" align="center" prop="deptNames" sortable>
<template #default="scope">
<span v-if="scope.row?.deptNames?.length > 0">
{{ scope.row.deptNames.join(' ') }}
@ -41,7 +41,7 @@
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button

@ -69,7 +69,7 @@
<el-tab-pane label="下属负责的" name="3" />
</el-tabs>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="160">
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -101,7 +101,7 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column
label="最后跟进时间"
@ -109,25 +109,25 @@
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" sortable />
<el-table-column
label="更新时间"
align="center"
prop="updateTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" sortable />
<el-table-column label="操作" align="center" min-width="110" fixed="right">
<template #default="scope">
<el-button

@ -33,7 +33,7 @@
:stripe="true"
>
<el-table-column v-if="queryParams.businessId" type="selection" width="55" />
<el-table-column align="center" fixed="left" label="姓名" prop="name">
<el-table-column align="center" fixed="left" label="姓名" prop="name" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -42,7 +42,7 @@
</el-table-column>
<el-table-column align="center" label="手机号" prop="mobile" />
<el-table-column align="center" label="职位" prop="post" />
<el-table-column align="center" label="直属上级" prop="parentName" />
<el-table-column align="center" label="直属上级" prop="parentName" sortable />
<el-table-column align="center" label="是否关键决策人" min-width="100" prop="master">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.master" />

@ -45,7 +45,7 @@
:stripe="true"
>
<el-table-column type="selection" width="55" />
<el-table-column align="center" fixed="left" label="姓名" prop="name">
<el-table-column align="center" fixed="left" label="姓名" prop="name" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
@ -54,7 +54,7 @@
</el-table-column>
<el-table-column align="center" label="手机号" prop="mobile" />
<el-table-column align="center" label="职位" prop="post" />
<el-table-column align="center" label="直属上级" prop="parentName" />
<el-table-column align="center" label="直属上级" prop="parentName" sortable />
<el-table-column align="center" label="是否关键决策人" min-width="100" prop="master">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.master" />

@ -109,14 +109,14 @@
<el-tab-pane label="下属负责的" name="3" />
</el-tabs>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" fixed="left" label="联系人姓名" prop="name" width="160">
<el-table-column align="center" fixed="left" label="联系人姓名" prop="name" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="120">
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="120" sortable>
<template #default="scope">
<el-link
:underline="false"
@ -137,7 +137,7 @@
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.master" />
</template>
</el-table-column>
<el-table-column align="center" label="直属上级" prop="parentName" width="160">
<el-table-column align="center" label="直属上级" prop="parentName" width="160" sortable>
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.parentId)">
{{ scope.row.parentName }}
@ -151,7 +151,7 @@
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
sortable />
<el-table-column align="center" label="性别" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
@ -164,24 +164,24 @@
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" />
sortable />
<el-table-column align="center" label="负责人" prop="ownerUserName" width="120" sortable />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="更新时间"
prop="updateTime"
width="180px"
/>
sortable />
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="创建人" prop="creatorName" width="120" />
sortable />
<el-table-column align="center" label="创建人" prop="creatorName" width="120" sortable />
<el-table-column align="center" fixed="right" label="操作" width="200">
<template #default="scope">
<el-button

@ -10,15 +10,15 @@
<!-- 列表 -->
<ContentWrap class="mt-10px">
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="合同名称" fixed="left" align="center" prop="name">
<el-table-column label="合同名称" fixed="left" align="center" prop="name" sortable>
<template #default="scope">
<el-link type="primary" :underline="false" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column label="合同编号" align="center" prop="no" />
<el-table-column label="客户名称" align="center" prop="customerName" />
<el-table-column label="合同编号" align="center" prop="no" sortable />
<el-table-column label="客户名称" align="center" prop="customerName" sortable />
<el-table-column
label="合同金额(元)"
align="center"
@ -31,15 +31,15 @@
prop="startTime"
:formatter="dateFormatter"
width="180px"
/>
sortable />
<el-table-column
label="结束时间"
align="center"
prop="endTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column align="center" label="状态" prop="auditStatus">
sortable />
<el-table-column align="center" label="状态" prop="auditStatus" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
</template>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save