Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
60deb39de8 | |
|
749b24a17f |
|
@ -1,48 +1,11 @@
|
||||||
import antfu from '@antfu/eslint-config'
|
import js from "@eslint/js";
|
||||||
|
import globals from "globals";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
import pluginReact from "eslint-plugin-react";
|
||||||
|
import { defineConfig } from "eslint/config";
|
||||||
|
|
||||||
// https://github.com/antfu/eslint-config
|
export default defineConfig([
|
||||||
export default antfu(
|
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } },
|
||||||
{
|
tseslint.configs.recommended,
|
||||||
vue: {
|
pluginReact.configs.flat.recommended,
|
||||||
overrides: {
|
]);
|
||||||
'vue/block-order': ['error', {
|
|
||||||
order: [['script', 'template'], 'style'],
|
|
||||||
}], // 强制组件顶级元素的顺序
|
|
||||||
'vue/define-macros-order': ['error', {
|
|
||||||
order: ['defineOptions', 'defineModel', 'defineProps', 'defineEmits', 'defineSlots'],
|
|
||||||
defineExposeLast: true,
|
|
||||||
}], // 强制执行定义限制和定义弹出编译器宏的顺序
|
|
||||||
'vue/singleline-html-element-content-newline': 'off', // 要求在单行元素的内容前后换行
|
|
||||||
'vue/html-self-closing': ['off', {
|
|
||||||
html: {
|
|
||||||
void: 'never',
|
|
||||||
normal: 'always',
|
|
||||||
component: 'never',
|
|
||||||
},
|
|
||||||
}], // 强制自结束样式
|
|
||||||
'vue/custom-event-name-casing': ['error', 'kebab-case'], // 对自定义事件名称强制使用特定大小写
|
|
||||||
},
|
|
||||||
},
|
|
||||||
typescript: true,
|
|
||||||
ignores: [
|
|
||||||
'**/*.md',
|
|
||||||
'.github',
|
|
||||||
'.image',
|
|
||||||
'src/types/shims-vue.d.ts',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rules: {
|
|
||||||
'curly': ['off', 'all'], // 对所有控制语句强制使用一致的大括号样式
|
|
||||||
'no-new': 'off', // 不允许在赋值或比较之外使用 new 运算符
|
|
||||||
'no-console': 'off', // 允许使用 console
|
|
||||||
'style/arrow-parens': ['error', 'always'], // 箭头函数参数需要括号
|
|
||||||
'style/brace-style': ['error', '1tbs', { allowSingleLine: true }], // 对块执行一致的大括号样式
|
|
||||||
'regexp/no-unused-capturing-group': 'off',
|
|
||||||
'regexp/no-super-linear-backtracking': 'off',
|
|
||||||
'node/prefer-global/process': 'off',
|
|
||||||
'antfu/top-level-function': 'off',
|
|
||||||
'antfu/if-newline': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
|
@ -58,21 +58,27 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^2.16.3",
|
"@antfu/eslint-config": "^2.16.3",
|
||||||
"@arco-design/web-vue": "^2.57.0",
|
"@arco-design/web-vue": "^2.57.0",
|
||||||
|
"@eslint/js": "^9.32.0",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.2.5",
|
"@types/node": "^20.2.5",
|
||||||
"@types/query-string": "^6.3.0",
|
"@types/query-string": "^6.3.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.39.0",
|
||||||
|
"@typescript-eslint/parser": "^8.39.0",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"boxen": "^7.1.1",
|
"boxen": "^7.1.1",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.32.0",
|
||||||
|
"eslint-plugin-react": "^7.37.5",
|
||||||
|
"globals": "^16.3.0",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.0.0",
|
"less-loader": "^11.0.0",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"sass": "^1.62.1",
|
"sass": "^1.62.1",
|
||||||
"sass-loader": "^13.2.2",
|
"sass-loader": "^13.2.2",
|
||||||
"typescript": "~5.0.4",
|
"typescript": "~5.0.4",
|
||||||
|
"typescript-eslint": "^8.39.0",
|
||||||
"unplugin-auto-import": "^0.16.4",
|
"unplugin-auto-import": "^0.16.4",
|
||||||
"unplugin-vue-components": "^0.25.1",
|
"unplugin-vue-components": "^0.25.1",
|
||||||
"vite": "^5.1.5",
|
"vite": "^5.1.5",
|
||||||
|
@ -205,6 +211,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@antfu/eslint-config/node_modules/globals": {
|
||||||
|
"version": "15.15.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz",
|
||||||
|
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@antfu/install-pkg": {
|
"node_modules/@antfu/install-pkg": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz",
|
||||||
|
@ -719,7 +737,6 @@
|
||||||
},
|
},
|
||||||
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
|
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"dev": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3074,16 +3091,16 @@
|
||||||
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
|
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.0.tgz",
|
||||||
"integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==",
|
"integrity": "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.38.0",
|
"@typescript-eslint/scope-manager": "8.39.0",
|
||||||
"@typescript-eslint/type-utils": "8.38.0",
|
"@typescript-eslint/type-utils": "8.39.0",
|
||||||
"@typescript-eslint/utils": "8.38.0",
|
"@typescript-eslint/utils": "8.39.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.38.0",
|
"@typescript-eslint/visitor-keys": "8.39.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
|
@ -3097,9 +3114,9 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.38.0",
|
"@typescript-eslint/parser": "^8.39.0",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
|
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
|
||||||
|
@ -3112,15 +3129,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.39.0.tgz",
|
||||||
"integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==",
|
"integrity": "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.38.0",
|
"@typescript-eslint/scope-manager": "8.39.0",
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.38.0",
|
"@typescript-eslint/typescript-estree": "8.39.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.38.0",
|
"@typescript-eslint/visitor-keys": "8.39.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3132,17 +3149,17 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
"node_modules/@typescript-eslint/project-service": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.39.0.tgz",
|
||||||
"integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==",
|
"integrity": "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.38.0",
|
"@typescript-eslint/tsconfig-utils": "^8.39.0",
|
||||||
"@typescript-eslint/types": "^8.38.0",
|
"@typescript-eslint/types": "^8.39.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3153,17 +3170,17 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.39.0.tgz",
|
||||||
"integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==",
|
"integrity": "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.38.0"
|
"@typescript-eslint/visitor-keys": "8.39.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3174,9 +3191,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.0.tgz",
|
||||||
"integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==",
|
"integrity": "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3186,18 +3203,18 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.39.0.tgz",
|
||||||
"integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==",
|
"integrity": "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.38.0",
|
"@typescript-eslint/typescript-estree": "8.39.0",
|
||||||
"@typescript-eslint/utils": "8.38.0",
|
"@typescript-eslint/utils": "8.39.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
|
@ -3210,13 +3227,13 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.39.0.tgz",
|
||||||
"integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==",
|
"integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3227,15 +3244,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.0.tgz",
|
||||||
"integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==",
|
"integrity": "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.38.0",
|
"@typescript-eslint/project-service": "8.39.0",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.38.0",
|
"@typescript-eslint/tsconfig-utils": "8.39.0",
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.38.0",
|
"@typescript-eslint/visitor-keys": "8.39.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
|
@ -3251,19 +3268,19 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.39.0.tgz",
|
||||||
"integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==",
|
"integrity": "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.38.0",
|
"@typescript-eslint/scope-manager": "8.39.0",
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.38.0"
|
"@typescript-eslint/typescript-estree": "8.39.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3274,16 +3291,16 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.38.0",
|
"version": "8.39.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.0.tgz",
|
||||||
"integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==",
|
"integrity": "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.38.0",
|
"@typescript-eslint/types": "8.39.0",
|
||||||
"eslint-visitor-keys": "^4.2.1"
|
"eslint-visitor-keys": "^4.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -4465,6 +4482,28 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/array-includes": {
|
||||||
|
"version": "3.1.9",
|
||||||
|
"resolved": "https://registry.npmmirror.com/array-includes/-/array-includes-3.1.9.tgz",
|
||||||
|
"integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.4",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.24.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.3.0",
|
||||||
|
"is-string": "^1.1.1",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/array-unique": {
|
"node_modules/array-unique": {
|
||||||
"version": "0.3.2",
|
"version": "0.3.2",
|
||||||
"resolved": "https://registry.npmmirror.com/array-unique/-/array-unique-0.3.2.tgz",
|
"resolved": "https://registry.npmmirror.com/array-unique/-/array-unique-0.3.2.tgz",
|
||||||
|
@ -4474,6 +4513,78 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/array.prototype.findlast": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
|
||||||
|
"integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.0.0",
|
||||||
|
"es-shim-unscopables": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/array.prototype.flat": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.5",
|
||||||
|
"es-shim-unscopables": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/array.prototype.flatmap": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.5",
|
||||||
|
"es-shim-unscopables": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/array.prototype.tosorted": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.3",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-shim-unscopables": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/arraybuffer.prototype.slice": {
|
"node_modules/arraybuffer.prototype.slice": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
|
"resolved": "https://registry.npmmirror.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
|
||||||
|
@ -5901,6 +6012,18 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/doctrine": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dom-serializer": {
|
"node_modules/dom-serializer": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-0.2.2.tgz",
|
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-0.2.2.tgz",
|
||||||
|
@ -6192,6 +6315,33 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-iterator-helpers": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.3",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.6",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-set-tostringtag": "^2.0.3",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"globalthis": "^1.0.4",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-property-descriptors": "^1.0.2",
|
||||||
|
"has-proto": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"internal-slot": "^1.1.0",
|
||||||
|
"iterator.prototype": "^1.1.4",
|
||||||
|
"safe-array-concat": "^1.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-module-lexer": {
|
"node_modules/es-module-lexer": {
|
||||||
"version": "0.9.3",
|
"version": "0.9.3",
|
||||||
"resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
|
"resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
|
||||||
|
@ -6223,6 +6373,18 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-shim-unscopables": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-to-primitive": {
|
"node_modules/es-to-primitive": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
|
||||||
|
@ -7025,6 +7187,18 @@
|
||||||
"eslint": ">=8.23.0"
|
"eslint": ">=8.23.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-n/node_modules/globals": {
|
||||||
|
"version": "15.15.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz",
|
||||||
|
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-no-only-tests": {
|
"node_modules/eslint-plugin-no-only-tests": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz",
|
||||||
|
@ -7070,6 +7244,86 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-react": {
|
||||||
|
"version": "7.37.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
|
||||||
|
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"array-includes": "^3.1.8",
|
||||||
|
"array.prototype.findlast": "^1.2.5",
|
||||||
|
"array.prototype.flatmap": "^1.3.3",
|
||||||
|
"array.prototype.tosorted": "^1.1.4",
|
||||||
|
"doctrine": "^2.1.0",
|
||||||
|
"es-iterator-helpers": "^1.2.1",
|
||||||
|
"estraverse": "^5.3.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"object.entries": "^1.1.9",
|
||||||
|
"object.fromentries": "^2.0.8",
|
||||||
|
"object.values": "^1.2.1",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
|
"resolve": "^2.0.0-next.5",
|
||||||
|
"semver": "^6.3.1",
|
||||||
|
"string.prototype.matchall": "^4.0.12",
|
||||||
|
"string.prototype.repeat": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-react/node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-react/node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-react/node_modules/resolve": {
|
||||||
|
"version": "2.0.0-next.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/resolve/-/resolve-2.0.0-next.5.tgz",
|
||||||
|
"integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-core-module": "^2.13.0",
|
||||||
|
"path-parse": "^1.0.7",
|
||||||
|
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"resolve": "bin/resolve"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-react/node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-regexp": {
|
"node_modules/eslint-plugin-regexp": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz",
|
"resolved": "https://registry.npmmirror.com/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz",
|
||||||
|
@ -7160,6 +7414,18 @@
|
||||||
"eslint": ">=8.56.0"
|
"eslint": ">=8.56.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-unicorn/node_modules/globals": {
|
||||||
|
"version": "15.15.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz",
|
||||||
|
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-unused-imports": {
|
"node_modules/eslint-plugin-unused-imports": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz",
|
"resolved": "https://registry.npmmirror.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz",
|
||||||
|
@ -8127,9 +8393,9 @@
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "15.15.0",
|
"version": "16.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz",
|
"resolved": "https://registry.npmmirror.com/globals/-/globals-16.3.0.tgz",
|
||||||
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
|
"integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
|
@ -9180,6 +9446,23 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/iterator.prototype": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"define-data-property": "^1.1.4",
|
||||||
|
"es-object-atoms": "^1.0.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"get-proto": "^1.0.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"set-function-name": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jest-worker": {
|
"node_modules/jest-worker": {
|
||||||
"version": "27.5.1",
|
"version": "27.5.1",
|
||||||
"resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz",
|
"resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||||
|
@ -9341,6 +9624,21 @@
|
||||||
"graceful-fs": "^4.1.6"
|
"graceful-fs": "^4.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsx-ast-utils": {
|
||||||
|
"version": "3.3.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||||
|
"integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"array-includes": "^3.1.6",
|
||||||
|
"array.prototype.flat": "^1.3.1",
|
||||||
|
"object.assign": "^4.1.4",
|
||||||
|
"object.values": "^1.1.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
|
||||||
|
@ -9697,6 +9995,18 @@
|
||||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"loose-envify": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lower-case": {
|
"node_modules/lower-case": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz",
|
||||||
|
@ -10460,6 +10770,39 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object.entries": {
|
||||||
|
"version": "1.1.9",
|
||||||
|
"resolved": "https://registry.npmmirror.com/object.entries/-/object.entries-1.1.9.tgz",
|
||||||
|
"integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.4",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-object-atoms": "^1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object.fromentries": {
|
||||||
|
"version": "2.0.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/object.fromentries/-/object.fromentries-2.0.8.tgz",
|
||||||
|
"integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.2",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object.pick": {
|
"node_modules/object.pick": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/object.pick/-/object.pick-1.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/object.pick/-/object.pick-1.3.0.tgz",
|
||||||
|
@ -10481,6 +10824,24 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object.values": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/object.values/-/object.values-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.3",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/on-finished": {
|
"node_modules/on-finished": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
|
@ -11040,6 +11401,17 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prop-types": {
|
||||||
|
"version": "15.8.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"react-is": "^16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prosemirror-changeset": {
|
"node_modules/prosemirror-changeset": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmmirror.com/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz",
|
"resolved": "https://registry.npmmirror.com/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz",
|
||||||
|
@ -11316,6 +11688,12 @@
|
||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-is": {
|
||||||
|
"version": "16.13.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/read-pkg": {
|
"node_modules/read-pkg": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||||
|
@ -12706,6 +13084,43 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string.prototype.matchall": {
|
||||||
|
"version": "4.0.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
|
||||||
|
"integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.8",
|
||||||
|
"call-bound": "^1.0.3",
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"es-abstract": "^1.23.6",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.0.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"internal-slot": "^1.1.0",
|
||||||
|
"regexp.prototype.flags": "^1.5.3",
|
||||||
|
"set-function-name": "^2.0.2",
|
||||||
|
"side-channel": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string.prototype.repeat": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"define-properties": "^1.1.3",
|
||||||
|
"es-abstract": "^1.17.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string.prototype.trim": {
|
"node_modules/string.prototype.trim": {
|
||||||
"version": "1.2.10",
|
"version": "1.2.10",
|
||||||
"resolved": "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
|
"resolved": "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
|
||||||
|
@ -13610,6 +14025,29 @@
|
||||||
"node": ">=12.20"
|
"node": ">=12.20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typescript-eslint": {
|
||||||
|
"version": "8.39.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.39.0.tgz",
|
||||||
|
"integrity": "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "8.39.0",
|
||||||
|
"@typescript-eslint/parser": "8.39.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "8.39.0",
|
||||||
|
"@typescript-eslint/utils": "8.39.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
|
"typescript": ">=4.8.4 <6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uc.micro": {
|
"node_modules/uc.micro": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||||
|
|
|
@ -64,21 +64,27 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^2.16.3",
|
"@antfu/eslint-config": "^2.16.3",
|
||||||
"@arco-design/web-vue": "^2.57.0",
|
"@arco-design/web-vue": "^2.57.0",
|
||||||
|
"@eslint/js": "^9.32.0",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.2.5",
|
"@types/node": "^20.2.5",
|
||||||
"@types/query-string": "^6.3.0",
|
"@types/query-string": "^6.3.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.39.0",
|
||||||
|
"@typescript-eslint/parser": "^8.39.0",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"boxen": "^7.1.1",
|
"boxen": "^7.1.1",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.32.0",
|
||||||
|
"eslint-plugin-react": "^7.37.5",
|
||||||
|
"globals": "^16.3.0",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.0.0",
|
"less-loader": "^11.0.0",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"sass": "^1.62.1",
|
"sass": "^1.62.1",
|
||||||
"sass-loader": "^13.2.2",
|
"sass-loader": "^13.2.2",
|
||||||
"typescript": "~5.0.4",
|
"typescript": "~5.0.4",
|
||||||
|
"typescript-eslint": "^8.39.0",
|
||||||
"unplugin-auto-import": "^0.16.4",
|
"unplugin-auto-import": "^0.16.4",
|
||||||
"unplugin-vue-components": "^0.25.1",
|
"unplugin-vue-components": "^0.25.1",
|
||||||
"vite": "^5.1.5",
|
"vite": "^5.1.5",
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import http from '@/utils/http'
|
||||||
|
import type { EquipmentListReq, EquipmentReq, EquipmentResp } from './type'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备采购管理API
|
||||||
|
*/
|
||||||
|
export const equipmentProcurementApi = {
|
||||||
|
/**
|
||||||
|
* 分页查询设备采购记录
|
||||||
|
*/
|
||||||
|
page: (params: EquipmentListReq) => {
|
||||||
|
console.log('🔍 API - equipmentProcurementApi.page 被调用')
|
||||||
|
console.log('🔍 API - 接收到的参数:', params)
|
||||||
|
console.log('🔍 API - 参数类型:', typeof params)
|
||||||
|
console.log('🔍 API - 参数的键值对:')
|
||||||
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
|
console.log(` ${key}: ${value} (${typeof value})`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 确保参数格式正确
|
||||||
|
const requestParams = {
|
||||||
|
...params,
|
||||||
|
// 确保分页参数存在
|
||||||
|
page: params.page || 1,
|
||||||
|
pageSize: params.pageSize || 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 API - 最终请求参数:', requestParams)
|
||||||
|
console.log('🔍 API - 准备发送GET请求到 /equipment/procurement/page')
|
||||||
|
console.log('🔍 API - 请求参数序列化前:', requestParams)
|
||||||
|
|
||||||
|
// 手动序列化参数进行调试(使用URLSearchParams)
|
||||||
|
const searchParams = new URLSearchParams()
|
||||||
|
Object.entries(requestParams).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined && value !== null && value !== '') {
|
||||||
|
searchParams.append(key, String(value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('🔍 API - 手动序列化后的参数:', searchParams.toString())
|
||||||
|
|
||||||
|
// 参考设备模块的调用方式,直接将参数作为第二个参数传递
|
||||||
|
return http.get<ApiRes<PageRes<EquipmentResp>>>('/equipment/procurement/page', requestParams)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试参数传递 - 使用API文档中的参数格式
|
||||||
|
*/
|
||||||
|
testPage: () => {
|
||||||
|
console.log('🧪 API - 测试参数传递')
|
||||||
|
|
||||||
|
// 使用API文档中的参数格式进行测试
|
||||||
|
const testParams = {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
equipmentName: '测试设备',
|
||||||
|
supplierName: '测试供应商',
|
||||||
|
quantity: 10,
|
||||||
|
unitPrice: 100.50,
|
||||||
|
totalPrice: 1005.00,
|
||||||
|
accountNumber: 'TEST001',
|
||||||
|
brand: '测试品牌',
|
||||||
|
locationStatus: 'spare',
|
||||||
|
physicalLocation: '测试位置',
|
||||||
|
purchaseOrder: 'PO001',
|
||||||
|
inventoryBasis: '测试依据',
|
||||||
|
dynamicRecord: '测试记录'
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🧪 API - 测试参数:', testParams)
|
||||||
|
|
||||||
|
return http.get<ApiRes<PageRes<EquipmentResp>>>('/equipment/procurement/page', testParams)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设备采购记录
|
||||||
|
*/
|
||||||
|
add: (data: EquipmentReq) => {
|
||||||
|
return http.post<ApiRes<null>>('/equipment/procurement', data)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改设备采购记录
|
||||||
|
*/
|
||||||
|
update: (equipmentId: string, data: EquipmentReq) => {
|
||||||
|
return http.put<ApiRes<null>>(`/equipment/procurement/${equipmentId}`, data)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备采购记录
|
||||||
|
*/
|
||||||
|
delete: (equipmentId: string) => {
|
||||||
|
return http.del<ApiRes<null>>(`/equipment/procurement/${equipmentId}`)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备采购记录详情
|
||||||
|
*/
|
||||||
|
detail: (equipmentId: string) => {
|
||||||
|
return http.get<ApiRes<EquipmentResp>>(`/equipment/procurement/detail/${equipmentId}`)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取采购统计信息
|
||||||
|
*/
|
||||||
|
getStats: () => {
|
||||||
|
return http.get<ApiRes<unknown>>('/equipment/procurement/stats')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除设备采购记录
|
||||||
|
*/
|
||||||
|
batchDelete: (equipmentIds: string[]) => {
|
||||||
|
return http.del<ApiRes<null>>('/equipment/procurement/batch', { data: equipmentIds })
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出设备采购记录
|
||||||
|
*/
|
||||||
|
export: (params: EquipmentListReq) => {
|
||||||
|
return http.get<Blob>('/equipment/procurement/export', {
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,10 @@
|
||||||
* 设备列表查询请求
|
* 设备列表查询请求
|
||||||
*/
|
*/
|
||||||
export interface EquipmentListReq {
|
export interface EquipmentListReq {
|
||||||
|
/** 最低价格 */
|
||||||
|
minPrice?: number
|
||||||
|
/** 最高价格 */
|
||||||
|
maxPrice?: number
|
||||||
/** 设备名称 */
|
/** 设备名称 */
|
||||||
equipmentName?: string
|
equipmentName?: string
|
||||||
/** 设备类型 */
|
/** 设备类型 */
|
||||||
|
@ -26,6 +30,44 @@ export interface EquipmentListReq {
|
||||||
projectId?: string
|
projectId?: string
|
||||||
/** 使用人ID */
|
/** 使用人ID */
|
||||||
userId?: string
|
userId?: string
|
||||||
|
/** 设备型号 */
|
||||||
|
equipmentModel?: string
|
||||||
|
/** 配置规格/参数 */
|
||||||
|
specification?: string
|
||||||
|
/** 设备当前物理位置 */
|
||||||
|
physicalLocation?: string
|
||||||
|
/** 供应商名称 */
|
||||||
|
supplierName?: string
|
||||||
|
/** 采购订单号 */
|
||||||
|
purchaseOrder?: string
|
||||||
|
/** 维护人员 */
|
||||||
|
maintenancePerson?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
|
/** 资产备注 */
|
||||||
|
assetRemark?: string
|
||||||
|
/** 采购时间开始 */
|
||||||
|
purchaseTimeStart?: string
|
||||||
|
/** 采购时间结束 */
|
||||||
|
purchaseTimeEnd?: string
|
||||||
|
/** 入库时间开始 */
|
||||||
|
inStockTimeStart?: string
|
||||||
|
/** 入库时间结束 */
|
||||||
|
inStockTimeEnd?: string
|
||||||
|
/** 启用时间开始 */
|
||||||
|
activationTimeStart?: string
|
||||||
|
/** 启用时间结束 */
|
||||||
|
activationTimeEnd?: string
|
||||||
/** 当前页码 */
|
/** 当前页码 */
|
||||||
pageNum?: number
|
pageNum?: number
|
||||||
/** 每页大小 */
|
/** 每页大小 */
|
||||||
|
@ -34,6 +76,10 @@ export interface EquipmentListReq {
|
||||||
orderBy?: string
|
orderBy?: string
|
||||||
/** 排序方向 */
|
/** 排序方向 */
|
||||||
orderDirection?: string
|
orderDirection?: string
|
||||||
|
/** 页码 */
|
||||||
|
page?: number
|
||||||
|
/** 库存条码 */
|
||||||
|
inventoryBarcode?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,6 +182,18 @@ export interface EquipmentResp {
|
||||||
createTime?: string
|
createTime?: string
|
||||||
/** 更新时间 */
|
/** 更新时间 */
|
||||||
updateTime?: string
|
updateTime?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,4 +262,16 @@ export interface EquipmentReq {
|
||||||
inventoryBarcode?: string
|
inventoryBarcode?: string
|
||||||
/** 资产备注 */
|
/** 资产备注 */
|
||||||
assetRemark?: string
|
assetRemark?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: '/asset-management/device-management/procurement',
|
path: '/asset-management/device-management/procurement',
|
||||||
name: 'DeviceProcurement',
|
name: 'DeviceProcurement',
|
||||||
component: () => import('@/views/system-resource/device-management/index.vue'),
|
component: () => import('@/views/system-resource/device-management/procurement/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '设备采购',
|
title: '设备采购',
|
||||||
icon: 'shopping-cart',
|
icon: 'shopping-cart',
|
||||||
|
|
|
@ -83,7 +83,7 @@ const storeSetup = () => {
|
||||||
// 合并路由
|
// 合并路由
|
||||||
const setRoutes = (data: RouteRecordRaw[]) => {
|
const setRoutes = (data: RouteRecordRaw[]) => {
|
||||||
// 合并路由并排序
|
// 合并路由并排序
|
||||||
routes.value = [...constantRoutes, ...systemRoutes].concat(data)
|
routes.value = [...constantRoutes, ...systemRoutes, ...data]
|
||||||
.sort((a, b) => (a.meta?.sort ?? 0) - (b.meta?.sort ?? 0))
|
.sort((a, b) => (a.meta?.sort ?? 0) - (b.meta?.sort ?? 0))
|
||||||
asyncRoutes.value = data
|
asyncRoutes.value = data
|
||||||
}
|
}
|
||||||
|
@ -181,8 +181,10 @@ const storeSetup = () => {
|
||||||
}]
|
}]
|
||||||
// 使用已转换的数据生成路由
|
// 使用已转换的数据生成路由
|
||||||
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
||||||
const flatRoutes = flatMultiLevelRoutes(cloneDeep(asyncRoutes))
|
// 合并路由,避免重复
|
||||||
setRoutes(asyncRoutes)
|
const allRoutes = [...asyncRoutes]
|
||||||
|
const flatRoutes = flatMultiLevelRoutes(cloneDeep(allRoutes))
|
||||||
|
setRoutes(allRoutes)
|
||||||
return flatRoutes
|
return flatRoutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化日期时间
|
||||||
|
* @param date 日期
|
||||||
|
* @param format 格式,默认为 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
* @returns 格式化后的日期字符串
|
||||||
|
*/
|
||||||
|
export function formatDateTime(date: string | Date | null | undefined, format = 'YYYY-MM-DD HH:mm:ss'): string {
|
||||||
|
if (!date) return '-'
|
||||||
|
return dayjs(date).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化日期
|
||||||
|
* @param date 日期
|
||||||
|
* @param format 格式,默认为 'YYYY-MM-DD'
|
||||||
|
* @returns 格式化后的日期字符串
|
||||||
|
*/
|
||||||
|
export function formatDate(date: string | Date | null | undefined, format = 'YYYY-MM-DD'): string {
|
||||||
|
if (!date) return '-'
|
||||||
|
return dayjs(date).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化时间
|
||||||
|
* @param date 日期
|
||||||
|
* @param format 格式,默认为 'HH:mm:ss'
|
||||||
|
* @returns 格式化后的时间字符串
|
||||||
|
*/
|
||||||
|
export function formatTime(date: string | Date | null | undefined, format = 'HH:mm:ss'): string {
|
||||||
|
if (!date) return '-'
|
||||||
|
return dayjs(date).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取相对时间
|
||||||
|
* @param date 日期
|
||||||
|
* @returns 相对时间字符串
|
||||||
|
*/
|
||||||
|
export function getRelativeTime(date: string | Date | null | undefined): string {
|
||||||
|
if (!date) return '-'
|
||||||
|
return dayjs(date).fromNow()
|
||||||
|
}
|
|
@ -293,22 +293,32 @@
|
||||||
|
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="采购价格" field="purchasePrice">
|
<a-form-item label="次户号" field="accountNumber">
|
||||||
<a-input-number
|
<a-input
|
||||||
v-model="formData.purchasePrice"
|
v-model="formData.accountNumber"
|
||||||
placeholder="请输入采购价格"
|
placeholder="请输入次户号"
|
||||||
:disabled="isView"
|
:disabled="isView"
|
||||||
style="width: 100%"
|
show-word-limit
|
||||||
:precision="2"
|
:max-length="50"
|
||||||
:min="0"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="8">
|
||||||
<a-form-item label="当前净值" field="currentNetValue">
|
<a-form-item label="数量" field="quantity">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="formData.currentNetValue"
|
v-model="formData.quantity"
|
||||||
placeholder="请输入当前净值"
|
placeholder="请输入数量"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
:min="1"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="单价" field="unitPrice">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.unitPrice"
|
||||||
|
placeholder="请输入单价"
|
||||||
:disabled="isView"
|
:disabled="isView"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
|
@ -320,10 +330,10 @@
|
||||||
|
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="残值" field="salvageValue">
|
<a-form-item label="总价" field="totalPrice">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="formData.salvageValue"
|
v-model="formData.totalPrice"
|
||||||
placeholder="请输入残值"
|
placeholder="请输入总价"
|
||||||
:disabled="isView"
|
:disabled="isView"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
|
@ -332,14 +342,41 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="折旧年限" field="depreciationYears">
|
<a-form-item label="采购价格" field="purchasePrice">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="formData.depreciationYears"
|
v-model="formData.purchasePrice"
|
||||||
placeholder="请输入折旧年限"
|
placeholder="请输入采购价格"
|
||||||
:disabled="isView"
|
:disabled="isView"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
:precision="2"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="100"
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="盘点依据" field="inventoryBasis">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.inventoryBasis"
|
||||||
|
placeholder="请输入盘点依据"
|
||||||
|
:disabled="isView"
|
||||||
|
:rows="3"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="500"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="动态记录" field="dynamicRecord">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.dynamicRecord"
|
||||||
|
placeholder="请输入动态记录"
|
||||||
|
:disabled="isView"
|
||||||
|
:rows="3"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="1000"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -803,6 +840,14 @@ const formData = ref<FormDataType>({
|
||||||
purchaseOrder: '',
|
purchaseOrder: '',
|
||||||
supplierName: '',
|
supplierName: '',
|
||||||
|
|
||||||
|
// 新增采购相关字段
|
||||||
|
accountNumber: '',
|
||||||
|
quantity: 1,
|
||||||
|
unitPrice: undefined,
|
||||||
|
totalPrice: undefined,
|
||||||
|
inventoryBasis: '',
|
||||||
|
dynamicRecord: '',
|
||||||
|
|
||||||
// 备注信息字段
|
// 备注信息字段
|
||||||
assetRemark: '',
|
assetRemark: '',
|
||||||
|
|
||||||
|
@ -880,6 +925,26 @@ const rules = {
|
||||||
{ maxLength: 200, message: '供应商名称长度不能超过200个字' },
|
{ maxLength: 200, message: '供应商名称长度不能超过200个字' },
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// 新增采购相关字段验证
|
||||||
|
accountNumber: [
|
||||||
|
{ maxLength: 50, message: '次户号长度不能超过50个字' },
|
||||||
|
],
|
||||||
|
quantity: [
|
||||||
|
{ type: 'number', min: 1, message: '数量必须大于等于1' },
|
||||||
|
],
|
||||||
|
unitPrice: [
|
||||||
|
{ type: 'number', min: 0, message: '单价必须大于等于0' },
|
||||||
|
],
|
||||||
|
totalPrice: [
|
||||||
|
{ type: 'number', min: 0, message: '总价必须大于等于0' },
|
||||||
|
],
|
||||||
|
inventoryBasis: [
|
||||||
|
{ maxLength: 500, message: '盘点依据长度不能超过500个字' },
|
||||||
|
],
|
||||||
|
dynamicRecord: [
|
||||||
|
{ maxLength: 1000, message: '动态记录长度不能超过1000个字' },
|
||||||
|
],
|
||||||
|
|
||||||
// 财务价值字段验证
|
// 财务价值字段验证
|
||||||
purchasePrice: [
|
purchasePrice: [
|
||||||
{ type: 'number', min: 0, message: '采购价格必须大于等于0' },
|
{ type: 'number', min: 0, message: '采购价格必须大于等于0' },
|
||||||
|
@ -1049,6 +1114,14 @@ const resetFormData = () => {
|
||||||
purchaseOrder: '',
|
purchaseOrder: '',
|
||||||
supplierName: '',
|
supplierName: '',
|
||||||
|
|
||||||
|
// 新增采购相关字段
|
||||||
|
accountNumber: '',
|
||||||
|
quantity: 1,
|
||||||
|
unitPrice: undefined,
|
||||||
|
totalPrice: undefined,
|
||||||
|
inventoryBasis: '',
|
||||||
|
dynamicRecord: '',
|
||||||
|
|
||||||
// 备注信息字段
|
// 备注信息字段
|
||||||
assetRemark: '',
|
assetRemark: '',
|
||||||
|
|
||||||
|
@ -1239,6 +1312,14 @@ const fillTestData = () => {
|
||||||
purchaseOrder: 'PO20250101001',
|
purchaseOrder: 'PO20250101001',
|
||||||
supplierName: '测试供应商有限公司',
|
supplierName: '测试供应商有限公司',
|
||||||
|
|
||||||
|
// 新增采购相关字段
|
||||||
|
accountNumber: '001',
|
||||||
|
quantity: 10,
|
||||||
|
unitPrice: 1000.00,
|
||||||
|
totalPrice: 10000.00,
|
||||||
|
inventoryBasis: '盘点',
|
||||||
|
dynamicRecord: '设备正常使用,无异常',
|
||||||
|
|
||||||
// 备注信息字段
|
// 备注信息字段
|
||||||
assetRemark: '这是一台测试设备,用于系统功能验证和演示。设备性能良好,维护记录完整。',
|
assetRemark: '这是一台测试设备,用于系统功能验证和演示。设备性能良好,维护记录完整。',
|
||||||
|
|
||||||
|
|
|
@ -220,15 +220,15 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, reactive, ref, watch } from 'vue'
|
import { onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { Modal } from '@arco-design/web-vue'
|
import { Modal } from '@arco-design/web-vue'
|
||||||
import {
|
import {
|
||||||
|
IconCheckCircle,
|
||||||
|
IconClockCircle,
|
||||||
|
IconDesktop,
|
||||||
|
IconDownload,
|
||||||
|
IconExclamationCircle,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
IconRefresh,
|
IconRefresh,
|
||||||
IconSearch,
|
IconSearch
|
||||||
IconDesktop,
|
|
||||||
IconCheckCircle,
|
|
||||||
IconClockCircle,
|
|
||||||
IconExclamationCircle,
|
|
||||||
IconDownload
|
|
||||||
} from '@arco-design/web-vue/es/icon'
|
} from '@arco-design/web-vue/es/icon'
|
||||||
import message from '@arco-design/web-vue/es/message'
|
import message from '@arco-design/web-vue/es/message'
|
||||||
import DeviceModal from './components/DeviceModal.vue'
|
import DeviceModal from './components/DeviceModal.vue'
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
# 设备采购模块
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
设备采购模块是一个完整的企业设备采购管理系统,提供设备采购的全生命周期管理,包括采购申请、订单管理、供应商管理、设备入库等功能。
|
||||||
|
|
||||||
|
## 主要功能
|
||||||
|
|
||||||
|
### 1. 采购记录管理
|
||||||
|
- **新增采购记录**:支持完整的设备采购信息录入
|
||||||
|
- **编辑采购记录**:修改已存在的采购记录信息
|
||||||
|
- **查看采购记录**:查看采购记录的详细信息
|
||||||
|
- **删除采购记录**:删除不需要的采购记录
|
||||||
|
|
||||||
|
### 2. 搜索功能
|
||||||
|
- **多条件搜索**:支持按设备名称、型号、供应商、状态等条件搜索
|
||||||
|
- **时间范围搜索**:支持按采购时间、入库时间、启用时间范围搜索
|
||||||
|
- **价格范围搜索**:支持按价格范围搜索
|
||||||
|
- **状态搜索**:支持按设备状态、位置状态、健康状态搜索
|
||||||
|
|
||||||
|
### 3. 数据展示
|
||||||
|
- **统计卡片**:显示采购总数、待处理、已完成、采购总额等统计信息
|
||||||
|
- **表格展示**:分页展示采购记录列表
|
||||||
|
- **状态标签**:使用不同颜色的标签显示设备状态
|
||||||
|
- **价格格式化**:自动格式化价格显示
|
||||||
|
|
||||||
|
### 4. 数据导出
|
||||||
|
- **Excel导出**:支持将采购记录导出为Excel文件
|
||||||
|
- **筛选导出**:支持按搜索条件导出数据
|
||||||
|
|
||||||
|
## 技术架构
|
||||||
|
|
||||||
|
### 前端技术栈
|
||||||
|
- **Vue 3**:使用Composition API
|
||||||
|
- **TypeScript**:提供类型安全
|
||||||
|
- **Arco Design Vue**:UI组件库
|
||||||
|
- **Vite**:构建工具
|
||||||
|
|
||||||
|
### 后端技术栈
|
||||||
|
- **Spring Boot**:后端框架
|
||||||
|
- **MyBatis Plus**:ORM框架
|
||||||
|
- **MySQL**:数据库
|
||||||
|
- **Swagger**:API文档
|
||||||
|
|
||||||
|
### 数据模型
|
||||||
|
- **EquipmentEntity**:设备实体类
|
||||||
|
- **EquipmentReq**:设备请求类
|
||||||
|
- **EquipmentResp**:设备响应类
|
||||||
|
- **EquipmentListReq**:设备列表查询请求类
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
procurement/
|
||||||
|
├── index.vue # 主页面
|
||||||
|
├── components/
|
||||||
|
│ ├── ProcurementSearch.vue # 搜索组件
|
||||||
|
│ └── ProcurementModal.vue # 弹窗组件
|
||||||
|
├── test.vue # 测试页面
|
||||||
|
└── README.md # 说明文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## API接口
|
||||||
|
|
||||||
|
### 1. 分页查询
|
||||||
|
- **接口**:`GET /equipment/procurement/page`
|
||||||
|
- **参数**:EquipmentListReq
|
||||||
|
- **返回**:PageResult<EquipmentResp>
|
||||||
|
|
||||||
|
### 2. 新增采购
|
||||||
|
- **接口**:`POST /equipment/procurement`
|
||||||
|
- **参数**:EquipmentReq
|
||||||
|
- **返回**:Result<null>
|
||||||
|
|
||||||
|
### 3. 更新采购
|
||||||
|
- **接口**:`PUT /equipment/procurement/{equipmentId}`
|
||||||
|
- **参数**:EquipmentReq
|
||||||
|
- **返回**:Result<null>
|
||||||
|
|
||||||
|
### 4. 删除采购
|
||||||
|
- **接口**:`DELETE /equipment/procurement/{equipmentId}`
|
||||||
|
- **参数**:equipmentId
|
||||||
|
- **返回**:Result<null>
|
||||||
|
|
||||||
|
### 5. 获取详情
|
||||||
|
- **接口**:`GET /equipment/procurement/detail/{equipmentId}`
|
||||||
|
- **参数**:equipmentId
|
||||||
|
- **返回**:Result<EquipmentResp>
|
||||||
|
|
||||||
|
### 6. 导出数据
|
||||||
|
- **接口**:`GET /equipment/procurement/export`
|
||||||
|
- **参数**:EquipmentListReq
|
||||||
|
- **返回**:Blob
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 1. 访问页面
|
||||||
|
在浏览器中访问设备采购模块页面。
|
||||||
|
|
||||||
|
### 2. 查看数据
|
||||||
|
页面会自动加载采购记录列表,显示统计信息和数据表格。
|
||||||
|
|
||||||
|
### 3. 搜索数据
|
||||||
|
点击"搜索采购"按钮,在弹出的搜索弹窗中输入搜索条件,点击"搜索"按钮。
|
||||||
|
|
||||||
|
### 4. 新增记录
|
||||||
|
点击"新增采购"按钮,在弹出的表单中填写设备采购信息,点击"确定"按钮。
|
||||||
|
|
||||||
|
### 5. 编辑记录
|
||||||
|
在表格中点击"编辑"按钮,在弹出的表单中修改信息,点击"确定"按钮。
|
||||||
|
|
||||||
|
### 6. 删除记录
|
||||||
|
在表格中点击"删除"按钮,确认删除操作。
|
||||||
|
|
||||||
|
### 7. 导出数据
|
||||||
|
点击"导出"按钮,选择保存位置下载Excel文件。
|
||||||
|
|
||||||
|
## 字段说明
|
||||||
|
|
||||||
|
### 基本信息
|
||||||
|
- **设备名称**:设备的名称
|
||||||
|
- **设备类型**:设备的分类(检测设备、安防设备、办公设备、车辆等)
|
||||||
|
- **设备型号**:设备的具体型号
|
||||||
|
- **序列号**:设备的唯一序列号
|
||||||
|
- **品牌**:设备的品牌
|
||||||
|
- **资产编号**:设备的资产编号
|
||||||
|
- **配置规格**:设备的配置规格和参数
|
||||||
|
|
||||||
|
### 采购信息
|
||||||
|
- **采购订单**:采购订单号
|
||||||
|
- **供应商**:供应商名称
|
||||||
|
- **数量**:采购数量
|
||||||
|
- **单价**:设备单价
|
||||||
|
- **总价**:设备总价
|
||||||
|
- **采购价格**:采购价格
|
||||||
|
- **当前净值**:设备的当前净值
|
||||||
|
- **采购时间**:采购时间
|
||||||
|
- **入库时间**:入库时间
|
||||||
|
- **启用时间**:启用时间
|
||||||
|
- **预计报废时间**:预计报废时间
|
||||||
|
- **折旧方法**:折旧方法(直线折旧、余额递减、年数总和)
|
||||||
|
- **折旧年限**:折旧年限
|
||||||
|
- **残值**:设备残值
|
||||||
|
- **保修截止日期**:保修截止日期
|
||||||
|
|
||||||
|
### 状态信息
|
||||||
|
- **设备状态**:设备状态(正常、维修中、已报废、闲置、丢失)
|
||||||
|
- **使用状态**:使用状态(空闲中、使用中)
|
||||||
|
- **位置状态**:位置状态(库存中、使用中、维修中、已报废、外借中、丢失、闲置)
|
||||||
|
- **健康状态**:健康状态(优秀、良好、一般、较差、危险)
|
||||||
|
- **负责人**:设备负责人
|
||||||
|
- **维护人员**:维护人员
|
||||||
|
- **物理位置**:设备的物理位置
|
||||||
|
- **库存条码**:库存条码
|
||||||
|
- **上次维护日期**:上次维护日期
|
||||||
|
- **下次维护日期**:下次维护日期
|
||||||
|
|
||||||
|
### 其他信息
|
||||||
|
- **次户号**:次户号
|
||||||
|
- **盘点依据**:盘点依据
|
||||||
|
- **动态记录**:动态记录信息
|
||||||
|
- **资产备注**:资产备注信息
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **数据验证**:所有必填字段都需要填写,系统会进行数据验证
|
||||||
|
2. **权限控制**:不同用户可能有不同的操作权限
|
||||||
|
3. **数据安全**:敏感数据会进行加密处理
|
||||||
|
4. **性能优化**:大量数据时会进行分页处理
|
||||||
|
5. **错误处理**:系统会显示友好的错误提示
|
||||||
|
|
||||||
|
## 开发说明
|
||||||
|
|
||||||
|
### 1. 开发环境
|
||||||
|
- Node.js 16+
|
||||||
|
- Vue 3.3+
|
||||||
|
- TypeScript 5.0+
|
||||||
|
|
||||||
|
### 2. 安装依赖
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动开发服务器
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 构建生产版本
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 代码规范
|
||||||
|
- 使用ESLint进行代码检查
|
||||||
|
- 使用Prettier进行代码格式化
|
||||||
|
- 遵循Vue 3 Composition API最佳实践
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.0.0 (2025-01-XX)
|
||||||
|
- 初始版本发布
|
||||||
|
- 实现基本的CRUD功能
|
||||||
|
- 实现搜索和导出功能
|
||||||
|
- 实现统计信息展示
|
||||||
|
- 实现响应式设计
|
||||||
|
|
||||||
|
## 联系方式
|
||||||
|
|
||||||
|
如有问题或建议,请联系开发团队。
|
|
@ -0,0 +1,865 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:visible="visible"
|
||||||
|
:title="getModalTitle()"
|
||||||
|
width="1200px"
|
||||||
|
:confirm-loading="loading"
|
||||||
|
:ok-button-props="{ disabled: !isFormValid || isView }"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@ok="handleSubmit"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:wrapper-col="{ span: 16 }"
|
||||||
|
auto-label-width
|
||||||
|
>
|
||||||
|
<!-- 标签页导航 -->
|
||||||
|
<div class="tab-navigation">
|
||||||
|
<div
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.key"
|
||||||
|
class="tab-item" :class="[{ active: activeTab === tab.key }]"
|
||||||
|
@click="activeTab = tab.key"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标签页内容 -->
|
||||||
|
<div class="tab-content">
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<div v-show="activeTab === 'basic'">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="设备名称" field="equipmentName">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.equipmentName"
|
||||||
|
placeholder="请输入设备名称"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="200"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="设备类型" field="equipmentType">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.equipmentType"
|
||||||
|
:options="equipmentTypeOptions"
|
||||||
|
placeholder="请选择设备类型"
|
||||||
|
:disabled="isView"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="设备型号" field="equipmentModel">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.equipmentModel"
|
||||||
|
placeholder="请输入设备型号"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="200"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="序列号" field="equipmentSn">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.equipmentSn"
|
||||||
|
placeholder="请输入序列号"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="品牌" field="brand">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.brand"
|
||||||
|
placeholder="请输入品牌"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="资产编号" field="assetCode">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.assetCode"
|
||||||
|
placeholder="请输入资产编号"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="50"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-form-item label="配置规格" field="specification">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.specification"
|
||||||
|
placeholder="请输入配置规格参数"
|
||||||
|
:disabled="isView"
|
||||||
|
:rows="3"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="500"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 采购信息 -->
|
||||||
|
<div v-show="activeTab === 'procurement'">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="采购订单" field="purchaseOrder">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.purchaseOrder"
|
||||||
|
placeholder="请输入采购订单号"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="供应商" field="supplierName">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.supplierName"
|
||||||
|
placeholder="请输入供应商名称"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="200"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="数量" field="quantity">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.quantity"
|
||||||
|
placeholder="请输入数量"
|
||||||
|
:min="1"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="单价" field="unitPrice">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.unitPrice"
|
||||||
|
placeholder="请输入单价"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="总价" field="totalPrice">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.totalPrice"
|
||||||
|
placeholder="请输入总价"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="采购价格" field="purchasePrice">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.purchasePrice"
|
||||||
|
placeholder="请输入采购价格"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="当前净值" field="currentNetValue">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.currentNetValue"
|
||||||
|
placeholder="请输入当前净值"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="采购时间" field="purchaseTime">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.purchaseTime"
|
||||||
|
placeholder="请选择采购时间"
|
||||||
|
:disabled="isView"
|
||||||
|
show-time
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="入库时间" field="inStockTime">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.inStockTime"
|
||||||
|
placeholder="请选择入库时间"
|
||||||
|
:disabled="isView"
|
||||||
|
show-time
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="启用时间" field="activationTime">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.activationTime"
|
||||||
|
placeholder="请选择启用时间"
|
||||||
|
:disabled="isView"
|
||||||
|
show-time
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="预计报废时间" field="expectedScrapTime">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.expectedScrapTime"
|
||||||
|
placeholder="请选择预计报废时间"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="折旧方法" field="depreciationMethod">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.depreciationMethod"
|
||||||
|
placeholder="请选择折旧方法"
|
||||||
|
:disabled="isView"
|
||||||
|
>
|
||||||
|
<a-option value="straight_line">直线折旧</a-option>
|
||||||
|
<a-option value="declining_balance">余额递减</a-option>
|
||||||
|
<a-option value="sum_of_years">年数总和</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="折旧年限" field="depreciationYears">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.depreciationYears"
|
||||||
|
placeholder="请输入折旧年限"
|
||||||
|
:min="1"
|
||||||
|
:max="50"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="残值" field="salvageValue">
|
||||||
|
<a-input-number
|
||||||
|
v-model="formData.salvageValue"
|
||||||
|
placeholder="请输入残值"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="保修截止日期" field="warrantyExpireDate">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.warrantyExpireDate"
|
||||||
|
placeholder="请选择保修截止日期"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 状态信息 -->
|
||||||
|
<div v-show="activeTab === 'status'">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="设备状态" field="equipmentStatus">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.equipmentStatus"
|
||||||
|
:options="equipmentStatusOptions"
|
||||||
|
placeholder="请选择设备状态"
|
||||||
|
:disabled="isView"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="使用状态" field="useStatus">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.useStatus"
|
||||||
|
:options="useStatusOptions"
|
||||||
|
placeholder="请选择使用状态"
|
||||||
|
:disabled="isView"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="位置状态" field="locationStatus">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.locationStatus"
|
||||||
|
:options="locationStatusOptions"
|
||||||
|
placeholder="请选择位置状态"
|
||||||
|
:disabled="isView"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="健康状态" field="healthStatus">
|
||||||
|
<a-select
|
||||||
|
v-model="formData.healthStatus"
|
||||||
|
:options="healthStatusOptions"
|
||||||
|
placeholder="请选择健康状态"
|
||||||
|
:disabled="isView"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="负责人" field="responsiblePerson">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.responsiblePerson"
|
||||||
|
placeholder="请输入负责人"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="维护人员" field="maintenancePerson">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.maintenancePerson"
|
||||||
|
placeholder="请输入维护人员"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="物理位置" field="physicalLocation">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.physicalLocation"
|
||||||
|
placeholder="请输入物理位置"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="200"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="库存条码" field="inventoryBarcode">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.inventoryBarcode"
|
||||||
|
placeholder="请输入库存条码"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="上次维护日期" field="lastMaintenanceDate">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.lastMaintenanceDate"
|
||||||
|
placeholder="请选择上次维护日期"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="下次维护日期" field="nextMaintenanceDate">
|
||||||
|
<a-date-picker
|
||||||
|
v-model="formData.nextMaintenanceDate"
|
||||||
|
placeholder="请选择下次维护日期"
|
||||||
|
:disabled="isView"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 其他信息 -->
|
||||||
|
<div v-show="activeTab === 'other'">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="次户号" field="accountNumber">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.accountNumber"
|
||||||
|
placeholder="请输入次户号"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="盘点依据" field="inventoryBasis">
|
||||||
|
<a-input
|
||||||
|
v-model="formData.inventoryBasis"
|
||||||
|
placeholder="请输入盘点依据"
|
||||||
|
:disabled="isView"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="200"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-form-item label="动态记录" field="dynamicRecord">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.dynamicRecord"
|
||||||
|
placeholder="请输入动态记录"
|
||||||
|
:disabled="isView"
|
||||||
|
:rows="4"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="1000"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="资产备注" field="assetRemark">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.assetRemark"
|
||||||
|
placeholder="请输入资产备注"
|
||||||
|
:disabled="isView"
|
||||||
|
:rows="3"
|
||||||
|
show-word-limit
|
||||||
|
:max-length="500"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import type { FormInstance } from '@arco-design/web-vue'
|
||||||
|
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||||||
|
import type { EquipmentResp, EquipmentReq } from '@/apis/equipment/type'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean
|
||||||
|
procurementData?: EquipmentResp | null
|
||||||
|
mode: 'add' | 'edit' | 'view'
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:visible', value: boolean): void
|
||||||
|
(e: 'success'): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
procurementData: null,
|
||||||
|
mode: 'add',
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const loading = ref(false)
|
||||||
|
const activeTab = ref('basic')
|
||||||
|
|
||||||
|
// 标签页配置
|
||||||
|
const tabs = [
|
||||||
|
{ key: 'basic', label: '基本信息' },
|
||||||
|
{ key: 'procurement', label: '采购信息' },
|
||||||
|
{ key: 'status', label: '状态信息' },
|
||||||
|
{ key: 'other', label: '其他信息' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formData = reactive<EquipmentReq>({
|
||||||
|
equipmentName: '',
|
||||||
|
equipmentModel: '',
|
||||||
|
equipmentType: '',
|
||||||
|
equipmentStatus: '',
|
||||||
|
useStatus: '',
|
||||||
|
equipmentSn: '',
|
||||||
|
assetCode: '',
|
||||||
|
brand: '',
|
||||||
|
specification: '',
|
||||||
|
locationStatus: '',
|
||||||
|
physicalLocation: '',
|
||||||
|
responsiblePerson: '',
|
||||||
|
healthStatus: '',
|
||||||
|
purchaseTime: '',
|
||||||
|
inStockTime: '',
|
||||||
|
activationTime: '',
|
||||||
|
expectedScrapTime: '',
|
||||||
|
actualScrapTime: '',
|
||||||
|
purchaseOrder: '',
|
||||||
|
supplierName: '',
|
||||||
|
purchasePrice: undefined,
|
||||||
|
currentNetValue: undefined,
|
||||||
|
depreciationMethod: '',
|
||||||
|
depreciationYears: undefined,
|
||||||
|
salvageValue: undefined,
|
||||||
|
warrantyExpireDate: '',
|
||||||
|
lastMaintenanceDate: '',
|
||||||
|
nextMaintenanceDate: '',
|
||||||
|
maintenancePerson: '',
|
||||||
|
inventoryBarcode: '',
|
||||||
|
assetRemark: '',
|
||||||
|
accountNumber: '',
|
||||||
|
quantity: 1,
|
||||||
|
unitPrice: undefined,
|
||||||
|
totalPrice: undefined,
|
||||||
|
inventoryBasis: '',
|
||||||
|
dynamicRecord: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = {
|
||||||
|
equipmentName: [{ required: true, message: '请输入设备名称' }],
|
||||||
|
equipmentModel: [{ required: true, message: '请输入设备型号' }],
|
||||||
|
equipmentType: [{ required: true, message: '请选择设备类型' }],
|
||||||
|
equipmentSn: [{ required: true, message: '请输入设备序列号' }],
|
||||||
|
equipmentStatus: [{ required: true, message: '请选择设备状态' }],
|
||||||
|
useStatus: [{ required: true, message: '请选择使用状态' }],
|
||||||
|
purchaseOrder: [{ required: true, message: '请输入采购订单号' }],
|
||||||
|
supplierName: [{ required: true, message: '请输入供应商名称' }],
|
||||||
|
purchasePrice: [{ required: true, message: '请输入采购价格' }],
|
||||||
|
quantity: [{ required: true, message: '请输入数量' }],
|
||||||
|
unitPrice: [{ required: true, message: '请输入单价' }],
|
||||||
|
totalPrice: [{ required: true, message: '请输入总价' }],
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选项配置
|
||||||
|
const equipmentTypeOptions = [
|
||||||
|
{ label: '检测设备', value: 'detection' },
|
||||||
|
{ label: '安防设备', value: 'security' },
|
||||||
|
{ label: '办公设备', value: 'office' },
|
||||||
|
{ label: '车辆', value: 'car' },
|
||||||
|
{ label: '其他设备', value: 'other' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const equipmentStatusOptions = [
|
||||||
|
{ label: '正常', value: 'normal' },
|
||||||
|
{ label: '维修中', value: 'repair' },
|
||||||
|
{ label: '已报废', value: 'scrap' },
|
||||||
|
{ label: '闲置', value: 'idle' },
|
||||||
|
{ label: '丢失', value: 'lost' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const useStatusOptions = [
|
||||||
|
{ label: '空闲中', value: '0' },
|
||||||
|
{ label: '使用中', value: '1' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const locationStatusOptions = [
|
||||||
|
{ label: '库存中', value: 'in_stock' },
|
||||||
|
{ label: '使用中', value: 'in_use' },
|
||||||
|
{ label: '维修中', value: 'repair' },
|
||||||
|
{ label: '已报废', value: 'scrapped' },
|
||||||
|
{ label: '外借中', value: 'on_loan' },
|
||||||
|
{ label: '丢失', value: 'lost' },
|
||||||
|
{ label: '闲置', value: 'idle' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const healthStatusOptions = [
|
||||||
|
{ label: '优秀', value: 'excellent' },
|
||||||
|
{ label: '良好', value: 'good' },
|
||||||
|
{ label: '一般', value: 'normal' },
|
||||||
|
{ label: '较差', value: 'poor' },
|
||||||
|
{ label: '危险', value: 'critical' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 计算属性
|
||||||
|
const isView = computed(() => props.mode === 'view')
|
||||||
|
const isFormValid = computed(() => {
|
||||||
|
return formData.equipmentName &&
|
||||||
|
formData.equipmentModel &&
|
||||||
|
formData.equipmentType &&
|
||||||
|
formData.equipmentSn
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取弹窗标题
|
||||||
|
const getModalTitle = () => {
|
||||||
|
const titles = {
|
||||||
|
add: '新增采购记录',
|
||||||
|
edit: '编辑采购记录',
|
||||||
|
view: '查看采购记录',
|
||||||
|
}
|
||||||
|
return titles[props.mode]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听弹窗显示状态
|
||||||
|
watch(() => props.visible, (newVal) => {
|
||||||
|
if (newVal && props.procurementData) {
|
||||||
|
initFormData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 初始化表单数据
|
||||||
|
const initFormData = () => {
|
||||||
|
if (props.procurementData) {
|
||||||
|
Object.assign(formData, {
|
||||||
|
equipmentName: props.procurementData.equipmentName || '',
|
||||||
|
equipmentModel: props.procurementData.equipmentModel || '',
|
||||||
|
equipmentType: props.procurementData.equipmentType || '',
|
||||||
|
equipmentStatus: props.procurementData.equipmentStatus || '',
|
||||||
|
useStatus: props.procurementData.useStatus || '',
|
||||||
|
equipmentSn: props.procurementData.equipmentSn || '',
|
||||||
|
assetCode: props.procurementData.assetCode || '',
|
||||||
|
brand: props.procurementData.brand || '',
|
||||||
|
specification: props.procurementData.specification || '',
|
||||||
|
locationStatus: props.procurementData.locationStatus || '',
|
||||||
|
physicalLocation: props.procurementData.physicalLocation || '',
|
||||||
|
responsiblePerson: props.procurementData.responsiblePerson || '',
|
||||||
|
healthStatus: props.procurementData.healthStatus || '',
|
||||||
|
purchaseTime: props.procurementData.purchaseTime || '',
|
||||||
|
inStockTime: props.procurementData.inStockTime || '',
|
||||||
|
activationTime: props.procurementData.activationTime || '',
|
||||||
|
expectedScrapTime: props.procurementData.expectedScrapTime || '',
|
||||||
|
actualScrapTime: props.procurementData.actualScrapTime || '',
|
||||||
|
purchaseOrder: props.procurementData.purchaseOrder || '',
|
||||||
|
supplierName: props.procurementData.supplierName || '',
|
||||||
|
purchasePrice: props.procurementData.purchasePrice,
|
||||||
|
currentNetValue: props.procurementData.currentNetValue,
|
||||||
|
depreciationMethod: props.procurementData.depreciationMethod || '',
|
||||||
|
depreciationYears: props.procurementData.depreciationYears,
|
||||||
|
salvageValue: props.procurementData.salvageValue,
|
||||||
|
warrantyExpireDate: props.procurementData.warrantyExpireDate || '',
|
||||||
|
lastMaintenanceDate: props.procurementData.lastMaintenanceDate || '',
|
||||||
|
nextMaintenanceDate: props.procurementData.nextMaintenanceDate || '',
|
||||||
|
maintenancePerson: props.procurementData.maintenancePerson || '',
|
||||||
|
inventoryBarcode: props.procurementData.inventoryBarcode || '',
|
||||||
|
assetRemark: props.procurementData.assetRemark || '',
|
||||||
|
accountNumber: props.procurementData.accountNumber || '',
|
||||||
|
quantity: props.procurementData.quantity || 1,
|
||||||
|
unitPrice: props.procurementData.unitPrice,
|
||||||
|
totalPrice: props.procurementData.totalPrice,
|
||||||
|
inventoryBasis: props.procurementData.inventoryBasis || '',
|
||||||
|
dynamicRecord: props.procurementData.dynamicRecord || '',
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(formData, {
|
||||||
|
equipmentName: '',
|
||||||
|
equipmentModel: '',
|
||||||
|
equipmentType: '',
|
||||||
|
equipmentStatus: '',
|
||||||
|
useStatus: '',
|
||||||
|
equipmentSn: '',
|
||||||
|
assetCode: '',
|
||||||
|
brand: '',
|
||||||
|
specification: '',
|
||||||
|
locationStatus: '',
|
||||||
|
physicalLocation: '',
|
||||||
|
responsiblePerson: '',
|
||||||
|
healthStatus: '',
|
||||||
|
purchaseTime: '',
|
||||||
|
inStockTime: '',
|
||||||
|
activationTime: '',
|
||||||
|
expectedScrapTime: '',
|
||||||
|
actualScrapTime: '',
|
||||||
|
purchaseOrder: '',
|
||||||
|
supplierName: '',
|
||||||
|
purchasePrice: undefined,
|
||||||
|
currentNetValue: undefined,
|
||||||
|
depreciationMethod: '',
|
||||||
|
depreciationYears: undefined,
|
||||||
|
salvageValue: undefined,
|
||||||
|
warrantyExpireDate: '',
|
||||||
|
lastMaintenanceDate: '',
|
||||||
|
nextMaintenanceDate: '',
|
||||||
|
maintenancePerson: '',
|
||||||
|
inventoryBarcode: '',
|
||||||
|
assetRemark: '',
|
||||||
|
accountNumber: '',
|
||||||
|
quantity: 1,
|
||||||
|
unitPrice: undefined,
|
||||||
|
totalPrice: undefined,
|
||||||
|
inventoryBasis: '',
|
||||||
|
dynamicRecord: '',
|
||||||
|
})
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value?.validate()
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
if (props.mode === 'edit' && props.procurementData) {
|
||||||
|
await equipmentProcurementApi.update(props.procurementData.equipmentId, formData)
|
||||||
|
Message.success('更新成功')
|
||||||
|
} else {
|
||||||
|
await equipmentProcurementApi.add(formData)
|
||||||
|
Message.success('新增成功')
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('success')
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('操作失败:', error)
|
||||||
|
Message.error(error?.message || '操作失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false)
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tab-navigation {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--color-primary);
|
||||||
|
border-bottom-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
.arco-form-item {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.arco-form-item-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-input,
|
||||||
|
.arco-select,
|
||||||
|
.arco-input-number,
|
||||||
|
.arco-date-picker {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-primary-light-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.arco-input-focus,
|
||||||
|
&.arco-select-focus {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-textarea {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-primary-light-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.arco-textarea-focus {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tab-navigation {
|
||||||
|
.tab-item {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
.arco-row {
|
||||||
|
.arco-col {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,491 @@
|
||||||
|
<template>
|
||||||
|
<a-button type="primary" @click="showSearchModal = true">
|
||||||
|
<template #icon>
|
||||||
|
<IconSearch />
|
||||||
|
</template>
|
||||||
|
搜索采购
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<!-- 搜索弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="showSearchModal"
|
||||||
|
title="采购记录搜索"
|
||||||
|
width="1000px"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="searchForm"
|
||||||
|
layout="vertical"
|
||||||
|
class="search-form"
|
||||||
|
>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备名称">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.equipmentName"
|
||||||
|
placeholder="请输入设备名称"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备型号">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.equipmentModel"
|
||||||
|
placeholder="请输入设备型号"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备类型">
|
||||||
|
<a-select
|
||||||
|
v-model="searchForm.equipmentType"
|
||||||
|
placeholder="请选择设备类型"
|
||||||
|
allow-clear
|
||||||
|
>
|
||||||
|
<a-option value="detection">检测设备</a-option>
|
||||||
|
<a-option value="security">安防设备</a-option>
|
||||||
|
<a-option value="office">办公设备</a-option>
|
||||||
|
<a-option value="car">车辆</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="品牌">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.brand"
|
||||||
|
placeholder="请输入品牌"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="供应商">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.supplierName"
|
||||||
|
placeholder="请输入供应商名称"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="采购订单">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.purchaseOrder"
|
||||||
|
placeholder="请输入采购订单号"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备状态">
|
||||||
|
<a-select
|
||||||
|
v-model="searchForm.equipmentStatus"
|
||||||
|
placeholder="请选择设备状态"
|
||||||
|
allow-clear
|
||||||
|
>
|
||||||
|
<a-option value="normal">正常</a-option>
|
||||||
|
<a-option value="repair">维修中</a-option>
|
||||||
|
<a-option value="scrap">已报废</a-option>
|
||||||
|
<a-option value="idle">闲置</a-option>
|
||||||
|
<a-option value="lost">丢失</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="位置状态">
|
||||||
|
<a-select
|
||||||
|
v-model="searchForm.locationStatus"
|
||||||
|
placeholder="请选择位置状态"
|
||||||
|
allow-clear
|
||||||
|
>
|
||||||
|
<a-option value="in_stock">库存中</a-option>
|
||||||
|
<a-option value="in_use">使用中</a-option>
|
||||||
|
<a-option value="repair">维修中</a-option>
|
||||||
|
<a-option value="scrapped">已报废</a-option>
|
||||||
|
<a-option value="on_loan">外借中</a-option>
|
||||||
|
<a-option value="lost">丢失</a-option>
|
||||||
|
<a-option value="idle">闲置</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="健康状态">
|
||||||
|
<a-select
|
||||||
|
v-model="searchForm.healthStatus"
|
||||||
|
placeholder="请选择健康状态"
|
||||||
|
allow-clear
|
||||||
|
>
|
||||||
|
<a-option value="excellent">优秀</a-option>
|
||||||
|
<a-option value="good">良好</a-option>
|
||||||
|
<a-option value="normal">一般</a-option>
|
||||||
|
<a-option value="poor">较差</a-option>
|
||||||
|
<a-option value="critical">危险</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="负责人">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.responsiblePerson"
|
||||||
|
placeholder="请输入负责人"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="维护人员">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.maintenancePerson"
|
||||||
|
placeholder="请输入维护人员"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="物理位置">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.physicalLocation"
|
||||||
|
placeholder="请输入物理位置"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="资产编号">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.assetCode"
|
||||||
|
placeholder="请输入资产编号"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备序列号">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.equipmentSn"
|
||||||
|
placeholder="请输入设备序列号"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="库存条码">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.inventoryBarcode"
|
||||||
|
placeholder="请输入库存条码"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="采购时间范围">
|
||||||
|
<a-range-picker
|
||||||
|
v-model="searchForm.purchaseTimeRange"
|
||||||
|
show-time
|
||||||
|
placeholder="['开始时间', '结束时间']"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="入库时间范围">
|
||||||
|
<a-range-picker
|
||||||
|
v-model="searchForm.inStockTimeRange"
|
||||||
|
show-time
|
||||||
|
placeholder="['开始时间', '结束时间']"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="启用时间范围">
|
||||||
|
<a-range-picker
|
||||||
|
v-model="searchForm.activationTimeRange"
|
||||||
|
show-time
|
||||||
|
placeholder="['开始时间', '结束时间']"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="价格范围">
|
||||||
|
<a-input-number
|
||||||
|
v-model="searchForm.minPrice"
|
||||||
|
placeholder="最低价格"
|
||||||
|
:min="0"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="至">
|
||||||
|
<a-input-number
|
||||||
|
v-model="searchForm.maxPrice"
|
||||||
|
placeholder="最高价格"
|
||||||
|
:min="0"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="配置规格">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.specification"
|
||||||
|
placeholder="请输入配置规格关键词"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="备注">
|
||||||
|
<a-input
|
||||||
|
v-model="searchForm.assetRemark"
|
||||||
|
placeholder="请输入备注关键词"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="search-actions">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="handleSearch" :loading="loading">
|
||||||
|
<template #icon>
|
||||||
|
<IconSearch />
|
||||||
|
</template>
|
||||||
|
搜索
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleReset">
|
||||||
|
<template #icon>
|
||||||
|
<IconRefresh />
|
||||||
|
</template>
|
||||||
|
重置
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="showSearchModal = false">
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { IconSearch, IconRefresh } from '@arco-design/web-vue/es/icon'
|
||||||
|
import type { EquipmentListReq } from '@/apis/equipment/type'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
loading?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'search', params: EquipmentListReq): void
|
||||||
|
(e: 'reset'): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
const showSearchModal = ref(false)
|
||||||
|
const formRef = ref()
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
equipmentName: '',
|
||||||
|
equipmentModel: '',
|
||||||
|
equipmentType: '',
|
||||||
|
brand: '',
|
||||||
|
supplierName: '',
|
||||||
|
purchaseOrder: '',
|
||||||
|
equipmentStatus: '',
|
||||||
|
locationStatus: '',
|
||||||
|
healthStatus: '',
|
||||||
|
responsiblePerson: '',
|
||||||
|
maintenancePerson: '',
|
||||||
|
physicalLocation: '',
|
||||||
|
assetCode: '',
|
||||||
|
equipmentSn: '',
|
||||||
|
inventoryBarcode: '',
|
||||||
|
purchaseTimeRange: [],
|
||||||
|
inStockTimeRange: [],
|
||||||
|
activationTimeRange: [],
|
||||||
|
minPrice: undefined,
|
||||||
|
maxPrice: undefined,
|
||||||
|
specification: '',
|
||||||
|
assetRemark: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
const params: EquipmentListReq = {
|
||||||
|
equipmentName: searchForm.equipmentName || undefined,
|
||||||
|
equipmentModel: searchForm.equipmentModel || undefined,
|
||||||
|
equipmentType: searchForm.equipmentType || undefined,
|
||||||
|
brand: searchForm.brand || undefined,
|
||||||
|
supplierName: searchForm.supplierName || undefined,
|
||||||
|
purchaseOrder: searchForm.purchaseOrder || undefined,
|
||||||
|
equipmentStatus: searchForm.equipmentStatus || undefined,
|
||||||
|
locationStatus: searchForm.locationStatus || undefined,
|
||||||
|
healthStatus: searchForm.healthStatus || undefined,
|
||||||
|
responsiblePerson: searchForm.responsiblePerson || undefined,
|
||||||
|
maintenancePerson: searchForm.maintenancePerson || undefined,
|
||||||
|
physicalLocation: searchForm.physicalLocation || undefined,
|
||||||
|
assetCode: searchForm.assetCode || undefined,
|
||||||
|
equipmentSn: searchForm.equipmentSn || undefined,
|
||||||
|
inventoryBarcode: searchForm.inventoryBarcode || undefined,
|
||||||
|
specification: searchForm.specification || undefined,
|
||||||
|
assetRemark: searchForm.assetRemark || undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间范围
|
||||||
|
if (searchForm.purchaseTimeRange && searchForm.purchaseTimeRange.length === 2) {
|
||||||
|
params.purchaseTimeStart = searchForm.purchaseTimeRange[0]
|
||||||
|
params.purchaseTimeEnd = searchForm.purchaseTimeRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchForm.inStockTimeRange && searchForm.inStockTimeRange.length === 2) {
|
||||||
|
params.inStockTimeStart = searchForm.inStockTimeRange[0]
|
||||||
|
params.inStockTimeEnd = searchForm.inStockTimeRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchForm.activationTimeRange && searchForm.activationTimeRange.length === 2) {
|
||||||
|
params.activationTimeStart = searchForm.activationTimeRange[0]
|
||||||
|
params.activationTimeEnd = searchForm.activationTimeRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理价格范围
|
||||||
|
if (searchForm.minPrice !== undefined) {
|
||||||
|
params.minPrice = searchForm.minPrice
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchForm.maxPrice !== undefined) {
|
||||||
|
params.maxPrice = searchForm.maxPrice
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('search', params)
|
||||||
|
showSearchModal.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
Object.keys(searchForm).forEach(key => {
|
||||||
|
if (Array.isArray(searchForm[key])) {
|
||||||
|
searchForm[key] = []
|
||||||
|
} else {
|
||||||
|
searchForm[key] = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
emit('reset')
|
||||||
|
showSearchModal.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.search-form {
|
||||||
|
.arco-form-item {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.arco-form-item-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-input,
|
||||||
|
.arco-select,
|
||||||
|
.arco-input-number {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-primary-light-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.arco-input-focus,
|
||||||
|
&.arco-select-focus {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-range-picker {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-primary-light-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.arco-range-picker-focus {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid var(--color-border);
|
||||||
|
|
||||||
|
.arco-btn {
|
||||||
|
border-radius: 6px;
|
||||||
|
font-weight: 500;
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.search-form {
|
||||||
|
.arco-row {
|
||||||
|
.arco-col {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
.arco-space {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,856 @@
|
||||||
|
<template>
|
||||||
|
<div class="equipment-procurement-container">
|
||||||
|
<!-- 页面头部 -->
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="header-content">
|
||||||
|
<div class="header-left">
|
||||||
|
<div class="page-title">
|
||||||
|
<IconDesktop style="font-size: 24px; margin-right: 12px; color: var(--color-primary);" />
|
||||||
|
<h1>设备采购管理</h1>
|
||||||
|
</div>
|
||||||
|
<div class="page-description">
|
||||||
|
管理企业设备采购流程,包括采购申请、订单管理、供应商管理等
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<a-space>
|
||||||
|
<ProcurementSearch
|
||||||
|
:loading="loading"
|
||||||
|
@search="handleSearch"
|
||||||
|
@reset="handleReset"
|
||||||
|
/>
|
||||||
|
<a-button type="primary" @click="handleAdd" size="large">
|
||||||
|
<template #icon>
|
||||||
|
<IconPlus />
|
||||||
|
</template>
|
||||||
|
新增采购
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 统计卡片 -->
|
||||||
|
<div class="stats-container">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card class="stat-card" :bordered="false">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
|
||||||
|
<IconDesktop />
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-number">{{ pagination.total }}</div>
|
||||||
|
<div class="stat-label">采购总数</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card class="stat-card" :bordered="false">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||||
|
<IconClockCircle />
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-number">{{ getPendingCount() }}</div>
|
||||||
|
<div class="stat-label">待处理</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card class="stat-card" :bordered="false">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
|
||||||
|
<IconCheckCircle />
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-number">{{ getCompletedCount() }}</div>
|
||||||
|
<div class="stat-label">已完成</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card class="stat-card" :bordered="false">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);">
|
||||||
|
<IconApps />
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-number">¥{{ getTotalAmount() }}</div>
|
||||||
|
<div class="stat-label">采购总额</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<a-card class="table-card" :bordered="false">
|
||||||
|
<template #title>
|
||||||
|
<div class="card-title">
|
||||||
|
<span>采购记录</span>
|
||||||
|
<div class="table-actions">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="text" @click="refreshData">
|
||||||
|
<template #icon>
|
||||||
|
<IconRefresh />
|
||||||
|
</template>
|
||||||
|
刷新
|
||||||
|
</a-button>
|
||||||
|
<a-button type="text" @click="handleExport">
|
||||||
|
<template #icon>
|
||||||
|
<IconDownload />
|
||||||
|
</template>
|
||||||
|
导出
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
:row-selection="rowSelection"
|
||||||
|
row-key="equipmentId"
|
||||||
|
@change="handleTableChange"
|
||||||
|
>
|
||||||
|
<!-- 设备状态 -->
|
||||||
|
<template #equipmentStatus="{ record }">
|
||||||
|
<a-tag :color="getEquipmentStatusColor(record.equipmentStatus)">
|
||||||
|
{{ getEquipmentStatusText(record.equipmentStatus) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 位置状态 -->
|
||||||
|
<template #locationStatus="{ record }">
|
||||||
|
<a-tag :color="getLocationStatusColor(record.locationStatus)">
|
||||||
|
{{ getLocationStatusText(record.locationStatus) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 健康状态 -->
|
||||||
|
<template #healthStatus="{ record }">
|
||||||
|
<a-tag :color="getHealthStatusColor(record.healthStatus)">
|
||||||
|
{{ getHealthStatusText(record.healthStatus) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 采购价格 -->
|
||||||
|
<template #purchasePrice="{ record }">
|
||||||
|
<span v-if="record.purchasePrice" class="price-text">
|
||||||
|
¥{{ formatPrice(record.purchasePrice) }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="no-data">-</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 当前净值 -->
|
||||||
|
<template #currentNetValue="{ record }">
|
||||||
|
<span v-if="record.currentNetValue" class="price-text">
|
||||||
|
¥{{ formatPrice(record.currentNetValue) }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="no-data">-</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 创建时间 -->
|
||||||
|
<template #createTime="{ record }">
|
||||||
|
<span v-if="record.createTime" class="time-text">
|
||||||
|
{{ formatDateTime(record.createTime) }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="no-data">-</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作 -->
|
||||||
|
<template #action="{ record }">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="text" size="small" @click="handleView(record)">
|
||||||
|
查看
|
||||||
|
</a-button>
|
||||||
|
<a-button type="text" size="small" @click="handleEdit(record)">
|
||||||
|
编辑
|
||||||
|
</a-button>
|
||||||
|
<a-popconfirm
|
||||||
|
content="确定要删除这条采购记录吗?"
|
||||||
|
@ok="handleDelete(record)"
|
||||||
|
>
|
||||||
|
<a-button type="text" size="small" status="danger">
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 新增/编辑弹窗 -->
|
||||||
|
<ProcurementModal
|
||||||
|
v-model:visible="modalVisible"
|
||||||
|
:procurement-data="currentProcurement"
|
||||||
|
:mode="modalMode"
|
||||||
|
@success="handleModalSuccess"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, reactive, ref, watch } from 'vue'
|
||||||
|
import { Modal } from '@arco-design/web-vue'
|
||||||
|
import {
|
||||||
|
IconCheckCircle,
|
||||||
|
IconClockCircle,
|
||||||
|
IconDownload,
|
||||||
|
IconPlus,
|
||||||
|
IconRefresh,
|
||||||
|
IconDesktop,
|
||||||
|
IconApps
|
||||||
|
} from '@arco-design/web-vue/es/icon'
|
||||||
|
import message from '@arco-design/web-vue/es/message'
|
||||||
|
import ProcurementModal from './components/ProcurementModal.vue'
|
||||||
|
import ProcurementSearch from './components/ProcurementSearch.vue'
|
||||||
|
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||||||
|
import type { EquipmentListReq, EquipmentResp } from '@/apis/equipment/type'
|
||||||
|
|
||||||
|
defineOptions({ name: 'EquipmentProcurement' })
|
||||||
|
|
||||||
|
// 当前搜索参数
|
||||||
|
const currentSearchParams = ref<EquipmentListReq>({
|
||||||
|
minPrice: undefined,
|
||||||
|
maxPrice: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref<EquipmentResp[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive<any>({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
showPageSize: true,
|
||||||
|
showJumper: true,
|
||||||
|
showTotal: (total: number) => `共 ${total} 条记录`,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 弹窗控制
|
||||||
|
const modalVisible = ref(false)
|
||||||
|
const currentProcurement = ref<EquipmentResp | null>(null)
|
||||||
|
const modalMode = ref<'add' | 'edit' | 'view'>('add')
|
||||||
|
|
||||||
|
// 表格选择
|
||||||
|
const selectedRowKeys = ref<string[]>([])
|
||||||
|
const rowSelection = reactive({
|
||||||
|
type: 'checkbox' as const,
|
||||||
|
showCheckedAll: true,
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: (keys: string[]) => {
|
||||||
|
selectedRowKeys.value = keys
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '资产编号',
|
||||||
|
dataIndex: 'assetCode',
|
||||||
|
key: 'assetCode',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '设备名称',
|
||||||
|
dataIndex: 'equipmentName',
|
||||||
|
key: 'equipmentName',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '设备类型',
|
||||||
|
dataIndex: 'equipmentType',
|
||||||
|
key: 'equipmentType',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '设备型号',
|
||||||
|
dataIndex: 'equipmentModel',
|
||||||
|
key: 'equipmentModel',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '品牌',
|
||||||
|
dataIndex: 'brand',
|
||||||
|
key: 'brand',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '供应商',
|
||||||
|
dataIndex: 'supplierName',
|
||||||
|
key: 'supplierName',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '采购订单',
|
||||||
|
dataIndex: 'purchaseOrder',
|
||||||
|
key: 'purchaseOrder',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '采购价格',
|
||||||
|
dataIndex: 'purchasePrice',
|
||||||
|
key: 'purchasePrice',
|
||||||
|
slotName: 'purchasePrice',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '当前净值',
|
||||||
|
dataIndex: 'currentNetValue',
|
||||||
|
key: 'currentNetValue',
|
||||||
|
slotName: 'currentNetValue',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '设备状态',
|
||||||
|
dataIndex: 'equipmentStatus',
|
||||||
|
key: 'equipmentStatus',
|
||||||
|
slotName: 'equipmentStatus',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '位置状态',
|
||||||
|
dataIndex: 'locationStatus',
|
||||||
|
key: 'locationStatus',
|
||||||
|
slotName: 'locationStatus',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '健康状态',
|
||||||
|
dataIndex: 'healthStatus',
|
||||||
|
key: 'healthStatus',
|
||||||
|
slotName: 'healthStatus',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '负责人',
|
||||||
|
dataIndex: 'responsiblePerson',
|
||||||
|
key: 'responsiblePerson',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
slotName: 'createTime',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
slotName: 'action',
|
||||||
|
width: 200,
|
||||||
|
fixed: 'right',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 获取设备状态颜色
|
||||||
|
const getEquipmentStatusColor = (status: string) => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
normal: 'green',
|
||||||
|
repair: 'orange',
|
||||||
|
scrap: 'red',
|
||||||
|
idle: 'blue',
|
||||||
|
lost: 'gray',
|
||||||
|
}
|
||||||
|
return colorMap[status] || 'blue'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取设备状态文本
|
||||||
|
const getEquipmentStatusText = (status: string) => {
|
||||||
|
const textMap: Record<string, string> = {
|
||||||
|
normal: '正常',
|
||||||
|
repair: '维修中',
|
||||||
|
scrap: '已报废',
|
||||||
|
idle: '闲置',
|
||||||
|
lost: '丢失',
|
||||||
|
}
|
||||||
|
return textMap[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取位置状态颜色
|
||||||
|
const getLocationStatusColor = (status: string) => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
in_stock: 'blue',
|
||||||
|
in_use: 'green',
|
||||||
|
repair: 'orange',
|
||||||
|
scrapped: 'red',
|
||||||
|
on_loan: 'purple',
|
||||||
|
lost: 'gray',
|
||||||
|
idle: 'cyan',
|
||||||
|
}
|
||||||
|
return colorMap[status] || 'blue'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取位置状态文本
|
||||||
|
const getLocationStatusText = (status: string) => {
|
||||||
|
const textMap: Record<string, string> = {
|
||||||
|
in_stock: '库存中',
|
||||||
|
in_use: '使用中',
|
||||||
|
repair: '维修中',
|
||||||
|
scrapped: '已报废',
|
||||||
|
on_loan: '外借中',
|
||||||
|
lost: '丢失',
|
||||||
|
idle: '闲置',
|
||||||
|
}
|
||||||
|
return textMap[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取健康状态颜色
|
||||||
|
const getHealthStatusColor = (status: string) => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
excellent: 'green',
|
||||||
|
good: 'blue',
|
||||||
|
normal: 'orange',
|
||||||
|
poor: 'red',
|
||||||
|
critical: 'red',
|
||||||
|
}
|
||||||
|
return colorMap[status] || 'blue'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取健康状态文本
|
||||||
|
const getHealthStatusText = (status: string) => {
|
||||||
|
const textMap: Record<string, string> = {
|
||||||
|
excellent: '优秀',
|
||||||
|
good: '良好',
|
||||||
|
normal: '一般',
|
||||||
|
poor: '较差',
|
||||||
|
critical: '危险',
|
||||||
|
}
|
||||||
|
return textMap[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化价格
|
||||||
|
const formatPrice = (price: number) => {
|
||||||
|
return price.toLocaleString('zh-CN', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime: string) => {
|
||||||
|
if (!dateTime) return '-'
|
||||||
|
const date = new Date(dateTime)
|
||||||
|
return date.toLocaleString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换后端数据
|
||||||
|
const transformBackendData = (data: any[]): EquipmentResp[] => {
|
||||||
|
return data.map((item: any) => ({
|
||||||
|
equipmentId: item.equipmentId || item.id,
|
||||||
|
assetCode: item.assetCode,
|
||||||
|
equipmentName: item.equipmentName,
|
||||||
|
equipmentType: item.equipmentType,
|
||||||
|
equipmentTypeLabel: item.equipmentTypeLabel,
|
||||||
|
equipmentModel: item.equipmentModel,
|
||||||
|
equipmentSn: item.equipmentSn,
|
||||||
|
brand: item.brand,
|
||||||
|
specification: item.specification,
|
||||||
|
equipmentStatus: item.equipmentStatus,
|
||||||
|
equipmentStatusLabel: item.equipmentStatusLabel,
|
||||||
|
useStatus: item.useStatus,
|
||||||
|
locationStatus: item.locationStatus,
|
||||||
|
locationStatusLabel: item.locationStatusLabel,
|
||||||
|
physicalLocation: item.physicalLocation,
|
||||||
|
responsiblePerson: item.responsiblePerson,
|
||||||
|
healthStatus: item.healthStatus,
|
||||||
|
healthStatusLabel: item.healthStatusLabel,
|
||||||
|
purchaseTime: item.purchaseTime,
|
||||||
|
inStockTime: item.inStockTime,
|
||||||
|
activationTime: item.activationTime,
|
||||||
|
expectedScrapTime: item.expectedScrapTime,
|
||||||
|
actualScrapTime: item.actualScrapTime,
|
||||||
|
statusChangeTime: item.statusChangeTime,
|
||||||
|
purchaseOrder: item.purchaseOrder,
|
||||||
|
supplierName: item.supplierName,
|
||||||
|
purchasePrice: item.purchasePrice,
|
||||||
|
currentNetValue: item.currentNetValue,
|
||||||
|
depreciationMethod: item.depreciationMethod,
|
||||||
|
depreciationYears: item.depreciationYears,
|
||||||
|
salvageValue: item.salvageValue,
|
||||||
|
warrantyExpireDate: item.warrantyExpireDate,
|
||||||
|
lastMaintenanceDate: item.lastMaintenanceDate,
|
||||||
|
nextMaintenanceDate: item.nextMaintenanceDate,
|
||||||
|
maintenancePerson: item.maintenancePerson,
|
||||||
|
inventoryBarcode: item.inventoryBarcode,
|
||||||
|
assetRemark: item.assetRemark,
|
||||||
|
projectId: item.projectId,
|
||||||
|
projectName: item.projectName,
|
||||||
|
userId: item.userId,
|
||||||
|
name: item.name,
|
||||||
|
createTime: item.createTime,
|
||||||
|
updateTime: item.updateTime,
|
||||||
|
accountNumber: item.accountNumber,
|
||||||
|
quantity: item.quantity,
|
||||||
|
unitPrice: item.unitPrice,
|
||||||
|
totalPrice: item.totalPrice,
|
||||||
|
inventoryBasis: item.inventoryBasis,
|
||||||
|
dynamicRecord: item.dynamicRecord,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
const loadData = async (searchParams?: EquipmentListReq) => {
|
||||||
|
console.log('📊 loadData - 开始加载数据')
|
||||||
|
console.log('📊 loadData - 接收到的搜索参数:', searchParams)
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const params: EquipmentListReq = {
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
page: pagination.current,
|
||||||
|
minPrice: undefined,
|
||||||
|
maxPrice: undefined,
|
||||||
|
...(searchParams || {}),
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('📊 loadData - 构建的完整请求参数:', params)
|
||||||
|
|
||||||
|
const res = await equipmentProcurementApi.page(params)
|
||||||
|
|
||||||
|
console.log('API响应:', res)
|
||||||
|
|
||||||
|
if (res.success || res.status === 200 || res.code === 200) {
|
||||||
|
let dataList: any[] = []
|
||||||
|
|
||||||
|
if (Array.isArray(res.data)) {
|
||||||
|
dataList = res.data
|
||||||
|
} else if (res.data && Array.isArray((res.data as any).records)) {
|
||||||
|
dataList = (res.data as any).records
|
||||||
|
} else if (res.data && Array.isArray((res.data as any).list)) {
|
||||||
|
dataList = (res.data as any).list
|
||||||
|
} else if (res.data && Array.isArray((res.data as any).rows)) {
|
||||||
|
dataList = (res.data as any).rows
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('处理后的数据列表:', dataList)
|
||||||
|
|
||||||
|
if (dataList.length > 0) {
|
||||||
|
const transformedData = transformBackendData(dataList)
|
||||||
|
console.log('转换后的数据:', transformedData)
|
||||||
|
tableData.value = transformedData
|
||||||
|
} else {
|
||||||
|
tableData.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
pagination.total = (res.data as any)?.total || (res as any).total || dataList.length || 0
|
||||||
|
console.log('总数:', pagination.total)
|
||||||
|
} else {
|
||||||
|
message.error(res.msg || '加载数据失败')
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('加载数据失败:', error)
|
||||||
|
message.error(error?.message || '加载数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const handleSearch = (searchParams: EquipmentListReq) => {
|
||||||
|
console.log('🔍 主组件 - 接收到的搜索参数:', searchParams)
|
||||||
|
pagination.current = 1
|
||||||
|
currentSearchParams.value = { ...searchParams }
|
||||||
|
loadData(searchParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const handleReset = () => {
|
||||||
|
console.log('🔄 主组件 - 重置操作')
|
||||||
|
pagination.current = 1
|
||||||
|
currentSearchParams.value = {
|
||||||
|
minPrice: undefined,
|
||||||
|
maxPrice: undefined
|
||||||
|
}
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格变化
|
||||||
|
const handleTableChange = (pag: any) => {
|
||||||
|
pagination.current = pag.current || 1
|
||||||
|
pagination.pageSize = pag.pageSize || 10
|
||||||
|
loadData(currentSearchParams.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增
|
||||||
|
const handleAdd = () => {
|
||||||
|
modalMode.value = 'add'
|
||||||
|
currentProcurement.value = null
|
||||||
|
modalVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看
|
||||||
|
const handleView = (record: EquipmentResp) => {
|
||||||
|
modalMode.value = 'view'
|
||||||
|
currentProcurement.value = { ...record }
|
||||||
|
modalVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (record: EquipmentResp) => {
|
||||||
|
modalMode.value = 'edit'
|
||||||
|
currentProcurement.value = { ...record }
|
||||||
|
modalVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (record: EquipmentResp) => {
|
||||||
|
try {
|
||||||
|
await equipmentProcurementApi.delete(record.equipmentId)
|
||||||
|
message.success('删除成功')
|
||||||
|
loadData(currentSearchParams.value)
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('删除失败:', error)
|
||||||
|
message.error(error?.message || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹窗成功回调
|
||||||
|
const handleModalSuccess = () => {
|
||||||
|
modalVisible.value = false
|
||||||
|
loadData(currentSearchParams.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = () => {
|
||||||
|
loadData(currentSearchParams.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出数据
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const response = await equipmentProcurementApi.export(currentSearchParams.value)
|
||||||
|
const blob = response.data || response
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = `设备采购记录_${new Date().toISOString().split('T')[0]}.xlsx`
|
||||||
|
link.click()
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
message.success('导出成功')
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('导出失败:', error)
|
||||||
|
message.error(error?.message || '导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计函数
|
||||||
|
const getPendingCount = () => {
|
||||||
|
return tableData.value.filter(item =>
|
||||||
|
item.equipmentStatus === 'pending' ||
|
||||||
|
item.locationStatus === 'pending'
|
||||||
|
).length
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCompletedCount = () => {
|
||||||
|
return tableData.value.filter(item =>
|
||||||
|
item.equipmentStatus === 'completed' ||
|
||||||
|
item.locationStatus === 'completed'
|
||||||
|
).length
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTotalAmount = () => {
|
||||||
|
const total = tableData.value.reduce((sum, item) => {
|
||||||
|
return sum + (item.purchasePrice || 0)
|
||||||
|
}, 0)
|
||||||
|
return formatPrice(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.equipment-procurement-container {
|
||||||
|
.page-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
.page-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
color: white;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-description {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
.arco-btn {
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 16px;
|
||||||
|
|
||||||
|
.arco-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-actions {
|
||||||
|
.arco-btn {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-table {
|
||||||
|
.arco-table-th {
|
||||||
|
background-color: var(--color-fill-2);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-table-tr:hover {
|
||||||
|
background-color: var(--color-fill-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-text {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
color: var(--color-text-4);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.equipment-procurement-container {
|
||||||
|
.page-header {
|
||||||
|
.header-content {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
margin-top: 16px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.arco-space {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container {
|
||||||
|
.arco-col {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,136 @@
|
||||||
|
<template>
|
||||||
|
<div class="procurement-test">
|
||||||
|
<a-card title="设备采购模块测试" :bordered="false">
|
||||||
|
<template #extra>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="testApi">
|
||||||
|
测试API
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="testSearch">
|
||||||
|
测试搜索
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="testAdd">
|
||||||
|
测试新增
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="test-results">
|
||||||
|
<h3>测试结果</h3>
|
||||||
|
<a-textarea
|
||||||
|
v-model="testResults"
|
||||||
|
:rows="10"
|
||||||
|
placeholder="测试结果将显示在这里..."
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="test-params">
|
||||||
|
<h3>测试参数</h3>
|
||||||
|
<a-form layout="vertical">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备名称">
|
||||||
|
<a-input v-model="testParams.equipmentName" placeholder="测试设备" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="设备型号">
|
||||||
|
<a-input v-model="testParams.equipmentModel" placeholder="测试型号" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item label="供应商">
|
||||||
|
<a-input v-model="testParams.supplierName" placeholder="测试供应商" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import { equipmentProcurementApi } from '@/apis/equipment/procurement'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProcurementTest' })
|
||||||
|
|
||||||
|
const testResults = ref('')
|
||||||
|
const testParams = reactive({
|
||||||
|
equipmentName: '测试设备',
|
||||||
|
equipmentModel: '测试型号',
|
||||||
|
supplierName: '测试供应商',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加测试结果
|
||||||
|
const addTestResult = (message: string) => {
|
||||||
|
const timestamp = new Date().toLocaleString()
|
||||||
|
testResults.value += `[${timestamp}] ${message}\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试API
|
||||||
|
const testApi = async () => {
|
||||||
|
try {
|
||||||
|
addTestResult('开始测试API...')
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
equipmentName: testParams.equipmentName,
|
||||||
|
equipmentModel: testParams.equipmentModel,
|
||||||
|
supplierName: testParams.supplierName,
|
||||||
|
}
|
||||||
|
|
||||||
|
addTestResult(`请求参数: ${JSON.stringify(params, null, 2)}`)
|
||||||
|
|
||||||
|
const response = await equipmentProcurementApi.page(params)
|
||||||
|
|
||||||
|
addTestResult(`API响应: ${JSON.stringify(response, null, 2)}`)
|
||||||
|
Message.success('API测试成功')
|
||||||
|
} catch (error: any) {
|
||||||
|
addTestResult(`API测试失败: ${error.message}`)
|
||||||
|
Message.error('API测试失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试搜索
|
||||||
|
const testSearch = () => {
|
||||||
|
addTestResult('测试搜索功能...')
|
||||||
|
addTestResult(`搜索参数: ${JSON.stringify(testParams, null, 2)}`)
|
||||||
|
Message.info('搜索测试完成')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试新增
|
||||||
|
const testAdd = () => {
|
||||||
|
addTestResult('测试新增功能...')
|
||||||
|
addTestResult(`新增参数: ${JSON.stringify(testParams, null, 2)}`)
|
||||||
|
Message.info('新增测试完成')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.procurement-test {
|
||||||
|
.test-results {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-params {
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue