提交 acc07129 authored 作者: lihuihui's avatar lihuihui
...@@ -3,7 +3,12 @@ require('@rushstack/eslint-patch/modern-module-resolution') ...@@ -3,7 +3,12 @@ require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = { module.exports = {
root: true, root: true,
extends: ['plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-typescript/recommended', './.eslintrc-auto-import.json'], extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript/recommended',
'./.eslintrc-auto-import.json'
],
env: { env: {
'vue/setup-compiler-macros': true 'vue/setup-compiler-macros': true
}, },
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"@tinymce/tinymce-vue": "^5.0.0", "@tinymce/tinymce-vue": "^5.0.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"drag-drop-tree-table": "^1.1.1",
"element-plus": "^2.2.2", "element-plus": "^2.2.2",
"pinia": "^2.0.14", "pinia": "^2.0.14",
"qs": "^6.10.3", "qs": "^6.10.3",
...@@ -23,16 +24,19 @@ ...@@ -23,16 +24,19 @@
"@types/blueimp-md5": "^2.18.0", "@types/blueimp-md5": "^2.18.0",
"@types/node": "^17.0.35", "@types/node": "^17.0.35",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@types/sortablejs": "^1.13.0",
"@vitejs/plugin-vue": "^2.3.3", "@vitejs/plugin-vue": "^2.3.3",
"@vue/eslint-config-typescript": "^10.0.0", "@vue/eslint-config-typescript": "^10.0.0",
"@vue/tsconfig": "^0.1.3", "@vue/tsconfig": "^0.1.3",
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"drag-tree-table": "^2.2.0",
"eslint": "^8.16.0", "eslint": "^8.16.0",
"eslint-plugin-vue": "^8.7.1", "eslint-plugin-vue": "^8.7.1",
"sass": "^1.52.1", "sass": "^1.52.1",
"sortablejs": "^1.15.0",
"typescript": "~4.7.2", "typescript": "~4.7.2",
"unplugin-auto-import": "^0.8.5", "unplugin-auto-import": "^0.8.7",
"vite": "^2.9.9", "vite": "^2.9.9",
"vite-plugin-checker": "^0.4.6", "vite-plugin-checker": "^0.4.6",
"vue-tsc": "^0.34.16" "vue-tsc": "^0.34.16"
...@@ -354,6 +358,12 @@ ...@@ -354,6 +358,12 @@
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true "dev": true
}, },
"node_modules/@types/sortablejs": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz",
"integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.26.0", "version": "5.26.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz",
...@@ -1263,6 +1273,16 @@ ...@@ -1263,6 +1273,16 @@
"integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=", "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=",
"dev": true "dev": true
}, },
"node_modules/core-js": {
"version": "3.22.8",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
"integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
...@@ -1448,6 +1468,42 @@ ...@@ -1448,6 +1468,42 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/drag-drop-tree-table": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/drag-drop-tree-table/-/drag-drop-tree-table-1.1.1.tgz",
"integrity": "sha512-DqrJu2IIhd8z3NR4v2Q0E5FFfLcZWSUPe9pcHC1yBM6ekoFfu9zXWZUtSsYHykkdaMkVOEyyKsGz+52sHq849Q==",
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11"
}
},
"node_modules/drag-drop-tree-table/node_modules/vue": {
"version": "2.6.14",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
},
"node_modules/drag-tree-table": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/drag-tree-table/-/drag-tree-table-2.2.0.tgz",
"integrity": "sha512-kFEJTgB77AdlUOyIDIWPK+RXy8Pf14RTMLDLlEVMyglTb31EyBnmn2CO0mA8Bv9waWuLLBBEgjYysjsy9dPTUg==",
"dev": true,
"dependencies": {
"vue": "^2.6.10",
"vue-router": "^3.1.3"
}
},
"node_modules/drag-tree-table/node_modules/vue": {
"version": "2.6.14",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==",
"dev": true
},
"node_modules/drag-tree-table/node_modules/vue-router": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.4.tgz",
"integrity": "sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ==",
"dev": true
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
...@@ -3881,6 +3937,12 @@ ...@@ -3881,6 +3937,12 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/sortablejs": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==",
"dev": true
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
...@@ -3966,6 +4028,18 @@ ...@@ -3966,6 +4028,18 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/strip-literal": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.3.0.tgz",
"integrity": "sha512-J+lfm3Pw5nzURj2B8acyvUSBqs3JbjM8WAfrmeH3qcn32+ew6kFwbZFV9+X8k9UOIAkQw9WPSzFZy3083c7l5Q==",
"dev": true,
"dependencies": {
"acorn": "^8.7.1"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
...@@ -4132,9 +4206,9 @@ ...@@ -4132,9 +4206,9 @@
} }
}, },
"node_modules/unimport": { "node_modules/unimport": {
"version": "0.2.4", "version": "0.2.6",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.4.tgz", "resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.6.tgz",
"integrity": "sha512-7OEUIlZMS1s1h1uFAGkCPylMtE8hnlJ/cFurJQHdzKAqIyuGiOREFKaCLbkNtFloZicCpRAlqC0Ny2yMoz6mFg==", "integrity": "sha512-4cOokUIEvaXAfVCHH87vR+wdKI1KDzxQREW9oi0r6J68TPFEeGLHHc2pdyL0uNDUMd2aLxUikhWARNfoQKqC4Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@rollup/pluginutils": "^4.2.1", "@rollup/pluginutils": "^4.2.1",
...@@ -4145,6 +4219,7 @@ ...@@ -4145,6 +4219,7 @@
"mlly": "^0.5.2", "mlly": "^0.5.2",
"pathe": "^0.3.0", "pathe": "^0.3.0",
"scule": "^0.2.1", "scule": "^0.2.1",
"strip-literal": "^0.3.0",
"unplugin": "^0.6.3" "unplugin": "^0.6.3"
} }
}, },
...@@ -4222,16 +4297,16 @@ ...@@ -4222,16 +4297,16 @@
} }
}, },
"node_modules/unplugin-auto-import": { "node_modules/unplugin-auto-import": {
"version": "0.8.5", "version": "0.8.7",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.5.tgz", "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.7.tgz",
"integrity": "sha512-JT43zA89fMjxtdqz+sTSkTsL9J0PNdnGmMOvcwbkpDi45yL5SU0aDCZgj0E8+qWLyQSIvvBaDBW3VuBrcc2MXg==", "integrity": "sha512-xepkl/lzlPmWym/ZqjgKpev30S5402qZYHnRZ7MQ78+WxBykvUw69PB0awWcWJ7atswNs6LkDRpGNqzjFCEH4w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@antfu/utils": "^0.5.2", "@antfu/utils": "^0.5.2",
"@rollup/pluginutils": "^4.2.1", "@rollup/pluginutils": "^4.2.1",
"local-pkg": "^0.4.1", "local-pkg": "^0.4.1",
"magic-string": "^0.26.2", "magic-string": "^0.26.2",
"unimport": "^0.2.4", "unimport": "^0.2.5",
"unplugin": "^0.6.3" "unplugin": "^0.6.3"
}, },
"engines": { "engines": {
...@@ -4952,6 +5027,12 @@ ...@@ -4952,6 +5027,12 @@
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true "dev": true
}, },
"@types/sortablejs": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz",
"integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==",
"dev": true
},
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {
"version": "5.26.0", "version": "5.26.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz",
...@@ -5603,6 +5684,11 @@ ...@@ -5603,6 +5684,11 @@
"integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=", "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=",
"dev": true "dev": true
}, },
"core-js": {
"version": "3.22.8",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
"integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA=="
},
"core-util-is": { "core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
...@@ -5739,6 +5825,46 @@ ...@@ -5739,6 +5825,46 @@
"esutils": "^2.0.2" "esutils": "^2.0.2"
} }
}, },
"drag-drop-tree-table": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/drag-drop-tree-table/-/drag-drop-tree-table-1.1.1.tgz",
"integrity": "sha512-DqrJu2IIhd8z3NR4v2Q0E5FFfLcZWSUPe9pcHC1yBM6ekoFfu9zXWZUtSsYHykkdaMkVOEyyKsGz+52sHq849Q==",
"requires": {
"core-js": "^3.6.5",
"vue": "^2.6.11"
},
"dependencies": {
"vue": {
"version": "2.6.14",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
}
}
},
"drag-tree-table": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/drag-tree-table/-/drag-tree-table-2.2.0.tgz",
"integrity": "sha512-kFEJTgB77AdlUOyIDIWPK+RXy8Pf14RTMLDLlEVMyglTb31EyBnmn2CO0mA8Bv9waWuLLBBEgjYysjsy9dPTUg==",
"dev": true,
"requires": {
"vue": "^2.6.10",
"vue-router": "^3.1.3"
},
"dependencies": {
"vue": {
"version": "2.6.14",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==",
"dev": true
},
"vue-router": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.4.tgz",
"integrity": "sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ==",
"dev": true
}
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
...@@ -7492,6 +7618,12 @@ ...@@ -7492,6 +7618,12 @@
"socks": "^2.3.3" "socks": "^2.3.3"
} }
}, },
"sortablejs": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==",
"dev": true
},
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
...@@ -7556,6 +7688,15 @@ ...@@ -7556,6 +7688,15 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true "dev": true
}, },
"strip-literal": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.3.0.tgz",
"integrity": "sha512-J+lfm3Pw5nzURj2B8acyvUSBqs3JbjM8WAfrmeH3qcn32+ew6kFwbZFV9+X8k9UOIAkQw9WPSzFZy3083c7l5Q==",
"dev": true,
"requires": {
"acorn": "^8.7.1"
}
},
"supports-color": { "supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
...@@ -7679,9 +7820,9 @@ ...@@ -7679,9 +7820,9 @@
} }
}, },
"unimport": { "unimport": {
"version": "0.2.4", "version": "0.2.6",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.4.tgz", "resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.6.tgz",
"integrity": "sha512-7OEUIlZMS1s1h1uFAGkCPylMtE8hnlJ/cFurJQHdzKAqIyuGiOREFKaCLbkNtFloZicCpRAlqC0Ny2yMoz6mFg==", "integrity": "sha512-4cOokUIEvaXAfVCHH87vR+wdKI1KDzxQREW9oi0r6J68TPFEeGLHHc2pdyL0uNDUMd2aLxUikhWARNfoQKqC4Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"@rollup/pluginutils": "^4.2.1", "@rollup/pluginutils": "^4.2.1",
...@@ -7692,6 +7833,7 @@ ...@@ -7692,6 +7833,7 @@
"mlly": "^0.5.2", "mlly": "^0.5.2",
"pathe": "^0.3.0", "pathe": "^0.3.0",
"scule": "^0.2.1", "scule": "^0.2.1",
"strip-literal": "^0.3.0",
"unplugin": "^0.6.3" "unplugin": "^0.6.3"
}, },
"dependencies": { "dependencies": {
...@@ -7736,16 +7878,16 @@ ...@@ -7736,16 +7878,16 @@
} }
}, },
"unplugin-auto-import": { "unplugin-auto-import": {
"version": "0.8.5", "version": "0.8.7",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.5.tgz", "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.7.tgz",
"integrity": "sha512-JT43zA89fMjxtdqz+sTSkTsL9J0PNdnGmMOvcwbkpDi45yL5SU0aDCZgj0E8+qWLyQSIvvBaDBW3VuBrcc2MXg==", "integrity": "sha512-xepkl/lzlPmWym/ZqjgKpev30S5402qZYHnRZ7MQ78+WxBykvUw69PB0awWcWJ7atswNs6LkDRpGNqzjFCEH4w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@antfu/utils": "^0.5.2", "@antfu/utils": "^0.5.2",
"@rollup/pluginutils": "^4.2.1", "@rollup/pluginutils": "^4.2.1",
"local-pkg": "^0.4.1", "local-pkg": "^0.4.1",
"magic-string": "^0.26.2", "magic-string": "^0.26.2",
"unimport": "^0.2.4", "unimport": "^0.2.5",
"unplugin": "^0.6.3" "unplugin": "^0.6.3"
}, },
"dependencies": { "dependencies": {
......
{ {
"name": "center-resource", "name": "center-resource",
"version": "0.0.0", "version": "0.0.0",
"type": "module",
"scripts": { "scripts": {
"dev": "vite --mode dev", "dev": "vite --mode dev",
"build": "vue-tsc --noEmit && vite build --mode prod && npm run deploy", "build": "vue-tsc --noEmit && vite build --mode prod && npm run deploy",
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
"@tinymce/tinymce-vue": "^5.0.0", "@tinymce/tinymce-vue": "^5.0.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"drag-drop-tree-table": "^1.1.1",
"element-plus": "^2.2.2", "element-plus": "^2.2.2",
"pinia": "^2.0.14", "pinia": "^2.0.14",
"qs": "^6.10.3", "qs": "^6.10.3",
...@@ -27,16 +29,19 @@ ...@@ -27,16 +29,19 @@
"@types/blueimp-md5": "^2.18.0", "@types/blueimp-md5": "^2.18.0",
"@types/node": "^17.0.35", "@types/node": "^17.0.35",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@types/sortablejs": "^1.13.0",
"@vitejs/plugin-vue": "^2.3.3", "@vitejs/plugin-vue": "^2.3.3",
"@vue/eslint-config-typescript": "^10.0.0", "@vue/eslint-config-typescript": "^10.0.0",
"@vue/tsconfig": "^0.1.3", "@vue/tsconfig": "^0.1.3",
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"drag-tree-table": "^2.2.0",
"eslint": "^8.16.0", "eslint": "^8.16.0",
"eslint-plugin-vue": "^8.7.1", "eslint-plugin-vue": "^8.7.1",
"sass": "^1.52.1", "sass": "^1.52.1",
"sortablejs": "^1.15.0",
"typescript": "~4.7.2", "typescript": "~4.7.2",
"unplugin-auto-import": "^0.8.5", "unplugin-auto-import": "^0.8.7",
"vite": "^2.9.9", "vite": "^2.9.9",
"vite-plugin-checker": "^0.4.6", "vite-plugin-checker": "^0.4.6",
"vue-tsc": "^0.34.16" "vue-tsc": "^0.34.16"
......
...@@ -32,7 +32,11 @@ export function uploadFile(data: Record<string, any>) { ...@@ -32,7 +32,11 @@ export function uploadFile(data: Record<string, any>) {
// 删除评论 // 删除评论
export function deleteComment(data: { id: string }) { export function deleteComment(data: { id: string }) {
return httpRequest.post('/api/psp/backend/comment/delete', data) return httpRequest.post('/api/resource/backend/comment/delete', data)
}
// 获取公共字典列表
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
} }
// 上传视频 // 上传视频
......
...@@ -33,8 +33,7 @@ const tableRef = ref() ...@@ -33,8 +33,7 @@ const tableRef = ref()
const dataList = ref<any[]>([]) const dataList = ref<any[]>([])
const page = reactive({ total: 0, size: props.limit, currentPage: 1 }) const page = reactive({ total: 0, size: props.limit, currentPage: 1 })
const params = reactive({ page: page.currentPage, page_size: page.size, ...props.remote?.params }) const params = reactive({ page: page.currentPage, ['per-page']: page.size, ...props.remote?.params })
watch( watch(
() => props.data, () => props.data,
list => { list => {
...@@ -59,7 +58,7 @@ const fetchList = (isReset = false) => { ...@@ -59,7 +58,7 @@ const fetchList = (isReset = false) => {
// 翻页参数设置 // 翻页参数设置
if (props.hasPagination) { if (props.hasPagination) {
requestParams.page = page.currentPage requestParams.page = page.currentPage
requestParams.page_size = page.size requestParams['per-page'] = page.size
} }
// 接口请求之前 // 接口请求之前
if (beforeRequest) { if (beforeRequest) {
...@@ -134,10 +133,27 @@ defineExpose({ refetch }) ...@@ -134,10 +133,27 @@ defineExpose({ refetch })
</template> </template>
<template v-else> <template v-else>
<!-- input --> <!-- input -->
<el-input v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'input'" /> <el-input
v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
v-if="item.type === 'input'"
/>
<!-- select --> <!-- select -->
<el-select v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'select'"> <el-select
<el-option :label="option[item.labelKey] || option.label" :value="option[item.valueKey] || option.value" v-for="(option, index) in item.options" :key="index" /> v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
v-if="item.type === 'select'"
>
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
v-for="(option, index) in item.options"
:key="index"
/>
</el-select> </el-select>
</template> </template>
</el-form-item> </el-form-item>
......
...@@ -14,7 +14,6 @@ import AppList from '@/components/base/AppList.vue' ...@@ -14,7 +14,6 @@ import AppList from '@/components/base/AppList.vue'
import AppUpload from '@/components/base/AppUpload.vue' import AppUpload from '@/components/base/AppUpload.vue'
import modules from './modules' import modules from './modules'
const app = createApp(App) const app = createApp(App)
// 注册公共组件 // 注册公共组件
app.component('AppCard', AppCard).component('AppList', AppList).component('AppUpload', AppUpload) app.component('AppCard', AppCard).component('AppList', AppList).component('AppUpload', AppUpload)
......
<script setup lang="ts"></script> <script setup lang="ts">
const form = reactive({
resource: '0',
auditor: ''
})
const options = [
{
user_name: '章三',
user_id: '0'
},
{
user_name: '里斯',
user_id: '1'
}
]
const handleSave = () => {
console.log(form)
console.log('000')
}
</script>
<template> <template>
<AppCard title="资源审核管理"></AppCard> <AppCard title="资源审核管理">
<el-form class="filter-form" :model="form">
<el-form-item label="是否需要资源审核:">
<el-radio-group v-model="form.resource">
<el-radio label="0">需要审核</el-radio>
<el-radio label="1">不需要审核</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="资源审核员:">
<el-select v-model="form.auditor" placeholder="请选择资料审核员">
<el-option
v-for="(item, index) in options"
:key="index"
:label="item.user_name"
:value="item.user_id"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-form-item>
</el-form>
</AppCard>
</template> </template>
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取分类列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) { export function getCategoryList(params: { type: string }) {
return httpRequest.get('/api/psp/backend/video/index', { params }) return httpRequest.get('/api/resource/v1/backend/category/list', { params })
}
// 新建分类
export function createCategory(data: {
category_name: string
depth?: string
status: string
need_pass: string
parent_id: string
}) {
return httpRequest.post('/api/resource/v1/backend/category/create', data)
}
// 编辑分类
export function updateCategory(data: {
id: string
category_name: string
depth?: string
status: string
need_pass: string
parent_id: string
}) {
return httpRequest.post('/api/resource/v1/backend/category/update', data)
}
// 删除分类
export function delCategory(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/category/delete', data)
}
// 移动分类
export function moveCategory(data: { id: string; brother_id: string; type: string }) {
return httpRequest.post('/api/resource/v1/backend/category/drag', data)
} }
<script lang="ts" setup>
import { Search } from '@element-plus/icons-vue'
import type { FormRules } from 'element-plus'
import TreeDialog from './TreeDialog.vue'
import { useMapStore } from '@/stores/map'
const categoryName = ref('')
const store = useMapStore()
const classList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const isTreeVisible = ref(false)
const formRef = ref()
const categoryForm = reactive({
parent_id: '',
category_name: '',
depth: 1,
name: '',
status: '0',
need_pass: '1'
})
const rules = reactive<FormRules>({
name: [
{ required: true, message: '请输入类别名称', trigger: 'blur' },
{ message: '请输入类别名称', trigger: 'blur' }
]
})
const props = defineProps({
// 是否弹框
dialogVisible: {
type: Boolean,
required: true
},
// 编辑数据
editData: {
type: Object,
required: true
},
// 是否编辑
isEdit: {
type: Boolean,
required: true
},
// 弹框标题
title: {
type: String,
required: true
},
// 上级类别名称
prevCategoryName: {
type: String,
required: true
}
})
const emit = defineEmits<{
(e: 'update:dialogVisible', dialogVisible: false): void
(e: 'confirm', categoryForm: any): void
}>()
// 打开类别选择弹框
const handleOpenTree = () => {
isTreeVisible.value = true
}
// 获取子组件确定之后节点回显
const getCheckedLabel = (val: any) => {
console.log(val, '99991111')
categoryName.value = val.checkedCategory.checkedLabel
categoryForm.parent_id = val.checkedCategory.checkedId
categoryForm.depth = parseInt(val.checkedCategory.checkedLevel) + 1
}
// 关闭弹框
const handleCancel = () => {
emit('update:dialogVisible', false)
console.log(formRef.value, 'formRef.value')
categoryName.value = ''
formRef.value.resetFields()
}
// 确认提交表单
const handleConfirm = () => {
console.log(categoryForm.parent_id, '0000')
emit('update:dialogVisible', false)
emit('confirm', categoryForm)
if (props.isEdit) {
emit('confirm', { categoryForm, isUpdate: 1, id: props.editData.id })
} else {
emit('confirm', { categoryForm, isUpdate: 0 })
}
}
onMounted(() => {
console.log(props.prevCategoryName, 'props.prevCategoryName')
categoryForm.depth = parseInt(props.editData.depth) + 1
categoryForm.parent_id = props.editData.id
categoryName.value = props.prevCategoryName
if (props.isEdit) {
categoryName.value = props.prevCategoryName
categoryForm.depth = props.editData.depth
categoryForm.category_name = props.editData.category_name
categoryForm.status = props.editData.status
categoryForm.need_pass = props.editData.need_pass
}
})
</script>
<template>
<el-dialog :model-value="dialogVisible" draggable :before-close="handleCancel" :title="props.title" width="60%">
<el-form :model="categoryForm" label-position="right" label-width="auto" :rules="rules" ref="formRef">
<el-form-item label="上级类别:" prop="parent_id">
<div @click="handleOpenTree" style="width: 100%">
<el-input v-model="categoryName" disabled>
<template #append>
<el-button :icon="Search" />
</template>
</el-input>
</div>
</el-form-item>
<el-form-item label="类别层级:" prop="hierarchy">
<el-input v-model="categoryForm.depth" disabled></el-input>
</el-form-item>
<el-form-item label="类别名称:" prop="category_name">
<el-input v-model="categoryForm.category_name"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="categoryForm.status">
<el-radio v-for="(item, id) in statusList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="互动课:" prop="need_pass">
<el-radio-group v-model="categoryForm.need_pass">
<el-radio v-for="(item, id) in classList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
</template>
</el-dialog>
<template v-if="isTreeVisible">
<TreeDialog v-model:isTreeVisible="isTreeVisible" @getCheckedLabel="getCheckedLabel" />
</template>
</template>
<script lang="ts" setup>
import { getCategoryList } from '../api'
import type { ElTree } from 'element-plus'
defineProps({
isTreeVisible: {
type: Boolean,
required: true
}
})
const emit = defineEmits<{
(e: 'update:isTreeVisible', isTreeVisible: false): void
(e: 'getCheckedLabel', checkedCategory: any): void
}>()
const handleCancel = () => {
emit('update:isTreeVisible', false)
}
interface ICategory {
category_name: string
depth: string
id: string
lft: string
need_pass: string
rgt: string
status: string
children?: ICategory[]
}
let data = ref<ICategory[]>([])
const filterText = ref('') // 搜索字段
const treeRef = ref<InstanceType<typeof ElTree>>()
const defaultProps = {
children: 'children',
label: 'category_name'
}
const checkedCategory = {
checkedId: '',
checkedLabel: '', // 默认选中项名称
checkedLevel: 0 // 默认选中项层级
}
// 监听搜索
watch(filterText, val => {
treeRef.value?.filter(val)
})
//搜索
const filterNode = (value: string, data: any) => {
console.log(value, 'value', data.category_name, 'data')
if (!value) return true
return data.category_name.indexOf(value) != -1
}
// 获取选中节点
const handleNodeClick = (TreeNode: any, node: any, attr: any) => {
console.log(TreeNode, node, attr, '999')
checkedCategory.checkedLabel = TreeNode.category_name // 类名
checkedCategory.checkedId = TreeNode.id // id
checkedCategory.checkedLevel = parseInt(TreeNode.depth) //层级
}
// 确认
const handleConfirm = () => {
checkedCategory.checkedLabel && emit('getCheckedLabel', { checkedCategory })
emit('update:isTreeVisible', false)
}
// 获取分类列表
const handleCategoryList = () => {
const params = { type: 'tree' }
getCategoryList(params).then((res: any) => {
data.value = res.data
console.log(data, 'tableData')
})
}
onMounted(() => {
handleCategoryList()
})
</script>
<template>
<el-dialog :model-value="isTreeVisible" draggable :before-close="handleCancel" title="类别选择" width="40%">
<el-input v-model="filterText" placeholder="请选择类别" />
<el-tree
ref="treeRef"
class="filter-tree"
:data="data"
:props="defaultProps"
default-expand-all
:expand-on-click-node="false"
:highlight-current="true"
@node-click="handleNodeClick"
:filter-node-method="filterNode"
/>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts"></script> <script setup lang="ts">
// import Sortable from 'sortablejs'
import AddDialog from '../component/AddDialog.vue'
import { Operation } from '@element-plus/icons-vue'
import { getCategoryList, delCategory, createCategory, updateCategory } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
const prevCategoryName = ref('')
const title = ref('')
const dialogVisible = ref(false)
let form = reactive({
category_name: ''
})
interface ICategory {
category_name: number
depth: string
id: string
lft: string
need_pass: string
rgt: string
status_name: string
children?: ICategory[]
}
let tableData = $ref<ICategory[]>([])
const editData = ref({})
const isEdit = ref(false)
const handleEdit = (index: number, row: ICategory) => {
title.value = '编辑类别'
isEdit.value = true
dialogVisible.value = true
editData.value = row
if (row.depth > '0') {
prevCategoryName.value = getParent(row.id, tableData[0]).category_name
} else {
prevCategoryName.value = ''
}
}
// 删除分类
const handleDelete = (index: number, row: ICategory) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delCategory(params).then(() => {
ElMessage.success('删除成功')
handleCategoryList()
})
})
}
// 行内新增类别
const handleAddRow = (index: number, row: ICategory) => {
isEdit.value = false
dialogVisible.value = true
title.value = '新增类别'
editData.value = row
if (row.depth > '0') {
prevCategoryName.value = getParent(row.id, tableData[0]).category_name
} else {
prevCategoryName.value = ''
}
}
// 外部新增类别
const handleAddCategory = () => {
isEdit.value = false
dialogVisible.value = true
title.value = '新增类别'
editData.value = tableData[0]
prevCategoryName.value = ''
}
// 获取上级类别
const getParent = (node: string, tree: any) => {
let result: any = []
function find(node: string, tree: any) {
tree.children.forEach((item: any) => {
if (item.id === node) {
result.push(tree)
}
if ('children' in item) {
find(node, item)
}
})
}
find(node, tree)
return result[0]
}
// const sortable = (className: any, targetName: any) => {
// const table = document.querySelector('.' + className + ' .el-table__body-wrapper tbody') as HTMLElement
// console.log(table)
// Sortable.create(table, {
// handle: '.handle',
// // 拖拽完毕后触发
// onEnd(data) {
// const newIndex = data.newIndex as number
// const oldIndex = data.oldIndex as number
// console.log(data, 'data')
// if (newIndex === oldIndex) return
// targetName.splice(newIndex, 0, targetName.splice(oldIndex, 1))
// }
// })
// }
// 获取分类列表
const handleCategoryList = () => {
const params = { type: 'tree' }
getCategoryList(params)
.then((res: any) => {
loading.value = true
tableData = res.data
})
.finally(() => {
loading.value = false
})
}
// 确定
const handleConfirm = (val: any) => {
console.log(val, 'val')
if (val.isUpdate === 1) {
const params = Object.assign({ id: val.id }, val.categoryForm)
updateCategory(params).then(() => {
ElMessage.success('更新类别成功')
handleCategoryList()
})
} else if (val.isUpdate === 0) {
const params = Object.assign({}, val.categoryForm)
createCategory(params).then(() => {
ElMessage.success('新建类别成功')
handleCategoryList()
})
}
}
// 重置
const handleReset = () => {
form.category_name = ''
handleCategoryList()
}
// 搜索
const handleSearch = () => {
// 调接口
if (form.category_name) {
tableData = rebuildData(form.category_name, tableData)
console.log(tableData, 'ppp')
}
}
// 重点代码 根据name字段模糊匹配树状结构数据,最后将处理好的数据返回出来
const rebuildData = (value: any, arr: any) => {
if (!arr) {
return []
}
let newArr: any = []
arr.forEach((element: any) => {
console.log(element, 'element')
// indexOf用来判读当前节点name字段是否包含所搜索的字符串value
// 返回值:包含则返回索引值,反之返回-1
if (element.category_name.indexOf(value) > -1) {
const ab = rebuildData(value, element.children)
const obj = {
...element,
children: ab
}
newArr.push(obj)
} else {
// 判断当前节点知否有子节点,并且子节点中有数据,有数据继续递归查找
if (element.children && element.children.length > 0) {
const ab = rebuildData(value, element.children)
const obj = {
...element,
children: ab
}
if (ab && ab.length > 0) {
newArr.push(obj)
}
}
}
})
return newArr
}
onMounted(() => {
// sortable('t1', tableData) // 参数分别为table的class名称,table的数据data
handleCategoryList()
})
</script>
<template> <template>
<AppCard title="类别管理"></AppCard> <AppCard title="类别管理">
<div class="table-list-filter">
<el-form class="filter-form" :model="form">
<el-form-item label="类别名称:" prop="name">
<el-input v-model="form.category_name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch" class="btn_query">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</div>
<el-button type="primary" @click="handleAddCategory">新增类别</el-button>
<el-table
class="t1"
:data="tableData"
style="width: 100%"
row-key="id"
ref="dragTable"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
highlight-current-row
v-loading="loading"
>
<el-table-column type="index" align="center" class-name="handle">
<el-icon><Operation /></el-icon>
</el-table-column>
<el-table-column prop="category_name" label="类别名称" align="center" class-name="handle" />
<el-table-column prop="depth" label="层级" align="center" />
<el-table-column prop="status_name" label="状态" align="center"> </el-table-column>
<el-table-column align="center" label="操作" width="300px">
<template #default="scope">
<el-button type="primary" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button @click="handleAddRow(scope.$index, scope.row)">新增</el-button>
<el-button @click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</AppCard>
<template v-if="dialogVisible === true">
<AddDialog
v-model:dialogVisible="dialogVisible"
@confirm="handleConfirm"
:editData="editData"
:isEdit="isEdit"
:title="title"
:prevCategoryName="prevCategoryName"
/>
</template>
</template> </template>
<style lang="scss" scoped>
.table-list-filter {
.filter-form {
display: flex;
justify-content: flex-start;
align-items: center;
.btn_query {
margin-left: 30px;
}
}
}
// 拖拽
.dragClass {
background: rgba($color: #41c21a, $alpha: 0.5) !important;
}
// 停靠
.ghostClass {
background: rgba($color: #6cacf5, $alpha: 0.5) !important;
}
// 选择
.chosenClass:hover > td {
background: rgba($color: #f56c6c, $alpha: 0.5) !important;
}
</style>
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取讲师列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params }) export function getTeacherList(params?: { type?: string; page?: number; ['per-page']?: number }) {
return httpRequest.get('/api/resource/v1/backend/lecturer/list', { params })
}
// 删除讲师
export function deleteTeacher(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/lecturer/delete', data)
}
// 更新讲师
export function updateTeacher(data: {
id: string
name: string
avatar: string
status: string
title: string
office: string
education: string
summarize: string
}) {
return httpRequest.post('/api/resource/v1/backend/lecturer/update', data)
}
// 创建讲师
export function createTeacher(data: {
name: string
avatar: string
title: string
status: string
office: string
education: string
summarize: string
}) {
return httpRequest.post('/api/resource/v1/backend/lecturer/create', data)
}
// 获取讲师详情
export function getTeacherDetail(params: { id: string }) {
return httpRequest.get('/api/resource/v1/backend/lecturer/view', { params })
} }
...@@ -5,6 +5,10 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -5,6 +5,10 @@ export const routes: Array<RouteRecordRaw> = [
{ {
path: '/admin/teacher', path: '/admin/teacher',
component: AppLayout, component: AppLayout,
children: [{ path: '', component: () => import('./views/List.vue') }] children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: '/admin/teacher/detail', component: () => import('./views/Detail.vue') },
{ path: '/admin/teacher/add', name: 'update', component: () => import('./views/Add.vue') }
]
} }
] ]
<script setup lang="ts">
import { createTeacher } from '../api'
import VEditor from '@tinymce/tinymce-vue'
import AppUpload from '@/components/base/AppUpload.vue'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const router = useRouter()
const ruleFormRef = ref<FormInstance>()
let ruleForm = reactive({
id: '',
status: '1',
name: '', // 姓名
title: '', // 职位
education: '', // 学历
office: '', // 讲师任职机构
avatar: '', // 头像
summarize: '' // 讲师简介
})
const rules = reactive<FormRules>({
name: [
{
required: true,
message: '请输入讲师姓名',
trigger: 'blur'
}
],
title: [
{
required: true,
message: '请输入讲师职位',
trigger: 'blur'
}
]
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
const params = Object.assign({}, ruleForm)
createTeacher(params).then(() => {
ElMessage.success('创建讲师成功')
router.push('/admin/teacher')
})
}
})
}
</script>
<template>
<AppCard title="添加讲师">
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm">
<el-row>
<el-col :span="10">
<el-form-item label="讲师姓名:" prop="name">
<el-input v-model="ruleForm.name" />
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="讲师职位:" prop="title">
<el-input v-model="ruleForm.title" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="10">
<el-form-item label="讲师学历:" prop="education">
<el-input v-model="ruleForm.education" />
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="讲师任职机构:" prop="office">
<el-input v-model="ruleForm.office" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="10">
<el-form-item label="讲师头像:" prop="avatar">
<AppUpload v-model="ruleForm.avatar" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="讲师简介:" prop="summarize">
<v-editor v-model="ruleForm.summarize" class="editor" style="width: 1000px"></v-editor>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">提交</el-button>
</el-form-item>
</el-form>
</AppCard>
</template>
<script setup lang="ts">
import { getTeacherDetail, updateTeacher } from '../api'
import { ElMessage } from 'element-plus'
import type { FormRules, FormInstance } from 'element-plus'
import VEditor from '@tinymce/tinymce-vue'
import AppUpload from '@/components/base/AppUpload.vue'
const router = useRouter()
const route = useRoute()
const appList = ref()
const id = route.query.id as string
const title = route.query.title as string
const isEdit = route.query.isEdit as string
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({
id: '',
name: '',
title: '', // 职位
education: '', // 学历
office: '', // 讲师任职机构
summarize: '', // 讲师简介
avatar: '', //讲师图片
status: '1'
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入讲师姓名', trigger: 'blur' }],
title: [{ required: true, message: ' 请输入职位', trigger: 'blur' }]
})
const listOptions = $computed(() => {
return {
remote: {
params: { type: '' }
},
columns: [
{ label: '#', type: 'index', align: 'center' },
{ label: '课程图片', slots: 'table-cover', align: 'center' },
{ label: '课程名称', prop: 'id', align: 'center' },
{ label: '分类名称', prop: 'course_name', align: 'center' },
{ label: '线上类型', prop: 'type_name', align: 'center' },
{ label: '选课类型', prop: 'pv', align: 'center' },
{ label: '课程学分', prop: 'pv', align: 'center' },
{ label: '是否可用', prop: 'pv', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '编辑', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 300, align: 'center' }
]
}
})
const handleDelete = (row: any) => {
console.log('删除', row)
}
const getTeacherInfo = () => {
getTeacherDetail({ id: id }).then(res => {
console.log(res.data)
Object.keys(ruleForm).forEach(key => {
ruleForm[key] = res.data[key]
})
})
}
// 更新讲师
const handleUpdate = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
const params = Object.assign({}, ruleForm)
updateTeacher(params).then(() => {
ElMessage.success('创建讲师成功')
router.push('/admin/teacher')
})
}
})
}
onMounted(() => {
// 更新获取讲师信息
getTeacherInfo()
})
</script>
<template>
<AppCard :title="title">
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-position="right" label-width="100px">
<el-row>
<el-col :span="8">
<el-form-item label="讲师图片:" prop="avatar">
<div v-if="isEdit === '1'" class="avatar_box">暂无照片</div>
<AppUpload v-model="ruleForm.avatar" v-else />
</el-form-item>
</el-col>
<el-col :span="8" style="margin-left: 80px">
<el-form-item label="讲师姓名:" prop="name">
<el-input v-model="ruleForm.name" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师职位:" prop="title">
<el-input v-model="ruleForm.title" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师学历:" prop="education">
<el-input v-model="ruleForm.education" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师任职机构:" prop="office">
<el-input v-model="ruleForm.office" :disabled="isEdit === '1'" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="讲师简介:" prop="summarize">
<v-editor v-model="ruleForm.summarize" style="width: 70%" :disabled="isEdit === '1'"></v-editor>
</el-form-item>
<el-form-item>
<el-button type="primary" v-if="isEdit !== '1'" @click="handleUpdate(ruleFormRef)">保存</el-button>
</el-form-item>
</el-form>
<el-card>
<div class="form_title">讲授课程:</div>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside> </template>
<template #table-operate="{ row }">
<el-space>
<router-link to="/admin/teacher/detail">
<el-button type="primary" plain>查看</el-button>
</router-link>
<router-link to="/admin/teacher/update">
<el-button type="primary" plain>更新</el-button>
</router-link>
<el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
</el-space>
</template>
</AppList>
</el-card>
</AppCard>
</template>
<style lang="scss" scoped>
.form_title {
font-size: 14px;
color: #606266;
}
.avatar_box {
width: 150px;
height: 200px;
text-align: center;
line-height: 200px;
color: #ccc;
border: 1px dashed #ccc;
}
</style>
<script setup lang="ts"></script> <script setup lang="ts">
import { ElMessage,ElMessageBox } from 'element-plus'
import { getTeacherList, deleteTeacher } from '../api'
const router = useRouter()
const appList = ref()
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getTeacherList,
params: { type: '' }
},
filters: [
{ type: 'input', prop: 'name', label: '讲师姓名:' },
{ type: 'input', prop: 'office', label: '讲师任职机构:' },
{ type: 'input', prop: 'title', label: '讲师职位:' },
{ type: 'input', prop: 'education', label: '讲师学历:' }
],
columns: [
{ label: '#', type: 'index', align: 'center' },
{ label: '讲师头像', slots: 'table-img', align: 'center' },
{ label: '讲师姓名', prop: 'name', align: 'center' },
{ label: '讲师任职机构', prop: 'office', align: 'center' },
{ label: '讲师职位', prop: 'title', align: 'center' },
{ label: '讲师学历', prop: 'education', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
]
}
})
// 删除讲师
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
deleteTeacher({ id: row.id }).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 更新讲师
const handleUpdate = (row: any) => {
router.push({
path: '/admin/teacher/detail',
query: {
id: row.id,
isEdit: '0',
title: '更新讲师'
}
})
}
//讲师详情
const handleDetail = (row: any) => {
console.log(row.id)
router.push({
path: '/admin/teacher/detail',
query: {
id: row.id,
isEdit: '1',
title: '讲师详情'
}
})
}
</script>
<template> <template>
<AppCard title="讲师管理"></AppCard> <AppCard title="讲师管理">
<AppList v-bind="listOptions" ref="appList">
<router-link to="/admin/teacher/add">
<el-button type="primary" round>添加讲师</el-button>
</router-link>
<template #header-aside> </template>
<template #table-img="{ row }"> <img :src="row.avatar" alt="" style="width: 100%" /></template>
<template #table-operate="{ row }">
<el-space>
<el-button type="primary" plain @click="handleDetail(row)">查看</el-button>
<el-button type="primary" plain @click="handleUpdate(row)">更新</el-button>
<el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
</el-space>
</template>
</AppList>
</AppCard>
</template> </template>
...@@ -22,10 +22,10 @@ export function getCoverList() { ...@@ -22,10 +22,10 @@ export function getCoverList() {
// 更新视频 // 更新视频
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) { export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data) return httpRequest.post('/api/resource/backend/video/update', data)
} }
// 获取视频详情 // 获取视频详情
export function getVideo(params: { id: string }) { export function getVideo(params: { id: string }) {
return httpRequest.get('/api/psp/backend/video/view', { params }) return httpRequest.get('/api/resource/backend/video/view', { params })
} }
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取封面列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) { export function getCoverList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params }) return httpRequest.get('/api/resource/v1/backend/cover/list', { params })
}
// 创建封面
export function createCover(data?: { title?: string; status?: number; type?: number; url?: number }) {
return httpRequest.post('/api/resource/v1/backend/cover/create', data)
}
// 更新封面
export function updateCover(data?: { title?: string; status?: number; type?: number; url?: number }) {
return httpRequest.post('/api/resource/v1/backend/cover/update', data)
}
// 删除封面
export function deleteCover(data: { id: any }) {
return httpRequest.post('/api/resource/v1/backend/cover/delete', data)
}
// 获取公共字典列表
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
} }
<script lang="ts" setup>
import AppUpload from '@/components/base/AppUpload.vue'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
// 封面类型
const typeList = store.mapList.filter((item: any) => item.key === 'system_cover_type')[0].values
// 封面状态
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const form = reactive({
title: '',
status: '1',
url: '',
type: '1'
})
const rules = reactive<FormRules>({
status: [{ required: true, message: '请选择状态', trigger: 'blur' }],
url: [{ required: true, message: '请上传图片', trigger: 'change' }],
type: [{ required: true, message: '请选择封面类型', trigger: 'blur' }]
})
const props = defineProps({
isShowDialog: {
type: Boolean,
required: true
},
editData: {
type: Object,
required: true
},
isEdit: {
type: Boolean,
required: true
}
})
interface Emits {
(e: 'update:isShowDialog', isShowDialog: boolean): void
(e: 'createCover', form: any): void
}
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
// 普通属性
const handleCancel = () => {
emit('update:isShowDialog', false)
}
// 确定
const handleConfirm = () => {
emit('update:isShowDialog', false)
if (props.isEdit === true) {
emit('createCover', { form, isUpdate: 1, id: props.editData.id })
} else {
form.title = form.url
emit('createCover', { form, isUpdate: 0 })
}
}
onMounted(() => {
if (props.isEdit) {
form.status = props.editData.status
form.url = props.editData.url
form.type = props.editData.type
form.title = props.editData.url
}
})
</script>
<template>
<el-dialog :model-value="isShowDialog" draggable :before-close="handleCancel" width="30%">
<el-form :model="form" :rules="rules" ref="ruleFormRef">
<el-form-item label="封面类型:" prop="type">
<el-select v-model="form.type">
<el-option v-for="(item, id) in typeList" :key="id" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图片地址:" prop="url">
<AppUpload v-model="form.url" />
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="(item, id) in statusList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts"></script> <script setup lang="ts">
import { getCoverList, createCover, updateCover, deleteCover } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
import AddDialog from '../component/AddDialog.vue'
const appList = ref()
const isShowDialog = ref(false)
const isEdit = ref(false)
const editData = ref({})
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getCoverList,
params: { type: '' }
},
columns: [
{ label: '封面地址', prop: 'url', align: 'center' },
{ label: '封面预览', prop: 'url', slots: 'table-cover', align: 'center' },
{ label: '封面类型', prop: 'type_name', align: 'center' },
{
label: '状态',
prop: 'status_name',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
]
}
})
// 删除
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params: any = { id: row.id }
deleteCover(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 确定
const handleConfirm = (val: any) => {
if (val.isUpdate === 1) {
// 更新封面
const params = Object.assign({ id: val.id }, val.form)
updateCover(params).then(() => {
appList.value.refetch()
})
} else {
// 添加封面
const params = Object.assign({}, val.form)
createCover(params).then(() => {
appList.value.refetch()
})
}
}
// 添加
const handleAdd = () => {
isShowDialog.value = true
isEdit.value = false
}
// 编辑
const handleEdit = (row: any) => {
isShowDialog.value = true
editData.value = row
isEdit.value = true
}
</script>
<template> <template>
<AppCard title="封面管理"></AppCard> <AppCard title="封面管理">
<el-button type="primary" round @click="handleAdd">添加</el-button>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside> </template>
<template #table-cover="{ row }">
<img :src="row.url" alt="" style="width: 100px" />
</template>
<template #table-operate="{ row }">
<el-space>
<el-button type="primary" plain @click="handleEdit(row)">编辑</el-button>
<el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
</el-space>
</template>
<template v-if="isShowDialog === true">
<AddDialog
v-model:isShowDialog="isShowDialog"
@createCover="handleConfirm"
:editData="editData"
:isEdit="isEdit"
/>
</template>
</AppList>
</AppCard>
</template> </template>
...@@ -2,5 +2,75 @@ import httpRequest from '@/utils/axios' ...@@ -2,5 +2,75 @@ import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) { export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params }) return httpRequest.get('/api/resource/backend/video/index', { params })
} }
// 获取字典列表
export function getDictionaryList(params?: {
name?: string
key?: number
status?: boolean
created_time_start?: string
created_time_end?: string
page?: number
page_size?: number
}) {
return httpRequest.get('/api/resource/v1/backend/data-dictionary/list', { params })
}
// 新增字典
export function createDictionary(data: {
name: string
key: number
status: boolean
remark: string
can_edit: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/create', data)
}
// 更新字典
export function updateDictionary(data: {
id: string
name: string
key: number
status: boolean
remark: string
can_edit: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/update', data)
}
// 删除字典
export function delDictionary(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/delete', data)
}
// 获取字典的值的列表
export function getDictionaryItemList(params?: { data_dictionary_id: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/resource/v1/backend/data-dictionary/value-list', { params })
}
// 新增字典的值
export function createDictionaryItem(data: {
data_dictionary_id: string
label: number
value: boolean
sort: string
remark: string
can_edit: string
status: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-create', data)
}
// 新增字典的值
export function updateDictionaryItem(data: {
id: string
data_dictionary_id: string
label: number
value: boolean
sort: string
remark: string
can_edit: string
status: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-update', data)
}
// 删除字典的值
export function delDictionaryItem(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-delete', data)
}
\ No newline at end of file
<script lang="ts" setup>
import { useMapStore } from '@/stores/map'
import type { FormInstance, FormRules } from 'element-plus'
const store = useMapStore()
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const ruleFormRef = ref<FormInstance>()
const form = reactive({
name: '',
key: '',
status: '1',
remark: ''
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
key: [{ required: true, message: '请输入字典类型', trigger: 'blur' }]
})
const props = defineProps({
isShowDialog: {
type: Boolean,
required: true
},
isEdit: {
type: Boolean,
required: true
},
rowInfo: {
type: Object,
required: true
}
})
interface Emits {
(e: 'update:isShowDialog', isShowDialog: boolean): void
(e: 'confirm', form: object): void
}
const emit = defineEmits<Emits>()
// 普通属性
const handleCancel = () => {
emit('update:isShowDialog', false)
}
// 确定
const handleConfirm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
if (props.isEdit === true) {
emit('update:isShowDialog', false)
emit('confirm', { form, isUpdate: 1, id: props.rowInfo.id })
} else {
emit('update:isShowDialog', false)
emit('confirm', { form, isUpdate: 0 })
}
}
})
}
onMounted(() => {
console.log(props.rowInfo, 'props.rowInfo')
if (props.isEdit) {
form.name = props.rowInfo.name
form.key = props.rowInfo.key
if (props.rowInfo.status === '有效') {
form.status = '1'
} else {
form.status = '0'
}
form.remark = props.rowInfo.remark
}
})
</script>
<template>
<el-dialog
:model-value="isShowDialog"
draggable
:before-close="handleCancel"
:title="isEdit === true ? '编辑字典' : '新增字典'"
>
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="字典类型:" prop="key">
<el-input v-model="form.key"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="(item, index) in statusList" :key="index" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
<el-input v-model="form.remark" autosize type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { useMapStore } from '@/stores/map'
import type { FormInstance, FormRules } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const store = useMapStore()
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const editList = store.mapList.filter((item: any) => item.key === 'system_can_edit')[0].values
const form = reactive({
label: '',
value: '',
key: '',
type: '',
status: '1',
remark: '',
sort: '',
can_edit: '1'
})
const rules = reactive<FormRules>({
label: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
value: [{ required: true, message: '请输入字典键值', trigger: 'blur' }],
sort: [{ required: true, message: '请输入字典排序', trigger: 'blur' }]
})
const props = defineProps({
isListAddDialog: {
type: Boolean,
required: true
},
isEdit: {
type: Boolean,
required: true
},
editData: {
type: Object,
required: true
},
title: {
type: String,
required: true
},
type: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isListAddDialog', isListAddDialog: boolean): void
(e: 'confirm', form: object): void
}
const emit = defineEmits<Emits>()
// 普通属性
const handleCancel = () => {
emit('update:isListAddDialog', false)
}
// 确定
const handleConfirm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
if (props.isEdit === true) {
emit('update:isListAddDialog', false)
emit('confirm', { form, isUpdate: 1, id: props.editData.id })
} else {
emit('update:isListAddDialog', false)
emit('confirm', { form, isUpdate: 0 })
}
}
})
}
onMounted(() => {
if (props.isEdit) {
form.label = props.editData.label
form.value = props.editData.value
form.type = props.editData.type
form.remark = props.editData.remark
form.status = props.editData.status
form.sort = props.editData.sort
}
})
</script>
<template>
<el-dialog :model-value="isListAddDialog" draggable :before-close="handleCancel" :title="props.title">
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典标签:" prop="label">
<el-input v-model="form.label"></el-input>
</el-form-item>
<el-form-item label="字典键值:" prop="value">
<el-input v-model="form.value" :disabled="form.can_edit === '0'"></el-input>
</el-form-item>
<el-form-item label="字典排序:" prop="sort">
<el-input v-model="form.sort"></el-input>
</el-form-item>
<el-form-item label="字典类型:">
<el-input disabled :placeholder="props.type"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="(item, index) in statusList" :key="index" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
<el-input v-model="form.remark" autosize type="textarea" />
</el-form-item>
<el-form-item label="能否编辑:" prop="can_edit">
<el-radio-group v-model="form.can_edit">
<el-radio v-for="(item, index) in editList" :key="index" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
...@@ -5,6 +5,9 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -5,6 +5,9 @@ export const routes: Array<RouteRecordRaw> = [
{ {
path: '/system/dictionary', path: '/system/dictionary',
component: AppLayout, component: AppLayout,
children: [{ path: '', component: () => import('./views/List.vue') }] children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: '/system/dictionary/rowList', component: () => import('./views/rowList.vue') }
]
} }
] ]
export interface IMapList {
label: string
value: string
data_dictionary_id: string
sort: string
remark: string
id: string
}
<script setup lang="ts"> <script setup lang="ts">
import { getVideoList } from '../api' import { ElMessage, ElMessageBox } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { getDictionaryList, createDictionary, updateDictionary, delDictionary } from '../api'
import AddDialog from '../component/AddDialog.vue'
const router = useRouter()
const appList = ref() const appList = ref()
const isShowDialog = ref(false) // 新增字典弹框状态
const isEdit = ref(false) //是否可编辑
const rowInfo = ref({})
const store = useMapStore()
const listOptions = { // 状态
remote: { //表单每行数据
httpRequest: getVideoList, const listOptions = $computed(() => {
params: { type: '' } return {
}, remote: {
filters: [ httpRequest: getDictionaryList,
{ type: 'select', prop: 'type', label: '状态' }, params: {
{ type: 'select', prop: 'project_id', label: '项目' }, type: '',
{ type: 'select', prop: 'category_id', label: '类别' } created_time_start: '',
], created_time_end: ''
columns: [ }
{ label: '封面', slots: 'table-cover', width: 224 }, },
{ label: 'ID', prop: 'id' }, filters: [
{ label: '标题', prop: 'course_name' }, { type: 'input', prop: 'name', label: '字典名称:' },
{ label: '类型', prop: 'type_name' }, { type: 'input', prop: 'key', label: '字典类型:' },
{ label: '浏览量', prop: 'pv' }, {
{ label: '创建时间', prop: 'created_time' }, type: 'select',
{ label: '操作', slots: 'table-operate', width: 230, align: 'right' } prop: 'status',
], label: '字典状态:',
data: [ options: store.mapList?.filter((item: any) => item.key === 'system_status')[0]?.values || []
{ id: 1, title: '视频标题', type: '视频分类' }, },
{ id: 2, title: '视频标题', type: '视频分类' } {
] type: 'input',
label: '创建时间:',
slots: 'created_time_start',
prop: 'created_time_start'
},
{ slots: 'created_time_end', prop: 'created_time_end' }
],
columns: [
{ label: '字典主键', prop: 'id', width: 224, align: 'center' },
{ label: '字典名称', prop: 'name', align: 'center' },
{ label: '字典类型', prop: 'key', align: 'center' },
{
label: '状态',
prop: 'status_name',
align: 'center'
},
{ label: '备注 ', prop: 'remark', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center', width: 300 }
]
}
})
// 新增弹窗
const handleAdd = () => {
isShowDialog.value = true
isEdit.value = false
}
// 编辑弹窗
const handleEdit = (row: any) => {
rowInfo.value = row
isShowDialog.value = true
isEdit.value = true
}
//删除
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delDictionary(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 跳转列表
const handleList = (row: any) => {
console.log('列表', row.rowList)
router.push({
path: '/system/dictionary/rowList',
query: {
id: row.id,
type: row.key
}
})
}
// 确定
const handleConfirm = (val: any) => {
if (val.isUpdate === 1) {
// 更新字典
const params = Object.assign({ id: val.id }, val.form)
updateDictionary(params).then(() => {
ElMessage.success('更新成功')
appList.value.refetch()
})
} else {
// 新增字典
const params = Object.assign({}, val.form)
createDictionary(params).then(() => {
ElMessage.success('新增成功')
appList.value.refetch()
})
}
} }
</script> </script>
<template> <template>
<AppCard title="数据字典"> <AppCard title="数据字典">
<router-link to="/resource/video/create">
<el-button type="primary" round>新建视频资源</el-button>
</router-link>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-aside> </template> <el-row>
<el-button type="primary" @click="handleAdd">新增字典</el-button>
</el-row>
<template v-slot:created_time_start="{ params }">
<el-date-picker v-model="params.created_time_start" type="date" placeholder="开始时间"> </el-date-picker>
<p class="separator">&nbsp;&nbsp;&nbsp;&nbsp;-</p>
</template>
<template v-slot:created_time_end="{ params }">
<el-date-picker v-model="params.created_time_end" type="date" placeholder="结束时间"> </el-date-picker>
</template>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-space> <el-space>
<router-link :to="`/video/update/${row.id}`"> <el-button type="primary" plain @click="handleEdit(row)">编辑</el-button>
<el-button plain>编辑</el-button> <el-button type="primary" plain @click="handleList(row)">列表</el-button>
</router-link> <el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
<!-- <router-link :to="`/video/view/${row.id}`">
<el-button type="primary" plain>查看</el-button>
</router-link> -->
</el-space> </el-space>
</template> </template>
<template v-if="isShowDialog === true">
<AddDialog v-model:isShowDialog="isShowDialog" :isEdit="isEdit" :rowInfo="rowInfo" @confirm="handleConfirm" />
</template>
</AppList> </AppList>
</AppCard> </AppCard>
</template> </template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import { getDictionaryItemList, createDictionaryItem, updateDictionaryItem, delDictionaryItem } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
import ListAddDialog from '../component/ListAddDialog.vue'
const route = useRoute()
const appList = ref()
const editData = ref({})
const title = ref('')
const type = route.query.type as string
const isEdit = ref(false)
const isListAddDialog = ref(false)
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getDictionaryItemList,
params: { data_dictionary_id: route.query.id }
},
columns: [
{ label: '字典编码', prop: 'data_dictionary_id', align: 'center' },
{ label: '字典标签', prop: 'label', align: 'center' },
{ label: '字典键值', prop: 'value', align: 'center' },
{
label: '状态',
prop: 'status_name',
align: 'center'
},
{ label: '备注 ', prop: 'remark', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center', minWidth: 180 }
]
}
})
const handleAdd = () => {
isListAddDialog.value = true
isEdit.value = false
editData.value = {}
title.value = '新增数据'
console.log('新增字典')
}
const handleEdit = (row: any) => {
isEdit.value = true
editData.value = row
isListAddDialog.value = true
title.value = '修改数据'
console.log('编辑字典', row)
}
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delDictionaryItem(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 确定
const handleConfirm = (val: any) => {
console.log(val.id, '9999')
if (val.isUpdate === 1) {
// 更新字典的值
const params = Object.assign({ id: val.id, data_dictionary_id: route.query.id }, val.form)
updateDictionaryItem(params).then(() => {
ElMessage.success('更新成功')
appList.value.refetch()
})
} else {
// 新增字典的值
const params = Object.assign({ data_dictionary_id: route.query.id }, val.form)
createDictionaryItem(params).then(() => {
ElMessage.success('新增成功')
appList.value.refetch()
})
}
}
</script>
<template>
<AppCard>
<AppList v-bind="listOptions" ref="appList">
<el-row>
<el-button type="primary" @click="handleAdd">新增</el-button>
</el-row>
<template #table-operate="{ row }">
<el-space>
<el-button type="primary" plain @click="handleEdit(row)">编辑</el-button>
<el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
</el-space>
</template>
</AppList>
</AppCard>
<template v-if="isListAddDialog === true">
<ListAddDialog
v-model:isListAddDialog="isListAddDialog"
@confirm="handleConfirm"
:editData="editData"
:isEdit="isEdit"
:title="title"
:type="type"
/>
</template>
</template>
import { defineStore } from 'pinia'
import { getMapList } from '@/api/base'
interface IMapState {
id: string
key: string
name: string
remark: string
values: IValuesList[]
}
interface IValuesList {
data_dictionary_id: string
id: string
label: string
remark: string
sort: string
value: string
}
export const useMapStore = defineStore({
id: 'map',
state: () => {
return {
mapList: [] as IMapState | any
}
},
getters: {},
actions: {
async getMapList() {
const res = await getMapList()
this.mapList = res.data
}
}
})
useMapStore().getMapList()
...@@ -29,6 +29,7 @@ export const useUserStore = defineStore({ ...@@ -29,6 +29,7 @@ export const useUserStore = defineStore({
async getUser() { async getUser() {
const res = await getUser() const res = await getUser()
this.user = res.data this.user = res.data
console.log(res.data, 'res.data')
}, },
async logout() { async logout() {
await logout() await logout()
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} },
"suppressImplicitAnyIndexErrors": true,
"types": ["element-plus/global"]
}, },
"references": [ "references": [
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论