Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f38676af7 | ||
|
|
9ea698e86c | ||
|
|
9b0890d195 | ||
|
|
ff0566bb7f | ||
|
|
db106834a7 | ||
|
|
3be088e370 | ||
|
|
8f14355903 | ||
|
|
74a66b7c70 | ||
|
|
1bc4eefeab | ||
|
|
560a336f8c | ||
|
|
9a4d1dcbce | ||
|
|
f413556c73 | ||
|
|
8d23c38f2f | ||
|
|
fe61119735 | ||
|
|
d884f71d57 | ||
|
|
f8580fdf2a | ||
|
|
ca8858a33f | ||
|
|
4e39c11d7c | ||
|
|
4231a7d133 | ||
|
|
aebb04a7c2 | ||
|
|
1a5e7902b8 | ||
|
|
8d88f4206b | ||
|
|
035bccb472 | ||
|
|
776846febc | ||
|
|
1694827c6c | ||
|
|
32d5892422 | ||
|
|
9e86e47c1c | ||
|
|
c0eaad3a4b | ||
|
|
249fe126ee | ||
|
|
c792e69aa5 | ||
|
|
d220ffae6a | ||
|
|
154f84a89e | ||
|
|
25665f548e | ||
|
|
c5e5228e78 | ||
|
|
5369328b37 | ||
|
|
70bf234133 | ||
|
|
56d92e5bfb | ||
|
|
fee444d191 | ||
|
|
5cb86589c6 | ||
|
|
f30f71b775 | ||
|
|
174724da98 | ||
|
|
d9e1ffd522 | ||
|
|
41e5cf667e | ||
|
|
6725318f27 | ||
|
|
12972cdf5c | ||
|
|
dcfe1abb67 | ||
|
|
6caa94ec47 | ||
|
|
8f8591fc45 | ||
|
|
43bdb3cdba | ||
|
|
7164ae5d49 | ||
|
|
28eb23738c | ||
|
|
a9e4ef9b7b | ||
|
|
56db6bf307 | ||
|
|
c1f507bcae | ||
|
|
9acd01e768 | ||
|
|
3bfdb2df33 | ||
|
|
9d44b9acaa | ||
|
|
11766f5107 | ||
|
|
bbf6c16b8d | ||
|
|
cf7036d34b | ||
|
|
8512fe6b43 | ||
|
|
01684aa6e8 | ||
|
|
29605800b5 | ||
|
|
6baeadc87a | ||
|
|
a2443e48f7 | ||
|
|
08bb022cb5 | ||
|
|
094b1925d6 | ||
|
|
a401fff74c | ||
|
|
4362251b59 | ||
|
|
ac9a77e6e4 | ||
|
|
04a42bc6d4 | ||
|
|
0ae6139e92 | ||
|
|
1047c5b097 | ||
|
|
e7bb17dc4e | ||
|
|
c804ec5e7a | ||
|
|
f5b8d92d97 | ||
|
|
f01bb2dc78 | ||
|
|
cd86c08e59 | ||
|
|
e067d5073d | ||
|
|
42b8df4767 | ||
|
|
ea68da9d8e | ||
|
|
71ac59f22e | ||
|
|
a3b21e70dc | ||
|
|
1549a57c4b | ||
|
|
d3fab9a0fd | ||
|
|
ffeaa891df | ||
|
|
a3e95b56ca | ||
|
|
b603515855 | ||
|
|
06e2019adf | ||
|
|
2f37232f5e | ||
|
|
6e9e9e88a8 | ||
|
|
a0497a6485 | ||
|
|
96071bdcb7 | ||
|
|
8d532dfc3a | ||
|
|
a451c0b7c8 | ||
|
|
6fd8856735 | ||
|
|
2a1e6518e2 | ||
|
|
bb6d6dac79 | ||
|
|
c1c48c20a3 | ||
|
|
c18b24e611 | ||
|
|
e07e19106c | ||
|
|
a2de0665eb | ||
|
|
e951ed1bd1 | ||
|
|
8a70b3fbba | ||
|
|
d7427bf49c | ||
|
|
aa964e17d6 | ||
|
|
58972e0b98 | ||
|
|
fcba2b4c48 | ||
|
|
db446330c3 | ||
|
|
ee35056767 | ||
|
|
57044cb716 | ||
|
|
3d4feeff6b | ||
|
|
5339cca40e | ||
|
|
600892b112 | ||
|
|
eae2ea0a82 | ||
|
|
3860aaef6f | ||
|
|
949096f776 | ||
|
|
5736083534 | ||
|
|
00a386dd7c | ||
|
|
c0db4df880 | ||
|
|
e535384f45 | ||
|
|
f7c5266015 | ||
|
|
b25d9c0f09 | ||
|
|
5deabcf692 | ||
|
|
ab63660bf8 | ||
|
|
2615054fb2 | ||
|
|
b55c8417fb | ||
|
|
14ab46c870 | ||
|
|
0319056e4b | ||
|
|
ae3d44d8bd | ||
|
|
3c4932bc77 | ||
|
|
896f9758ed | ||
|
|
616fd3f7ba | ||
|
|
318d5261ad | ||
|
|
3308a494c7 | ||
|
|
1c98deaf27 | ||
|
|
115c30ea40 | ||
|
|
361c06bd6f | ||
|
|
5bdf0fc0ff | ||
|
|
9cbdfe0ecb | ||
|
|
53c94af027 | ||
|
|
d92404f351 | ||
|
|
26343635e4 | ||
|
|
6d9ca290b3 | ||
|
|
36a0330277 | ||
|
|
3cdcd67a6a | ||
|
|
e033793a94 | ||
|
|
89fdb5ced9 | ||
|
|
ce9317e3d0 | ||
|
|
dd08fbcb46 | ||
|
|
490bb901e1 | ||
|
|
cac39ae126 | ||
|
|
6d0231d409 | ||
|
|
3ad68c3227 | ||
|
|
fffc9aed63 | ||
|
|
fe91c5ec5c | ||
|
|
6d0e242387 | ||
|
|
4549f8ed3c | ||
|
|
d6438943b8 | ||
|
|
956f19d9d0 | ||
|
|
34a796de89 | ||
|
|
9d9cdf427a | ||
|
|
a5f8c3d79c | ||
|
|
4271788a83 | ||
|
|
f0a2c529b2 | ||
|
|
df7806d8d3 | ||
|
|
770e551900 | ||
|
|
41195d5b4a | ||
|
|
668da2fa86 | ||
|
|
90e0baf5bc | ||
|
|
4a2349ecf5 | ||
|
|
331b6c5611 | ||
|
|
ed94205fa7 | ||
|
|
a64d4240a3 | ||
|
|
5adf75d15b | ||
|
|
26daa3a1ff | ||
|
|
6203744272 | ||
|
|
acc3a6bcfd | ||
|
|
b3ed46db72 | ||
|
|
64cfcbf6e0 | ||
|
|
24062c7a3b | ||
|
|
530107eba7 | ||
|
|
bc934f56ad | ||
|
|
66ff10d00c | ||
|
|
213af427a2 | ||
|
|
e0bc3ea6dc | ||
|
|
3471b5c5b2 | ||
|
|
c38bbb99a1 | ||
|
|
7c0c651592 | ||
|
|
d735f782fc | ||
|
|
24e8bd4c47 | ||
|
|
9628517b8b | ||
|
|
f88b26e3c3 | ||
|
|
040b80b35f | ||
|
|
48693b50f2 | ||
|
|
39da43cc7d | ||
|
|
e106fb73b6 | ||
|
|
c2038b95bf | ||
|
|
89dbb8c9e8 |
No files matched your search
@@ -13,5 +13,8 @@ VITE_APP_TENANT_ENABLE=true
|
|||||||
# 验证码的开关
|
# 验证码的开关
|
||||||
VITE_APP_CAPTCHA_ENABLE=true
|
VITE_APP_CAPTCHA_ENABLE=true
|
||||||
|
|
||||||
|
# 文档地址的开关
|
||||||
|
VITE_APP_DOCALERT_ENABLE=true
|
||||||
|
|
||||||
# 百度统计
|
# 百度统计
|
||||||
VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc
|
VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc
|
||||||
@@ -7,6 +7,8 @@ VITE_DEV=true
|
|||||||
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
||||||
# VITE_BASE_URL='http://dofast.demo.huizhizao.vip:20001'
|
# VITE_BASE_URL='http://dofast.demo.huizhizao.vip:20001'
|
||||||
|
|
||||||
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
|
VITE_UPLOAD_TYPE=server
|
||||||
# 上传路径
|
# 上传路径
|
||||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ VITE_DEV=true
|
|||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://localhost:48080'
|
VITE_BASE_URL='http://localhost:48080'
|
||||||
|
|
||||||
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||||
|
VITE_UPLOAD_TYPE=server
|
||||||
# 上传路径
|
# 上传路径
|
||||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ VITE_DEV=false
|
|||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://localhost:48080'
|
VITE_BASE_URL='http://localhost:48080'
|
||||||
|
|
||||||
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
|
VITE_UPLOAD_TYPE=server
|
||||||
# 上传路径
|
# 上传路径
|
||||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ VITE_DEV=false
|
|||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
||||||
|
|
||||||
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
|
VITE_UPLOAD_TYPE=server
|
||||||
# 上传路径
|
# 上传路径
|
||||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ VITE_DEV=false
|
|||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://localhost:48080'
|
VITE_BASE_URL='http://localhost:48080'
|
||||||
|
|
||||||
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
|
VITE_UPLOAD_TYPE=server
|
||||||
# 上传路径
|
# 上传路径
|
||||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -68,6 +68,8 @@ module.exports = defineConfig({
|
|||||||
],
|
],
|
||||||
'vue/multi-word-component-names': 'off',
|
'vue/multi-word-component-names': 'off',
|
||||||
'vue/no-v-html': 'off',
|
'vue/no-v-html': 'off',
|
||||||
'prettier/prettier': 'off' // 芋艿:默认关闭 prettier 的 ESLint 校验,因为我们使用的是 IDE 的 Prettier 插件
|
'prettier/prettier': 'off', // 芋艿:默认关闭 prettier 的 ESLint 校验,因为我们使用的是 IDE 的 Prettier 插件
|
||||||
|
'@unocss/order': 'off', // 芋艿:禁用 unocss 【css】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
|
||||||
|
'@unocss/order-attributify': 'off' // 芋艿:禁用 unocss 【属性】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -90,6 +90,8 @@
|
|||||||
* 数据报表
|
* 数据报表
|
||||||
* 商城系统
|
* 商城系统
|
||||||
* 微信公众号
|
* 微信公众号
|
||||||
|
* ERP 系统
|
||||||
|
* CRM 系统
|
||||||
|
|
||||||
### 系统功能
|
### 系统功能
|
||||||
|
|
||||||
@@ -194,6 +196,18 @@ _前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋
|
|||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/mall-preview/>
|
演示地址:<https://doc.iocoder.cn/mall-preview/>
|
||||||
|
|
||||||
|
### ERP 系统
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
演示地址:<https://doc.iocoder.cn/erp-preview/>
|
||||||
|
|
||||||
|
### CRM 系统
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
演示地址:<https://doc.iocoder.cn/crm-preview/>
|
||||||
|
|
||||||
## 🐷 演示图
|
## 🐷 演示图
|
||||||
|
|
||||||
### 系统功能
|
### 系统功能
|
||||||
@@ -238,6 +252,7 @@ _前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋
|
|||||||
|---------|---------------------------|---------------------------------|---------------------------------|
|
|---------|---------------------------|---------------------------------|---------------------------------|
|
||||||
| 商家 & 应用 |  |  |  |
|
| 商家 & 应用 |  |  |  |
|
||||||
| 支付 & 退款 |  |  | --- |
|
| 支付 & 退款 |  |  | --- |
|
||||||
|
|
||||||
### 数据报表
|
### 数据报表
|
||||||
|
|
||||||
| 模块 | biu | biu | biu |
|
| 模块 | biu | biu | biu |
|
||||||
|
|||||||
+44
-43
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yudao-ui-admin-vue3",
|
"name": "yudao-ui-admin-vue3",
|
||||||
"version": "2.0.0-snapshot",
|
"version": "2.0.1-snapshot",
|
||||||
"description": "基于vue3、vite4、element-plus、typesScript",
|
"description": "基于vue3、vite4、element-plus、typesScript",
|
||||||
"author": "xingyu",
|
"author": "xingyu",
|
||||||
"private": false,
|
"private": false,
|
||||||
@@ -30,12 +30,12 @@
|
|||||||
"@form-create/element-ui": "^3.1.24",
|
"@form-create/element-ui": "^3.1.24",
|
||||||
"@iconify/iconify": "^3.1.1",
|
"@iconify/iconify": "^3.1.1",
|
||||||
"@videojs-player/vue": "^1.0.0",
|
"@videojs-player/vue": "^1.0.0",
|
||||||
"@vueuse/core": "^10.6.1",
|
"@vueuse/core": "^10.9.0",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||||
"@zxcvbn-ts/core": "^3.0.4",
|
"@zxcvbn-ts/core": "^3.0.4",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^1.6.1",
|
"axios": "^1.6.7",
|
||||||
"benz-amr-recorder": "^1.1.5",
|
"benz-amr-recorder": "^1.1.5",
|
||||||
"bpmn-js-token-simulation": "^0.10.0",
|
"bpmn-js-token-simulation": "^0.10.0",
|
||||||
"camunda-bpmn-moddle": "^7.0.1",
|
"camunda-bpmn-moddle": "^7.0.1",
|
||||||
@@ -44,9 +44,9 @@
|
|||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"diagram-js": "^12.8.0",
|
"diagram-js": "^12.8.0",
|
||||||
"driver.js": "^1.3.1",
|
"driver.js": "^1.3.1",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.5.0",
|
||||||
"echarts-wordcloud": "^2.1.0",
|
"echarts-wordcloud": "^2.1.0",
|
||||||
"element-plus": "2.4.2",
|
"element-plus": "2.5.3",
|
||||||
"fast-xml-parser": "^4.3.2",
|
"fast-xml-parser": "^4.3.2",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
@@ -55,76 +55,77 @@
|
|||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"qs": "^6.11.2",
|
"qs": "^6.11.2",
|
||||||
"steady-xml": "^0.1.0",
|
"steady-xml": "^0.1.0",
|
||||||
"url": "^0.11.3",
|
"url": "^0.11.3",
|
||||||
"video.js": "^7.21.5",
|
"video.js": "^7.21.5",
|
||||||
"vue": "^3.3.8",
|
"vue": "3.4.20",
|
||||||
"vue-dompurify-html": "^4.1.4",
|
"vue-dompurify-html": "^4.1.4",
|
||||||
"vue-i18n": "^9.6.5",
|
"vue-i18n": "9.9.1",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.3.0",
|
||||||
"vue-types": "^5.1.1",
|
"vue-types": "^5.1.1",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"web-storage-cache": "^1.1.1",
|
"web-storage-cache": "^1.1.1",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^18.4.1",
|
"@commitlint/cli": "^19.0.1",
|
||||||
"@commitlint/config-conventional": "^18.4.0",
|
"@commitlint/config-conventional": "^19.0.0",
|
||||||
"@iconify/json": "^2.2.142",
|
"@iconify/json": "^2.2.187",
|
||||||
"@intlify/unplugin-vue-i18n": "^1.5.0",
|
"@intlify/unplugin-vue-i18n": "^2.0.0",
|
||||||
"@purge-icons/generated": "^0.9.0",
|
"@purge-icons/generated": "^0.9.0",
|
||||||
"@types/lodash-es": "^4.17.11",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.9.0",
|
"@types/node": "^20.11.21",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/qrcode": "^1.5.5",
|
"@types/qrcode": "^1.5.5",
|
||||||
"@types/qs": "^6.9.10",
|
"@types/qs": "^6.9.12",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||||
"@typescript-eslint/parser": "^6.11.0",
|
"@typescript-eslint/parser": "^7.1.0",
|
||||||
"@unocss/transformer-variant-group": "^0.57.4",
|
"@unocss/transformer-variant-group": "^0.58.5",
|
||||||
"@unocss/eslint-config": "^0.57.4",
|
"@unocss/eslint-config": "^0.57.4",
|
||||||
"@vitejs/plugin-legacy": "^4.1.1",
|
"@vitejs/plugin-legacy": "^5.3.1",
|
||||||
"@vitejs/plugin-vue": "^4.4.1",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.17",
|
||||||
"bpmn-js": "8.9.0",
|
"bpmn-js": "8.9.0",
|
||||||
"bpmn-js-properties-panel": "0.46.0",
|
"bpmn-js-properties-panel": "0.46.0",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"eslint": "^8.53.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-define-config": "^1.24.1",
|
"eslint-define-config": "^2.1.0",
|
||||||
"eslint-plugin-prettier": "^5.0.1",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-vue": "^9.18.1",
|
"eslint-plugin-vue": "^9.22.0",
|
||||||
"lint-staged": "^15.1.0",
|
"lint-staged": "^15.2.2",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.35",
|
||||||
"postcss-html": "^1.5.0",
|
"postcss-html": "^1.6.0",
|
||||||
"postcss-scss": "^4.0.9",
|
"postcss-scss": "^4.0.9",
|
||||||
"prettier": "^3.1.0",
|
"prettier": "^3.2.5",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"rollup": "^4.4.1",
|
"rollup": "^4.12.0",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"stylelint": "^15.11.0",
|
"stylelint": "^16.2.1",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-recommended": "^13.0.0",
|
"stylelint-config-recommended": "^14.0.0",
|
||||||
"stylelint-config-standard": "^34.0.0",
|
"stylelint-config-standard": "^36.0.0",
|
||||||
"stylelint-order": "^6.0.3",
|
"stylelint-order": "^6.0.4",
|
||||||
"terser": "^5.24.0",
|
"terser": "^5.28.1",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.3.3",
|
||||||
"unocss": "^0.57.4",
|
"unocss": "^0.58.5",
|
||||||
"unplugin-auto-import": "^0.16.7",
|
"unplugin-auto-import": "^0.16.7",
|
||||||
"unplugin-element-plus": "^0.8.0",
|
"unplugin-element-plus": "^0.8.0",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "4.5.0",
|
"vite": "5.1.4",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-ejs": "^1.6.4",
|
"vite-plugin-ejs": "^1.7.0",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vite-plugin-progress": "^0.0.7",
|
"vite-plugin-progress": "^0.0.7",
|
||||||
"vite-plugin-purge-icons": "^0.9.2",
|
"vite-plugin-purge-icons": "^0.10.0",
|
||||||
"vite-plugin-svg-icons": "^2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vite-plugin-top-level-await": "^1.3.1",
|
"vite-plugin-top-level-await": "^1.3.1",
|
||||||
"vue-eslint-parser": "^9.3.2",
|
"vue-eslint-parser": "^9.3.2",
|
||||||
"vue-tsc": "^1.8.22"
|
"vue-tsc": "^1.8.27"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -1,24 +1,45 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
import { TransferReqVO } from '@/api/crm/customer'
|
||||||
|
|
||||||
export interface BusinessVO {
|
export interface BusinessVO {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
statusTypeId: number
|
|
||||||
statusId: number
|
|
||||||
contactNextTime: Date
|
|
||||||
customerId: number
|
customerId: number
|
||||||
dealTime: Date
|
customerName?: string
|
||||||
price: number
|
followUpStatus: boolean
|
||||||
discountPercent: number
|
contactLastTime: Date
|
||||||
productPrice: number
|
contactNextTime: Date
|
||||||
remark: string
|
|
||||||
ownerUserId: number
|
ownerUserId: number
|
||||||
roUserIds: string
|
ownerUserName?: string // 负责人的用户名称
|
||||||
rwUserIds: string
|
ownerUserDept?: string // 负责人的部门名称
|
||||||
|
statusTypeId: number
|
||||||
|
statusTypeName?: string
|
||||||
|
statusId: number
|
||||||
|
statusName?: string
|
||||||
endStatus: number
|
endStatus: number
|
||||||
endRemark: string
|
endRemark: string
|
||||||
contactLastTime: Date
|
dealTime: Date
|
||||||
followUpStatus: number
|
totalProductPrice: number
|
||||||
|
totalPrice: number
|
||||||
|
discountPercent: number
|
||||||
|
remark: string
|
||||||
|
creator: string // 创建人
|
||||||
|
creatorName?: string // 创建人名称
|
||||||
|
createTime: Date // 创建时间
|
||||||
|
updateTime: Date // 更新时间
|
||||||
|
products?: [
|
||||||
|
{
|
||||||
|
id: number
|
||||||
|
productId: number
|
||||||
|
productName: string
|
||||||
|
productNo: string
|
||||||
|
productUnit: number
|
||||||
|
productPrice: number
|
||||||
|
businessPrice: number
|
||||||
|
count: number
|
||||||
|
totalPrice: number
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询 CRM 商机列表
|
// 查询 CRM 商机列表
|
||||||
@@ -51,6 +72,11 @@ export const updateBusiness = async (data: BusinessVO) => {
|
|||||||
return await request.put({ url: `/crm/business/update`, data })
|
return await request.put({ url: `/crm/business/update`, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改 CRM 商机状态
|
||||||
|
export const updateBusinessStatus = async (data: BusinessVO) => {
|
||||||
|
return await request.put({ url: `/crm/business/update-status`, data })
|
||||||
|
}
|
||||||
|
|
||||||
// 删除 CRM 商机
|
// 删除 CRM 商机
|
||||||
export const deleteBusiness = async (id: number) => {
|
export const deleteBusiness = async (id: number) => {
|
||||||
return await request.delete({ url: `/crm/business/delete?id=` + id })
|
return await request.delete({ url: `/crm/business/delete?id=` + id })
|
||||||
@@ -66,7 +92,7 @@ export const getBusinessPageByContact = async (params) => {
|
|||||||
return await request.get({ url: `/crm/business/page-by-contact`, params })
|
return await request.get({ url: `/crm/business/page-by-contact`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得 CRM 商机列表
|
// 商机转移
|
||||||
export const getBusinessListByIds = async (val: number[]) => {
|
export const transferBusiness = async (data: TransferReqVO) => {
|
||||||
return await request.get({ url: '/crm/business/list-by-ids', params: { ids: val.join(',') } })
|
return await request.put({ url: '/crm/business/transfer', data })
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface BusinessStatusTypeVO {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
deptIds: number[]
|
||||||
|
statuses?: {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
percent: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_STATUSES = [
|
||||||
|
{
|
||||||
|
endStatus: 1,
|
||||||
|
key: '结束',
|
||||||
|
name: '赢单',
|
||||||
|
percent: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endStatus: 2,
|
||||||
|
key: '结束',
|
||||||
|
name: '输单',
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endStatus: 3,
|
||||||
|
key: '结束',
|
||||||
|
name: '无效',
|
||||||
|
percent: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 查询商机状态组列表
|
||||||
|
export const getBusinessStatusPage = async (params: any) => {
|
||||||
|
return await request.get({ url: `/crm/business-status/page`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增商机状态组
|
||||||
|
export const createBusinessStatus = async (data: BusinessStatusTypeVO) => {
|
||||||
|
return await request.post({ url: `/crm/business-status/create`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改商机状态组
|
||||||
|
export const updateBusinessStatus = async (data: BusinessStatusTypeVO) => {
|
||||||
|
return await request.put({ url: `/crm/business-status/update`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询商机状态类型详情
|
||||||
|
export const getBusinessStatus = async (id: number) => {
|
||||||
|
return await request.get({ url: `/crm/business-status/get?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除商机状态
|
||||||
|
export const deleteBusinessStatus = async (id: number) => {
|
||||||
|
return await request.delete({ url: `/crm/business-status/delete?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得商机状态组列表
|
||||||
|
export const getBusinessStatusTypeSimpleList = async () => {
|
||||||
|
return await request.get({ url: `/crm/business-status/type-simple-list` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得商机阶段列表
|
||||||
|
export const getBusinessStatusSimpleList = async (typeId: number) => {
|
||||||
|
return await request.get({ url: `/crm/business-status/status-simple-list`, params: { typeId } })
|
||||||
|
}
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import request from '@/config/axios'
|
|
||||||
|
|
||||||
export interface BusinessStatusTypeVO {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
deptIds: number[]
|
|
||||||
status: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询商机状态类型列表
|
|
||||||
export const getBusinessStatusTypePage = async (params) => {
|
|
||||||
return await request.get({ url: `/crm/business-status-type/page`, params })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询商机状态类型详情
|
|
||||||
export const getBusinessStatusType = async (id: number) => {
|
|
||||||
return await request.get({ url: `/crm/business-status-type/get?id=` + id })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增商机状态类型
|
|
||||||
export const createBusinessStatusType = async (data: BusinessStatusTypeVO) => {
|
|
||||||
return await request.post({ url: `/crm/business-status-type/create`, data })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改商机状态类型
|
|
||||||
export const updateBusinessStatusType = async (data: BusinessStatusTypeVO) => {
|
|
||||||
return await request.put({ url: `/crm/business-status-type/update`, data })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除商机状态类型
|
|
||||||
export const deleteBusinessStatusType = async (id: number) => {
|
|
||||||
return await request.delete({ url: `/crm/business-status-type/delete?id=` + id })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出商机状态类型 Excel
|
|
||||||
export const exportBusinessStatusType = async (params) => {
|
|
||||||
return await request.download({ url: `/crm/business-status-type/export-excel`, params })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取商机状态类型信息列表
|
|
||||||
export const getBusinessStatusTypeList = async () => {
|
|
||||||
return await request.get({ url: `/crm/business-status-type/get-simple-list` })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据类型ID获取商机状态信息列表
|
|
||||||
export const getBusinessStatusListByTypeId = async (typeId: number) => {
|
|
||||||
return await request.get({ url: `/crm/business-status-type/get-status-list?typeId=` + typeId })
|
|
||||||
}
|
|
||||||
+45
-13
@@ -1,22 +1,39 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
import { TransferReqVO } from '@/api/crm/customer'
|
||||||
|
|
||||||
export interface ClueVO {
|
export interface ClueVO {
|
||||||
id: number
|
id: number // 编号
|
||||||
transformStatus: boolean
|
name: string // 线索名称
|
||||||
followUpStatus: boolean
|
followUpStatus: boolean // 跟进状态
|
||||||
name: string
|
contactLastTime: Date // 最后跟进时间
|
||||||
customerId: number
|
contactLastContent: string // 最后跟进内容
|
||||||
contactNextTime: Date
|
contactNextTime: Date // 下次联系时间
|
||||||
telephone: string
|
ownerUserId: number // 负责人的用户编号
|
||||||
mobile: string
|
ownerUserName?: string // 负责人的用户名称
|
||||||
address: string
|
ownerUserDept?: string // 负责人的部门名称
|
||||||
ownerUserId: number
|
transformStatus: boolean // 转化状态
|
||||||
contactLastTime: Date
|
customerId: number // 客户编号
|
||||||
remark: string
|
customerName?: string // 客户名称
|
||||||
|
mobile: string // 手机号
|
||||||
|
telephone: string // 电话
|
||||||
|
qq: string // QQ
|
||||||
|
wechat: string // wechat
|
||||||
|
email: string // email
|
||||||
|
areaId: number // 所在地
|
||||||
|
areaName?: string // 所在地名称
|
||||||
|
detailAddress: string // 详细地址
|
||||||
|
industryId: number // 所属行业
|
||||||
|
level: number // 客户等级
|
||||||
|
source: number // 客户来源
|
||||||
|
remark: string // 备注
|
||||||
|
creator: string // 创建人
|
||||||
|
creatorName?: string // 创建人名称
|
||||||
|
createTime: Date // 创建时间
|
||||||
|
updateTime: Date // 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询线索列表
|
// 查询线索列表
|
||||||
export const getCluePage = async (params) => {
|
export const getCluePage = async (params: any) => {
|
||||||
return await request.get({ url: `/crm/clue/page`, params })
|
return await request.get({ url: `/crm/clue/page`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,3 +61,18 @@ export const deleteClue = async (id: number) => {
|
|||||||
export const exportClue = async (params) => {
|
export const exportClue = async (params) => {
|
||||||
return await request.download({ url: `/crm/clue/export-excel`, params })
|
return await request.download({ url: `/crm/clue/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 线索转移
|
||||||
|
export const transferClue = async (data: TransferReqVO) => {
|
||||||
|
return await request.put({ url: '/crm/clue/transfer', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 线索转化为客户
|
||||||
|
export const transformClue = async (id: number) => {
|
||||||
|
return await request.put({ url: '/crm/clue/transform', params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得分配给我的、待跟进的线索数量
|
||||||
|
export const getFollowClueCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/clue/follow-count' })
|
||||||
|
}
|
||||||
@@ -1,29 +1,35 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
import { TransferReqVO } from '@/api/crm/customer'
|
||||||
|
|
||||||
export interface ContactVO {
|
export interface ContactVO {
|
||||||
name: string
|
id: number // 编号
|
||||||
nextTime: Date
|
name: string // 联系人名称
|
||||||
mobile: string
|
customerId: number // 客户编号
|
||||||
telephone: string
|
customerName?: string // 客户名称
|
||||||
email: string
|
contactLastTime: Date // 最后跟进时间
|
||||||
post: string
|
contactLastContent: string // 最后跟进内容
|
||||||
customerId: number
|
contactNextTime: Date // 下次联系时间
|
||||||
detailAddress: string
|
ownerUserId: number // 负责人的用户编号
|
||||||
remark: string
|
ownerUserName?: string // 负责人的用户名称
|
||||||
ownerUserId: string
|
ownerUserDept?: string // 负责人的部门名称
|
||||||
lastTime: Date
|
mobile: string // 手机号
|
||||||
id: number
|
telephone: string // 电话
|
||||||
parentId: number
|
qq: string // QQ
|
||||||
qq: number
|
wechat: string // wechat
|
||||||
wechat: string
|
email: string // email
|
||||||
sex: number
|
areaId: number // 所在地
|
||||||
master: boolean
|
areaName?: string // 所在地名称
|
||||||
creatorName: string
|
detailAddress: string // 详细地址
|
||||||
updateTime?: Date
|
sex: number // 性别
|
||||||
createTime?: Date
|
master: boolean // 是否主联系人
|
||||||
customerName: string
|
post: string // 职务
|
||||||
areaName: string
|
parentId: number // 上级联系人编号
|
||||||
ownerUserName: string
|
parentName?: string // 上级联系人名称
|
||||||
|
remark: string // 备注
|
||||||
|
creator: string // 创建人
|
||||||
|
creatorName?: string // 创建人名称
|
||||||
|
createTime: Date // 创建时间
|
||||||
|
updateTime: Date // 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContactBusinessReqVO {
|
export interface ContactBusinessReqVO {
|
||||||
@@ -31,6 +37,11 @@ export interface ContactBusinessReqVO {
|
|||||||
businessIds: number[]
|
businessIds: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ContactBusiness2ReqVO {
|
||||||
|
businessId: number
|
||||||
|
contactIds: number[]
|
||||||
|
}
|
||||||
|
|
||||||
// 查询 CRM 联系人列表
|
// 查询 CRM 联系人列表
|
||||||
export const getContactPage = async (params) => {
|
export const getContactPage = async (params) => {
|
||||||
return await request.get({ url: `/crm/contact/page`, params })
|
return await request.get({ url: `/crm/contact/page`, params })
|
||||||
@@ -41,6 +52,11 @@ export const getContactPageByCustomer = async (params: any) => {
|
|||||||
return await request.get({ url: `/crm/contact/page-by-customer`, params })
|
return await request.get({ url: `/crm/contact/page-by-customer`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 联系人列表,基于指定商机
|
||||||
|
export const getContactPageByBusiness = async (params: any) => {
|
||||||
|
return await request.get({ url: `/crm/contact/page-by-business`, params })
|
||||||
|
}
|
||||||
|
|
||||||
// 查询 CRM 联系人详情
|
// 查询 CRM 联系人详情
|
||||||
export const getContact = async (id: number) => {
|
export const getContact = async (id: number) => {
|
||||||
return await request.get({ url: `/crm/contact/get?id=` + id })
|
return await request.get({ url: `/crm/contact/get?id=` + id })
|
||||||
@@ -71,22 +87,27 @@ export const getSimpleContactList = async () => {
|
|||||||
return await request.get({ url: `/crm/contact/simple-all-list` })
|
return await request.get({ url: `/crm/contact/simple-all-list` })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得 CRM 联系人列表
|
|
||||||
export const getContactListByIds = async (val: number[]) => {
|
|
||||||
return await request.get({ url: '/crm/contact/list-by-ids', params: { ids: val.join(',') } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量新增联系人商机关联
|
// 批量新增联系人商机关联
|
||||||
export const createContactBusinessList = async (data: ContactBusinessReqVO) => {
|
export const createContactBusinessList = async (data: ContactBusinessReqVO) => {
|
||||||
return await request.post({ url: `/crm/contact/create-business-list`, data })
|
return await request.post({ url: `/crm/contact/create-business-list`, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量新增联系人商机关联
|
||||||
|
export const createContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
|
||||||
|
return await request.post({ url: `/crm/contact/create-business-list2`, data })
|
||||||
|
}
|
||||||
|
|
||||||
// 解除联系人商机关联
|
// 解除联系人商机关联
|
||||||
export const deleteContactBusinessList = async (data: ContactBusinessReqVO) => {
|
export const deleteContactBusinessList = async (data: ContactBusinessReqVO) => {
|
||||||
return await request.delete({ url: `/crm/contact/delete-business-list`, data })
|
return await request.delete({ url: `/crm/contact/delete-business-list`, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询联系人操作日志
|
// 解除联系人商机关联
|
||||||
export const getOperateLogPage = async (params: any) => {
|
export const deleteContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
|
||||||
return await request.get({ url: '/crm/contact/operate-log-page', params })
|
return await request.delete({ url: `/crm/contact/delete-business-list2`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 联系人转移
|
||||||
|
export const transferContact = async (data: TransferReqVO) => {
|
||||||
|
return await request.put({ url: '/crm/contact/transfer', data })
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface ContractConfigVO {
|
||||||
|
notifyEnabled?: boolean
|
||||||
|
notifyDays?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取合同配置
|
||||||
|
export const getContractConfig = async () => {
|
||||||
|
return await request.get({ url: `/crm/contract-config/get` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新合同配置
|
||||||
|
export const saveContractConfig = async (data: ContractConfigVO) => {
|
||||||
|
return await request.put({ url: `/crm/contract-config/save`, data })
|
||||||
|
}
|
||||||
@@ -1,25 +1,49 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
import { TransferReqVO } from '@/api/crm/customer'
|
||||||
|
|
||||||
export interface ContractVO {
|
export interface ContractVO {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
customerId: number
|
|
||||||
businessId: number
|
|
||||||
processInstanceId: number
|
|
||||||
orderDate: Date
|
|
||||||
ownerUserId: number
|
|
||||||
no: string
|
no: string
|
||||||
|
customerId: number
|
||||||
|
customerName?: string
|
||||||
|
businessId: number
|
||||||
|
businessName: string
|
||||||
|
contactLastTime: Date
|
||||||
|
ownerUserId: number
|
||||||
|
ownerUserName?: string
|
||||||
|
ownerUserDeptName?: string
|
||||||
|
processInstanceId: number
|
||||||
|
auditStatus: number
|
||||||
|
orderDate: Date
|
||||||
startTime: Date
|
startTime: Date
|
||||||
endTime: Date
|
endTime: Date
|
||||||
price: number
|
totalProductPrice: number
|
||||||
discountPercent: number
|
discountPercent: number
|
||||||
productPrice: number
|
totalPrice: number
|
||||||
roUserIds: string
|
totalReceivablePrice: number
|
||||||
rwUserIds: string
|
signContactId: number
|
||||||
contactId: number
|
signContactName?: string
|
||||||
signUserId: number
|
signUserId: number
|
||||||
contactLastTime: Date
|
signUserName: string
|
||||||
remark: string
|
remark: string
|
||||||
|
createTime?: Date
|
||||||
|
creator: string
|
||||||
|
creatorName: string
|
||||||
|
updateTime?: Date
|
||||||
|
products?: [
|
||||||
|
{
|
||||||
|
id: number
|
||||||
|
productId: number
|
||||||
|
productName: string
|
||||||
|
productNo: string
|
||||||
|
productUnit: number
|
||||||
|
productPrice: number
|
||||||
|
contractPrice: number
|
||||||
|
count: number
|
||||||
|
totalPrice: number
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询 CRM 合同列表
|
// 查询 CRM 合同列表
|
||||||
@@ -32,11 +56,23 @@ export const getContractPageByCustomer = async (params: any) => {
|
|||||||
return await request.get({ url: `/crm/contract/page-by-customer`, params })
|
return await request.get({ url: `/crm/contract/page-by-customer`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 联系人列表,基于指定商机
|
||||||
|
export const getContractPageByBusiness = async (params: any) => {
|
||||||
|
return await request.get({ url: `/crm/contract/page-by-business`, params })
|
||||||
|
}
|
||||||
|
|
||||||
// 查询 CRM 合同详情
|
// 查询 CRM 合同详情
|
||||||
export const getContract = async (id: number) => {
|
export const getContract = async (id: number) => {
|
||||||
return await request.get({ url: `/crm/contract/get?id=` + id })
|
return await request.get({ url: `/crm/contract/get?id=` + id })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 合同下拉列表
|
||||||
|
export const getContractSimpleList = async (customerId: number) => {
|
||||||
|
return await request.get({
|
||||||
|
url: `/crm/contract/simple-list?customerId=${customerId}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 新增 CRM 合同
|
// 新增 CRM 合同
|
||||||
export const createContract = async (data: ContractVO) => {
|
export const createContract = async (data: ContractVO) => {
|
||||||
return await request.post({ url: `/crm/contract/create`, data })
|
return await request.post({ url: `/crm/contract/create`, data })
|
||||||
@@ -56,3 +92,23 @@ export const deleteContract = async (id: number) => {
|
|||||||
export const exportContract = async (params) => {
|
export const exportContract = async (params) => {
|
||||||
return await request.download({ url: `/crm/contract/export-excel`, params })
|
return await request.download({ url: `/crm/contract/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交审核
|
||||||
|
export const submitContract = async (id: number) => {
|
||||||
|
return await request.put({ url: `/crm/contract/submit?id=${id}` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合同转移
|
||||||
|
export const transferContract = async (data: TransferReqVO) => {
|
||||||
|
return await request.put({ url: '/crm/contract/transfer', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得待审核合同数量
|
||||||
|
export const getAuditContractCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/contract/audit-count' })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得即将到期(提醒)的合同数量
|
||||||
|
export const getRemindContractCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/contract/remind-count' })
|
||||||
|
}
|
||||||
@@ -1,36 +1,33 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
|
|
||||||
export interface CustomerVO {
|
export interface CustomerVO {
|
||||||
id?: number
|
id: number // 编号
|
||||||
name: string
|
name: string // 客户名称
|
||||||
industryId: number
|
followUpStatus: boolean // 跟进状态
|
||||||
level: number
|
contactLastTime: Date // 最后跟进时间
|
||||||
source: number
|
contactLastContent: string // 最后跟进内容
|
||||||
followUpStatus?: boolean
|
contactNextTime: Date // 下次联系时间
|
||||||
|
ownerUserId: number // 负责人的用户编号
|
||||||
|
ownerUserName?: string // 负责人的用户名称
|
||||||
|
ownerUserDept?: string // 负责人的部门名称
|
||||||
lockStatus?: boolean
|
lockStatus?: boolean
|
||||||
dealStatus?: boolean
|
dealStatus?: boolean
|
||||||
mobile: string
|
mobile: string // 手机号
|
||||||
telephone: string
|
telephone: string // 电话
|
||||||
website: string
|
qq: string // QQ
|
||||||
qq: string
|
wechat: string // wechat
|
||||||
wechat: string
|
email: string // email
|
||||||
email: string
|
areaId: number // 所在地
|
||||||
description: string
|
areaName?: string // 所在地名称
|
||||||
remark: string
|
detailAddress: string // 详细地址
|
||||||
ownerUserId?: number
|
industryId: number // 所属行业
|
||||||
ownerUserName?: string
|
level: number // 客户等级
|
||||||
ownerUserDept?: string
|
source: number // 客户来源
|
||||||
roUserIds?: string
|
remark: string // 备注
|
||||||
rwUserIds?: string
|
creator: string // 创建人
|
||||||
areaId?: number
|
creatorName?: string // 创建人名称
|
||||||
areaName?: string
|
createTime: Date // 创建时间
|
||||||
detailAddress: string
|
updateTime: Date // 更新时间
|
||||||
contactLastTime?: Date
|
|
||||||
contactNextTime: Date
|
|
||||||
createTime?: Date
|
|
||||||
updateTime?: Date
|
|
||||||
creator?: string
|
|
||||||
creatorName?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询客户列表
|
// 查询客户列表
|
||||||
@@ -38,6 +35,26 @@ export const getCustomerPage = async (params) => {
|
|||||||
return await request.get({ url: `/crm/customer/page`, params })
|
return await request.get({ url: `/crm/customer/page`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 进入公海客户提醒的客户列表
|
||||||
|
export const getPutPoolRemindCustomerPage = async (params) => {
|
||||||
|
return await request.get({ url: `/crm/customer/put-pool-remind-page`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得待进入公海客户数量
|
||||||
|
export const getPutPoolRemindCustomerCount = async () => {
|
||||||
|
return await request.get({ url: `/crm/customer/put-pool-remind-count` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得今日需联系客户数量
|
||||||
|
export const getTodayContactCustomerCount = async () => {
|
||||||
|
return await request.get({ url: `/crm/customer/today-contact-count` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得分配给我、待跟进的线索数量的客户数量
|
||||||
|
export const getFollowCustomerCount = async () => {
|
||||||
|
return await request.get({ url: `/crm/customer/follow-count` })
|
||||||
|
}
|
||||||
|
|
||||||
// 查询客户详情
|
// 查询客户详情
|
||||||
export const getCustomer = async (id: number) => {
|
export const getCustomer = async (id: number) => {
|
||||||
return await request.get({ url: `/crm/customer/get?id=` + id })
|
return await request.get({ url: `/crm/customer/get?id=` + id })
|
||||||
@@ -53,6 +70,11 @@ export const updateCustomer = async (data: CustomerVO) => {
|
|||||||
return await request.put({ url: `/crm/customer/update`, data })
|
return await request.put({ url: `/crm/customer/update`, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新客户的成交状态
|
||||||
|
export const updateCustomerDealStatus = async (id: number, dealStatus: boolean) => {
|
||||||
|
return await request.put({ url: `/crm/customer/update-deal-status`, params: { id, dealStatus } })
|
||||||
|
}
|
||||||
|
|
||||||
// 删除客户
|
// 删除客户
|
||||||
export const deleteCustomer = async (id: number) => {
|
export const deleteCustomer = async (id: number) => {
|
||||||
return await request.delete({ url: `/crm/customer/delete?id=` + id })
|
return await request.delete({ url: `/crm/customer/delete?id=` + id })
|
||||||
@@ -63,14 +85,19 @@ export const exportCustomer = async (params: any) => {
|
|||||||
return await request.download({ url: `/crm/customer/export-excel`, params })
|
return await request.download({ url: `/crm/customer/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 客户列表
|
// 下载客户导入模板
|
||||||
export const getSimpleCustomerList = async () => {
|
export const importCustomerTemplate = () => {
|
||||||
return await request.get({ url: `/crm/customer/list-all-simple` })
|
return request.download({ url: '/crm/customer/get-import-template' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询客户操作日志
|
// 导入客户
|
||||||
export const getOperateLogPage = async (id: number) => {
|
export const handleImport = async (formData) => {
|
||||||
return await request.get({ url: '/crm/customer/operate-log-page?id=' + id })
|
return await request.upload({ url: `/crm/customer/import`, data: formData })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客户列表
|
||||||
|
export const getCustomerSimpleList = async () => {
|
||||||
|
return await request.get({ url: `/crm/customer/simple-list` })
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================= 业务操作 =======================
|
// ======================= 业务操作 =======================
|
||||||
@@ -82,7 +109,7 @@ export interface TransferReqVO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 客户转移
|
// 客户转移
|
||||||
export const transfer = async (data: TransferReqVO) => {
|
export const transferCustomer = async (data: TransferReqVO) => {
|
||||||
return await request.put({ url: '/crm/customer/transfer', data })
|
return await request.put({ url: '/crm/customer/transfer', data })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +123,14 @@ export const receiveCustomer = async (ids: any[]) => {
|
|||||||
return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } })
|
return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分配公海给对应负责人
|
||||||
|
export const distributeCustomer = async (ids: any[], ownerUserId: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: '/crm/customer/distribute',
|
||||||
|
data: { ids: ids, ownerUserId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 客户放入公海
|
// 客户放入公海
|
||||||
export const putCustomerPool = async (id: number) => {
|
export const putCustomerPool = async (id: number) => {
|
||||||
return await request.put({ url: `/crm/customer/put-pool?id=${id}` })
|
return await request.put({ url: `/crm/customer/put-pool?id=${id}` })
|
||||||
|
|||||||
@@ -7,9 +7,21 @@ export interface FollowUpRecordVO {
|
|||||||
bizId: number // 数据编号
|
bizId: number // 数据编号
|
||||||
type: number // 跟进类型
|
type: number // 跟进类型
|
||||||
content: string // 跟进内容
|
content: string // 跟进内容
|
||||||
|
picUrls: string[] // 图片
|
||||||
|
fileUrls: string[] // 附件
|
||||||
nextTime: Date // 下次联系时间
|
nextTime: Date // 下次联系时间
|
||||||
businessIds: number[] // 关联的商机编号数组
|
businessIds: number[] // 关联的商机编号数组
|
||||||
|
businesses: {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
}[] // 关联的商机数组
|
||||||
contactIds: number[] // 关联的联系人编号数组
|
contactIds: number[] // 关联的联系人编号数组
|
||||||
|
contacts: {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
}[] // 关联的联系人数组
|
||||||
|
creator: string
|
||||||
|
creatorName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跟进记录 API
|
// 跟进记录 API
|
||||||
@@ -19,28 +31,13 @@ export const FollowUpRecordApi = {
|
|||||||
return await request.get({ url: `/crm/follow-up-record/page`, params })
|
return await request.get({ url: `/crm/follow-up-record/page`, params })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 查询跟进记录详情
|
|
||||||
getFollowUpRecord: async (id: number) => {
|
|
||||||
return await request.get({ url: `/crm/follow-up-record/get?id=` + id })
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新增跟进记录
|
// 新增跟进记录
|
||||||
createFollowUpRecord: async (data: FollowUpRecordVO) => {
|
createFollowUpRecord: async (data: FollowUpRecordVO) => {
|
||||||
return await request.post({ url: `/crm/follow-up-record/create`, data })
|
return await request.post({ url: `/crm/follow-up-record/create`, data })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修改跟进记录
|
|
||||||
updateFollowUpRecord: async (data: FollowUpRecordVO) => {
|
|
||||||
return await request.put({ url: `/crm/follow-up-record/update`, data })
|
|
||||||
},
|
|
||||||
|
|
||||||
// 删除跟进记录
|
// 删除跟进记录
|
||||||
deleteFollowUpRecord: async (id: number) => {
|
deleteFollowUpRecord: async (id: number) => {
|
||||||
return await request.delete({ url: `/crm/follow-up-record/delete?id=` + id })
|
return await request.delete({ url: `/crm/follow-up-record/delete?id=` + id })
|
||||||
},
|
|
||||||
|
|
||||||
// 导出跟进记录 Excel
|
|
||||||
exportFollowUpRecord: async (params) => {
|
|
||||||
return await request.download({ url: `/crm/follow-up-record/export-excel`, params })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import request from '@/config/axios'
|
|
||||||
|
|
||||||
export interface CustomerVO {
|
|
||||||
id?: number
|
|
||||||
name: string
|
|
||||||
industryId: number
|
|
||||||
level: number
|
|
||||||
source: number
|
|
||||||
followUpStatus?: boolean
|
|
||||||
lockStatus?: boolean
|
|
||||||
dealStatus?: boolean
|
|
||||||
mobile: string
|
|
||||||
telephone: string
|
|
||||||
website: string
|
|
||||||
qq: string
|
|
||||||
wechat: string
|
|
||||||
email: string
|
|
||||||
description: string
|
|
||||||
remark: string
|
|
||||||
ownerUserId?: number
|
|
||||||
ownerUserName?: string
|
|
||||||
ownerUserDept?: string
|
|
||||||
roUserIds?: string
|
|
||||||
rwUserIds?: string
|
|
||||||
areaId?: number
|
|
||||||
areaName?: string
|
|
||||||
detailAddress: string
|
|
||||||
contactLastTime?: Date
|
|
||||||
contactNextTime: Date
|
|
||||||
createTime?: Date
|
|
||||||
updateTime?: Date
|
|
||||||
creator?: string
|
|
||||||
creatorName?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询客户列表
|
|
||||||
// TODO @芋艿:看看是不是后续融合到 getCustomerPage 里;
|
|
||||||
export const getTodayCustomerPage = async (params) => {
|
|
||||||
return await request.get({ url: `/crm/message/todayCustomer`, params })
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface OperateLogVO extends PageParam {
|
||||||
|
bizType: number
|
||||||
|
bizId: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得操作日志
|
||||||
|
export const getOperateLogPage = async (params: OperateLogVO) => {
|
||||||
|
return await request.get({ url: `/crm/operate-log/page`, params })
|
||||||
|
}
|
||||||
@@ -2,14 +2,15 @@ import request from '@/config/axios'
|
|||||||
|
|
||||||
export interface PermissionVO {
|
export interface PermissionVO {
|
||||||
id?: number // 数据权限编号
|
id?: number // 数据权限编号
|
||||||
userId: number | undefined // 用户编号
|
userId: number // 用户编号
|
||||||
bizType: number | undefined // Crm 类型
|
bizType: number // Crm 类型
|
||||||
bizId: number | undefined // Crm 类型数据编号
|
bizId: number // Crm 类型数据编号
|
||||||
level: number | undefined // 权限级别
|
level: number // 权限级别
|
||||||
deptName?: string // 部门名称
|
deptName?: string // 部门名称
|
||||||
nickname?: string // 用户昵称
|
nickname?: string // 用户昵称
|
||||||
postNames?: string[] // 岗位名称数组
|
postNames?: string[] // 岗位名称数组
|
||||||
createTime?: Date
|
createTime?: Date
|
||||||
|
ids?: number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,11 +19,14 @@ export interface PermissionVO {
|
|||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
export enum BizTypeEnum {
|
export enum BizTypeEnum {
|
||||||
CRM_LEADS = 1, // 线索
|
CRM_CLUE = 1, // 线索
|
||||||
CRM_CUSTOMER = 2, // 客户
|
CRM_CUSTOMER = 2, // 客户
|
||||||
CRM_CONTACT = 3, // 联系人
|
CRM_CONTACT = 3, // 联系人
|
||||||
CRM_BUSINESS = 5, // 商机
|
CRM_BUSINESS = 4, // 商机
|
||||||
CRM_CONTRACT = 6 // 合同
|
CRM_CONTRACT = 5, // 合同
|
||||||
|
CRM_PRODUCT = 6, // 产品
|
||||||
|
CRM_RECEIVABLE = 7, // 回款
|
||||||
|
CRM_RECEIVABLE_PLAN = 8 // 回款计划
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,11 +54,11 @@ export const updatePermission = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除数据权限(删除团队成员)
|
// 删除数据权限(删除团队成员)
|
||||||
export const deletePermissionBatch = async (params) => {
|
export const deletePermissionBatch = async (val: number[]) => {
|
||||||
return await request.delete({ url: '/crm/permission/delete', params })
|
return await request.delete({ url: '/crm/permission/delete?ids=' + val.join(',') })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除自己的数据权限(退出团队)
|
// 删除自己的数据权限(退出团队)
|
||||||
export const deleteSelfPermission = async (id) => {
|
export const deleteSelfPermission = async (id: number) => {
|
||||||
return await request.delete({ url: '/crm/permission/quit-team?id=' + id })
|
return await request.delete({ url: '/crm/permission/delete-self?id=' + id })
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -8,6 +8,7 @@ export interface ProductVO {
|
|||||||
price: number
|
price: number
|
||||||
status: number
|
status: number
|
||||||
categoryId: number
|
categoryId: number
|
||||||
|
categoryName?: string
|
||||||
description: string
|
description: string
|
||||||
ownerUserId: number
|
ownerUserId: number
|
||||||
}
|
}
|
||||||
@@ -17,6 +18,11 @@ export const getProductPage = async (params) => {
|
|||||||
return await request.get({ url: `/crm/product/page`, params })
|
return await request.get({ url: `/crm/product/page`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获得产品精简列表
|
||||||
|
export const getProductSimpleList = async () => {
|
||||||
|
return await request.get({ url: `/crm/product/simple-list` })
|
||||||
|
}
|
||||||
|
|
||||||
// 查询产品详情
|
// 查询产品详情
|
||||||
export const getProduct = async (id: number) => {
|
export const getProduct = async (id: number) => {
|
||||||
return await request.get({ url: `/crm/product/get?id=` + id })
|
return await request.get({ url: `/crm/product/get?id=` + id })
|
||||||
@@ -41,8 +47,3 @@ export const deleteProduct = async (id: number) => {
|
|||||||
export const exportProduct = async (params) => {
|
export const exportProduct = async (params) => {
|
||||||
return await request.download({ url: `/crm/product/export-excel`, params })
|
return await request.download({ url: `/crm/product/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询产品操作日志
|
|
||||||
export const getOperateLogPage = async (params: any) => {
|
|
||||||
return await request.get({ url: '/crm/product/operate-log-page', params })
|
|
||||||
}
|
|
||||||
@@ -5,15 +5,24 @@ export interface ReceivableVO {
|
|||||||
no: string
|
no: string
|
||||||
planId: number
|
planId: number
|
||||||
customerId: number
|
customerId: number
|
||||||
|
customerName?: string
|
||||||
contractId: number
|
contractId: number
|
||||||
|
contract?: {
|
||||||
|
no: string
|
||||||
|
totalPrice: number
|
||||||
|
}
|
||||||
auditStatus: number
|
auditStatus: number
|
||||||
processInstanceId: number
|
processInstanceId: number
|
||||||
returnTime: Date
|
returnTime: Date
|
||||||
returnType: string
|
returnType: string
|
||||||
price: number
|
price: number
|
||||||
ownerUserId: number
|
ownerUserId: number
|
||||||
sort: number
|
ownerUserName?: string
|
||||||
remark: string
|
remark: string
|
||||||
|
creator: string // 创建人
|
||||||
|
creatorName?: string // 创建人名称
|
||||||
|
createTime: Date // 创建时间
|
||||||
|
updateTime: Date // 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询回款列表
|
// 查询回款列表
|
||||||
@@ -50,3 +59,13 @@ export const deleteReceivable = async (id: number) => {
|
|||||||
export const exportReceivable = async (params) => {
|
export const exportReceivable = async (params) => {
|
||||||
return await request.download({ url: `/crm/receivable/export-excel`, params })
|
return await request.download({ url: `/crm/receivable/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交审核
|
||||||
|
export const submitReceivable = async (id: number) => {
|
||||||
|
return await request.put({ url: `/crm/receivable/submit?id=${id}` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得待审核回款数量
|
||||||
|
export const getAuditReceivableCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/receivable/audit-count' })
|
||||||
|
}
|
||||||
@@ -4,18 +4,26 @@ export interface ReceivablePlanVO {
|
|||||||
id: number
|
id: number
|
||||||
period: number
|
period: number
|
||||||
receivableId: number
|
receivableId: number
|
||||||
status: number
|
|
||||||
checkStatus: string
|
|
||||||
processInstanceId: number
|
|
||||||
price: number
|
price: number
|
||||||
returnTime: Date
|
returnTime: Date
|
||||||
remindDays: number
|
remindDays: number
|
||||||
|
returnType: number
|
||||||
remindTime: Date
|
remindTime: Date
|
||||||
customerId: number
|
customerId: number
|
||||||
|
customerName?: string
|
||||||
contractId: number
|
contractId: number
|
||||||
|
contractNo?: string
|
||||||
ownerUserId: number
|
ownerUserId: number
|
||||||
sort: number
|
ownerUserName?: string
|
||||||
remark: string
|
remark: string
|
||||||
|
creator: string // 创建人
|
||||||
|
creatorName?: string // 创建人名称
|
||||||
|
createTime: Date // 创建时间
|
||||||
|
updateTime: Date // 更新时间
|
||||||
|
receivable?: {
|
||||||
|
price: number
|
||||||
|
returnTime: Date
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询回款计划列表
|
// 查询回款计划列表
|
||||||
@@ -33,6 +41,13 @@ export const getReceivablePlan = async (id: number) => {
|
|||||||
return await request.get({ url: `/crm/receivable-plan/get?id=` + id })
|
return await request.get({ url: `/crm/receivable-plan/get?id=` + id })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询回款计划下拉数据
|
||||||
|
export const getReceivablePlanSimpleList = async (customerId: number, contractId: number) => {
|
||||||
|
return await request.get({
|
||||||
|
url: `/crm/receivable-plan/simple-list?customerId=${customerId}&contractId=${contractId}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 新增回款计划
|
// 新增回款计划
|
||||||
export const createReceivablePlan = async (data: ReceivablePlanVO) => {
|
export const createReceivablePlan = async (data: ReceivablePlanVO) => {
|
||||||
return await request.post({ url: `/crm/receivable-plan/create`, data })
|
return await request.post({ url: `/crm/receivable-plan/create`, data })
|
||||||
@@ -52,3 +67,8 @@ export const deleteReceivablePlan = async (id: number) => {
|
|||||||
export const exportReceivablePlan = async (params) => {
|
export const exportReceivablePlan = async (params) => {
|
||||||
return await request.download({ url: `/crm/receivable-plan/export-excel`, params })
|
return await request.download({ url: `/crm/receivable-plan/export-excel`, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获得待回款提醒数量
|
||||||
|
export const getReceivablePlanRemindCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/receivable-plan/remind-count' })
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface StatisticsRankRespVO {
|
||||||
|
count: number
|
||||||
|
nickname: string
|
||||||
|
deptName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排行 API
|
||||||
|
export const StatisticsRankApi = {
|
||||||
|
// 获得合同排行榜
|
||||||
|
getContractPriceRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-contract-price-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获得回款排行榜
|
||||||
|
getReceivablePriceRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-receivable-price-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 签约合同排行
|
||||||
|
getContractCountRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-contract-count-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 产品销量排行
|
||||||
|
getProductSalesRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-product-sales-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 新增客户数排行
|
||||||
|
getCustomerCountRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-customer-count-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 新增联系人数排行
|
||||||
|
getContactsCountRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-contacts-count-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跟进次数排行
|
||||||
|
getFollowCountRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-follow-count-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 跟进客户数排行
|
||||||
|
getFollowCustomerCountRank: (params: any) => {
|
||||||
|
return request.get({
|
||||||
|
url: '/crm/statistics-rank/get-follow-customer-count-rank',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 结算账户 VO
|
||||||
|
export interface AccountVO {
|
||||||
|
id: number // 结算账户编号
|
||||||
|
no: string // 账户编码
|
||||||
|
remark: string // 备注
|
||||||
|
status: number // 开启状态
|
||||||
|
sort: number // 排序
|
||||||
|
defaultStatus: boolean // 是否默认
|
||||||
|
name: string // 账户名称
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 结算账户 API
|
||||||
|
export const AccountApi = {
|
||||||
|
// 查询结算账户分页
|
||||||
|
getAccountPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/account/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询结算账户精简列表
|
||||||
|
getAccountSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/account/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询结算账户详情
|
||||||
|
getAccount: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/account/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增结算账户
|
||||||
|
createAccount: async (data: AccountVO) => {
|
||||||
|
return await request.post({ url: `/erp/account/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改结算账户
|
||||||
|
updateAccount: async (data: AccountVO) => {
|
||||||
|
return await request.put({ url: `/erp/account/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改结算账户默认状态
|
||||||
|
updateAccountDefaultStatus: async (id: number, defaultStatus: boolean) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/account/update-default-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
defaultStatus
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除结算账户
|
||||||
|
deleteAccount: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/account/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出结算账户 Excel
|
||||||
|
exportAccount: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/account/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 付款单 VO
|
||||||
|
export interface FinancePaymentVO {
|
||||||
|
id: number // 付款单编号
|
||||||
|
no: string // 付款单号
|
||||||
|
supplierId: number // 供应商编号
|
||||||
|
paymentTime: Date // 付款时间
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 付款单 API
|
||||||
|
export const FinancePaymentApi = {
|
||||||
|
// 查询付款单分页
|
||||||
|
getFinancePaymentPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/finance-payment/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询付款单详情
|
||||||
|
getFinancePayment: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/finance-payment/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增付款单
|
||||||
|
createFinancePayment: async (data: FinancePaymentVO) => {
|
||||||
|
return await request.post({ url: `/erp/finance-payment/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改付款单
|
||||||
|
updateFinancePayment: async (data: FinancePaymentVO) => {
|
||||||
|
return await request.put({ url: `/erp/finance-payment/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新付款单的状态
|
||||||
|
updateFinancePaymentStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/finance-payment/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除付款单
|
||||||
|
deleteFinancePayment: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/finance-payment/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出付款单 Excel
|
||||||
|
exportFinancePayment: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/finance-payment/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 收款单 VO
|
||||||
|
export interface FinanceReceiptVO {
|
||||||
|
id: number // 收款单编号
|
||||||
|
no: string // 收款单号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
receiptTime: Date // 收款时间
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 收款单 API
|
||||||
|
export const FinanceReceiptApi = {
|
||||||
|
// 查询收款单分页
|
||||||
|
getFinanceReceiptPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/finance-receipt/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询收款单详情
|
||||||
|
getFinanceReceipt: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/finance-receipt/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增收款单
|
||||||
|
createFinanceReceipt: async (data: FinanceReceiptVO) => {
|
||||||
|
return await request.post({ url: `/erp/finance-receipt/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改收款单
|
||||||
|
updateFinanceReceipt: async (data: FinanceReceiptVO) => {
|
||||||
|
return await request.put({ url: `/erp/finance-receipt/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新收款单的状态
|
||||||
|
updateFinanceReceiptStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/finance-receipt/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除收款单
|
||||||
|
deleteFinanceReceipt: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/finance-receipt/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出收款单 Excel
|
||||||
|
exportFinanceReceipt: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/finance-receipt/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 产品分类 VO
|
||||||
|
export interface ProductCategoryVO {
|
||||||
|
id: number // 分类编号
|
||||||
|
parentId: number // 父分类编号
|
||||||
|
name: string // 分类名称
|
||||||
|
code: string // 分类编码
|
||||||
|
sort: number // 分类排序
|
||||||
|
status: number // 开启状态
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 产品分类 API
|
||||||
|
export const ProductCategoryApi = {
|
||||||
|
// 查询产品分类列表
|
||||||
|
getProductCategoryList: async (params) => {
|
||||||
|
return await request.get({ url: `/erp/product-category/list`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品分类精简列表
|
||||||
|
getProductCategorySimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/product-category/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品分类详情
|
||||||
|
getProductCategory: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/product-category/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增产品分类
|
||||||
|
createProductCategory: async (data: ProductCategoryVO) => {
|
||||||
|
return await request.post({ url: `/erp/product-category/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改产品分类
|
||||||
|
updateProductCategory: async (data: ProductCategoryVO) => {
|
||||||
|
return await request.put({ url: `/erp/product-category/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除产品分类
|
||||||
|
deleteProductCategory: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/product-category/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出产品分类 Excel
|
||||||
|
exportProductCategory: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/product-category/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 产品 VO
|
||||||
|
export interface ProductVO {
|
||||||
|
id: number // 产品编号
|
||||||
|
name: string // 产品名称
|
||||||
|
barCode: string // 产品条码
|
||||||
|
categoryId: number // 产品类型编号
|
||||||
|
unitId: number // 单位编号
|
||||||
|
unitName?: string // 单位名字
|
||||||
|
status: number // 产品状态
|
||||||
|
standard: string // 产品规格
|
||||||
|
remark: string // 产品备注
|
||||||
|
expiryDay: number // 保质期天数
|
||||||
|
weight: number // 重量(kg)
|
||||||
|
purchasePrice: number // 采购价格,单位:元
|
||||||
|
salePrice: number // 销售价格,单位:元
|
||||||
|
minPrice: number // 最低价格,单位:元
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 产品 API
|
||||||
|
export const ProductApi = {
|
||||||
|
// 查询产品分页
|
||||||
|
getProductPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/product/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品精简列表
|
||||||
|
getProductSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/product/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品详情
|
||||||
|
getProduct: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/product/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增产品
|
||||||
|
createProduct: async (data: ProductVO) => {
|
||||||
|
return await request.post({ url: `/erp/product/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改产品
|
||||||
|
updateProduct: async (data: ProductVO) => {
|
||||||
|
return await request.put({ url: `/erp/product/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除产品
|
||||||
|
deleteProduct: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/product/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出产品 Excel
|
||||||
|
exportProduct: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/product/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 产品单位 VO
|
||||||
|
export interface ProductUnitVO {
|
||||||
|
id: number // 单位编号
|
||||||
|
name: string // 单位名字
|
||||||
|
status: number // 单位状态
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 产品单位 API
|
||||||
|
export const ProductUnitApi = {
|
||||||
|
// 查询产品单位分页
|
||||||
|
getProductUnitPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/product-unit/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品单位精简列表
|
||||||
|
getProductUnitSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/product-unit/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品单位详情
|
||||||
|
getProductUnit: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/product-unit/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增产品单位
|
||||||
|
createProductUnit: async (data: ProductUnitVO) => {
|
||||||
|
return await request.post({ url: `/erp/product-unit/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改产品单位
|
||||||
|
updateProductUnit: async (data: ProductUnitVO) => {
|
||||||
|
return await request.put({ url: `/erp/product-unit/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除产品单位
|
||||||
|
deleteProductUnit: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/product-unit/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出产品单位 Excel
|
||||||
|
exportProductUnit: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/product-unit/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 采购入库 VO
|
||||||
|
export interface PurchaseInVO {
|
||||||
|
id: number // 入库工单编号
|
||||||
|
no: string // 采购入库号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
inTime: Date // 入库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
outCount: number // 采购出库数量
|
||||||
|
returnCount: number // 采购退货数量
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 采购入库 API
|
||||||
|
export const PurchaseInApi = {
|
||||||
|
// 查询采购入库分页
|
||||||
|
getPurchaseInPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-in/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询采购入库详情
|
||||||
|
getPurchaseIn: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-in/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增采购入库
|
||||||
|
createPurchaseIn: async (data: PurchaseInVO) => {
|
||||||
|
return await request.post({ url: `/erp/purchase-in/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改采购入库
|
||||||
|
updatePurchaseIn: async (data: PurchaseInVO) => {
|
||||||
|
return await request.put({ url: `/erp/purchase-in/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新采购入库的状态
|
||||||
|
updatePurchaseInStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/purchase-in/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除采购入库
|
||||||
|
deletePurchaseIn: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/purchase-in/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出采购入库 Excel
|
||||||
|
exportPurchaseIn: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/purchase-in/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 采购订单 VO
|
||||||
|
export interface PurchaseOrderVO {
|
||||||
|
id: number // 订单工单编号
|
||||||
|
no: string // 采购订单号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
orderTime: Date // 订单时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
outCount: number // 采购出库数量
|
||||||
|
returnCount: number // 采购退货数量
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 采购订单 API
|
||||||
|
export const PurchaseOrderApi = {
|
||||||
|
// 查询采购订单分页
|
||||||
|
getPurchaseOrderPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-order/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询采购订单详情
|
||||||
|
getPurchaseOrder: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-order/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增采购订单
|
||||||
|
createPurchaseOrder: async (data: PurchaseOrderVO) => {
|
||||||
|
return await request.post({ url: `/erp/purchase-order/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改采购订单
|
||||||
|
updatePurchaseOrder: async (data: PurchaseOrderVO) => {
|
||||||
|
return await request.put({ url: `/erp/purchase-order/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新采购订单的状态
|
||||||
|
updatePurchaseOrderStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/purchase-order/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除采购订单
|
||||||
|
deletePurchaseOrder: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/purchase-order/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出采购订单 Excel
|
||||||
|
exportPurchaseOrder: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/purchase-order/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 采购退货 VO
|
||||||
|
export interface PurchaseReturnVO {
|
||||||
|
id: number // 采购退货编号
|
||||||
|
no: string // 采购退货号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
returnTime: Date // 退货时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 采购退货 API
|
||||||
|
export const PurchaseReturnApi = {
|
||||||
|
// 查询采购退货分页
|
||||||
|
getPurchaseReturnPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-return/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询采购退货详情
|
||||||
|
getPurchaseReturn: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/purchase-return/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增采购退货
|
||||||
|
createPurchaseReturn: async (data: PurchaseReturnVO) => {
|
||||||
|
return await request.post({ url: `/erp/purchase-return/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改采购退货
|
||||||
|
updatePurchaseReturn: async (data: PurchaseReturnVO) => {
|
||||||
|
return await request.put({ url: `/erp/purchase-return/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新采购退货的状态
|
||||||
|
updatePurchaseReturnStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/purchase-return/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除采购退货
|
||||||
|
deletePurchaseReturn: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/purchase-return/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出采购退货 Excel
|
||||||
|
exportPurchaseReturn: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/purchase-return/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 供应商 VO
|
||||||
|
export interface SupplierVO {
|
||||||
|
id: number // 供应商编号
|
||||||
|
name: string // 供应商名称
|
||||||
|
contact: string // 联系人
|
||||||
|
mobile: string // 手机号码
|
||||||
|
telephone: string // 联系电话
|
||||||
|
email: string // 电子邮箱
|
||||||
|
fax: string // 传真
|
||||||
|
remark: string // 备注
|
||||||
|
status: number // 开启状态
|
||||||
|
sort: number // 排序
|
||||||
|
taxNo: string // 纳税人识别号
|
||||||
|
taxPercent: number // 税率
|
||||||
|
bankName: string // 开户行
|
||||||
|
bankAccount: string // 开户账号
|
||||||
|
bankAddress: string // 开户地址
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 供应商 API
|
||||||
|
export const SupplierApi = {
|
||||||
|
// 查询供应商分页
|
||||||
|
getSupplierPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/supplier/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得供应商精简列表
|
||||||
|
getSupplierSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/supplier/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询供应商详情
|
||||||
|
getSupplier: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/supplier/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增供应商
|
||||||
|
createSupplier: async (data: SupplierVO) => {
|
||||||
|
return await request.post({ url: `/erp/supplier/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改供应商
|
||||||
|
updateSupplier: async (data: SupplierVO) => {
|
||||||
|
return await request.put({ url: `/erp/supplier/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除供应商
|
||||||
|
deleteSupplier: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/supplier/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出供应商 Excel
|
||||||
|
exportSupplier: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/supplier/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 客户 VO
|
||||||
|
export interface CustomerVO {
|
||||||
|
id: number // 客户编号
|
||||||
|
name: string // 客户名称
|
||||||
|
contact: string // 联系人
|
||||||
|
mobile: string // 手机号码
|
||||||
|
telephone: string // 联系电话
|
||||||
|
email: string // 电子邮箱
|
||||||
|
fax: string // 传真
|
||||||
|
remark: string // 备注
|
||||||
|
status: number // 开启状态
|
||||||
|
sort: number // 排序
|
||||||
|
taxNo: string // 纳税人识别号
|
||||||
|
taxPercent: number // 税率
|
||||||
|
bankName: string // 开户行
|
||||||
|
bankAccount: string // 开户账号
|
||||||
|
bankAddress: string // 开户地址
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 客户 API
|
||||||
|
export const CustomerApi = {
|
||||||
|
// 查询客户分页
|
||||||
|
getCustomerPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/customer/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询客户精简列表
|
||||||
|
getCustomerSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/customer/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询客户详情
|
||||||
|
getCustomer: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/customer/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增客户
|
||||||
|
createCustomer: async (data: CustomerVO) => {
|
||||||
|
return await request.post({ url: `/erp/customer/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改客户
|
||||||
|
updateCustomer: async (data: CustomerVO) => {
|
||||||
|
return await request.put({ url: `/erp/customer/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除客户
|
||||||
|
deleteCustomer: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/customer/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出客户 Excel
|
||||||
|
exportCustomer: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/customer/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 销售订单 VO
|
||||||
|
export interface SaleOrderVO {
|
||||||
|
id: number // 订单工单编号
|
||||||
|
no: string // 销售订单号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
orderTime: Date // 订单时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
outCount: number // 销售出库数量
|
||||||
|
returnCount: number // 销售退货数量
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 销售订单 API
|
||||||
|
export const SaleOrderApi = {
|
||||||
|
// 查询销售订单分页
|
||||||
|
getSaleOrderPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/sale-order/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询销售订单详情
|
||||||
|
getSaleOrder: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/sale-order/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增销售订单
|
||||||
|
createSaleOrder: async (data: SaleOrderVO) => {
|
||||||
|
return await request.post({ url: `/erp/sale-order/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改销售订单
|
||||||
|
updateSaleOrder: async (data: SaleOrderVO) => {
|
||||||
|
return await request.put({ url: `/erp/sale-order/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新销售订单的状态
|
||||||
|
updateSaleOrderStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/sale-order/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除销售订单
|
||||||
|
deleteSaleOrder: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/sale-order/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出销售订单 Excel
|
||||||
|
exportSaleOrder: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/sale-order/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 销售出库 VO
|
||||||
|
export interface SaleOutVO {
|
||||||
|
id: number // 销售出库编号
|
||||||
|
no: string // 销售出库号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
outTime: Date // 出库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 销售出库 API
|
||||||
|
export const SaleOutApi = {
|
||||||
|
// 查询销售出库分页
|
||||||
|
getSaleOutPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/sale-out/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询销售出库详情
|
||||||
|
getSaleOut: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/sale-out/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增销售出库
|
||||||
|
createSaleOut: async (data: SaleOutVO) => {
|
||||||
|
return await request.post({ url: `/erp/sale-out/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改销售出库
|
||||||
|
updateSaleOut: async (data: SaleOutVO) => {
|
||||||
|
return await request.put({ url: `/erp/sale-out/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新销售出库的状态
|
||||||
|
updateSaleOutStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/sale-out/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除销售出库
|
||||||
|
deleteSaleOut: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/sale-out/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出销售出库 Excel
|
||||||
|
exportSaleOut: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/sale-out/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 销售退货 VO
|
||||||
|
export interface SaleReturnVO {
|
||||||
|
id: number // 销售退货编号
|
||||||
|
no: string // 销售退货号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
returnTime: Date // 退货时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 销售退货 API
|
||||||
|
export const SaleReturnApi = {
|
||||||
|
// 查询销售退货分页
|
||||||
|
getSaleReturnPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/sale-return/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询销售退货详情
|
||||||
|
getSaleReturn: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/sale-return/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增销售退货
|
||||||
|
createSaleReturn: async (data: SaleReturnVO) => {
|
||||||
|
return await request.post({ url: `/erp/sale-return/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改销售退货
|
||||||
|
updateSaleReturn: async (data: SaleReturnVO) => {
|
||||||
|
return await request.put({ url: `/erp/sale-return/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新销售退货的状态
|
||||||
|
updateSaleReturnStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/sale-return/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除销售退货
|
||||||
|
deleteSaleReturn: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/sale-return/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出销售退货 Excel
|
||||||
|
exportSaleReturn: async (params: any) => {
|
||||||
|
return await request.download({ url: `/erp/sale-return/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 采购全局统计 VO
|
||||||
|
export interface ErpPurchaseSummaryRespVO {
|
||||||
|
todayPrice: number // 今日采购金额
|
||||||
|
yesterdayPrice: number // 昨日采购金额
|
||||||
|
monthPrice: number // 本月采购金额
|
||||||
|
yearPrice: number // 今年采购金额
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 采购时间段统计 VO
|
||||||
|
export interface ErpPurchaseTimeSummaryRespVO {
|
||||||
|
time: string // 时间
|
||||||
|
price: number // 采购金额
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 采购统计 API
|
||||||
|
export const PurchaseStatisticsApi = {
|
||||||
|
// 获得采购统计
|
||||||
|
getPurchaseSummary: async (): Promise<ErpPurchaseSummaryRespVO> => {
|
||||||
|
return await request.get({ url: `/erp/purchase-statistics/summary` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得采购时间段统计
|
||||||
|
getPurchaseTimeSummary: async (): Promise<ErpPurchaseTimeSummaryRespVO[]> => {
|
||||||
|
return await request.get({ url: `/erp/purchase-statistics/time-summary` })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 销售全局统计 VO
|
||||||
|
export interface ErpSaleSummaryRespVO {
|
||||||
|
todayPrice: number // 今日销售金额
|
||||||
|
yesterdayPrice: number // 昨日销售金额
|
||||||
|
monthPrice: number // 本月销售金额
|
||||||
|
yearPrice: number // 今年销售金额
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 销售时间段统计 VO
|
||||||
|
export interface ErpSaleTimeSummaryRespVO {
|
||||||
|
time: string // 时间
|
||||||
|
price: number // 销售金额
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 销售统计 API
|
||||||
|
export const SaleStatisticsApi = {
|
||||||
|
// 获得销售统计
|
||||||
|
getSaleSummary: async (): Promise<ErpSaleSummaryRespVO> => {
|
||||||
|
return await request.get({ url: `/erp/sale-statistics/summary` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得销售时间段统计
|
||||||
|
getSaleTimeSummary: async (): Promise<ErpSaleTimeSummaryRespVO[]> => {
|
||||||
|
return await request.get({ url: `/erp/sale-statistics/time-summary` })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 库存盘点单 VO
|
||||||
|
export interface StockCheckVO {
|
||||||
|
id: number // 出库编号
|
||||||
|
no: string // 出库单号
|
||||||
|
outTime: Date // 出库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 库存盘点单 API
|
||||||
|
export const StockCheckApi = {
|
||||||
|
// 查询库存盘点单分页
|
||||||
|
getStockCheckPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock-check/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询库存盘点单详情
|
||||||
|
getStockCheck: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock-check/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增库存盘点单
|
||||||
|
createStockCheck: async (data: StockCheckVO) => {
|
||||||
|
return await request.post({ url: `/erp/stock-check/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改库存盘点单
|
||||||
|
updateStockCheck: async (data: StockCheckVO) => {
|
||||||
|
return await request.put({ url: `/erp/stock-check/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新库存盘点单的状态
|
||||||
|
updateStockCheckStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/stock-check/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除库存盘点单
|
||||||
|
deleteStockCheck: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/stock-check/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出库存盘点单 Excel
|
||||||
|
exportStockCheck: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock-check/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 其它入库单 VO
|
||||||
|
export interface StockInVO {
|
||||||
|
id: number // 入库编号
|
||||||
|
no: string // 入库单号
|
||||||
|
supplierId: number // 供应商编号
|
||||||
|
inTime: Date // 入库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 其它入库单 API
|
||||||
|
export const StockInApi = {
|
||||||
|
// 查询其它入库单分页
|
||||||
|
getStockInPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock-in/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询其它入库单详情
|
||||||
|
getStockIn: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock-in/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增其它入库单
|
||||||
|
createStockIn: async (data: StockInVO) => {
|
||||||
|
return await request.post({ url: `/erp/stock-in/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改其它入库单
|
||||||
|
updateStockIn: async (data: StockInVO) => {
|
||||||
|
return await request.put({ url: `/erp/stock-in/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新其它入库单的状态
|
||||||
|
updateStockInStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/stock-in/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除其它入库单
|
||||||
|
deleteStockIn: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/stock-in/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出其它入库单 Excel
|
||||||
|
exportStockIn: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock-in/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 库存调度单 VO
|
||||||
|
export interface StockMoveVO {
|
||||||
|
id: number // 出库编号
|
||||||
|
no: string // 出库单号
|
||||||
|
outTime: Date // 出库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 库存调度单 API
|
||||||
|
export const StockMoveApi = {
|
||||||
|
// 查询库存调度单分页
|
||||||
|
getStockMovePage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock-move/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询库存调度单详情
|
||||||
|
getStockMove: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock-move/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增库存调度单
|
||||||
|
createStockMove: async (data: StockMoveVO) => {
|
||||||
|
return await request.post({ url: `/erp/stock-move/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改库存调度单
|
||||||
|
updateStockMove: async (data: StockMoveVO) => {
|
||||||
|
return await request.put({ url: `/erp/stock-move/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新库存调度单的状态
|
||||||
|
updateStockMoveStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/stock-move/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除库存调度单
|
||||||
|
deleteStockMove: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/stock-move/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出库存调度单 Excel
|
||||||
|
exportStockMove: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock-move/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 其它出库单 VO
|
||||||
|
export interface StockOutVO {
|
||||||
|
id: number // 出库编号
|
||||||
|
no: string // 出库单号
|
||||||
|
customerId: number // 客户编号
|
||||||
|
outTime: Date // 出库时间
|
||||||
|
totalCount: number // 合计数量
|
||||||
|
totalPrice: number // 合计金额,单位:元
|
||||||
|
status: number // 状态
|
||||||
|
remark: string // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 其它出库单 API
|
||||||
|
export const StockOutApi = {
|
||||||
|
// 查询其它出库单分页
|
||||||
|
getStockOutPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock-out/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询其它出库单详情
|
||||||
|
getStockOut: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock-out/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增其它出库单
|
||||||
|
createStockOut: async (data: StockOutVO) => {
|
||||||
|
return await request.post({ url: `/erp/stock-out/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改其它出库单
|
||||||
|
updateStockOut: async (data: StockOutVO) => {
|
||||||
|
return await request.put({ url: `/erp/stock-out/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新其它出库单的状态
|
||||||
|
updateStockOutStatus: async (id: number, status: number) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/stock-out/update-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除其它出库单
|
||||||
|
deleteStockOut: async (ids: number[]) => {
|
||||||
|
return await request.delete({
|
||||||
|
url: `/erp/stock-out/delete`,
|
||||||
|
params: {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出其它出库单 Excel
|
||||||
|
exportStockOut: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock-out/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 产品库存明细 VO
|
||||||
|
export interface StockRecordVO {
|
||||||
|
id: number // 编号
|
||||||
|
productId: number // 产品编号
|
||||||
|
warehouseId: number // 仓库编号
|
||||||
|
count: number // 出入库数量
|
||||||
|
totalCount: number // 总库存量
|
||||||
|
bizType: number // 业务类型
|
||||||
|
bizId: number // 业务编号
|
||||||
|
bizItemId: number // 业务项编号
|
||||||
|
bizNo: string // 业务单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 产品库存明细 API
|
||||||
|
export const StockRecordApi = {
|
||||||
|
// 查询产品库存明细分页
|
||||||
|
getStockRecordPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock-record/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品库存明细详情
|
||||||
|
getStockRecord: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock-record/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出产品库存明细 Excel
|
||||||
|
exportStockRecord: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock-record/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 产品库存 VO
|
||||||
|
export interface StockVO {
|
||||||
|
// 编号
|
||||||
|
id: number
|
||||||
|
// 产品编号
|
||||||
|
productId: number
|
||||||
|
// 仓库编号
|
||||||
|
warehouseId: number
|
||||||
|
// 库存数量
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 产品库存 API
|
||||||
|
export const StockApi = {
|
||||||
|
// 查询产品库存分页
|
||||||
|
getStockPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/stock/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品库存详情
|
||||||
|
getStock: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询产品库存详情
|
||||||
|
getStock2: async (productId: number, warehouseId: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock/get`, params: { productId, warehouseId } })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得产品库存数量
|
||||||
|
getStockCount: async (productId: number) => {
|
||||||
|
return await request.get({ url: `/erp/stock/get-count`, params: { productId } })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出产品库存 Excel
|
||||||
|
exportStock: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/stock/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// ERP 仓库 VO
|
||||||
|
export interface WarehouseVO {
|
||||||
|
id: number // 仓库编号
|
||||||
|
name: string // 仓库名称
|
||||||
|
address: string // 仓库地址
|
||||||
|
sort: number // 排序
|
||||||
|
remark: string // 备注
|
||||||
|
principal: string // 负责人
|
||||||
|
warehousePrice: number // 仓储费,单位:元
|
||||||
|
truckagePrice: number // 搬运费,单位:元
|
||||||
|
status: number // 开启状态
|
||||||
|
defaultStatus: boolean // 是否默认
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERP 仓库 API
|
||||||
|
export const WarehouseApi = {
|
||||||
|
// 查询仓库分页
|
||||||
|
getWarehousePage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/erp/warehouse/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询仓库精简列表
|
||||||
|
getWarehouseSimpleList: async () => {
|
||||||
|
return await request.get({ url: `/erp/warehouse/simple-list` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询仓库详情
|
||||||
|
getWarehouse: async (id: number) => {
|
||||||
|
return await request.get({ url: `/erp/warehouse/get?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增仓库
|
||||||
|
createWarehouse: async (data: WarehouseVO) => {
|
||||||
|
return await request.post({ url: `/erp/warehouse/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改仓库
|
||||||
|
updateWarehouse: async (data: WarehouseVO) => {
|
||||||
|
return await request.put({ url: `/erp/warehouse/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改仓库默认状态
|
||||||
|
updateWarehouseDefaultStatus: async (id: number, defaultStatus: boolean) => {
|
||||||
|
return await request.put({
|
||||||
|
url: `/erp/warehouse/update-default-status`,
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
defaultStatus
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除仓库
|
||||||
|
deleteWarehouse: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/erp/warehouse/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出仓库 Excel
|
||||||
|
exportWarehouse: async (params) => {
|
||||||
|
return await request.download({ url: `/erp/warehouse/export-excel`, params })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,16 @@ export interface FilePageReqVO extends PageParam {
|
|||||||
createTime?: Date[]
|
createTime?: Date[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 文件预签名地址 Response VO
|
||||||
|
export interface FilePresignedUrlRespVO {
|
||||||
|
// 文件配置编号
|
||||||
|
configId: number
|
||||||
|
// 文件上传 URL
|
||||||
|
uploadUrl: string
|
||||||
|
// 文件 URL
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
// 查询文件列表
|
// 查询文件列表
|
||||||
export const getFilePage = (params: FilePageReqVO) => {
|
export const getFilePage = (params: FilePageReqVO) => {
|
||||||
return request.get({ url: '/infra/file/page', params })
|
return request.get({ url: '/infra/file/page', params })
|
||||||
@@ -15,3 +25,21 @@ export const getFilePage = (params: FilePageReqVO) => {
|
|||||||
export const deleteFile = (id: number) => {
|
export const deleteFile = (id: number) => {
|
||||||
return request.delete({ url: '/infra/file/delete?id=' + id })
|
return request.delete({ url: '/infra/file/delete?id=' + id })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取文件预签名地址
|
||||||
|
export const getFilePresignedUrl = (path: string) => {
|
||||||
|
return request.get<FilePresignedUrlRespVO>({
|
||||||
|
url: '/infra/file/presigned-url',
|
||||||
|
params: { path }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建文件
|
||||||
|
export const createFile = (data: any) => {
|
||||||
|
return request.post({ url: '/infra/file/create', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
export const updateFile = (data: any) => {
|
||||||
|
return request.upload({ url: '/infra/file/upload', data })
|
||||||
|
}
|
||||||
@@ -25,6 +25,9 @@ defineProps({
|
|||||||
</template>
|
</template>
|
||||||
<Icon :size="14" class="ml-5px" icon="ep:question-filled" />
|
<Icon :size="14" class="ml-5px" icon="ep:question-filled" />
|
||||||
</ElTooltip>
|
</ElTooltip>
|
||||||
|
<div class="flex flex-grow pl-20px">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { useDesign } from '@/hooks/web/useDesign'
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import CopperModal from './CopperModal.vue'
|
import CopperModal from './CopperModal.vue'
|
||||||
import avatar from '@/assets/imgs/avatar.jpg'
|
import avatar from '@/assets/imgs/avatar.gif'
|
||||||
|
|
||||||
defineOptions({ name: 'CropperAvatar' })
|
defineOptions({ name: 'CropperAvatar' })
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,11 @@ const toggleClick = () => {
|
|||||||
<slot v-else-if="item.dictType">
|
<slot v-else-if="item.dictType">
|
||||||
<DictTag :type="item.dictType" :value="data[item.field] + ''" />
|
<DictTag :type="item.dictType" :value="data[item.field] + ''" />
|
||||||
</slot>
|
</slot>
|
||||||
<slot v-else :name="item.field" :row="data">{{ data[item.field] }}</slot>
|
<slot v-else :name="item.field" :row="data">
|
||||||
|
{{
|
||||||
|
item.mappedField ? data[item.mappedField] : data[item.field]
|
||||||
|
}}
|
||||||
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
</ElDescriptions>
|
</ElDescriptions>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const goToUrl = () => {
|
|||||||
|
|
||||||
/** 是否开启 */
|
/** 是否开启 */
|
||||||
const getEnable = () => {
|
const getEnable = () => {
|
||||||
return import.meta.env.VITE_APP_TENANT_ENABLE === 'true'
|
return import.meta.env.VITE_APP_DOCALERT_ENABLE !== 'false'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -180,12 +180,12 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="z-99 border-1 border-[var(--el-border-color)] border-solid">
|
<div class="border-1 border-solid border-[var(--tags-view-border-color)] z-10">
|
||||||
<!-- 工具栏 -->
|
<!-- 工具栏 -->
|
||||||
<Toolbar
|
<Toolbar
|
||||||
:editor="editorRef"
|
:editor="editorRef"
|
||||||
:editorId="editorId"
|
:editorId="editorId"
|
||||||
class="border-0 b-b-1 border-[var(--el-border-color)] border-solid"
|
class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
|
||||||
/>
|
/>
|
||||||
<!-- 编辑器 -->
|
<!-- 编辑器 -->
|
||||||
<Editor
|
<Editor
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function createImageViewer(options: ImageViewerProps) {
|
|||||||
initialIndex = 0,
|
initialIndex = 0,
|
||||||
infinite = true,
|
infinite = true,
|
||||||
hideOnClickModal = false,
|
hideOnClickModal = false,
|
||||||
appendToBody = false,
|
teleported = false,
|
||||||
zIndex = 2000,
|
zIndex = 2000,
|
||||||
show = true
|
show = true
|
||||||
} = options
|
} = options
|
||||||
@@ -23,7 +23,7 @@ export function createImageViewer(options: ImageViewerProps) {
|
|||||||
propsData.initialIndex = initialIndex
|
propsData.initialIndex = initialIndex
|
||||||
propsData.infinite = infinite
|
propsData.infinite = infinite
|
||||||
propsData.hideOnClickModal = hideOnClickModal
|
propsData.hideOnClickModal = hideOnClickModal
|
||||||
propsData.appendToBody = appendToBody
|
propsData.teleported = teleported
|
||||||
propsData.zIndex = zIndex
|
propsData.zIndex = zIndex
|
||||||
propsData.show = show
|
propsData.show = show
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const props = defineProps({
|
|||||||
initialIndex: propTypes.number.def(0),
|
initialIndex: propTypes.number.def(0),
|
||||||
infinite: propTypes.bool.def(true),
|
infinite: propTypes.bool.def(true),
|
||||||
hideOnClickModal: propTypes.bool.def(false),
|
hideOnClickModal: propTypes.bool.def(false),
|
||||||
appendToBody: propTypes.bool.def(false),
|
teleported: propTypes.bool.def(false),
|
||||||
show: propTypes.bool.def(false)
|
show: propTypes.bool.def(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ export interface ImageViewerProps {
|
|||||||
initialIndex?: number
|
initialIndex?: number
|
||||||
infinite?: boolean
|
infinite?: boolean
|
||||||
hideOnClickModal?: boolean
|
hideOnClickModal?: boolean
|
||||||
appendToBody?: boolean
|
teleported?: boolean
|
||||||
show?: boolean
|
show?: boolean
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
placeholder="请输入菜单内容"
|
placeholder="请输入菜单内容"
|
||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
class="overflow-hidden transition-all-600"
|
class="overflow-hidden transition-all-600"
|
||||||
:class="showTopSearch ? 'w-220px ml2' : 'w-0'"
|
:class="showTopSearch ? '!w-220px ml2' : '!w-0'"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Table from './src/Table.vue'
|
import Table from './src/Table.vue'
|
||||||
import { ElTable } from 'element-plus'
|
import { ElTable } from 'element-plus'
|
||||||
import { TableSetPropsType } from '@/types/table'
|
import { TableSetPropsType } from '@/types/table'
|
||||||
|
import TableSelectForm from './src/TableSelectForm.vue'
|
||||||
|
|
||||||
export interface TableExpose {
|
export interface TableExpose {
|
||||||
setProps: (props: Recordable) => void
|
setProps: (props: Recordable) => void
|
||||||
@@ -9,4 +10,4 @@ export interface TableExpose {
|
|||||||
elTableRef: ComponentRef<typeof ElTable>
|
elTableRef: ComponentRef<typeof ElTable>
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Table }
|
export { Table, TableSelectForm }
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<!-- 列表选择通用组件,参考 ProductList 组件使用 -->
|
||||||
|
<template>
|
||||||
|
<Dialog v-model="dialogVisible" :appendToBody="true" :scroll="true" :title="title" width="60%">
|
||||||
|
<el-table
|
||||||
|
ref="multipleTableRef"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="list"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
:stripe="true"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<slot></slot>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<Pagination
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
v-model:page="queryParams.pageNo"
|
||||||
|
:total="total"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
<template #footer>
|
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElTable } from 'element-plus'
|
||||||
|
|
||||||
|
defineOptions({ name: 'TableSelectForm' })
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
modelValue: any[]
|
||||||
|
title: string
|
||||||
|
}>(),
|
||||||
|
{ modelValue: () => [], title: '选择' }
|
||||||
|
)
|
||||||
|
const list = ref([]) // 列表的数据
|
||||||
|
const total = ref(0) // 列表的总页数
|
||||||
|
const loading = ref(false) // 列表的加载中
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const formLoading = ref(false)
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
// 确认选择时的触发事件
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:modelValue', v: number[]): void
|
||||||
|
}>()
|
||||||
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
|
||||||
|
const multipleSelection = ref<any[]>([])
|
||||||
|
const handleSelectionChange = (val: any[]) => {
|
||||||
|
multipleSelection.value = val
|
||||||
|
}
|
||||||
|
/** 触发 */
|
||||||
|
const submitForm = () => {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
emits('update:modelValue', multipleSelection.value) // 返回选择的原始数据由使用方处理
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
// 关闭弹窗
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async (getListFunc: Function) => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await getListFunc(queryParams)
|
||||||
|
list.value = data.list
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (getListFunc: Function) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
await nextTick()
|
||||||
|
if (multipleSelection.value.length > 0) {
|
||||||
|
multipleTableRef.value!.clearSelection()
|
||||||
|
}
|
||||||
|
await getList(getListFunc)
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
</script>
|
||||||
@@ -3,11 +3,10 @@
|
|||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
:action="updateUrl"
|
:action="uploadUrl"
|
||||||
:auto-upload="autoUpload"
|
:auto-upload="autoUpload"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
:drag="drag"
|
:drag="drag"
|
||||||
:headers="uploadHeaders"
|
|
||||||
:limit="props.limit"
|
:limit="props.limit"
|
||||||
:multiple="props.limit > 1"
|
:multiple="props.limit > 1"
|
||||||
:on-error="excelUploadError"
|
:on-error="excelUploadError"
|
||||||
@@ -16,6 +15,7 @@
|
|||||||
:on-remove="handleRemove"
|
:on-remove="handleRemove"
|
||||||
:on-success="handleFileSuccess"
|
:on-success="handleFileSuccess"
|
||||||
:show-file-list="true"
|
:show-file-list="true"
|
||||||
|
:http-request="httpRequest"
|
||||||
class="upload-file-uploader"
|
class="upload-file-uploader"
|
||||||
name="file"
|
name="file"
|
||||||
>
|
>
|
||||||
@@ -36,9 +36,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
|
||||||
import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus'
|
import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus'
|
||||||
import { isString } from '@/utils/is'
|
import { isString } from '@/utils/is'
|
||||||
|
import { useUpload } from '@/components/UploadFile/src/useUpload'
|
||||||
|
import { UploadFile } from 'element-plus/es/components/upload/src/upload'
|
||||||
|
|
||||||
defineOptions({ name: 'UploadFile' })
|
defineOptions({ name: 'UploadFile' })
|
||||||
|
|
||||||
@@ -48,7 +49,6 @@ const emit = defineEmits(['update:modelValue'])
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
||||||
title: propTypes.string.def('文件上传'),
|
title: propTypes.string.def('文件上传'),
|
||||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
|
||||||
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
fileSize: propTypes.number.def(5), // 大小限制(MB)
|
fileSize: propTypes.number.def(5), // 大小限制(MB)
|
||||||
limit: propTypes.number.def(5), // 数量限制
|
limit: propTypes.number.def(5), // 数量限制
|
||||||
@@ -62,10 +62,8 @@ const uploadRef = ref<UploadInstance>()
|
|||||||
const uploadList = ref<UploadUserFile[]>([])
|
const uploadList = ref<UploadUserFile[]>([])
|
||||||
const fileList = ref<UploadUserFile[]>([])
|
const fileList = ref<UploadUserFile[]>([])
|
||||||
const uploadNumber = ref<number>(0)
|
const uploadNumber = ref<number>(0)
|
||||||
const uploadHeaders = ref({
|
|
||||||
Authorization: 'Bearer ' + getAccessToken(),
|
const { uploadUrl, httpRequest } = useUpload()
|
||||||
'tenant-id': getTenantId()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 文件上传之前判断
|
// 文件上传之前判断
|
||||||
const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
|
const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
|
||||||
@@ -120,10 +118,10 @@ const excelUploadError: UploadProps['onError'] = (): void => {
|
|||||||
message.error('导入数据失败,请您重新上传!')
|
message.error('导入数据失败,请您重新上传!')
|
||||||
}
|
}
|
||||||
// 删除上传文件
|
// 删除上传文件
|
||||||
const handleRemove = (file) => {
|
const handleRemove = (file: UploadFile) => {
|
||||||
const findex = fileList.value.map((f) => f.name).indexOf(file.name)
|
const index = fileList.value.map((f) => f.name).indexOf(file.name)
|
||||||
if (findex > -1) {
|
if (index > -1) {
|
||||||
fileList.value.splice(findex, 1)
|
fileList.value.splice(index, 1)
|
||||||
emitUpdateModelValue()
|
emitUpdateModelValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +158,7 @@ const emitUpdateModelValue = () => {
|
|||||||
// 情况1:数组结果
|
// 情况1:数组结果
|
||||||
let result: string | string[] = fileList.value.map((file) => file.url!)
|
let result: string | string[] = fileList.value.map((file) => file.url!)
|
||||||
// 情况2:逗号分隔的字符串
|
// 情况2:逗号分隔的字符串
|
||||||
if (isString(props.modelValue)) {
|
if (props.limit === 1 || isString(props.modelValue)) {
|
||||||
result = result.join(',')
|
result = result.join(',')
|
||||||
}
|
}
|
||||||
emit('update:modelValue', result)
|
emit('update:modelValue', result)
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
<el-upload
|
<el-upload
|
||||||
:id="uuid"
|
:id="uuid"
|
||||||
:accept="fileType.join(',')"
|
:accept="fileType.join(',')"
|
||||||
:action="updateUrl"
|
:action="uploadUrl"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
:class="['upload', drag ? 'no-border' : '']"
|
:class="['upload', drag ? 'no-border' : '']"
|
||||||
:drag="drag"
|
:drag="drag"
|
||||||
:headers="uploadHeaders"
|
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:on-error="uploadError"
|
:on-error="uploadError"
|
||||||
:on-success="uploadSuccess"
|
:on-success="uploadSuccess"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
|
:http-request="httpRequest"
|
||||||
>
|
>
|
||||||
<template v-if="modelValue">
|
<template v-if="modelValue">
|
||||||
<img :src="modelValue" class="upload-image" />
|
<img :src="modelValue" class="upload-image" />
|
||||||
@@ -50,8 +50,8 @@ import type { UploadProps } from 'element-plus'
|
|||||||
|
|
||||||
import { generateUUID } from '@/utils'
|
import { generateUUID } from '@/utils'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
|
import { useUpload } from '@/components/UploadFile/src/useUpload'
|
||||||
|
|
||||||
defineOptions({ name: 'UploadImg' })
|
defineOptions({ name: 'UploadImg' })
|
||||||
|
|
||||||
@@ -70,7 +70,6 @@ type FileTypes =
|
|||||||
// 接受父组件参数
|
// 接受父组件参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: propTypes.string.def(''),
|
modelValue: propTypes.string.def(''),
|
||||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
|
||||||
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
||||||
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||||
fileSize: propTypes.number.def(5), // 图片大小限制 ==> 非必传(默认为 5M)
|
fileSize: propTypes.number.def(5), // 图片大小限制 ==> 非必传(默认为 5M)
|
||||||
@@ -101,10 +100,7 @@ const deleteImg = () => {
|
|||||||
emit('update:modelValue', '')
|
emit('update:modelValue', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadHeaders = ref({
|
const { uploadUrl, httpRequest } = useUpload()
|
||||||
Authorization: 'Bearer ' + getAccessToken(),
|
|
||||||
'tenant-id': getTenantId()
|
|
||||||
})
|
|
||||||
|
|
||||||
const editImg = () => {
|
const editImg = () => {
|
||||||
const dom = document.querySelector(`#${uuid.value} .el-upload__input`)
|
const dom = document.querySelector(`#${uuid.value} .el-upload__input`)
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
<el-upload
|
<el-upload
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
:accept="fileType.join(',')"
|
:accept="fileType.join(',')"
|
||||||
:action="updateUrl"
|
:action="uploadUrl"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
:class="['upload', drag ? 'no-border' : '']"
|
:class="['upload', drag ? 'no-border' : '']"
|
||||||
:drag="drag"
|
:drag="drag"
|
||||||
:headers="uploadHeaders"
|
|
||||||
:limit="limit"
|
:limit="limit"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:on-error="uploadError"
|
:on-error="uploadError"
|
||||||
:on-exceed="handleExceed"
|
:on-exceed="handleExceed"
|
||||||
:on-success="uploadSuccess"
|
:on-success="uploadSuccess"
|
||||||
|
:http-request="httpRequest"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
>
|
>
|
||||||
<div class="upload-empty">
|
<div class="upload-empty">
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<Icon icon="ep:zoom-in" />
|
<Icon icon="ep:zoom-in" />
|
||||||
<span>查看</span>
|
<span>查看</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="handle-icon" @click="handleRemove(file)" v-if="!disabled">
|
<div v-if="!disabled" class="handle-icon" @click="handleRemove(file)">
|
||||||
<Icon icon="ep:delete" />
|
<Icon icon="ep:delete" />
|
||||||
<span>删除</span>
|
<span>删除</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,12 +46,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PropType } from 'vue'
|
|
||||||
import type { UploadFile, UploadProps, UploadUserFile } from 'element-plus'
|
import type { UploadFile, UploadProps, UploadUserFile } from 'element-plus'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
|
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
import { useUpload } from '@/components/UploadFile/src/useUpload'
|
||||||
|
|
||||||
defineOptions({ name: 'UploadImgs' })
|
defineOptions({ name: 'UploadImgs' })
|
||||||
|
|
||||||
@@ -70,11 +69,7 @@ type FileTypes =
|
|||||||
| 'image/x-icon'
|
| 'image/x-icon'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
||||||
type: Array as PropType<UploadUserFile[]>,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
|
||||||
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
||||||
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||||
limit: propTypes.number.def(5), // 最大图片上传数 ==> 非必传(默认为 5张)
|
limit: propTypes.number.def(5), // 最大图片上传数 ==> 非必传(默认为 5张)
|
||||||
@@ -85,24 +80,11 @@ const props = defineProps({
|
|||||||
borderradius: propTypes.string.def('8px') // 组件边框圆角 ==> 非必传(默认为 8px)
|
borderradius: propTypes.string.def('8px') // 组件边框圆角 ==> 非必传(默认为 8px)
|
||||||
})
|
})
|
||||||
|
|
||||||
const uploadHeaders = ref({
|
const { uploadUrl, httpRequest } = useUpload()
|
||||||
Authorization: 'Bearer ' + getAccessToken(),
|
|
||||||
'tenant-id': getTenantId()
|
|
||||||
})
|
|
||||||
|
|
||||||
const fileList = ref<UploadUserFile[]>([])
|
const fileList = ref<UploadUserFile[]>([])
|
||||||
// fix: 改为动态监听赋值解决图片回显问题
|
const uploadNumber = ref<number>(0)
|
||||||
watch(
|
const uploadList = ref<UploadUserFile[]>([])
|
||||||
() => props.modelValue,
|
|
||||||
(data) => {
|
|
||||||
if (!data) return
|
|
||||||
fileList.value = data
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deep: true,
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
/**
|
/**
|
||||||
* @description 文件上传之前判断
|
* @description 文件上传之前判断
|
||||||
* @param rawFile 上传的文件
|
* @param rawFile 上传的文件
|
||||||
@@ -122,29 +104,60 @@ const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
|||||||
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
|
uploadNumber.value++
|
||||||
return imgType.includes(rawFile.type as FileTypes) && imgSize
|
return imgType.includes(rawFile.type as FileTypes) && imgSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片上传成功
|
// 图片上传成功
|
||||||
interface UploadEmits {
|
interface UploadEmits {
|
||||||
(e: 'update:modelValue', value: UploadUserFile[]): void
|
(e: 'update:modelValue', value: string[]): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<UploadEmits>()
|
const emit = defineEmits<UploadEmits>()
|
||||||
const uploadSuccess = (response, uploadFile: UploadFile) => {
|
const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
|
||||||
if (!response) return
|
|
||||||
// TODO 多图上传组件成功后只是把保存成功后的url替换掉组件选图时的文件路径,所以返回的fileList包含的是一个包含文件信息的对象列表
|
|
||||||
uploadFile.url = response.data
|
|
||||||
emit('update:modelValue', fileList.value)
|
|
||||||
message.success('上传成功')
|
message.success('上传成功')
|
||||||
|
// 删除自身
|
||||||
|
const index = fileList.value.findIndex((item) => item.response?.data === res.data)
|
||||||
|
fileList.value.splice(index, 1)
|
||||||
|
uploadList.value.push({ name: res.data, url: res.data })
|
||||||
|
if (uploadList.value.length == uploadNumber.value) {
|
||||||
|
fileList.value.push(...uploadList.value)
|
||||||
|
uploadList.value = []
|
||||||
|
uploadNumber.value = 0
|
||||||
|
emitUpdateModelValue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听模型绑定值变动
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(val: string | string[]) => {
|
||||||
|
if (!val) {
|
||||||
|
fileList.value = [] // fix:处理掉缓存,表单重置后上传组件的内容并没有重置
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileList.value = [] // 保障数据为空
|
||||||
|
fileList.value.push(
|
||||||
|
...(val as string[]).map((url) => ({ name: url.substring(url.lastIndexOf('/') + 1), url }))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
// 发送图片链接列表更新
|
||||||
|
const emitUpdateModelValue = () => {
|
||||||
|
let result: string[] = fileList.value.map((file) => file.url!)
|
||||||
|
emit('update:modelValue', result)
|
||||||
|
}
|
||||||
// 删除图片
|
// 删除图片
|
||||||
const handleRemove = (uploadFile: UploadFile) => {
|
const handleRemove = (uploadFile: UploadFile) => {
|
||||||
fileList.value = fileList.value.filter(
|
fileList.value = fileList.value.filter(
|
||||||
(item) => item.url !== uploadFile.url || item.name !== uploadFile.name
|
(item) => item.url !== uploadFile.url || item.name !== uploadFile.name
|
||||||
)
|
)
|
||||||
emit('update:modelValue', fileList.value)
|
emit(
|
||||||
|
'update:modelValue',
|
||||||
|
fileList.value.map((file) => file.url!)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片上传错误提示
|
// 图片上传错误提示
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import * as FileApi from '@/api/infra/file'
|
||||||
|
import CryptoJS from 'crypto-js'
|
||||||
|
import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export const useUpload = () => {
|
||||||
|
// 后端上传地址
|
||||||
|
const uploadUrl = import.meta.env.VITE_UPLOAD_URL
|
||||||
|
// 是否使用前端直连上传
|
||||||
|
const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE
|
||||||
|
// 重写ElUpload上传方法
|
||||||
|
const httpRequest = async (options: UploadRequestOptions) => {
|
||||||
|
// 模式一:前端上传
|
||||||
|
if (isClientUpload) {
|
||||||
|
// 1.1 生成文件名称
|
||||||
|
const fileName = await generateFileName(options.file)
|
||||||
|
// 1.2 获取文件预签名地址
|
||||||
|
const presignedInfo = await FileApi.getFilePresignedUrl(fileName)
|
||||||
|
// 1.3 上传文件(不能使用 ElUpload 的 ajaxUpload 方法的原因:其使用的是 FormData 上传,Minio 不支持)
|
||||||
|
return axios.put(presignedInfo.uploadUrl, options.file).then(() => {
|
||||||
|
// 1.4. 记录文件信息到后端(异步)
|
||||||
|
createFile(presignedInfo, fileName, options.file)
|
||||||
|
// 通知成功,数据格式保持与后端上传的返回结果一致
|
||||||
|
return { data: presignedInfo.url }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 模式二:后端上传
|
||||||
|
// 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
FileApi.updateFile({ file: options.file })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
resolve(res)
|
||||||
|
} else {
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((res) => {
|
||||||
|
reject(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
uploadUrl,
|
||||||
|
httpRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建文件信息
|
||||||
|
* @param vo 文件预签名信息
|
||||||
|
* @param name 文件名称
|
||||||
|
* @param file 文件
|
||||||
|
*/
|
||||||
|
function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) {
|
||||||
|
const fileVo = {
|
||||||
|
configId: vo.configId,
|
||||||
|
url: vo.url,
|
||||||
|
path: name,
|
||||||
|
name: file.name,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size
|
||||||
|
}
|
||||||
|
FileApi.createFile(fileVo)
|
||||||
|
return fileVo
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成文件名称(使用算法SHA256)
|
||||||
|
* @param file 要上传的文件
|
||||||
|
*/
|
||||||
|
async function generateFileName(file: UploadRawFile) {
|
||||||
|
// 读取文件内容
|
||||||
|
const data = await file.arrayBuffer()
|
||||||
|
const wordArray = CryptoJS.lib.WordArray.create(data)
|
||||||
|
// 计算SHA256
|
||||||
|
const sha256 = CryptoJS.SHA256(wordArray).toString()
|
||||||
|
// 拼接后缀
|
||||||
|
const ext = file.name.substring(file.name.lastIndexOf('.'))
|
||||||
|
return `${sha256}${ext}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传类型
|
||||||
|
*/
|
||||||
|
enum UPLOAD_TYPE {
|
||||||
|
// 客户端直接上传(只支持S3服务)
|
||||||
|
CLIENT = 'client',
|
||||||
|
// 客户端发送到后端上传
|
||||||
|
SERVER = 'server'
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } f
|
|||||||
import errorCode from './errorCode'
|
import errorCode from './errorCode'
|
||||||
|
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
import { deleteUserCache } from '@/hooks/web/useCache'
|
||||||
|
|
||||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||||
const { result_code, base_url, request_timeout } = config
|
const { result_code, base_url, request_timeout } = config
|
||||||
@@ -217,9 +217,8 @@ const handleAuthorized = () => {
|
|||||||
confirmButtonText: t('login.relogin'),
|
confirmButtonText: t('login.relogin'),
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const { wsCache } = useCache()
|
|
||||||
resetRouter() // 重置静态路由表
|
resetRouter() // 重置静态路由表
|
||||||
wsCache.clear()
|
deleteUserCache() // 删除用户缓存
|
||||||
removeToken()
|
removeToken()
|
||||||
isRelogin.show = false
|
isRelogin.show = false
|
||||||
// 干掉token后再走一次路由让它过router.beforeEach的校验
|
// 干掉token后再走一次路由让它过router.beforeEach的校验
|
||||||
|
|||||||
@@ -7,13 +7,18 @@ import WebStorageCache from 'web-storage-cache'
|
|||||||
type CacheType = 'localStorage' | 'sessionStorage'
|
type CacheType = 'localStorage' | 'sessionStorage'
|
||||||
|
|
||||||
export const CACHE_KEY = {
|
export const CACHE_KEY = {
|
||||||
IS_DARK: 'isDark',
|
// 用户相关
|
||||||
|
ROLE_ROUTERS: 'roleRouters',
|
||||||
USER: 'user',
|
USER: 'user',
|
||||||
|
// 系统设置
|
||||||
|
IS_DARK: 'isDark',
|
||||||
LANG: 'lang',
|
LANG: 'lang',
|
||||||
THEME: 'theme',
|
THEME: 'theme',
|
||||||
LAYOUT: 'layout',
|
LAYOUT: 'layout',
|
||||||
ROLE_ROUTERS: 'roleRouters',
|
DICT_CACHE: 'dictCache',
|
||||||
DICT_CACHE: 'dictCache'
|
// 登录表单
|
||||||
|
LoginForm: 'loginForm',
|
||||||
|
TenantId: 'tenantId'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCache = (type: CacheType = 'localStorage') => {
|
export const useCache = (type: CacheType = 'localStorage') => {
|
||||||
@@ -25,3 +30,10 @@ export const useCache = (type: CacheType = 'localStorage') => {
|
|||||||
wsCache
|
wsCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteUserCache = () => {
|
||||||
|
const { wsCache } = useCache()
|
||||||
|
wsCache.delete(CACHE_KEY.USER)
|
||||||
|
wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
|
||||||
|
// 注意,不要清理 LoginForm 登录表单
|
||||||
|
}
|
||||||
@@ -24,13 +24,12 @@ const toggleCollapse = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="prefixCls">
|
<div :class="prefixCls" @click="toggleCollapse">
|
||||||
<Icon
|
<Icon
|
||||||
:color="color"
|
:color="color"
|
||||||
:icon="collapse ? 'ep:expand' : 'ep:fold'"
|
:icon="collapse ? 'ep:expand' : 'ep:fold'"
|
||||||
:size="18"
|
:size="18"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
@click="toggleCollapse"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -124,16 +124,6 @@ export default defineComponent({
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$prefix-cls: #{$namespace}-menu;
|
$prefix-cls: #{$namespace}-menu;
|
||||||
|
|
||||||
.is-active--after {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 4px;
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--el-color-primary);
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$prefix-cls} {
|
.#{$prefix-cls} {
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: width var(--transition-time-02);
|
transition: width var(--transition-time-02);
|
||||||
@@ -159,7 +149,6 @@ $prefix-cls: #{$namespace}-menu;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置选中时的高亮背景和高亮颜色
|
// 设置选中时的高亮背景和高亮颜色
|
||||||
.#{$elNamespace}-sub-menu.is-active,
|
|
||||||
.#{$elNamespace}-menu-item.is-active {
|
.#{$elNamespace}-menu-item.is-active {
|
||||||
color: var(--left-menu-text-active-color) !important;
|
color: var(--left-menu-text-active-color) !important;
|
||||||
background-color: var(--left-menu-bg-active-color) !important;
|
background-color: var(--left-menu-bg-active-color) !important;
|
||||||
@@ -171,10 +160,6 @@ $prefix-cls: #{$namespace}-menu;
|
|||||||
|
|
||||||
.#{$elNamespace}-menu-item.is-active {
|
.#{$elNamespace}-menu-item.is-active {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::after {
|
|
||||||
@extend .is-active--after;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置子菜单的背景颜色
|
// 设置子菜单的背景颜色
|
||||||
@@ -194,10 +179,6 @@ $prefix-cls: #{$namespace}-menu;
|
|||||||
& > .is-active > .#{$elNamespace}-sub-menu__title {
|
& > .is-active > .#{$elNamespace}-sub-menu__title {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: var(--left-menu-collapse-bg-active-color) !important;
|
background-color: var(--left-menu-collapse-bg-active-color) !important;
|
||||||
|
|
||||||
&::after {
|
|
||||||
@extend .is-active--after;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,16 +226,6 @@ $prefix-cls: #{$namespace}-menu;
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
$prefix-cls: #{$namespace}-menu-popper;
|
$prefix-cls: #{$namespace}-menu-popper;
|
||||||
|
|
||||||
.is-active--after {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 4px;
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--el-color-primary);
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$prefix-cls}--vertical,
|
.#{$prefix-cls}--vertical,
|
||||||
.#{$prefix-cls}--horizontal {
|
.#{$prefix-cls}--horizontal {
|
||||||
// 设置选中时子标题的颜色
|
// 设置选中时子标题的颜色
|
||||||
@@ -281,10 +252,6 @@ $prefix-cls: #{$namespace}-menu-popper;
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--left-menu-bg-active-color) !important;
|
background-color: var(--left-menu-bg-active-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
|
||||||
@extend .is-active--after;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,59 +1,50 @@
|
|||||||
import { ElSubMenu, ElMenuItem } from 'element-plus'
|
import { ElSubMenu, ElMenuItem } from 'element-plus'
|
||||||
import type { RouteMeta } from 'vue-router'
|
|
||||||
import { hasOneShowingChild } from '../helper'
|
import { hasOneShowingChild } from '../helper'
|
||||||
import { isUrl } from '@/utils/is'
|
import { isUrl } from '@/utils/is'
|
||||||
import { useRenderMenuTitle } from './useRenderMenuTitle'
|
import { useRenderMenuTitle } from './useRenderMenuTitle'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
|
||||||
import { pathResolve } from '@/utils/routerHelper'
|
import { pathResolve } from '@/utils/routerHelper'
|
||||||
|
|
||||||
export const useRenderMenuItem = (
|
const { renderMenuTitle } = useRenderMenuTitle()
|
||||||
|
|
||||||
|
export const useRenderMenuItem = () =>
|
||||||
// allRouters: AppRouteRecordRaw[] = [],
|
// allRouters: AppRouteRecordRaw[] = [],
|
||||||
menuMode: 'vertical' | 'horizontal'
|
{
|
||||||
) => {
|
const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => {
|
||||||
const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => {
|
return routers
|
||||||
return routers.map((v) => {
|
.filter((v) => !v.meta?.hidden)
|
||||||
const meta = (v.meta ?? {}) as RouteMeta
|
.map((v) => {
|
||||||
if (!meta.hidden) {
|
const meta = v.meta ?? {}
|
||||||
const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v)
|
const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v)
|
||||||
const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath<AppRouteRecordRaw>(allRouters, v.path).join('/')
|
const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath<AppRouteRecordRaw>(allRouters, v.path).join('/')
|
||||||
|
|
||||||
const { renderMenuTitle } = useRenderMenuTitle()
|
if (
|
||||||
|
oneShowingChild &&
|
||||||
|
(!onlyOneChild?.children || onlyOneChild?.noShowingChildren) &&
|
||||||
|
!meta?.alwaysShow
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<ElMenuItem
|
||||||
|
index={onlyOneChild ? pathResolve(fullPath, onlyOneChild.path) : fullPath}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta)
|
||||||
|
}}
|
||||||
|
</ElMenuItem>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<ElSubMenu index={fullPath}>
|
||||||
|
{{
|
||||||
|
title: () => renderMenuTitle(meta),
|
||||||
|
default: () => renderMenuItem(v.children!, fullPath)
|
||||||
|
}}
|
||||||
|
</ElSubMenu>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
return {
|
||||||
oneShowingChild &&
|
renderMenuItem
|
||||||
(!onlyOneChild?.children || onlyOneChild?.noShowingChildren) &&
|
}
|
||||||
!meta?.alwaysShow
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<ElMenuItem index={onlyOneChild ? pathResolve(fullPath, onlyOneChild.path) : fullPath}>
|
|
||||||
{{
|
|
||||||
default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta)
|
|
||||||
}}
|
|
||||||
</ElMenuItem>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
const { getPrefixCls } = useDesign()
|
|
||||||
|
|
||||||
const preFixCls = getPrefixCls('menu-popper')
|
|
||||||
return (
|
|
||||||
<ElSubMenu
|
|
||||||
index={fullPath}
|
|
||||||
popperClass={
|
|
||||||
menuMode === 'vertical' ? `${preFixCls}--vertical` : `${preFixCls}--horizontal`
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
title: () => renderMenuTitle(meta),
|
|
||||||
default: () => renderMenuItem(v.children!, fullPath)
|
|
||||||
}}
|
|
||||||
</ElSubMenu>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
renderMenuItem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { RouteMeta } from 'vue-router'
|
import type { RouteMeta } from 'vue-router'
|
||||||
import { Icon } from '@/components/Icon'
|
import { Icon } from '@/components/Icon'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
|
||||||
export const useRenderMenuTitle = () => {
|
export const useRenderMenuTitle = () => {
|
||||||
const renderMenuTitle = (meta: RouteMeta) => {
|
const renderMenuTitle = (meta: RouteMeta) => {
|
||||||
@@ -9,10 +10,14 @@ export const useRenderMenuTitle = () => {
|
|||||||
return icon ? (
|
return icon ? (
|
||||||
<>
|
<>
|
||||||
<Icon icon={meta.icon}></Icon>
|
<Icon icon={meta.icon}></Icon>
|
||||||
<span class="v-menu__title">{t(title as string)}</span>
|
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
|
||||||
|
{t(title as string)}
|
||||||
|
</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span class="v-menu__title">{t(title as string)}</span>
|
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
|
||||||
|
{t(title as string)}
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export default defineComponent({
|
|||||||
id={`${variables.namespace}-menu`}
|
id={`${variables.namespace}-menu`}
|
||||||
class={[
|
class={[
|
||||||
prefixCls,
|
prefixCls,
|
||||||
'relative bg-[var(--left-menu-bg-color)] top-1px z-3000 layout-border__right',
|
'relative bg-[var(--left-menu-bg-color)] top-1px layout-border__right',
|
||||||
{
|
{
|
||||||
'w-[var(--tab-menu-max-width)]': !unref(collapse),
|
'w-[var(--tab-menu-max-width)]': !unref(collapse),
|
||||||
'w-[var(--tab-menu-min-width)]': unref(collapse)
|
'w-[var(--tab-menu-min-width)]': unref(collapse)
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
|
||||||
import avatarImg from '@/assets/imgs/avatar.gif'
|
import avatarImg from '@/assets/imgs/avatar.gif'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import LockDialog from './components/LockDialog.vue'
|
||||||
|
import LockPage from './components/LockPage.vue'
|
||||||
|
import { useLockStore } from '@/store/modules/lock'
|
||||||
|
|
||||||
defineOptions({ name: 'UserInfo' })
|
defineOptions({ name: 'UserInfo' })
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
|
||||||
|
|
||||||
const { push, replace } = useRouter()
|
const { push, replace } = useRouter()
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
@@ -23,24 +23,28 @@ const { getPrefixCls } = useDesign()
|
|||||||
|
|
||||||
const prefixCls = getPrefixCls('user-info')
|
const prefixCls = getPrefixCls('user-info')
|
||||||
|
|
||||||
const user = wsCache.get(CACHE_KEY.USER)
|
const avatar = computed(() => userStore.user.avatar ?? avatarImg)
|
||||||
|
const userName = computed(() => userStore.user.nickname ?? 'Admin')
|
||||||
|
|
||||||
const avatar = user.user.avatar ? user.user.avatar : avatarImg
|
// 锁定屏幕
|
||||||
|
const lockStore = useLockStore()
|
||||||
|
const getIsLock = computed(() => lockStore.getLockInfo?.isLock ?? false)
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const lockScreen = () => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
const userName = user.user.nickname ? user.user.nickname : 'Admin'
|
const loginOut = async () => {
|
||||||
|
try {
|
||||||
const loginOut = () => {
|
await ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
|
||||||
ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
|
confirmButtonText: t('common.ok'),
|
||||||
confirmButtonText: t('common.ok'),
|
cancelButtonText: t('common.cancel'),
|
||||||
cancelButtonText: t('common.cancel'),
|
type: 'warning'
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
.then(async () => {
|
|
||||||
await userStore.loginOut()
|
|
||||||
tagsViewStore.delAllViews()
|
|
||||||
replace('/login?redirect=/index')
|
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
await userStore.loginOut()
|
||||||
|
tagsViewStore.delAllViews()
|
||||||
|
replace('/login?redirect=/index')
|
||||||
|
} catch {}
|
||||||
}
|
}
|
||||||
const toProfile = async () => {
|
const toProfile = async () => {
|
||||||
push('/user/profile')
|
push('/user/profile')
|
||||||
@@ -68,6 +72,10 @@ const toDocument = () => {
|
|||||||
<Icon icon="ep:menu" />
|
<Icon icon="ep:menu" />
|
||||||
<div @click="toDocument">{{ t('common.document') }}</div>
|
<div @click="toDocument">{{ t('common.document') }}</div>
|
||||||
</ElDropdownItem>
|
</ElDropdownItem>
|
||||||
|
<ElDropdownItem divided>
|
||||||
|
<Icon icon="ep:lock" />
|
||||||
|
<div @click="lockScreen">{{ t('lock.lockScreen') }}</div>
|
||||||
|
</ElDropdownItem>
|
||||||
<ElDropdownItem divided @click="loginOut">
|
<ElDropdownItem divided @click="loginOut">
|
||||||
<Icon icon="ep:switch-button" />
|
<Icon icon="ep:switch-button" />
|
||||||
<div>{{ t('common.loginOut') }}</div>
|
<div>{{ t('common.loginOut') }}</div>
|
||||||
@@ -75,4 +83,31 @@ const toDocument = () => {
|
|||||||
</ElDropdownMenu>
|
</ElDropdownMenu>
|
||||||
</template>
|
</template>
|
||||||
</ElDropdown>
|
</ElDropdown>
|
||||||
|
|
||||||
|
<LockDialog v-if="dialogVisible" v-model="dialogVisible" />
|
||||||
|
|
||||||
|
<teleport to="body">
|
||||||
|
<transition name="fade-bottom" mode="out-in">
|
||||||
|
<LockPage v-if="getIsLock" />
|
||||||
|
</transition>
|
||||||
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.fade-bottom-enter-active,
|
||||||
|
.fade-bottom-leave-active {
|
||||||
|
transition:
|
||||||
|
opacity 0.25s,
|
||||||
|
transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-bottom-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-bottom-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useValidator } from '@/hooks/web/useValidator'
|
||||||
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { useLockStore } from '@/store/modules/lock'
|
||||||
|
import avatarImg from '@/assets/imgs/avatar.gif'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
|
const { getPrefixCls } = useDesign()
|
||||||
|
const prefixCls = getPrefixCls('lock-dialog')
|
||||||
|
|
||||||
|
const { required } = useValidator()
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const lockStore = useLockStore()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const avatar = computed(() => userStore.user.avatar ?? avatarImg)
|
||||||
|
const userName = computed(() => userStore.user.nickname ?? 'Admin')
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
|
const dialogVisible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (val) => {
|
||||||
|
console.log('set: ', val)
|
||||||
|
emit('update:modelValue', val)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogTitle = ref(t('lock.lockScreen'))
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
password: undefined
|
||||||
|
})
|
||||||
|
const formRules = reactive({
|
||||||
|
password: [required()]
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
const handleLock = async () => {
|
||||||
|
// 校验表单
|
||||||
|
if (!formRef) return
|
||||||
|
const valid = await formRef.value.validate()
|
||||||
|
if (!valid) return
|
||||||
|
// 提交请求
|
||||||
|
dialogVisible.value = false
|
||||||
|
lockStore.setLockInfo({
|
||||||
|
...formData.value,
|
||||||
|
isLock: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
width="500px"
|
||||||
|
max-height="170px"
|
||||||
|
:class="prefixCls"
|
||||||
|
:title="dialogTitle"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<img :src="avatar" alt="" class="w-70px h-70px rounded-[50%]" />
|
||||||
|
<span class="text-14px my-10px text-[var(--top-header-text-color)]">
|
||||||
|
{{ userName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
|
||||||
|
<el-form-item :label="t('lock.lockPassword')" prop="password">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
v-model="formData.password"
|
||||||
|
:placeholder="'请输入' + t('lock.lockPassword')"
|
||||||
|
clearable
|
||||||
|
show-password
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<ElButton type="primary" @click="handleLock">{{ t('lock.lock') }}</ElButton>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:global(.v-lock-dialog) {
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
max-width: calc(100vw - 16px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { resetRouter } from '@/router'
|
||||||
|
import { deleteUserCache } from '@/hooks/web/useCache'
|
||||||
|
import { useLockStore } from '@/store/modules/lock'
|
||||||
|
import { useNow } from '@/hooks/web/useNow'
|
||||||
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import avatarImg from '@/assets/imgs/avatar.gif'
|
||||||
|
|
||||||
|
const tagsViewStore = useTagsViewStore()
|
||||||
|
|
||||||
|
const { replace } = useRouter()
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const password = ref('')
|
||||||
|
const loading = ref(false)
|
||||||
|
const errMsg = ref(false)
|
||||||
|
const showDate = ref(true)
|
||||||
|
|
||||||
|
const { getPrefixCls } = useDesign()
|
||||||
|
const prefixCls = getPrefixCls('lock-page')
|
||||||
|
|
||||||
|
const avatar = computed(() => userStore.user.avatar ?? avatarImg)
|
||||||
|
const userName = computed(() => userStore.user.nickname ?? 'Admin')
|
||||||
|
|
||||||
|
const lockStore = useLockStore()
|
||||||
|
|
||||||
|
const { hour, month, minute, meridiem, year, day, week } = useNow(true)
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
// 解锁
|
||||||
|
async function unLock() {
|
||||||
|
if (!password.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let pwd = password.value
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await lockStore.unLock(pwd)
|
||||||
|
errMsg.value = !res
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回登录
|
||||||
|
async function goLogin() {
|
||||||
|
await userStore.loginOut().catch(() => {})
|
||||||
|
// 登出后清理
|
||||||
|
deleteUserCache() // 清空用户缓存
|
||||||
|
tagsViewStore.delAllViews()
|
||||||
|
resetRouter() // 重置静态路由表
|
||||||
|
lockStore.resetLockInfo()
|
||||||
|
replace('/login')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleShowForm(show = false) {
|
||||||
|
showDate.value = show
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="prefixCls"
|
||||||
|
class="fixed inset-0 flex h-screen w-screen bg-black items-center justify-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:class="`${prefixCls}__unlock`"
|
||||||
|
class="absolute top-0 left-1/2 flex pt-5 h-16 items-center justify-center sm:text-md xl:text-xl text-white flex-col cursor-pointer transform translate-x-1/2"
|
||||||
|
@click="handleShowForm(false)"
|
||||||
|
v-show="showDate"
|
||||||
|
>
|
||||||
|
<Icon icon="ep:lock" />
|
||||||
|
<span>{{ t('lock.unlock') }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex w-screen h-screen justify-center items-center">
|
||||||
|
<div :class="`${prefixCls}__hour`" class="relative mr-5 md:mr-20 w-2/5 h-2/5 md:h-4/5">
|
||||||
|
<span>{{ hour }}</span>
|
||||||
|
<span class="meridiem absolute left-5 top-5 text-md xl:text-xl" v-show="showDate">
|
||||||
|
{{ meridiem }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div :class="`${prefixCls}__minute w-2/5 h-2/5 md:h-4/5 `">
|
||||||
|
<span> {{ minute }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<transition name="fade-slide">
|
||||||
|
<div :class="`${prefixCls}-entry`" v-show="!showDate">
|
||||||
|
<div :class="`${prefixCls}-entry-content`">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<img :src="avatar" alt="" class="w-70px h-70px rounded-[50%]" />
|
||||||
|
<span class="text-14px my-10px text-[var(--logo-title-text-color)]">
|
||||||
|
{{ userName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ElInput
|
||||||
|
type="password"
|
||||||
|
:placeholder="t('lock.placeholder')"
|
||||||
|
class="enter-x"
|
||||||
|
v-model="password"
|
||||||
|
/>
|
||||||
|
<span :class="`text-14px ${prefixCls}-entry__err-msg enter-x`" v-if="errMsg">
|
||||||
|
{{ t('lock.message') }}
|
||||||
|
</span>
|
||||||
|
<div :class="`${prefixCls}-entry__footer enter-x`">
|
||||||
|
<ElButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
class="mt-2 mr-2 enter-x"
|
||||||
|
link
|
||||||
|
:disabled="loading"
|
||||||
|
@click="handleShowForm(true)"
|
||||||
|
>
|
||||||
|
{{ t('common.back') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
class="mt-2 mr-2 enter-x"
|
||||||
|
link
|
||||||
|
:disabled="loading"
|
||||||
|
@click="goLogin"
|
||||||
|
>
|
||||||
|
{{ t('lock.backToLogin') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton
|
||||||
|
type="primary"
|
||||||
|
class="mt-2"
|
||||||
|
size="small"
|
||||||
|
link
|
||||||
|
@click="unLock()"
|
||||||
|
:disabled="loading"
|
||||||
|
>
|
||||||
|
{{ t('lock.entrySystem') }}
|
||||||
|
</ElButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<div class="absolute bottom-5 w-full text-gray-300 xl:text-xl 2xl:text-3xl text-center enter-y">
|
||||||
|
<div class="text-5xl mb-4 enter-x" v-show="!showDate">
|
||||||
|
{{ hour }}:{{ minute }} <span class="text-3xl">{{ meridiem }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-2xl">{{ year }}/{{ month }}/{{ day }} {{ week }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$prefix-cls: '#{$namespace}-lock-page';
|
||||||
|
|
||||||
|
// Small screen / tablet
|
||||||
|
$screen-sm: 576px;
|
||||||
|
|
||||||
|
// Medium screen / desktop
|
||||||
|
$screen-md: 768px;
|
||||||
|
|
||||||
|
// Large screen / wide desktop
|
||||||
|
$screen-lg: 992px;
|
||||||
|
|
||||||
|
// Extra large screen / full hd
|
||||||
|
$screen-xl: 1200px;
|
||||||
|
|
||||||
|
// Extra extra large screen / large desktop
|
||||||
|
$screen-2xl: 1600px;
|
||||||
|
|
||||||
|
$error-color: #ed6f6f;
|
||||||
|
|
||||||
|
.#{$prefix-cls} {
|
||||||
|
z-index: 3000;
|
||||||
|
|
||||||
|
&__unlock {
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__hour,
|
||||||
|
&__minute {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #bababa;
|
||||||
|
background-color: #141313;
|
||||||
|
border-radius: 30px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
@media screen and (max-width: $screen-md) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $screen-md) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: $screen-sm) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: $screen-lg) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 220px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $screen-xl) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 260px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: $screen-2xl) {
|
||||||
|
span:not(.meridiem) {
|
||||||
|
font-size: 320px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-entry {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&-img {
|
||||||
|
width: 70px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-name {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #bababa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__err-msg {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: $error-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -56,6 +56,16 @@ export default {
|
|||||||
copySuccess: 'Copy Success',
|
copySuccess: 'Copy Success',
|
||||||
copyError: 'Copy Error'
|
copyError: 'Copy Error'
|
||||||
},
|
},
|
||||||
|
lock: {
|
||||||
|
lockScreen: 'Lock screen',
|
||||||
|
lock: 'Lock',
|
||||||
|
lockPassword: 'Lock screen password',
|
||||||
|
unlock: 'Click to unlock',
|
||||||
|
backToLogin: 'Back to login',
|
||||||
|
entrySystem: 'Entry the system',
|
||||||
|
placeholder: 'Please enter the lock screen password',
|
||||||
|
message: 'Lock screen password error'
|
||||||
|
},
|
||||||
error: {
|
error: {
|
||||||
noPermission: `Sorry, you don't have permission to access this page.`,
|
noPermission: `Sorry, you don't have permission to access this page.`,
|
||||||
pageError: 'Sorry, the page you visited does not exist.',
|
pageError: 'Sorry, the page you visited does not exist.',
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ export default {
|
|||||||
copySuccess: '复制成功',
|
copySuccess: '复制成功',
|
||||||
copyError: '复制失败'
|
copyError: '复制失败'
|
||||||
},
|
},
|
||||||
|
lock: {
|
||||||
|
lockScreen: '锁定屏幕',
|
||||||
|
lock: '锁定',
|
||||||
|
lockPassword: '锁屏密码',
|
||||||
|
unlock: '点击解锁',
|
||||||
|
backToLogin: '返回登录',
|
||||||
|
entrySystem: '进入系统',
|
||||||
|
placeholder: '请输入锁屏密码',
|
||||||
|
message: '锁屏密码错误'
|
||||||
|
},
|
||||||
error: {
|
error: {
|
||||||
noPermission: `抱歉,您无权访问此页面。`,
|
noPermission: `抱歉,您无权访问此页面。`,
|
||||||
pageError: '抱歉,您访问的页面不存在。',
|
pageError: '抱歉,您访问的页面不存在。',
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/dict',
|
path: '/dict',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
@@ -496,6 +495,17 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||||||
name: 'CrmCenter',
|
name: 'CrmCenter',
|
||||||
meta: { hidden: true },
|
meta: { hidden: true },
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: 'clue/detail/:id',
|
||||||
|
name: 'CrmClueDetail',
|
||||||
|
meta: {
|
||||||
|
title: '线索详情',
|
||||||
|
noCache: true,
|
||||||
|
hidden: true,
|
||||||
|
activeMenu: '/crm/clue'
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/clue/detail/index.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'customer/detail/:id',
|
path: 'customer/detail/:id',
|
||||||
name: 'CrmCustomerDetail',
|
name: 'CrmCustomerDetail',
|
||||||
@@ -507,6 +517,50 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
component: () => import('@/views/crm/customer/detail/index.vue')
|
component: () => import('@/views/crm/customer/detail/index.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'business/detail/:id',
|
||||||
|
name: 'CrmBusinessDetail',
|
||||||
|
meta: {
|
||||||
|
title: '商机详情',
|
||||||
|
noCache: true,
|
||||||
|
hidden: true,
|
||||||
|
activeMenu: '/crm/business'
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/business/detail/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'contract/detail/:id',
|
||||||
|
name: 'CrmContractDetail',
|
||||||
|
meta: {
|
||||||
|
title: '合同详情',
|
||||||
|
noCache: true,
|
||||||
|
hidden: true,
|
||||||
|
activeMenu: '/crm/contract'
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/contract/detail/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'receivable-plan/detail/:id',
|
||||||
|
name: 'CrmReceivablePlanDetail',
|
||||||
|
meta: {
|
||||||
|
title: '回款计划详情',
|
||||||
|
noCache: true,
|
||||||
|
hidden: true,
|
||||||
|
activeMenu: '/crm/receivable-plan'
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/receivable/plan/detail/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'receivable/detail/:id',
|
||||||
|
name: 'CrmReceivableDetail',
|
||||||
|
meta: {
|
||||||
|
title: '回款详情',
|
||||||
|
noCache: true,
|
||||||
|
hidden: true,
|
||||||
|
activeMenu: '/crm/receivable'
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/receivable/detail/index.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'contact/detail/:id',
|
path: 'contact/detail/:id',
|
||||||
name: 'CrmContactDetail',
|
name: 'CrmContactDetail',
|
||||||
@@ -528,17 +582,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||||||
activeMenu: '/crm/product'
|
activeMenu: '/crm/product'
|
||||||
},
|
},
|
||||||
component: () => import('@/views/crm/product/detail/index.vue')
|
component: () => import('@/views/crm/product/detail/index.vue')
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'message',
|
|
||||||
name: 'CrmMessage',
|
|
||||||
meta: {
|
|
||||||
title: '待办事项',
|
|
||||||
noCache: true,
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
// TODO @db52:后面搞,搞成菜单
|
|
||||||
component: () => import('@/views/crm/message/index.vue')
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||||
|
|
||||||
const store = createPinia()
|
const store = createPinia()
|
||||||
|
store.use(piniaPluginPersistedstate)
|
||||||
|
|
||||||
export const setupStore = (app: App<Element>) => {
|
export const setupStore = (app: App<Element>) => {
|
||||||
app.use(store)
|
app.use(store)
|
||||||
|
|||||||
@@ -268,7 +268,8 @@ export const useAppStore = defineStore('app', {
|
|||||||
setFooter(footer: boolean) {
|
setFooter(footer: boolean) {
|
||||||
this.footer = footer
|
this.footer = footer
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
persist: false
|
||||||
})
|
})
|
||||||
|
|
||||||
export const useAppStoreWithOut = () => {
|
export const useAppStoreWithOut = () => {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { store } from '@/store'
|
||||||
|
|
||||||
|
interface lockInfo {
|
||||||
|
isLock?: boolean
|
||||||
|
password?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LockState {
|
||||||
|
lockInfo: lockInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLockStore = defineStore('lock', {
|
||||||
|
state: (): LockState => {
|
||||||
|
return {
|
||||||
|
lockInfo: {
|
||||||
|
// isLock: false, // 是否锁定屏幕
|
||||||
|
// password: '' // 锁屏密码
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
getLockInfo(): lockInfo {
|
||||||
|
return this.lockInfo
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setLockInfo(lockInfo: lockInfo) {
|
||||||
|
this.lockInfo = lockInfo
|
||||||
|
},
|
||||||
|
resetLockInfo() {
|
||||||
|
this.lockInfo = {}
|
||||||
|
},
|
||||||
|
unLock(password: string) {
|
||||||
|
if (this.lockInfo?.password === password) {
|
||||||
|
this.resetLockInfo()
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persist: true
|
||||||
|
})
|
||||||
|
|
||||||
|
export const useLockStoreWithOut = () => {
|
||||||
|
return useLockStore(store)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { store } from '../index'
|
import { store } from '@/store'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
import remainingRouter from '@/router/modules/remaining'
|
import remainingRouter from '@/router/modules/remaining'
|
||||||
import { flatMultiLevelRoutes, generateRoute } from '@/utils/routerHelper'
|
import { flatMultiLevelRoutes, generateRoute } from '@/utils/routerHelper'
|
||||||
@@ -59,7 +59,8 @@ export const usePermissionStore = defineStore('permission', {
|
|||||||
setMenuTabRouters(routers: AppRouteRecordRaw[]): void {
|
setMenuTabRouters(routers: AppRouteRecordRaw[]): void {
|
||||||
this.menuTabRouters = routers
|
this.menuTabRouters = routers
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
persist: false
|
||||||
})
|
})
|
||||||
|
|
||||||
export const usePermissionStoreWithOut = () => {
|
export const usePermissionStoreWithOut = () => {
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ export const useTagsViewStore = defineStore('tagsView', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
persist: false
|
||||||
})
|
})
|
||||||
|
|
||||||
export const useTagsViewStoreWithOut = () => {
|
export const useTagsViewStoreWithOut = () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { store } from '../index'
|
import { store } from '@/store'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { getAccessToken, removeToken } from '@/utils/auth'
|
import { getAccessToken, removeToken } from '@/utils/auth'
|
||||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
import { CACHE_KEY, useCache, deleteUserCache } from '@/hooks/web/useCache'
|
||||||
import { getInfo, loginOut } from '@/api/login'
|
import { getInfo, loginOut } from '@/api/login'
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
@@ -10,8 +10,11 @@ interface UserVO {
|
|||||||
id: number
|
id: number
|
||||||
avatar: string
|
avatar: string
|
||||||
nickname: string
|
nickname: string
|
||||||
|
deptId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserInfoVO {
|
interface UserInfoVO {
|
||||||
|
// USER 缓存
|
||||||
permissions: string[]
|
permissions: string[]
|
||||||
roles: string[]
|
roles: string[]
|
||||||
isSetUser: boolean
|
isSetUser: boolean
|
||||||
@@ -26,7 +29,8 @@ export const useUserStore = defineStore('admin-user', {
|
|||||||
user: {
|
user: {
|
||||||
id: 0,
|
id: 0,
|
||||||
avatar: '',
|
avatar: '',
|
||||||
nickname: ''
|
nickname: '',
|
||||||
|
deptId: 0
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
@@ -60,10 +64,24 @@ export const useUserStore = defineStore('admin-user', {
|
|||||||
wsCache.set(CACHE_KEY.USER, userInfo)
|
wsCache.set(CACHE_KEY.USER, userInfo)
|
||||||
wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
|
wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
|
||||||
},
|
},
|
||||||
|
async setUserAvatarAction(avatar: string) {
|
||||||
|
const userInfo = wsCache.get(CACHE_KEY.USER)
|
||||||
|
// NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null`
|
||||||
|
this.user.avatar = avatar
|
||||||
|
userInfo.user.avatar = avatar
|
||||||
|
wsCache.set(CACHE_KEY.USER, userInfo)
|
||||||
|
},
|
||||||
|
async setUserNicknameAction(nickname: string) {
|
||||||
|
const userInfo = wsCache.get(CACHE_KEY.USER)
|
||||||
|
// NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null`
|
||||||
|
this.user.nickname = nickname
|
||||||
|
userInfo.user.nickname = nickname
|
||||||
|
wsCache.set(CACHE_KEY.USER, userInfo)
|
||||||
|
},
|
||||||
async loginOut() {
|
async loginOut() {
|
||||||
await loginOut()
|
await loginOut()
|
||||||
removeToken()
|
removeToken()
|
||||||
wsCache.clear()
|
deleteUserCache() // 删除用户缓存
|
||||||
this.resetState()
|
this.resetState()
|
||||||
},
|
},
|
||||||
resetState() {
|
resetState() {
|
||||||
@@ -73,7 +91,8 @@ export const useUserStore = defineStore('admin-user', {
|
|||||||
this.user = {
|
this.user = {
|
||||||
id: 0,
|
id: 0,
|
||||||
avatar: '',
|
avatar: '',
|
||||||
nickname: ''
|
nickname: '',
|
||||||
|
deptId: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -2,6 +2,7 @@ export interface DescriptionsSchema {
|
|||||||
span?: number // 占多少分
|
span?: number // 占多少分
|
||||||
field: string // 字段名
|
field: string // 字段名
|
||||||
label?: string // label名
|
label?: string // label名
|
||||||
|
mappedField?: string // 字段映射
|
||||||
width?: string | number
|
width?: string | number
|
||||||
minWidth?: string | number
|
minWidth?: string | number
|
||||||
align?: 'left' | 'center' | 'right'
|
align?: 'left' | 'center' | 'right'
|
||||||
|
|||||||
+6
-27
@@ -1,4 +1,4 @@
|
|||||||
import { useCache } from '@/hooks/web/useCache'
|
import { useCache, CACHE_KEY } from '@/hooks/web/useCache'
|
||||||
import { TokenType } from '@/api/login/types'
|
import { TokenType } from '@/api/login/types'
|
||||||
import { decrypt, encrypt } from '@/utils/jsencrypt'
|
import { decrypt, encrypt } from '@/utils/jsencrypt'
|
||||||
|
|
||||||
@@ -36,8 +36,6 @@ export const formatToken = (token: string): string => {
|
|||||||
}
|
}
|
||||||
// ========== 账号相关 ==========
|
// ========== 账号相关 ==========
|
||||||
|
|
||||||
const LoginFormKey = 'LOGINFORM'
|
|
||||||
|
|
||||||
export type LoginFormType = {
|
export type LoginFormType = {
|
||||||
tenantName: string
|
tenantName: string
|
||||||
username: string
|
username: string
|
||||||
@@ -46,7 +44,7 @@ export type LoginFormType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getLoginForm = () => {
|
export const getLoginForm = () => {
|
||||||
const loginForm: LoginFormType = wsCache.get(LoginFormKey)
|
const loginForm: LoginFormType = wsCache.get(CACHE_KEY.LoginForm)
|
||||||
if (loginForm) {
|
if (loginForm) {
|
||||||
loginForm.password = decrypt(loginForm.password) as string
|
loginForm.password = decrypt(loginForm.password) as string
|
||||||
}
|
}
|
||||||
@@ -55,38 +53,19 @@ export const getLoginForm = () => {
|
|||||||
|
|
||||||
export const setLoginForm = (loginForm: LoginFormType) => {
|
export const setLoginForm = (loginForm: LoginFormType) => {
|
||||||
loginForm.password = encrypt(loginForm.password) as string
|
loginForm.password = encrypt(loginForm.password) as string
|
||||||
wsCache.set(LoginFormKey, loginForm, { exp: 30 * 24 * 60 * 60 })
|
wsCache.set(CACHE_KEY.LoginForm, loginForm, { exp: 30 * 24 * 60 * 60 })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeLoginForm = () => {
|
export const removeLoginForm = () => {
|
||||||
wsCache.delete(LoginFormKey)
|
wsCache.delete(CACHE_KEY.LoginForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 租户相关 ==========
|
// ========== 租户相关 ==========
|
||||||
|
|
||||||
const TenantIdKey = 'TENANT_ID'
|
|
||||||
const TenantNameKey = 'TENANT_NAME'
|
|
||||||
|
|
||||||
export const getTenantName = () => {
|
|
||||||
return wsCache.get(TenantNameKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setTenantName = (username: string) => {
|
|
||||||
wsCache.set(TenantNameKey, username, { exp: 30 * 24 * 60 * 60 })
|
|
||||||
}
|
|
||||||
|
|
||||||
export const removeTenantName = () => {
|
|
||||||
wsCache.delete(TenantNameKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTenantId = () => {
|
export const getTenantId = () => {
|
||||||
return wsCache.get(TenantIdKey)
|
return wsCache.get(CACHE_KEY.TenantId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setTenantId = (username: string) => {
|
export const setTenantId = (username: string) => {
|
||||||
wsCache.set(TenantIdKey, username)
|
wsCache.set(CACHE_KEY.TenantId, username)
|
||||||
}
|
|
||||||
|
|
||||||
export const removeTenantId = () => {
|
|
||||||
wsCache.delete(TenantIdKey)
|
|
||||||
}
|
}
|
||||||
@@ -418,3 +418,14 @@ export const TradeOrderStatusEnum = {
|
|||||||
name: '已取消'
|
name: '已取消'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== ERP - 企业资源计划 ==========
|
||||||
|
|
||||||
|
export const ErpBizType = {
|
||||||
|
PURCHASE_ORDER: 10,
|
||||||
|
PURCHASE_IN: 11,
|
||||||
|
PURCHASE_RETURN: 12,
|
||||||
|
SALE_ORDER: 20,
|
||||||
|
SALE_OUT: 21,
|
||||||
|
SALE_RETURN: 22
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Independent time operation tool to facilitate subsequent switch to dayjs
|
||||||
|
*/
|
||||||
|
// TODO 芋艿:【锁屏】可能后面删除掉
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
const DATE_FORMAT = 'YYYY-MM-DD'
|
||||||
|
|
||||||
|
export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string {
|
||||||
|
return dayjs(date).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string {
|
||||||
|
return dayjs(date).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const dateUtil = dayjs
|
||||||
+5
-1
@@ -203,5 +203,9 @@ export enum DICT_TYPE {
|
|||||||
CRM_PRODUCT_STATUS = 'crm_product_status',
|
CRM_PRODUCT_STATUS = 'crm_product_status',
|
||||||
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
|
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
|
||||||
CRM_PRODUCT_UNIT = 'crm_product_unit', // 产品单位
|
CRM_PRODUCT_UNIT = 'crm_product_unit', // 产品单位
|
||||||
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type' // 跟进方式
|
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // 跟进方式
|
||||||
|
|
||||||
|
// ========== ERP - 企业资源计划模块 ==========
|
||||||
|
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
|
||||||
|
ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type' // 库存明细的业务类型
|
||||||
}
|
}
|
||||||
+12
-22
@@ -1,4 +1,5 @@
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import type { TableColumnCtx } from 'element-plus'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日期快捷选项适用于 el-date-picker
|
* 日期快捷选项适用于 el-date-picker
|
||||||
@@ -68,10 +69,7 @@ export function formatDate(date: Date, format?: string): string {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
// 日期存在,则进行格式化
|
// 日期存在,则进行格式化
|
||||||
if (format === undefined) {
|
return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : ''
|
||||||
format = 'YYYY-MM-DD HH:mm:ss'
|
|
||||||
}
|
|
||||||
return dayjs(date).format(format)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +169,7 @@ export function formatAxis(param: Date): string {
|
|||||||
* @param ms 毫秒
|
* @param ms 毫秒
|
||||||
* @returns {string} 字符串
|
* @returns {string} 字符串
|
||||||
*/
|
*/
|
||||||
export function formatPast2(ms) {
|
export function formatPast2(ms: number): string {
|
||||||
const day = Math.floor(ms / (24 * 60 * 60 * 1000))
|
const day = Math.floor(ms / (24 * 60 * 60 * 1000))
|
||||||
const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24)
|
const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24)
|
||||||
const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60)
|
const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60)
|
||||||
@@ -199,12 +197,8 @@ export function formatPast2(ms) {
|
|||||||
* @param column 字段
|
* @param column 字段
|
||||||
* @param cellValue 字段值
|
* @param cellValue 字段值
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
export function dateFormatter(_row: any, _column: TableColumnCtx<any>, cellValue: any): string {
|
||||||
export const dateFormatter = (row, column, cellValue): string => {
|
return cellValue ? formatDate(cellValue) : ''
|
||||||
if (!cellValue) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
return formatDate(cellValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,12 +208,8 @@ export const dateFormatter = (row, column, cellValue): string => {
|
|||||||
* @param column 字段
|
* @param column 字段
|
||||||
* @param cellValue 字段值
|
* @param cellValue 字段值
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
export function dateFormatter2(_row: any, _column: TableColumnCtx<any>, cellValue: any): string {
|
||||||
export const dateFormatter2 = (row, column, cellValue) => {
|
return cellValue ? formatDate(cellValue, 'YYYY-MM-DD') : ''
|
||||||
if (!cellValue) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return formatDate(cellValue, 'YYYY-MM-DD')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,7 +217,7 @@ export const dateFormatter2 = (row, column, cellValue) => {
|
|||||||
* @param param 传入日期
|
* @param param 传入日期
|
||||||
* @returns 带时间00:00:00的日期
|
* @returns 带时间00:00:00的日期
|
||||||
*/
|
*/
|
||||||
export function beginOfDay(param: Date) {
|
export function beginOfDay(param: Date): Date {
|
||||||
return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 0, 0, 0)
|
return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +226,7 @@ export function beginOfDay(param: Date) {
|
|||||||
* @param param 传入日期
|
* @param param 传入日期
|
||||||
* @returns 带时间23:59:59的日期
|
* @returns 带时间23:59:59的日期
|
||||||
*/
|
*/
|
||||||
export function endOfDay(param: Date) {
|
export function endOfDay(param: Date): Date {
|
||||||
return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 23, 59, 59)
|
return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 23, 59, 59)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +235,7 @@ export function endOfDay(param: Date) {
|
|||||||
* @param param1 日期1
|
* @param param1 日期1
|
||||||
* @param param2 日期2
|
* @param param2 日期2
|
||||||
*/
|
*/
|
||||||
export function betweenDay(param1: Date, param2: Date) {
|
export function betweenDay(param1: Date, param2: Date): number {
|
||||||
param1 = convertDate(param1)
|
param1 = convertDate(param1)
|
||||||
param2 = convertDate(param2)
|
param2 = convertDate(param2)
|
||||||
// 计算差值
|
// 计算差值
|
||||||
@@ -257,7 +247,7 @@ export function betweenDay(param1: Date, param2: Date) {
|
|||||||
* @param param1 日期
|
* @param param1 日期
|
||||||
* @param param2 添加的时间
|
* @param param2 添加的时间
|
||||||
*/
|
*/
|
||||||
export function addTime(param1: Date, param2: number) {
|
export function addTime(param1: Date, param2: number): Date {
|
||||||
param1 = convertDate(param1)
|
param1 = convertDate(param1)
|
||||||
return new Date(param1.getTime() + param2)
|
return new Date(param1.getTime() + param2)
|
||||||
}
|
}
|
||||||
@@ -266,7 +256,7 @@ export function addTime(param1: Date, param2: number) {
|
|||||||
* 日期转换
|
* 日期转换
|
||||||
* @param param 日期
|
* @param param 日期
|
||||||
*/
|
*/
|
||||||
export function convertDate(param: Date | string) {
|
export function convertDate(param: Date | string): Date {
|
||||||
if (typeof param === 'string') {
|
if (typeof param === 'string') {
|
||||||
return new Date(param)
|
return new Date(param)
|
||||||
}
|
}
|
||||||
|
|||||||
+127
-17
@@ -190,6 +190,56 @@ export const copyValueToTarget = (target: any, source: any) => {
|
|||||||
Object.assign(target, newObj)
|
Object.assign(target, newObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取链接的参数值
|
||||||
|
* @param key 参数键名
|
||||||
|
* @param urlStr 链接地址,默认为当前浏览器的地址
|
||||||
|
*/
|
||||||
|
export const getUrlValue = (key: string, urlStr: string = location.href): string => {
|
||||||
|
if (!urlStr || !key) return ''
|
||||||
|
const url = new URL(decodeURIComponent(urlStr))
|
||||||
|
return url.searchParams.get(key) ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取链接的参数值(值类型)
|
||||||
|
* @param key 参数键名
|
||||||
|
* @param urlStr 链接地址,默认为当前浏览器的地址
|
||||||
|
*/
|
||||||
|
export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
|
||||||
|
return toNumber(getUrlValue(key, urlStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建排序字段
|
||||||
|
* @param prop 字段名称
|
||||||
|
* @param order 顺序
|
||||||
|
*/
|
||||||
|
export const buildSortingField = ({ prop, order }) => {
|
||||||
|
return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== NumberUtils 数字方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组求和
|
||||||
|
*
|
||||||
|
* @param values 数字数组
|
||||||
|
* @return 求和结果,默认为 0
|
||||||
|
*/
|
||||||
|
export const getSumValue = (values: number[]): number => {
|
||||||
|
return values.reduce((prev, curr) => {
|
||||||
|
const value = Number(curr)
|
||||||
|
if (!Number.isNaN(value)) {
|
||||||
|
return prev + curr
|
||||||
|
} else {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 通用金额方法 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将一个整数转换为分数保留两位小数
|
* 将一个整数转换为分数保留两位小数
|
||||||
* @param num
|
* @param num
|
||||||
@@ -206,6 +256,7 @@ export const formatToFraction = (num: number | string | undefined): string => {
|
|||||||
*
|
*
|
||||||
* @param num 整数
|
* @param num 整数
|
||||||
*/
|
*/
|
||||||
|
// TODO @芋艿:看看怎么融合掉
|
||||||
export const floatToFixed2 = (num: number | string | undefined): string => {
|
export const floatToFixed2 = (num: number | string | undefined): string => {
|
||||||
let str = '0.00'
|
let str = '0.00'
|
||||||
if (typeof num === 'undefined') {
|
if (typeof num === 'undefined') {
|
||||||
@@ -232,6 +283,7 @@ export const floatToFixed2 = (num: number | string | undefined): string => {
|
|||||||
* 将一个分数转换为整数
|
* 将一个分数转换为整数
|
||||||
* @param num
|
* @param num
|
||||||
*/
|
*/
|
||||||
|
// TODO @芋艿:看看怎么融合掉
|
||||||
export const convertToInteger = (num: number | string | undefined): number => {
|
export const convertToInteger = (num: number | string | undefined): number => {
|
||||||
if (typeof num === 'undefined') return 0
|
if (typeof num === 'undefined') return 0
|
||||||
const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
|
const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
|
||||||
@@ -266,31 +318,89 @@ export const calculateRelativeRate = (value?: number, reference?: number) => {
|
|||||||
return ((100 * ((value || 0) - reference)) / reference).toFixed(0)
|
return ((100 * ((value || 0) - reference)) / reference).toFixed(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== ERP 专属方法 ==========
|
||||||
|
|
||||||
|
const ERP_COUNT_DIGIT = 3
|
||||||
|
const ERP_PRICE_DIGIT = 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取链接的参数值
|
* 【ERP】格式化 Input 数字
|
||||||
* @param key 参数键名
|
*
|
||||||
* @param urlStr 链接地址,默认为当前浏览器的地址
|
* 例如说:库存数量
|
||||||
|
*
|
||||||
|
* @param num 数量
|
||||||
|
* @return 格式化后的数量
|
||||||
*/
|
*/
|
||||||
export const getUrlValue = (key: string, urlStr: string = location.href): string => {
|
export const erpNumberFormatter = (num: number | string | undefined, digit: number) => {
|
||||||
if (!urlStr || !key) return ''
|
if (num === null) {
|
||||||
const url = new URL(decodeURIComponent(urlStr))
|
return ''
|
||||||
return url.searchParams.get(key) ?? ''
|
}
|
||||||
|
if (typeof num === 'string') {
|
||||||
|
num = parseFloat(num)
|
||||||
|
}
|
||||||
|
// 如果非 number,则直接返回空串
|
||||||
|
if (isNaN(num)) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return num.toFixed(digit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取链接的参数值(值类型)
|
* 【ERP】格式化数量,保留三位小数
|
||||||
* @param key 参数键名
|
*
|
||||||
* @param urlStr 链接地址,默认为当前浏览器的地址
|
* 例如说:库存数量
|
||||||
|
*
|
||||||
|
* @param num 数量
|
||||||
|
* @return 格式化后的数量
|
||||||
*/
|
*/
|
||||||
export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
|
export const erpCountInputFormatter = (num: number | string | undefined) => {
|
||||||
return toNumber(getUrlValue(key, urlStr))
|
return erpNumberFormatter(num, ERP_COUNT_DIGIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// noinspection JSCommentMatchesSignature
|
||||||
|
/**
|
||||||
|
* 【ERP】格式化数量,保留三位小数
|
||||||
|
*
|
||||||
|
* @param cellValue 数量
|
||||||
|
* @return 格式化后的数量
|
||||||
|
*/
|
||||||
|
export const erpCountTableColumnFormatter = (_, __, cellValue: any, ___) => {
|
||||||
|
return erpNumberFormatter(cellValue, ERP_COUNT_DIGIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建排序字段
|
* 【ERP】格式化金额,保留二位小数
|
||||||
* @param prop 字段名称
|
*
|
||||||
* @param order 顺序
|
* 例如说:库存数量
|
||||||
|
*
|
||||||
|
* @param num 数量
|
||||||
|
* @return 格式化后的数量
|
||||||
*/
|
*/
|
||||||
export const buildSortingField = ({ prop, order }) => {
|
export const erpPriceInputFormatter = (num: number | string | undefined) => {
|
||||||
return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
|
return erpNumberFormatter(num, ERP_PRICE_DIGIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// noinspection JSCommentMatchesSignature
|
||||||
|
/**
|
||||||
|
* 【ERP】格式化金额,保留二位小数
|
||||||
|
*
|
||||||
|
* @param cellValue 数量
|
||||||
|
* @return 格式化后的数量
|
||||||
|
*/
|
||||||
|
export const erpPriceTableColumnFormatter = (_, __, cellValue: any, ___) => {
|
||||||
|
return erpNumberFormatter(cellValue, ERP_PRICE_DIGIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【ERP】价格计算,四舍五入保留两位小数
|
||||||
|
*
|
||||||
|
* @param price 价格
|
||||||
|
* @param count 数量
|
||||||
|
* @return 总价格。如果有任一为空,则返回 undefined
|
||||||
|
*/
|
||||||
|
export const erpPriceMultiply = (price: number, count: number) => {
|
||||||
|
if (price == null || count == null) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return parseFloat((price * count).toFixed(ERP_PRICE_DIGIT))
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="prefixCls"
|
:class="prefixCls"
|
||||||
class="relative h-[100%] lt-xl:px-10px lt-md:px-10px lt-sm:px-10px lt-xl:px-10px"
|
class="relative h-[100%] lt-md:px-10px lt-sm:px-10px lt-xl:px-10px lt-xl:px-10px"
|
||||||
>
|
>
|
||||||
<div class="relative mx-auto h-full flex">
|
<div class="relative mx-auto h-full flex">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -193,8 +193,8 @@ const LoginRules = {
|
|||||||
}
|
}
|
||||||
const loginData = reactive({
|
const loginData = reactive({
|
||||||
isShowPassword: false,
|
isShowPassword: false,
|
||||||
captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,
|
captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE !== 'false',
|
||||||
tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
|
tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE !== 'false',
|
||||||
loginForm: {
|
loginForm: {
|
||||||
tenantName: '芋道源码',
|
tenantName: '芋道源码',
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
@@ -207,7 +207,7 @@ const loginData = reactive({
|
|||||||
// 获取验证码
|
// 获取验证码
|
||||||
const getCode = async () => {
|
const getCode = async () => {
|
||||||
// 情况一,未开启:则直接登录
|
// 情况一,未开启:则直接登录
|
||||||
if (loginData.captchaEnable === 'false') {
|
if (loginData.captchaEnable) {
|
||||||
await handleLogin({})
|
await handleLogin({})
|
||||||
} else {
|
} else {
|
||||||
// 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录
|
// 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录
|
||||||
@@ -217,7 +217,7 @@ const getCode = async () => {
|
|||||||
}
|
}
|
||||||
//获取租户ID
|
//获取租户ID
|
||||||
const getTenantId = async () => {
|
const getTenantId = async () => {
|
||||||
if (loginData.tenantEnable === 'true') {
|
if (loginData.tenantEnable) {
|
||||||
const res = await LoginApi.getTenantIdByName(loginData.loginForm.tenantName)
|
const res = await LoginApi.getTenantIdByName(loginData.loginForm.tenantName)
|
||||||
authUtil.setTenantId(res)
|
authUtil.setTenantId(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ const loginData = reactive({
|
|||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: 'admin123',
|
password: 'admin123',
|
||||||
captchaVerification: '',
|
captchaVerification: '',
|
||||||
rememberMe: false
|
rememberMe: true // 默认记录我。如果不需要,可手动修改
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -218,14 +218,14 @@ const getTenantId = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 记住我
|
// 记住我
|
||||||
const getCookie = () => {
|
const getLoginFormCache = () => {
|
||||||
const loginForm = authUtil.getLoginForm()
|
const loginForm = authUtil.getLoginForm()
|
||||||
if (loginForm) {
|
if (loginForm) {
|
||||||
loginData.loginForm = {
|
loginData.loginForm = {
|
||||||
...loginData.loginForm,
|
...loginData.loginForm,
|
||||||
username: loginForm.username ? loginForm.username : loginData.loginForm.username,
|
username: loginForm.username ? loginForm.username : loginData.loginForm.username,
|
||||||
password: loginForm.password ? loginForm.password : loginData.loginForm.password,
|
password: loginForm.password ? loginForm.password : loginData.loginForm.password,
|
||||||
rememberMe: loginForm.rememberMe ? true : false,
|
rememberMe: loginForm.rememberMe,
|
||||||
tenantName: loginForm.tenantName ? loginForm.tenantName : loginData.loginForm.tenantName
|
tenantName: loginForm.tenantName ? loginForm.tenantName : loginData.loginForm.tenantName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCookie()
|
getLoginFormCache()
|
||||||
getTenantByWebsite()
|
getTenantByWebsite()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ import {
|
|||||||
updateUserProfile,
|
updateUserProfile,
|
||||||
UserProfileUpdateReqVO
|
UserProfileUpdateReqVO
|
||||||
} from '@/api/system/user/profile'
|
} from '@/api/system/user/profile'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
defineOptions({ name: 'BasicInfo' })
|
defineOptions({ name: 'BasicInfo' })
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
|
const userStore = useUserStore()
|
||||||
// 表单校验
|
// 表单校验
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
nickname: [{ required: true, message: t('profile.rules.nickname'), trigger: 'blur' }],
|
nickname: [{ required: true, message: t('profile.rules.nickname'), trigger: 'blur' }],
|
||||||
@@ -78,13 +80,15 @@ const submit = () => {
|
|||||||
const data = unref(formRef)?.formModel as UserProfileUpdateReqVO
|
const data = unref(formRef)?.formModel as UserProfileUpdateReqVO
|
||||||
await updateUserProfile(data)
|
await updateUserProfile(data)
|
||||||
message.success(t('common.updateSuccess'))
|
message.success(t('common.updateSuccess'))
|
||||||
await init()
|
const profile = await init()
|
||||||
|
userStore.setUserNicknameAction(profile.nickname)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
const res = await getUserProfile()
|
const res = await getUserProfile()
|
||||||
unref(formRef)?.setValues(res)
|
unref(formRef)?.setValues(res)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await init()
|
await init()
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { uploadAvatar } from '@/api/system/user/profile'
|
import { uploadAvatar } from '@/api/system/user/profile'
|
||||||
import { CropperAvatar } from '@/components/Cropper'
|
import { CropperAvatar } from '@/components/Cropper'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
|
|
||||||
defineOptions({ name: 'UserAvatar' })
|
defineOptions({ name: 'UserAvatar' })
|
||||||
|
|
||||||
@@ -21,10 +23,14 @@ defineProps({
|
|||||||
img: propTypes.string.def('')
|
img: propTypes.string.def('')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
|
||||||
const cropperRef = ref()
|
const cropperRef = ref()
|
||||||
const handelUpload = async ({ data }) => {
|
const handelUpload = async ({ data }) => {
|
||||||
await uploadAvatar({ avatarFile: data })
|
const res = await uploadAvatar({ avatarFile: data })
|
||||||
cropperRef.value.close()
|
cropperRef.value.close()
|
||||||
|
userStore.setUserAvatarAction(res.data)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<doc-alert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
|
||||||
|
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-table v-loading="loading" :data="list">
|
<el-table v-loading="loading" :data="list">
|
||||||
<el-table-column label="定义编号" align="center" prop="id" width="400" />
|
<el-table-column label="定义编号" align="center" prop="id" width="400" />
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<doc-alert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
|
||||||
|
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<!-- 搜索工作栏 -->
|
<!-- 搜索工作栏 -->
|
||||||
<el-form
|
<el-form
|
||||||
|
|||||||
Loaded 100 of 323 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user