Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev

This commit is contained in:
easy 2023-01-16 18:15:24 +08:00
commit bc9fa060f5
40 changed files with 6256 additions and 3978 deletions

395
package-lock.json generated
View File

@ -10,6 +10,7 @@
"dependencies": {
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vuemap/vue-amap": "^1.1.20",
"@vueuse/core": "^9.10.0",
"ant-design-vue": "^3.2.15",
"axios": "^1.2.1",
"echarts": "^5.4.1",
@ -24,7 +25,8 @@
"unplugin-auto-import": "^0.12.1",
"unplugin-vue-components": "^0.22.12",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
"vue-router": "^4.1.6",
"vue3-markdown-it": "^1.0.10"
},
"devDependencies": {
"@commitlint/cli": "^17.4.1",
@ -1481,6 +1483,12 @@
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ=="
},
"node_modules/@types/linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==",
"peer": true
},
"node_modules/@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
@ -1496,6 +1504,22 @@
"@types/lodash": "*"
}
},
"node_modules/@types/markdown-it": {
"version": "12.2.3",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
"peer": true,
"dependencies": {
"@types/linkify-it": "*",
"@types/mdurl": "*"
}
},
"node_modules/@types/mdurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
"integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
"peer": true
},
"node_modules/@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz",
@ -1532,6 +1556,11 @@
"@types/webxr": "*"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/@types/webxr": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.0.tgz",
@ -1823,6 +1852,39 @@
"vue": "^3.2.0"
}
},
"node_modules/@vueuse/core": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.10.0.tgz",
"integrity": "sha512-CxMewME07qeuzuT/AOIQGv0EhhDoojniqU6pC3F8m5VC76L47UT18DcX88kWlP3I7d3qMJ4u/PD8iSRsy3bmNA==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.10.0",
"@vueuse/shared": "9.10.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/metadata": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.10.0.tgz",
"integrity": "sha512-G5VZhgTCapzU9rv0Iq2HBrVOSGzOKb+OE668NxhXNcTjUjwYxULkEhAw70FtRLMZc+hxcFAzDZlKYA0xcwNMuw==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.10.0.tgz",
"integrity": "sha512-vakHJ2ZRklAzqmcVBL38RS7BxdBA4+5poG9NsSyqJxrt9kz0zX3P5CXMy0Hm6LFbZXUgvKdqAS3pUH1zX/5qTQ==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/3d-tiles-renderer": {
"version": "0.3.16",
"resolved": "https://registry.npmjs.org/3d-tiles-renderer/-/3d-tiles-renderer-0.3.16.tgz",
@ -1998,8 +2060,7 @@
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/array-ify": {
"version": "1.0.0",
@ -3883,6 +3944,14 @@
"tslib": "^2.0.3"
}
},
"node_modules/highlight.js": {
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz",
"integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
@ -5465,6 +5534,14 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"node_modules/linkify-it": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
"dependencies": {
"uc.micro": "^1.0.1"
}
},
"node_modules/lint-staged": {
"version": "13.1.0",
"resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.1.0.tgz",
@ -5741,6 +5818,11 @@
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"dev": true
},
"node_modules/lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
"integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
},
"node_modules/lodash.isfunction": {
"version": "3.0.9",
"resolved": "https://registry.npmmirror.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
@ -5952,6 +6034,102 @@
"node": ">=8"
}
},
"node_modules/markdown-it": {
"version": "12.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
"integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
"dependencies": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/markdown-it-abbr": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz",
"integrity": "sha512-ZeA4Z4SaBbYysZap5iZcxKmlPL6bYA8grqhzJIHB1ikn7njnzaP8uwbtuXc4YXD5LicI4/2Xmc0VwmSiFV04gg=="
},
"node_modules/markdown-it-anchor": {
"version": "8.6.6",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.6.tgz",
"integrity": "sha512-jRW30YGywD2ESXDc+l17AiritL0uVaSnWsb26f+68qaW9zgbIIr1f4v2Nsvc0+s0Z2N3uX6t/yAw7BwCQ1wMsA==",
"peerDependencies": {
"@types/markdown-it": "*",
"markdown-it": "*"
}
},
"node_modules/markdown-it-deflist": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz",
"integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg=="
},
"node_modules/markdown-it-emoji": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
"integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ=="
},
"node_modules/markdown-it-footnote": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz",
"integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w=="
},
"node_modules/markdown-it-highlightjs": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/markdown-it-highlightjs/-/markdown-it-highlightjs-3.6.0.tgz",
"integrity": "sha512-ex+Lq3cVkprh0GpGwFyc53A/rqY6GGzopPCG1xMsf8Ya3XtGC8Uw9tChN1rWbpyDae7tBBhVHVcMM29h4Btamw==",
"dependencies": {
"highlight.js": "^11.3.1",
"lodash.flow": "^3.5.0"
}
},
"node_modules/markdown-it-ins": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-3.0.1.tgz",
"integrity": "sha512-32SSfZqSzqyAmmQ4SHvhxbFqSzPDqsZgMHDwxqPzp+v+t8RsmqsBZRG+RfRQskJko9PfKC2/oxyOs4Yg/CfiRw=="
},
"node_modules/markdown-it-mark": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-3.0.1.tgz",
"integrity": "sha512-HyxjAu6BRsdt6Xcv6TKVQnkz/E70TdGXEFHRYBGLncRE9lBFwDNLVtFojKxjJWgJ+5XxUwLaHXy+2sGBbDn+4A=="
},
"node_modules/markdown-it-sub": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-1.0.0.tgz",
"integrity": "sha512-z2Rm/LzEE1wzwTSDrI+FlPEveAAbgdAdPhdWarq/ZGJrGW/uCQbKAnhoCsE4hAbc3SEym26+W2z/VQB0cQiA9Q=="
},
"node_modules/markdown-it-sup": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz",
"integrity": "sha512-E32m0nV9iyhRR7CrhnzL5msqic7rL1juWre6TQNxsnApg7Uf+F97JOKxUijg5YwXz86lZ0mqfOnutoryyNdntQ=="
},
"node_modules/markdown-it-task-lists": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
"integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA=="
},
"node_modules/markdown-it-toc-done-right": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/markdown-it-toc-done-right/-/markdown-it-toc-done-right-4.2.0.tgz",
"integrity": "sha512-UB/IbzjWazwTlNAX0pvWNlJS8NKsOQ4syrXZQ/C72j+jirrsjVRT627lCaylrKJFBQWfRsPmIVQie8x38DEhAQ=="
},
"node_modules/markdown-it/node_modules/entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
},
"node_modules/meow": {
"version": "8.1.2",
"resolved": "https://registry.npmmirror.com/meow/-/meow-8.1.2.tgz",
@ -7943,6 +8121,11 @@
"node": ">=4.2.0"
}
},
"node_modules/uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"node_modules/ufo": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz",
@ -8499,6 +8682,26 @@
"vue": "^3.0.0"
}
},
"node_modules/vue3-markdown-it": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/vue3-markdown-it/-/vue3-markdown-it-1.0.10.tgz",
"integrity": "sha512-mTvHu0zl7jrh7ojgaZ+tTpCLiS4CVg4bTgTu4KGhw/cRRY5YgIG8QgFAPu6kCzSW6Znc9a52Beb6hFvF4hSMkQ==",
"dependencies": {
"markdown-it": "^12.3.2",
"markdown-it-abbr": "^1.0.4",
"markdown-it-anchor": "^8.4.1",
"markdown-it-deflist": "^2.1.0",
"markdown-it-emoji": "^2.0.0",
"markdown-it-footnote": "^3.0.3",
"markdown-it-highlightjs": "^3.6.0",
"markdown-it-ins": "^3.0.1",
"markdown-it-mark": "^3.0.1",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-task-lists": "^2.1.1",
"markdown-it-toc-done-right": "^4.2.0"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
@ -9766,6 +9969,12 @@
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ=="
},
"@types/linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==",
"peer": true
},
"@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
@ -9781,6 +9990,22 @@
"@types/lodash": "*"
}
},
"@types/markdown-it": {
"version": "12.2.3",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
"peer": true,
"requires": {
"@types/linkify-it": "*",
"@types/mdurl": "*"
}
},
"@types/mdurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
"integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
"peer": true
},
"@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz",
@ -9816,6 +10041,11 @@
"@types/webxr": "*"
}
},
"@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"@types/webxr": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.0.tgz",
@ -10077,6 +10307,30 @@
"uppercamelcase": "^1.1.0"
}
},
"@vueuse/core": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.10.0.tgz",
"integrity": "sha512-CxMewME07qeuzuT/AOIQGv0EhhDoojniqU6pC3F8m5VC76L47UT18DcX88kWlP3I7d3qMJ4u/PD8iSRsy3bmNA==",
"requires": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.10.0",
"@vueuse/shared": "9.10.0",
"vue-demi": "*"
}
},
"@vueuse/metadata": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.10.0.tgz",
"integrity": "sha512-G5VZhgTCapzU9rv0Iq2HBrVOSGzOKb+OE668NxhXNcTjUjwYxULkEhAw70FtRLMZc+hxcFAzDZlKYA0xcwNMuw=="
},
"@vueuse/shared": {
"version": "9.10.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.10.0.tgz",
"integrity": "sha512-vakHJ2ZRklAzqmcVBL38RS7BxdBA4+5poG9NsSyqJxrt9kz0zX3P5CXMy0Hm6LFbZXUgvKdqAS3pUH1zX/5qTQ==",
"requires": {
"vue-demi": "*"
}
},
"3d-tiles-renderer": {
"version": "0.3.16",
"resolved": "https://registry.npmjs.org/3d-tiles-renderer/-/3d-tiles-renderer-0.3.16.tgz",
@ -10216,8 +10470,7 @@
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"array-ify": {
"version": "1.0.0",
@ -11742,6 +11995,11 @@
"tslib": "^2.0.3"
}
},
"highlight.js": {
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz",
"integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ=="
},
"homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
@ -12976,6 +13234,14 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"linkify-it": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"lint-staged": {
"version": "13.1.0",
"resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.1.0.tgz",
@ -13183,6 +13449,11 @@
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"dev": true
},
"lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
"integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
},
"lodash.isfunction": {
"version": "3.0.9",
"resolved": "https://registry.npmmirror.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
@ -13363,6 +13634,95 @@
"integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
"dev": true
},
"markdown-it": {
"version": "12.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
"integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
"requires": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"dependencies": {
"entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
}
}
},
"markdown-it-abbr": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz",
"integrity": "sha512-ZeA4Z4SaBbYysZap5iZcxKmlPL6bYA8grqhzJIHB1ikn7njnzaP8uwbtuXc4YXD5LicI4/2Xmc0VwmSiFV04gg=="
},
"markdown-it-anchor": {
"version": "8.6.6",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.6.tgz",
"integrity": "sha512-jRW30YGywD2ESXDc+l17AiritL0uVaSnWsb26f+68qaW9zgbIIr1f4v2Nsvc0+s0Z2N3uX6t/yAw7BwCQ1wMsA==",
"requires": {}
},
"markdown-it-deflist": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz",
"integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg=="
},
"markdown-it-emoji": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
"integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ=="
},
"markdown-it-footnote": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz",
"integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w=="
},
"markdown-it-highlightjs": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/markdown-it-highlightjs/-/markdown-it-highlightjs-3.6.0.tgz",
"integrity": "sha512-ex+Lq3cVkprh0GpGwFyc53A/rqY6GGzopPCG1xMsf8Ya3XtGC8Uw9tChN1rWbpyDae7tBBhVHVcMM29h4Btamw==",
"requires": {
"highlight.js": "^11.3.1",
"lodash.flow": "^3.5.0"
}
},
"markdown-it-ins": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-3.0.1.tgz",
"integrity": "sha512-32SSfZqSzqyAmmQ4SHvhxbFqSzPDqsZgMHDwxqPzp+v+t8RsmqsBZRG+RfRQskJko9PfKC2/oxyOs4Yg/CfiRw=="
},
"markdown-it-mark": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-3.0.1.tgz",
"integrity": "sha512-HyxjAu6BRsdt6Xcv6TKVQnkz/E70TdGXEFHRYBGLncRE9lBFwDNLVtFojKxjJWgJ+5XxUwLaHXy+2sGBbDn+4A=="
},
"markdown-it-sub": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-1.0.0.tgz",
"integrity": "sha512-z2Rm/LzEE1wzwTSDrI+FlPEveAAbgdAdPhdWarq/ZGJrGW/uCQbKAnhoCsE4hAbc3SEym26+W2z/VQB0cQiA9Q=="
},
"markdown-it-sup": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz",
"integrity": "sha512-E32m0nV9iyhRR7CrhnzL5msqic7rL1juWre6TQNxsnApg7Uf+F97JOKxUijg5YwXz86lZ0mqfOnutoryyNdntQ=="
},
"markdown-it-task-lists": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
"integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA=="
},
"markdown-it-toc-done-right": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/markdown-it-toc-done-right/-/markdown-it-toc-done-right-4.2.0.tgz",
"integrity": "sha512-UB/IbzjWazwTlNAX0pvWNlJS8NKsOQ4syrXZQ/C72j+jirrsjVRT627lCaylrKJFBQWfRsPmIVQie8x38DEhAQ=="
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
},
"meow": {
"version": "8.1.2",
"resolved": "https://registry.npmmirror.com/meow/-/meow-8.1.2.tgz",
@ -14934,6 +15294,11 @@
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
"devOptional": true
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"ufo": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz",
@ -15351,6 +15716,26 @@
"is-plain-object": "3.0.1"
}
},
"vue3-markdown-it": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/vue3-markdown-it/-/vue3-markdown-it-1.0.10.tgz",
"integrity": "sha512-mTvHu0zl7jrh7ojgaZ+tTpCLiS4CVg4bTgTu4KGhw/cRRY5YgIG8QgFAPu6kCzSW6Znc9a52Beb6hFvF4hSMkQ==",
"requires": {
"markdown-it": "^12.3.2",
"markdown-it-abbr": "^1.0.4",
"markdown-it-anchor": "^8.4.1",
"markdown-it-deflist": "^2.1.0",
"markdown-it-emoji": "^2.0.0",
"markdown-it-footnote": "^3.0.3",
"markdown-it-highlightjs": "^3.6.0",
"markdown-it-ins": "^3.0.1",
"markdown-it-mark": "^3.0.1",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-task-lists": "^2.1.1",
"markdown-it-toc-done-right": "^4.2.0"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -22,3 +22,33 @@ export const saveMetadata = (id: string, data: string) => server.put(`/device/in
* @returns
*/
export const detail = (id: string) => server.get<DeviceInstance>(`/device-instance/${id}/detail`)
/**
*
* @param data
* @returns
*/
export const query = (data?: Record<string, any>) => server.post('/device-instance/_query', data)
/**
*
* @param id ID
* @returns
*/
export const _delete = (id: string) => server.remove(`/device-instance/${id}`)
/**
*
* @param id ID
* @param data
* @returns
*/
export const _deploy = (id: string) => server.post(`/device-instance/${id}/deploy`)
/**
*
* @param id ID
* @param data
* @returns
*/
export const _undeploy = (id: string) => server.post(`/device-instance/${id}/undeploy`)

View File

View File

@ -0,0 +1,8 @@
import server from '@/utils/request'
/**
*
* @param data
* @returns
*/
export const query = (data: Record<string, any>) => server.post('/dueros/product/_query', data)

View File

@ -0,0 +1,12 @@
import { patch, post, get } from '@/utils/request'
export default {
// 列表
list: (data: any) => post(`/notifier/template/_query`, data),
// 详情
detail: (id: string): any => get(`/notifier/template/${id}`),
// 新增
save: (data: any) => post(`/notifier/template`, data),
// 修改
update: (data: any) => patch(`/notifier/template`, data)
}

View File

@ -1,7 +0,0 @@
import { createFromIconfontCN } from '@ant-design/icons-vue';
const AliIcon = createFromIconfontCN({
scriptUrl: '/icons/iconfont.js', // 在 iconfont.cn 上生成
});
export default AliIcon

View File

@ -0,0 +1,32 @@
import { createFromIconfontCN } from '@ant-design/icons-vue';
import * as $Icon from '@ant-design/icons-vue';
import { createVNode } from 'vue';
const AliIcon = createFromIconfontCN({
scriptUrl: '/icons/iconfont.js', // 在 iconfont.cn 上生成
});
const AntdIcon = (props: {type: string}) => {
const {type} = props;
let antIcon: {[key: string]: any} = $Icon
return createVNode(antIcon[type])
}
const iconKeys = [
'EyeOutlined',
'EditOutlined',
'PlusOutlined',
'DeleteOutlined',
'CheckCircleOutlined',
'StopOutlined',
'CheckOutlined',
'CloseOutlined',
'DownOutlined'
]
const Icon = (props: {type: string}) => {
if(iconKeys.includes(props.type)) return <AntdIcon {...props} />
return <AliIcon {...props} />
}
export default Icon

View File

@ -6,8 +6,7 @@
</template>
<script setup lang="ts">
import { StatusColorEnum } from '@/utils/consts.ts';
// import { StatusColorEnum } from '@/utils/consts.ts';
const props = defineProps({
text: {
type: String,
@ -15,10 +14,10 @@ const props = defineProps({
status: {
type: String || Number,
default: 'default',
validator: (value) => {
//
return Object.keys(StatusColorEnum).includes(value);
},
// validator: (value) => {
// //
// return Object.keys(StatusColorEnum).includes(value);
// },
},
/**
* 自定义status值颜色

View File

@ -108,7 +108,6 @@ const props = defineProps({
type: Boolean,
default: true,
},
statusText: {
type: String,
default: '正常',

View File

@ -75,6 +75,7 @@ const JTable = defineComponent<JTableProps>({
],
emits: [
'modelChange', // 切换卡片和表格
'reload' // 刷新数据
],
props: {
request: {
@ -139,7 +140,7 @@ const JTable = defineComponent<JTableProps>({
}
}
} as any,
setup(props: JTableProps ,{ slots, emit }){
setup(props: JTableProps ,{ slots, emit, expose }){
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
const _model = ref<keyof typeof ModelEnum>(props.model ? props.model : ModelEnum.CARD); // 模式切换
const column = ref<number>(props.gridColumn || 4);
@ -217,6 +218,23 @@ const JTable = defineComponent<JTableProps>({
window.onresize = null
})
/**
*
* @param _params
*/
const reload = (_params?: Record<string, any>) => {
handleSearch({
..._params,
pageSize: 12,
pageIndex: 0
})
}
/**
*
*/
expose({ reload })
return () => <Spin spinning={loading.value}>
<div class={styles["jtable-body"]}>
<div class={styles["jtable-body-header"]}>

View File

@ -66,6 +66,11 @@ export default [
},
// end: 测试用, 可删除
// 设备管理
{
path: '/device/Instance',
component: () => import('@/views/device/Instance/index.vue')
},
// link 运维管理
{
path: '/link/log',
@ -107,4 +112,13 @@ export default [
path: '/iot-card/home',
component: () => import('@/views/iot-card/Home/index.vue')
},
// 北向输出
{
path: '/northbound/DuerOS',
component: () => import('@/views/northbound/DuerOS/index.vue')
},
{
path: '/northbound/AliCloud',
component: () => import('@/views/northbound/AliCloud/index.vue')
},
]

View File

@ -0,0 +1,260 @@
<template>
<JTable ref="instanceRef" :columns="columns" :request="query" :defaultParams="{sorts: [{name: 'createTime', order: 'desc'}]}" :params="{pageIndex: 0, pageSize: 12}">
<template #headerTitle>
<a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-dropdown>
<a-button>批量操作 <AIcon type="DownOutlined" /></a-button>
<template #overlay>
<a-menu>
<a-menu-item>
<a href="javascript:;">1st menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">2nd menu item</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:;">3rd menu item</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
@click="handleView"
:actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{
online: 'success',
offline: 'error',
notActive: 'warning',
}"
>
<template #img>
<slot name="img">
<img :src="getImage('/device/instance/device-card.png')" />
</slot>
</template>
<template #content>
<h3>{{ slotProps.name }}</h3>
<a-row>
<a-col :span="12">
<div class="card-item-content-text">设备类型</div>
<div>{{slotProps.deviceType.text}}</div>
</a-col>
<a-col :span="12">
<div class="card-item-content-text">产品名称</div>
<div>{{slotProps.productName}}</div>
</a-col>
</a-row>
</template>
<template #actions="item">
<a-tooltip v-bind="item.tooltip" :title="item.disabled && item.tooltip.title">
<a-popconfirm
v-if="item.popConfirm"
v-bind="item.popConfirm"
:disabled="item.disabled"
>
<a-button :disabled="item.disabled">
<AIcon type="DeleteOutlined" v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</a-popconfirm>
<template v-else>
<a-button :disabled="item.disabled" @click="item.onClick">
<AIcon type="DeleteOutlined" v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</template>
</a-tooltip>
</template>
</CardBox>
</template>
<template #state="slotProps">
<a-badge :text="slotProps.state.text" :status="statusMap.get(slotProps.state.value)" />
</template>
<template #action="slotProps">
<a-space :size="16">
<a-tooltip
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
v-bind="i.tooltip"
>
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm" :disabled="i.disabled">
<a-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-popconfirm>
<a-button
style="padding: 0"
type="link"
v-else
@click="i.onClick && i.onClick(slotProps)"
>
<a-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip>
</a-space>
</template>
</JTable>
</template>
<script setup lang="ts">
import { query, _delete, _deploy, _undeploy } from '@/api/device/instance'
import type { ActionsType } from '@/components/Table/index.vue'
import { getImage } from '@/utils/comm';
import { message } from "ant-design-vue";
const instanceRef = ref<Record<string, any>>({});
const statusMap = new Map();
statusMap.set('online', 'processing');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'warning');
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id'
},
{
title: '设备名称',
dataIndex: 'name',
key: 'name',
},
{
title: '产品名称',
dataIndex: 'productName',
key: 'productName',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
scopedSlots: true
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
scopedSlots: true
},
{
title: '说明',
dataIndex: 'describe',
key: 'describe'
},
{
title: '操作',
key: 'action',
fixed: 'right',
width: 250,
scopedSlots: true
}
]
const handleAdd = () => {
message.warn('123')
}
const handleView = (dt: any) => {
}
const getActions = (data: Partial<Record<string, any>>, type: 'card' | 'table'): ActionsType[] => {
if(!data) return []
const actions = [
{
key: 'view',
text: "查看",
tooltip: {
title: '查看'
},
icon: 'EyeOutlined',
onClick: () => {
handleView(data)
}
},
{
key: 'edit',
text: "编辑",
tooltip: {
title: '编辑'
},
icon: 'EditOutlined',
onClick: () => {
message.warn('edit')
}
},
{
key: 'action',
text: data.state.value !== 'notActive' ? "禁用" : "启用",
tooltip: {
title: data.state.value !== 'notActive' ? "禁用" : "启用",
},
icon: data.state.value !== 'notActive' ? 'StopOutlined' : 'CheckCircleOutlined',
popConfirm: {
title: `确认${data.state.value !== 'notActive' ? "禁用" : "启用"}?`,
onConfirm: async () => {
let response = undefined
if(data.state.value !== 'notActive') {
response = await _undeploy(data.id)
} else {
response = await _deploy(data.id)
}
if(response && response.status === 200) {
message.success('操作成功!')
instanceRef.value?.reload()
} else {
message.error('操作失败!')
}
}
}
},
{
key: 'delete',
text: "删除",
disabled: data.state.value !== 'notActive',
tooltip: {
title: data.state.value !== 'notActive' ? '已启用的设备不能删除' : '删除'
},
popConfirm: {
title: '确认删除?',
onConfirm: async () => {
const resp = await _delete(data.id)
if(resp.status === 200) {
message.success('操作成功!')
instanceRef.value?.reload()
} else {
message.error('操作失败!')
}
}
},
icon: 'DeleteOutlined'
}
]
if(type === 'card') return actions.filter((i: ActionsType) => i.key !== 'view')
return actions
}
</script>

View File

@ -0,0 +1,7 @@
<template>
<div>123</div>
</template>
<script setup>
</script>

View File

@ -0,0 +1,154 @@
<template>
<div>
<JTable
:columns="columns"
:request="request"
>
<template #headerTitle>
<a-button type="primary" @click="add">新增</a-button>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
@click="handleClick"
:actions="getActions(slotProps)"
v-bind="slotProps"
:status="slotProps.state ? 'success' : 'error'"
>
<template #img>
<slot name="img">
<img :src="getImage('/device-product.png')" />
</slot>
</template>
<template #content>
<h3>{{slotProps.name}}</h3>
<a-row>
<a-col :span="12">
<div class="card-item-content-text">
设备类型
</div>
<div>直连设备</div>
</a-col>
</a-row>
</template>
<template #actions="item">
<a-popconfirm v-if="item.popConfirm" v-bind="item.popConfirm">
<a-button :disabled="item.disabled">
<DeleteOutlined v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</a-popconfirm>
<template v-else>
<a-button :disabled="item.disabled">
<DeleteOutlined v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</template>
</template>
</CardBox>
</template>
<template #id="slotProps">
<a>{{slotProps.id}}</a>
</template>
<template #action="slotProps">
<a-space :size="16">
<a-tooltip v-for="i in getActions(slotProps)" :key="i.key" v-bind="i.tooltip">
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
<a-button :disabled="i.disabled" style="padding: 0" type="link"><AIcon :type="i.icon" /></a-button>
</a-popconfirm>
<a-button style="padding: 0" type="link" v-else @click="i.onClick && i.onClick(slotProps)">
<a-button :disabled="i.disabled" style="padding: 0" type="link"><AIcon :type="i.icon" /></a-button>
</a-button>
</a-tooltip>
</a-space>
</template>
</JTable>
</div>
</template>
<script setup lang="ts">
import { query } from '@/api/northbound/dueros'
import type { ActionsType } from '@/components/Table/index.vue'
import { getImage } from '@/utils/comm';
import { DeleteOutlined } from '@ant-design/icons-vue'
import { message } from "ant-design-vue";
const request = (data: any) => query({})
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
},
{
title: 'ID',
dataIndex: 'id',
key: 'id',
scopedSlots: true
},
{
title: '分类',
dataIndex: 'classifiedName',
key: 'classifiedName',
},
{
title: '操作',
key: 'action',
fixed: 'right',
width: 250,
scopedSlots: true
}
]
const handleClick = (dt: any) => {
}
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
if(!data){
return []
}
return [
{
key: 'edit',
text: "编辑",
tooltip: {
title: '编辑'
},
icon: 'icon-rizhifuwu'
},
{
key: 'import',
text: "导入",
tooltip: {
title: '导入'
},
disabled: true,
icon: 'icon-xiazai'
},
{
key: 'delete',
text: "删除",
tooltip: {
title: !!data?.state ? '正常的产品不能删除' : '删除'
},
popConfirm: {
title: '确认删除?'
},
icon: 'icon-huishouzhan'
}
]
}
const add = () => {
message.warn('123')
}
</script>

View File

@ -0,0 +1,48 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const AliyunSms = () => {
const accessKey = getImage(
'/notice/doc/config/aliyun-sms-voice/AccesskeyIDSecret.jpg',
);
return (
<div class={'doc'}>
<div class={'url'}>
<a
href="https://home.console.aliyun.com"
target="_blank"
rel="noopener noreferrer"
>
https://home.console.aliyun.com
</a>
</div>
<h1>1.</h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2>1RegionID</h2>
<div>
</div>
<div>
https://help.aliyun.com/document_detail/40654.html?spm=a2c6h.13066369.0.0.54a174710O7rWH
</div>
</div>
<h2>2AccesskeyID/Secret</h2>
<div>
<div>API的用户标识和秘钥</div>
<div>
------AccessKey管理--
</div>
<div class={'image'}>
<Image width="100%" src={accessKey} />
</div>
</div>
</div>
);
};
export default AliyunSms;

View File

@ -0,0 +1,45 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const AliyunVoice = () => {
const accessKey = getImage(
'/notice/doc/config/aliyun-sms-voice/AccesskeyIDSecret.jpg',
);
return (
<div class={'doc'}>
<div class={'url'}>
<a
href="https://home.console.aliyun.com"
target="_blank"
rel="noopener noreferrer"
>
https://home.console.aliyun.com
</a>
</div>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2>1RegionID</h2>
<div>
RegionID
</div>
</div>
<h2>2AccesskeyID/Secret</h2>
<div>
<div>
API的用户标识和秘钥获取路径------AccessKey管理--
</div>
</div>
<div class={'image'}>
<Image width="100%" src={accessKey} />
</div>
</div>
);
};
export default AliyunVoice;

View File

@ -1,5 +1,5 @@
import { Image } from 'ant-design-vue';
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const DingTalk = () => {
@ -9,6 +9,7 @@ const DingTalk = () => {
const appSecret = getImage(
'/notice/doc/config/dingTalk-message/02-AppSecret.jpg',
);
return (
<div class={'doc'}>
<div class={'url'}>

View File

@ -0,0 +1,44 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const DingTalkRebot = () => {
const groupSetting = getImage(
'/notice/doc/config/dingTalk-rebot/01-group-setting.jpg',
);
const rebot = getImage('/notice/doc/config/dingTalk-rebot/02-rebot.jpg');
const webhook = getImage(
'/notice/doc/config/dingTalk-rebot/03-Webhook.jpg',
);
return (
<div class={'doc'}>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2> 1WebHook</h2>
<div>
WebHook地址
</div>
<div>
------
</div>
<div class={'image'}>
<Image width="100%" src={rebot} />
</div>
<h2>1</h2>
<div class={'image'}>
<Image width="100%" src={groupSetting} />
</div>
<h2>2</h2>
<div class={'image'}>
<Image width="100%" src={webhook} />
</div>
</div>
</div>
);
};
export default DingTalkRebot;

View File

@ -0,0 +1,27 @@
import './index.less';
const Email = () => {
return (
<div class={'doc'}>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<h2>1 </h2>
<div>
</div>
<div>
使POP协议POP允许电子邮件客户端下载服务器上的邮件
</div>
<h2>2</h2>
<div></div>
<h2>3 </h2>
<div></div>
<h2>4</h2>
<div></div>
</div>
);
};
export default Email;

View File

@ -0,0 +1,23 @@
import './index.less';
const Webhook = () => {
return (
<div class={'doc'}>
<h1>1. </h1>
<div>
webhook是一个接收HTTP请求的URLHTTP
POST请求Webhook的第三方系统可以基于该URL订阅本平台系统信息便
</div>
<h1>2.</h1>
<h2>1Webhook</h2>
<div>Webhook地址</div>
<h2>2</h2>
<div>
Accept-Language
Content-Type
</div>
</div>
);
};
export default Webhook;

View File

@ -0,0 +1,51 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const WeixinApp = () => {
const appId = getImage('/notice/doc/config/weixin-official/01-AppID.jpg');
const appSecret = getImage(
'/notice/doc/config/weixin-official/02-AppSecret.jpg',
);
return (
<div class={'doc'}>
<div class={'url'}>
<a
href="https://mp.weixin.qq.com/"
target="_blank"
rel="noopener noreferrer"
>
https://mp.weixin.qq.com/
</a>
</div>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2>1AppID</h2>
<div></div>
<div>
----
</div>
<div class={'image'}>
<Image width="100%" src={appId} />
</div>
</div>
<h2>2AppSecret</h2>
<div>
<div></div>
<div>
----
</div>
<div class={'image'}>
<Image width="100%" src={appSecret} />
</div>
</div>
</div>
);
};
export default WeixinApp;

View File

@ -0,0 +1,51 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const WeixinCorp = () => {
const corpId = getImage(
'/notice/doc/config/weixin-corp/01-corpId.jpg',
);
const corpSecret = getImage(
'/notice/doc/config/weixin-corp/02-corpSecret.jpg',
);
return (
<div class={'doc'}>
<div class={'url'}>
<a
href="https://work.weixin.qq.com"
target="_blank"
rel="noopener noreferrer"
>
https://work.weixin.qq.com
</a>
</div>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2>1corpId</h2>
<div></div>
<div>----ID</div>
<div class={'image'}>
<Image width="100%" src={corpId} />
</div>
</div>
<h2>2corpSecret</h2>
<div>
<div>secret,corpSecret</div>
<div>
----
</div>
<div class={'image'}>
<Image width="100%" src={corpSecret} />
</div>
</div>
</div>
);
};
export default WeixinCorp;

View File

@ -1,6 +1,46 @@
import DingTalk from './DingTalk';
import DingTalkRebot from './DingTalkRebot';
import AliyunSms from './AliyunSms';
import AliyunVoice from './AliyunVoice';
import Email from './Email';
import Webhook from './Webhook';
import WeixinApp from './WeixinApp';
import WeixinCorp from './WeixinCorp';
const Doc = () => {
return <DingTalk />;
export default defineComponent({
name: 'Doc',
props: {
docData: {
type: Object,
default: () => ({}),
},
},
setup(props) {
const docMap = {
weixin: {
corpMessage: <WeixinCorp />,
officialMessage: <WeixinApp />,
},
dingTalk: {
dingTalkMessage: <DingTalk />,
dingTalkRobotWebHook: <DingTalkRebot />,
},
voice: {
aliyun: <AliyunVoice />,
},
sms: {
aliyunSms: <AliyunSms />,
},
email: {
embedded: <Email />,
},
webhook: {
http: <Webhook />,
},
};
export default Doc;
return () => (
docMap?.[props.docData.type]?.[props.docData.provider]
)
},
});

View File

@ -268,7 +268,7 @@
</a-form>
</a-col>
<a-col :span="12" :push="2">
<Doc />
<Doc :docData="formData" />
</a-col>
</a-row>
</a-card>
@ -320,6 +320,7 @@ const formData = ref<ConfigFormData>({
provider: 'dingTalkMessage',
type: 'dingTalk',
});
//
watch(
() => formData.value.type,
@ -408,9 +409,9 @@ watch(
const getDetail = async () => {
const res = await configApi.detail(route.params.id as string);
console.log('res: ', res);
// console.log('res: ', res);
formData.value = res.result;
console.log('formData.value: ', formData.value);
// console.log('formData.value: ', formData.value);
};
getDetail();

View File

@ -0,0 +1,43 @@
import './index.less';
const AliyunSms = () => {
return (
<div class="doc">
<div class="url">
<a
href="https://dysms.console.aliyun.com"
target="_blank"
rel="noopener noreferrer"
>
https://dysms.console.aliyun.com
</a>
</div>
<h1>1. </h1>
<div>
使
</div>
<h1>2.</h1>
<div>
<h2> 1</h2>
<div> 使</div>
<h2> 2</h2>
<div> </div>
<h2> 3</h2>
<div>
{' '}
</div>
<h2> 4</h2>
<div> </div>
<h2> 5</h2>
<div>
</div>
</div>
</div>
);
};
export default AliyunSms;

View File

@ -0,0 +1,43 @@
import './index.less';
const AliyunVoice = () => {
return (
<div class="doc">
<div class="url">
<a href="https://account.console.aliyun.com" target="_blank" rel="noopener noreferrer">
https://account.console.aliyun.com
</a>
</div>
<h1>1. </h1>
<div>
使
</div>
<h1>2.</h1>
<div>
<h2>1</h2>
<div> 使</div>
<h2>2</h2>
<div> </div>
<h2> 3ID</h2>
<div> ID标识</div>
<h2> 4</h2>
<div> </div>
<div>使</div>
<div>使</div>
<h2> 5</h2>
<div> </div>
<h2> 6</h2>
<div> 3</div>
<h2> 7</h2>
<div>
${'{name}'}
便
</div>
</div>
</div>
);
};
export default AliyunVoice;

View File

@ -0,0 +1,54 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const DingTalk = () => {
const agentId = getImage('/notice/doc/template/dingTalk-message/01-Agentid.jpg');
// const userId = getImage('/notice/doc/template/dingTalk-message/02-user-id.jpg');
// const dept = getImage('/notice/doc/template/dingTalk-message/03-dept.jpg');
const a = '{name}';
return (
<div class="doc">
<div class="url">
<a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener noreferrer">
https://open-dev.dingtalk.com
</a>
<br />
<a href="https://www.dingtalk.com" target="_blank" rel="noopener noreferrer">
https://www.dingtalk.com
</a>
</div>
<h1>1. </h1>
<div>
<div>使</div>
</div>
<h1> 2.</h1>
<h2> 1</h2>
<div> 使</div>
<h2> 2Agentid</h2>
<div> </div>
<div> ----</div>
<div class="image">
<Image width="100%" src={agentId} />
</div>
<h2> 3</h2>
<div></div>
{/*<div> 收信人ID获取路径“钉钉管理后台”--“通讯录”--“查看用户”</div>*/}
{/*<div> 收信部门ID获取路径“钉钉管理后台”--“通讯录”--“编辑部门”</div>*/}
{/*<div class="image">*/}
{/* <Image width="100%" src={userId} />*/}
{/* <Image width="100%" src={dept} />*/}
{/*</div>*/}
<h2> 4</h2>
<div>
${a}
便
</div>
</div>
);
};
export default DingTalk;

View File

@ -0,0 +1,35 @@
import './index.less';
const DingTalkRebot = () => {
const b = '{name}';
return (
<div class="doc">
<div class="url">
<a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener noreferrer">
https://open-dev.dingtalk.com
</a>
</div>
<h1>1. </h1>
<div>
</div>
<div>
使
</div>
<h1>2.</h1>
<div>
<h2> 1</h2>
<div> 使</div>
<h2> 2</h2>
<div> textmarkdownlink3种</div>
<h2> 3</h2>
<div>
${b}
便
</div>
</div>
</div>
);
};
export default DingTalkRebot;

View File

@ -0,0 +1,30 @@
import './index.less';
const Email = () => {
const a = '{标题}';
const b = '{name}';
return (
<div class="doc">
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
{/* <h2> 1</h2>
<div></div> */}
<h2> 1</h2>
<div>${a}</div>
<h2> 2</h2>
<div> </div>
<h2> 3</h2>
<div>
${b}
便
</div>
</div>
</div>
);
};
export default Email;

View File

@ -0,0 +1,18 @@
import './index.less';
const Webhook = () => {
return (
<div class="doc">
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
1 ,
使webhook通知时URL地址POST方式发送
</div>
</div>
);
};
export default Webhook;

View File

@ -0,0 +1,58 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const WeixinApp = () => {
const appId = getImage('/notice/doc/template/weixin-official/02-mini-Program-Appid.png');
return (
<div class="doc">
<div class="url">
<a href="https://work.weixin.qq.com" target="_blank" rel="noopener noreferrer">
https://work.weixin.qq.com
</a>
</div>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2>1</h2>
<div>使</div>
</div>
<div>
<h2>2</h2>
<div></div>
</div>
<div>
<h2>3</h2>
<div></div>
</div>
<div>
<h2>4</h2>
<div></div>
</div>
<div>
<h2>5Appid</h2>
<div></div>
</div>
<div>
<h2>6</h2>
<div></div>
<div class="image">
<Image width="100%" src={appId} />
</div>
</div>
<div>
<h2>7</h2>
<div>
${name}
便
</div>
</div>
</div>
);
};
export default WeixinApp;

View File

@ -0,0 +1,48 @@
import './index.less';
import { Image } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
const WeixinCorp = () => {
const agentId = getImage('/notice/doc/template/weixin-corp/01-Agentid.jpg');
const userId = getImage('/notice/doc/template/weixin-corp/02-userID.jpg');
const toDept = getImage('/notice/doc/template/weixin-corp/03-toDept.jpg');
const toTags = getImage('/notice/doc/template/weixin-corp/04-toTags.jpg');
return (
<div class="doc">
<div class="url">
<a href="https://work.weixin.qq.com" target="_blank" rel="noopener noreferrer">
https://work.weixin.qq.com
</a>
</div>
<h1>1. </h1>
<div>
</div>
<h1>2.</h1>
<div>
<h2> 1</h2>
<div> 使</div>
<h2> 2Agentid</h2>
<div> </div>
<div> ------</div>
<div class="image">
<Image width="100%" src={agentId} />
</div>
<h2> 3IDID</h2>
<div>
33
</div>
<div> ID获取路径-{'>'}</div>
<div> ID获取路径-{'>'}ID</div>
<div class="image">
<Image width="100%" src={userId} />
<Image width="100%" src={toDept} />
<Image width="100%" src={toTags} />
</div>
</div>
</div>
);
};
export default WeixinCorp;

View File

@ -0,0 +1,39 @@
.doc {
height: 750px;
padding: 24px;
overflow-y: auto;
color: rgba(#000, 0.8);
font-size: 14px;
background-color: #fafafa;
.url {
padding: 8px 16px;
color: #2f54eb;
background-color: rgba(#a7bdf7, 0.2);
}
h1 {
margin: 16px 0;
color: rgba(#000, 0.85);
font-weight: bold;
font-size: 14px;
&:first-child {
margin-top: 0;
}
}
h2 {
margin: 6px 0;
color: rgba(0, 0, 0, 0.8);
font-size: 14px;
}
span {
color: rgba(0, 0, 0, 0.8);
font-weight: 600;
}
.image {
margin: 16px 0;
}
}

View File

@ -0,0 +1,46 @@
import DingTalk from './DingTalk';
import DingTalkRebot from './DingTalkRebot';
import AliyunSms from './AliyunSms';
import AliyunVoice from './AliyunVoice';
import Email from './Email';
import Webhook from './Webhook';
import WeixinApp from './WeixinApp';
import WeixinCorp from './WeixinCorp';
export default defineComponent({
name: 'Doc',
props: {
docData: {
type: Object,
default: () => ({}),
},
},
setup(props) {
const docMap = {
weixin: {
corpMessage: <WeixinCorp />,
officialMessage: <WeixinApp />,
},
dingTalk: {
dingTalkMessage: <DingTalk />,
dingTalkRobotWebHook: <DingTalkRebot />,
},
voice: {
aliyun: <AliyunVoice />,
},
sms: {
aliyunSms: <AliyunSms />,
},
email: {
embedded: <Email />,
},
webhook: {
http: <Webhook />,
},
};
return () => (
docMap?.[props.docData.type]?.[props.docData.provider]
)
},
});

View File

@ -1,8 +1,433 @@
<!-- 通知模板详情 -->
<template>
<div class="page-container">通知模板详情</div>
<div class="page-container">
<a-card>
<a-row>
<a-col :span="10">
<a-form layout="vertical">
<a-form-item
label="通知方式"
v-bind="validateInfos.type"
>
<a-select
v-model:value="formData.type"
placeholder="请选择通知方式"
>
<a-select-option
v-for="(item, index) in NOTICE_METHOD"
:key="index"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="名称" v-bind="validateInfos.name">
<a-input
v-model:value="formData.name"
placeholder="请输入名称"
/>
</a-form-item>
<a-form-item
label="类型"
v-bind="validateInfos.provider"
v-if="formData.type !== 'email'"
>
<RadioCard
:options="msgType"
v-model="formData.provider"
/>
</a-form-item>
<!-- 钉钉 -->
<template v-if="formData.type === 'dingTalk'">
<template
v-if="formData.provider === 'dingTalkMessage'"
>
<a-form-item
label="AppKey"
v-bind="
validateInfos['configuration.appKey']
"
>
<a-input
v-model:value="
formData.configuration.appKey
"
placeholder="请输入AppKey"
/>
</a-form-item>
<a-form-item
label="AppSecret"
v-bind="
validateInfos['configuration.appSecret']
"
>
<a-input
v-model:value="
formData.configuration.appSecret
"
placeholder="请输入AppSecret"
/>
</a-form-item>
</template>
<template
v-if="
formData.provider === 'dingTalkRobotWebHook'
"
>
<a-form-item
label="webHook"
v-bind="validateInfos['configuration.url']"
>
<a-input
v-model:value="
formData.configuration.url
"
placeholder="请输入webHook"
/>
</a-form-item>
</template>
</template>
<!-- 微信 -->
<template v-if="formData.type === 'weixin'">
<a-form-item
label="corpId"
v-bind="validateInfos['configuration.corpId']"
>
<a-input
v-model:value="
formData.configuration.corpId
"
placeholder="请输入corpId"
/>
</a-form-item>
<a-form-item
label="corpSecret"
v-bind="
validateInfos['configuration.corpSecret']
"
>
<a-input
v-model:value="
formData.configuration.corpSecret
"
placeholder="请输入corpSecret"
/>
</a-form-item>
</template>
<!-- 邮件 -->
<template v-if="formData.type === 'email'">
<a-form-item
label="服务器地址"
v-bind="validateInfos['configuration.host']"
>
<a-space>
<a-input
v-model:value="
formData.configuration.host
"
placeholder="请输入服务器地址"
/>
<a-input-number
v-model:value="
formData.configuration.port
"
/>
<a-checkbox
v-model:value="
formData.configuration.ssl
"
>
开启SSL
</a-checkbox>
</a-space>
</a-form-item>
<a-form-item
label="发件人"
v-bind="validateInfos['configuration.sender']"
>
<a-input
v-model:value="
formData.configuration.sender
"
placeholder="请输入发件人"
/>
</a-form-item>
<a-form-item
label="用户名"
v-bind="validateInfos['configuration.username']"
>
<a-input
v-model:value="
formData.configuration.username
"
placeholder="请输入用户名"
/>
</a-form-item>
<a-form-item
label="密码"
v-bind="validateInfos['configuration.password']"
>
<a-input
v-model:value="
formData.configuration.password
"
placeholder="请输入密码"
/>
</a-form-item>
</template>
<!-- 语音/短信 -->
<template
v-if="
formData.type === 'voice' ||
formData.type === 'sms'
"
>
<a-form-item
label="AccessKeyId"
v-bind="
validateInfos['configuration.accessKeyId']
"
>
<a-input
v-model:value="
formData.configuration.accessKeyId
"
placeholder="请输入AccessKeyId"
/>
</a-form-item>
<a-form-item
label="Secret"
v-bind="validateInfos['configuration.secret']"
>
<a-input
v-model:value="
formData.configuration.secret
"
placeholder="Secret"
/>
</a-form-item>
</template>
<!-- webhook -->
<template v-if="formData.type === 'webhook'">
<a-form-item
label="Webhook"
v-bind="validateInfos['configuration.url']"
>
<a-input
v-model:value="formData.configuration.url"
placeholder="请输入Webhook"
/>
</a-form-item>
<a-form-item label="请求头">
<!-- <EditTable
v-model:headers="
formData.configuration.headers
"
/> -->
</a-form-item>
</template>
<a-form-item label="说明">
<a-textarea
v-model:value="formData.description"
show-count
:maxlength="200"
:rows="5"
placeholder="请输入说明"
/>
</a-form-item>
<a-form-item :wrapper-col="{ offset: 0, span: 3 }">
<a-button
type="primary"
@click="handleSubmit"
:loading="btnLoading"
style="width: 100%"
>
保存
</a-button>
</a-form-item>
</a-form>
</a-col>
<a-col :span="12" :push="2">
<Doc :docData="formData" />
</a-col>
</a-row>
</a-card>
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { getImage } from '@/utils/comm';
import { Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import { TemplateFormData } from '../types';
import {
NOTICE_METHOD,
CONFIG_FIELD_MAP,
MSG_TYPE,
} from '@/views/notice/const';
// import EditTable from './components/EditTable.vue';
import configApi from '@/api/notice/config';
import Doc from './doc/index';
<style lang="less" scoped></style>
const router = useRouter();
const route = useRoute();
const useForm = Form.useForm;
//
const msgType = ref([
{
label: '钉钉消息',
value: 'dingTalkMessage',
logo: getImage('/notice/dingtalk.png'),
},
{
label: '群机器人消息',
value: 'dingTalkRobotWebHook',
logo: getImage('/notice/dingTalk-rebot.png'),
},
]);
//
const formData = ref<TemplateFormData>({
description: '',
name: '',
provider: '',
type: NOTICE_METHOD[2].value,
template: {
subject: '',
sendTo: [],
attachments: [],
message: '',
text: '',
},
});
//
watch(
() => formData.value.type,
(val) => {
formData.value.configuration = CONFIG_FIELD_MAP[val];
msgType.value = MSG_TYPE[val];
formData.value.provider = msgType.value[0].value;
},
);
//
const formRules = ref({
type: [{ required: true, message: '请选择通知方式' }],
name: [
{ required: true, message: '请输入名称' },
{ max: 64, message: '最多可输入64个字符' },
],
provider: [{ required: true, message: '请选择类型' }],
//
'configuration.appKey': [
{ required: true, message: '请输入AppKey' },
{ max: 64, message: '最多可输入64个字符' },
],
'configuration.appSecret': [
{ required: true, message: '请输入AppSecret' },
{ max: 64, message: '最多可输入64个字符' },
],
// 'configuration.url': [{ required: true, message: 'WebHook' }],
//
'configuration.corpId': [
{ required: true, message: '请输入corpId' },
{ max: 64, message: '最多可输入64个字符' },
],
'configuration.corpSecret': [
{ required: true, message: '请输入corpSecret' },
{ max: 64, message: '最多可输入64个字符' },
],
// /
'configuration.regionId': [
{ required: true, message: '请输入RegionId' },
{ max: 64, message: '最多可输入64个字符' },
],
'configuration.accessKeyId': [
{ required: true, message: '请输入AccessKeyId' },
{ max: 64, message: '最多可输入64个字符' },
],
'configuration.secret': [
{ required: true, message: '请输入Secret' },
{ max: 64, message: '最多可输入64个字符' },
],
//
'configuration.host': [{ required: true, message: '请输入服务器地址' }],
'configuration.sender': [{ required: true, message: '请输入发件人' }],
'configuration.username': [
{ required: true, message: '请输入用户名' },
{ max: 64, message: '最多可输入64个字符' },
],
'configuration.password': [
{ required: true, message: '请输入密码' },
{ max: 64, message: '最多可输入64个字符' },
],
// webhook
'configuration.url': [
{ required: true, message: '请输入Webhook' },
{
pattern:
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/,
message: 'Webhook需要是一个合法的URL',
},
],
description: [{ max: 200, message: '最多可输入200个字符' }],
});
const { resetFields, validate, validateInfos, clearValidate } = useForm(
formData.value,
formRules.value,
);
watch(
() => formData.value.type,
() => {
clearValidate();
},
{ deep: true },
);
const getDetail = async () => {
const res = await configApi.detail(route.params.id as string);
// console.log('res: ', res);
formData.value = res.result;
// console.log('formData.value: ', formData.value);
};
getDetail();
/**
* 表单提交
*/
const btnLoading = ref<boolean>(false);
const handleSubmit = () => {
validate()
.then(async () => {
// console.log('formData.value: ', formData.value);
btnLoading.value = true;
let res;
if (!formData.value.id) {
res = await configApi.save(formData.value);
} else {
res = await configApi.update(formData.value);
}
// console.log('res: ', res);
if (res?.success) {
message.success('保存成功');
router.back();
}
btnLoading.value = false;
})
.catch((err) => {
console.log('err: ', err);
});
};
</script>
<style lang="less" scoped>
.page-container {
background: #f0f2f5;
padding: 24px;
}
</style>

74
src/views/notice/Template/types.d.ts vendored Normal file
View File

@ -0,0 +1,74 @@
export interface IHeaders {
id?: number;
key: string;
value: string;
}
interface IAttachments {
location: string;
name: string;
}
interface IVariableDefinitions {
id: string;
name: string;
type: string;
format: string;
}
export type TemplateFormData = {
name: string;
type: string;
provider: string;
description: string;
id?: string;
creatorId?: string;
createTime?: number;
configId?: string;
template: {
// 钉钉消息
agentId?: string;
message?: string;
// 钉钉机器人
messageType?: string;
markdown?: {
text: string;
title: string;
};
link?: {
title: string;
picUrl: string;
messageUrl: string;
text: string;
};
// 微信
agentId?: string;
// message?: string;
toParty?: string;
toUser?: string;
toTag?: string;
// 邮件
subject?: string;
sendTo?: string[];
attachments?: IAttachments[];
// message?: string;
text?: string;
// 语音
templateType?: string;
templateCode?: string;
ttsCode?: string;
// message?: string;
playTimes?: number;
calledShowNumbers?: string;
calledNumber?: string;
// 短信
code?: string;
// message?: string;
phoneNumber?: string;
signName?: string;
// webhook
contextAsBody?: boolean;
body?: string;
};
variableDefinitions: IVariableDefinitions[];
};

View File

@ -124,3 +124,71 @@ export const CONFIG_FIELD_MAP = {
headers: [],
},
};
// 模板
export const TEMPLATE_FIELD_MAP = {
dingTalk: {
dingTalkMessage: {
agentId: '',
message: '',
},
dingTalkRobotWebHook: {
message: '',
messageType: '',
markdown: {
text: '',
title: '',
},
link: {
title: '',
picUrl: '',
messageUrl: '',
text: '',
},
}
},
weixin: {
corpMessage: {
agentId: '',
message: '',
toParty: '',
toUser: '',
toTag: '',
},
officialMessage: {},
},
email: {
embedded: {
subject: '',
sendTo: [],
attachments: [],
message: '',
text: '',
}
},
voice: {
aliyun: {
templateType: '',
templateCode: '',
ttsCode: '',
message: '',
playTimes: undefined,
calledShowNumbers: '',
calledNumber: '',
}
},
sms: {
aliyunSms: {
code: '',
message: '',
phoneNumber: '',
signName: '',
}
},
webhook: {
http: {
contextAsBody: false,
body: ''
}
},
};

7947
yarn.lock

File diff suppressed because it is too large Load Diff