Merge branch 'master' of https://git.echol.cn/GW-web/scholarship-adult-admin
Conflicts: .drone.yml .gitignore
This commit is contained in:
		| @@ -18,9 +18,9 @@ steps: | ||||
|     commands: | ||||
|       - pwd | ||||
|       - ls -alt | ||||
| #      - npm config set registry https://registry.npm.taobao.org # 切换淘宝镜像 | ||||
|       - npm install | ||||
|       - npm run build | ||||
|       - npm config set registry https://registry.npm.taobao.org # 切换淘宝镜像 | ||||
|       - yarn | ||||
|       - yarn build | ||||
|     when: | ||||
|       event: push | ||||
|   - name: deploy-project | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| ENV = 'development' | ||||
| VITE_CLI_PORT = 8080 | ||||
| VITE_CLI_PORT = 8088 | ||||
| VITE_SERVER_PORT = 8888 | ||||
| VITE_BASE_API = /api | ||||
| VITE_BASE_PATH = http://127.0.0.1 | ||||
| VITE_BASE_PATH = http://192.168.1.133 | ||||
| VITE_EDITOR = vscode | ||||
| // VITE_EDITOR = webstorm 如果使用webstorm开发且要使用dom定位到代码行功能 请先自定添加 webstorm到环境变量 再将VITE_EDITOR值修改为webstorm | ||||
| // 如果使用docker-compose开发模式,设置为下面的地址或本机主机IP | ||||
|   | ||||
| @@ -4,4 +4,4 @@ VITE_CLI_PORT = 8080 | ||||
| VITE_SERVER_PORT = 8888 | ||||
| VITE_BASE_API = /api | ||||
| #下方修改为你的线上ip | ||||
| VITE_BASE_PATH = https://demo.gin-vue-admin.com | ||||
| VITE_BASE_PATH = https://admin.api.gwkjxb.com | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -10,5 +10,4 @@ docs/_book | ||||
| test/ | ||||
|  | ||||
| node_modules | ||||
|  | ||||
| .idea | ||||
| dist | ||||
|   | ||||
							
								
								
									
										5
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,5 +0,0 @@ | ||||
| # 默认忽略的文件 | ||||
| /shelf/ | ||||
| /workspace.xml | ||||
| # 基于编辑器的 HTTP 客户端请求 | ||||
| /httpRequests/ | ||||
							
								
								
									
										
											BIN
										
									
								
								favicon.ico
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								favicon.ico
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								favicon2.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								favicon2.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.2 KiB | 
							
								
								
									
										105
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,52 +1,57 @@ | ||||
| { | ||||
|     "name": "gin-vue-admin", | ||||
|     "version": "2.5.5", | ||||
|     "private": true, | ||||
|     "scripts": { | ||||
|         "serve": "vite --host --mode development", | ||||
|         "build": "vite build --mode production", | ||||
|         "limit-build": "npm install increase-memory-limit-fixbug cross-env -g && npm run fix-memory-limit && node ./limit && npm run build", | ||||
|         "preview": "vite preview", | ||||
|         "fix-memory-limit": "cross-env LIMIT=4096 increase-memory-limit" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@element-plus/icons-vue": "^0.2.7", | ||||
|         "axios": "^0.19.2", | ||||
|         "core-js": "^3.6.5", | ||||
|         "echarts": "5.3.2", | ||||
|         "element-plus": "2.2.9", | ||||
|         "highlight.js": "^10.6.0", | ||||
|         "marked": "^2.0.0", | ||||
|         "mitt": "^3.0.0", | ||||
|         "nprogress": "^0.2.0", | ||||
|         "path": "^0.12.7", | ||||
|         "pinia": "^2.0.9", | ||||
|         "qs": "^6.8.0", | ||||
|         "quill": "^1.3.7", | ||||
|         "screenfull": "^5.0.2", | ||||
|         "spark-md5": "^3.0.1", | ||||
|         "vue": "^3.2.25", | ||||
|         "vue-router": "^4.0.0-0" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@vitejs/plugin-legacy": "^2.0.0", | ||||
|         "@vitejs/plugin-vue": "^3.0.1", | ||||
|         "@vue/cli-plugin-babel": "~4.5.0", | ||||
|         "@vue/cli-plugin-eslint": "~4.5.0", | ||||
|         "@vue/cli-plugin-router": "~4.5.0", | ||||
|         "@vue/cli-plugin-vuex": "~4.5.0", | ||||
|         "@vue/cli-service": "~4.5.0", | ||||
|         "@vue/compiler-sfc": "^3.1.5", | ||||
|         "babel-eslint": "^10.1.0", | ||||
|         "babel-plugin-import": "^1.13.3", | ||||
|         "chalk": "^4.1.2", | ||||
|         "dotenv": "^10.0.0", | ||||
|         "eslint": "^6.7.2", | ||||
|         "eslint-plugin-vue": "^7.0.0", | ||||
|         "sass": "^1.54.0", | ||||
|         "terser": "^5.4.0", | ||||
|         "vite": "^3.0.1", | ||||
|         "vite-plugin-banner": "^0.1.3", | ||||
|         "vite-plugin-importer": "^0.2.5" | ||||
|     } | ||||
|   "name": "gin-vue-admin", | ||||
|   "version": "2.5.5", | ||||
|   "private": true, | ||||
|   "scripts": { | ||||
|     "serve": "vite --host --mode development", | ||||
|     "build": "vite build --mode production", | ||||
|     "limit-build": "npm install increase-memory-limit-fixbug cross-env -g && npm run fix-memory-limit && node ./limit && npm run build", | ||||
|     "preview": "vite preview", | ||||
|     "fix-memory-limit": "cross-env LIMIT=4096 increase-memory-limit" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@ckeditor/ckeditor5-build-classic": "^36.0.1", | ||||
|     "@ckeditor/ckeditor5-vue": "^4.0.1", | ||||
|     "@element-plus/icons-vue": "^0.2.7", | ||||
|     "ali-oss": "^6.17.1", | ||||
|     "axios": "^0.19.2", | ||||
|     "axl-editor": "^1.0.1", | ||||
|     "core-js": "^3.6.5", | ||||
|     "echarts": "5.3.2", | ||||
|     "element-plus": "2.2.9", | ||||
|     "highlight.js": "^10.6.0", | ||||
|     "js-cookie": "^3.0.1", | ||||
|     "marked": "^2.0.0", | ||||
|     "mitt": "^3.0.0", | ||||
|     "nprogress": "^0.2.0", | ||||
|     "path": "^0.12.7", | ||||
|     "pinia": "^2.0.9", | ||||
|     "qs": "^6.8.0", | ||||
|     "quill": "^1.3.7", | ||||
|     "screenfull": "^5.0.2", | ||||
|     "spark-md5": "^3.0.1", | ||||
|     "vue": "^3.2.25", | ||||
|     "vue-router": "^4.0.0-0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@vitejs/plugin-legacy": "^2.0.0", | ||||
|     "@vitejs/plugin-vue": "^3.0.1", | ||||
|     "@vue/cli-plugin-babel": "~4.5.0", | ||||
|     "@vue/cli-plugin-eslint": "~4.5.0", | ||||
|     "@vue/cli-plugin-router": "~4.5.0", | ||||
|     "@vue/cli-plugin-vuex": "~4.5.0", | ||||
|     "@vue/cli-service": "~4.5.0", | ||||
|     "@vue/compiler-sfc": "^3.1.5", | ||||
|     "babel-eslint": "^10.1.0", | ||||
|     "babel-plugin-import": "^1.13.3", | ||||
|     "chalk": "^4.1.2", | ||||
|     "dotenv": "^10.0.0", | ||||
|     "eslint": "^6.7.2", | ||||
|     "eslint-plugin-vue": "^7.0.0", | ||||
|     "sass": "^1.54.0", | ||||
|     "terser": "^5.4.0", | ||||
|     "vite": "^3.0.1", | ||||
|     "vite-plugin-banner": "^0.1.3", | ||||
|     "vite-plugin-importer": "^0.2.5" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										20
									
								
								src/App.vue
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/App.vue
									
									
									
									
									
								
							| @@ -24,4 +24,24 @@ export default { | ||||
| .el-button{ | ||||
|   font-weight: 400 !important; | ||||
| } | ||||
| .avatar-uploader .el-upload { | ||||
|   border: 1px dashed var(--el-border-color); | ||||
|   border-radius: 6px; | ||||
|   cursor: pointer; | ||||
|   position: relative; | ||||
|   overflow: hidden; | ||||
|   transition: var(--el-transition-duration-fast); | ||||
| } | ||||
|  | ||||
| .avatar-uploader .el-upload:hover { | ||||
|   border-color: var(--el-color-primary); | ||||
| } | ||||
|  | ||||
| .el-icon.avatar-uploader-icon { | ||||
|   font-size: 28px; | ||||
|   color: #8c939d; | ||||
|   width: 178px; | ||||
|   height: 178px; | ||||
|   text-align: center; | ||||
| } | ||||
| </style> | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/api/common.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/api/common.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| import service from '@/utils/request' | ||||
| const headers = { | ||||
|     "Content-Type": "multipart/form-data;binary", | ||||
| }; | ||||
| const api = { | ||||
|   upload:data=>{//文件上传 | ||||
|         return service({ | ||||
|             data, | ||||
|             url: '/public/uploadFile', | ||||
|             method: 'POST', | ||||
|             headers | ||||
|         }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										96
									
								
								src/api/course.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/api/course.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 课程api | ||||
|   getCourseList : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   getCourse : data => { // 获取课程详情 | ||||
|     return service({ | ||||
|       url: '/sys-course/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   }, | ||||
|   addCourse : data => { // 添加课程 | ||||
|     return service({ | ||||
|       url: '/sys-course', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editCourse : data => { // 编辑课程 | ||||
|     return service({ | ||||
|       url: '/sys-course', | ||||
|       method: 'put', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delCourse : data => { // 删除课程 | ||||
|     return service({ | ||||
|       url: '/sys-course', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   // 课程分类api | ||||
|   getSubjectList : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-category', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addSubject : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-category', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editSubject : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-category/'+data.id, | ||||
|       method: 'put', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delSubject : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-category', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   // 章节api | ||||
|   getChapter:data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-ware/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   }, | ||||
|   addChapter : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-ware', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editChapter : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-ware/update', | ||||
|       method: 'put', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delChapter : data => { | ||||
|     return service({ | ||||
|       url: '/sys-course-ware', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										40
									
								
								src/api/examination.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/api/examination.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 试卷 | ||||
|   getExaminationList : data => { | ||||
|     return service({ | ||||
|       url: '/exam/list', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addExamination : data => { // 新增试卷 | ||||
|     return service({ | ||||
|       url: '/exam', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editExamination : data => { // 更新试卷 | ||||
|     return service({ | ||||
|       url: '/exam/update', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delExamination : data => { // 删除试卷 | ||||
|     return service({ | ||||
|       url: '/exam/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   getExamGroupList: data => { // 获取试卷组别 | ||||
|     return service({ | ||||
|       url: '/exam/type', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										33
									
								
								src/api/exercises.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/exercises.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 习题 | ||||
|   getExercisesList : data => { | ||||
|     return service({ | ||||
|       url: '/question', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addExercises : data => { // 新增习题 | ||||
|     return service({ | ||||
|       url: '/question', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editExercises : data => { // 编辑习题 | ||||
|     return service({ | ||||
|       url: '/question/update', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delExercises : data => { // 删除习题 | ||||
|     return service({ | ||||
|       url: '/question/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										69
									
								
								src/api/integral.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/api/integral.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 积分 | ||||
|   getIntegralList : data => { | ||||
|     return service({ | ||||
|       url: '/point', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   // 竞拍 | ||||
|   getAuctionList : data => { // 竞拍列表 | ||||
|     return service({ | ||||
|       url: '/auction', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addAucitonData: data => { // 创建竞拍 | ||||
|     return service({ | ||||
|       url: '/auction', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editAucitonData: data => { // 编辑竞拍 | ||||
|     return service({ | ||||
|       url: '/auction', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delAucitonData: data => { // 删除竞拍 | ||||
|     return service({ | ||||
|       url: '/auction', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   getDrawList: data => { | ||||
|     return service({ | ||||
|       url: '/lottery', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addDrawData: data => { // 创建竞拍 | ||||
|     return service({ | ||||
|       url: '/lottery', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editDrawData: data => { // 编辑竞拍 | ||||
|     return service({ | ||||
|       url: '/lottery', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delDrawData: data => { // 删除竞拍 | ||||
|     return service({ | ||||
|       url: '/lottery', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										33
									
								
								src/api/lbt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/lbt.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 轮播图api | ||||
|   getLbtManageList : data => { | ||||
|     return service({ | ||||
|       url: '/sys-index-lbt', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addLbtManage : data => { | ||||
|     return service({ | ||||
|       url: '/sys-index-lbt', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editLbtManage : data => { | ||||
|     return service({ | ||||
|       url: '/sys-index-lbt/'+data.banner_id, | ||||
|       method: 'put', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delLbt: data => { | ||||
|     return service({ | ||||
|       url: '/sys-index-lbt', | ||||
|       method: 'delete', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										34
									
								
								src/api/market.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/api/market.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   /*助教*/ | ||||
|    getAssistantList : data => { // 助教列表 | ||||
|     return service({ | ||||
|       url: '/assistant', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   getAssistantDetail: data => { // 助教详情 | ||||
|     return service({ | ||||
|       url: '/assistant/'+data.id, | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   /*主管*/ | ||||
|    getManagerList : data => { // 主管列表 | ||||
|     return service({ | ||||
|       url: '/manager', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   getManagerDetail: data => { // 主管详情 | ||||
|     return service({ | ||||
|       url: '/manager/'+data.managerId, | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										39
									
								
								src/api/order.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/api/order.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 订单 | ||||
|   getOrderList : data => { | ||||
|     return service({ | ||||
|       url: '/order/list', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   addOrder : data => { // 新增订单 | ||||
|     return service({ | ||||
|       url: '/exam', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   editOrder : data => { // 更新订单 | ||||
|     return service({ | ||||
|       url: '/exam/update', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   delOrder : data => { // 删除订单 | ||||
|     return service({ | ||||
|       url: '/exam/delete', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   getOrderDetail : data => { | ||||
|     return service({ | ||||
|       url: '/order/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										39
									
								
								src/api/teacher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/api/teacher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 教师 | ||||
|   getTeacherList : data => { | ||||
|     return service({ | ||||
|       url: '/teacher', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   getTeacherDetail : data => { | ||||
|     return service({ | ||||
|       url: '/teacher/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   }, | ||||
|   teacherOperator : data => {// 审核提交 | ||||
|     return service({ | ||||
|       url: '/teacher/change', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
|   getAssistantList : data => { // 助教列表 | ||||
|     return service({ | ||||
|       url: '/assistant', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   assistantOperator : data => {// 审核提交-助教 | ||||
|     return service({ | ||||
|       url: '/assistant/change', | ||||
|       method: 'post', | ||||
|       data | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| export default api | ||||
							
								
								
									
										24
									
								
								src/api/userManage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/api/userManage.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| import service from '@/utils/request' | ||||
| const api = { | ||||
|   // 积分 | ||||
|   getUserList : data => { | ||||
|     return service({ | ||||
|       url: '/user', | ||||
|       method: 'get', | ||||
|       params:data | ||||
|     }) | ||||
|   }, | ||||
|   viewUser : data => { | ||||
|     return service({ | ||||
|       url: '/user/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   }, | ||||
|   getDealMoneyList: data => { // 获取资金交易明细 | ||||
|     return service({ | ||||
|       url: '/user/'+data.id, | ||||
|       method: 'get' | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| export default api | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/logo2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/logo2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.9 KiB | 
							
								
								
									
										180
									
								
								src/components/richText/ckEditor4.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/components/richText/ckEditor4.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| <template> | ||||
|   <div id="app-ckeditor"> | ||||
|     <ckeditor | ||||
|       v-model="editorData2" | ||||
|       :config="editorConfig" | ||||
|       @ready="logEvent('ready', $event)" | ||||
|     /> | ||||
|   </div> | ||||
| </template> | ||||
| <!--<script src="/node_modules/ckeditor4/ckeditor.js"></script>--> | ||||
| <!--<script src="/node_modules/ckeditor4-vue/dist/ckeditor.js"></script>--> | ||||
| <!--<script src="https://cdn.ckeditor.com/4.19.1/standard-all/ckeditor.js"></script>--> | ||||
| <script> | ||||
| // import { MyCustomUploadAdapterPlugin } from "@/components/richText/customUploadAdapter"; | ||||
| import { getToken } from '@/utils/auth' | ||||
| export default { | ||||
|   name: 'ckEditor4', | ||||
|   model: { | ||||
|     prop: 'content', | ||||
|     event: 'change' | ||||
|   }, | ||||
|   props: ['modelValue', 'content'], | ||||
|   emits: ['update:modelValue'], | ||||
|   data() { | ||||
|     return { | ||||
|       img_url:'', | ||||
|       events: [], | ||||
|       // editorUrl: "https://xxx/ckeditor/ckeditor.js", | ||||
|       editorConfig: { | ||||
|         extraPlugins: 'uploadimage,image2', | ||||
|         uploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile?command=QuickUpload&type=Files&responseType=json', | ||||
|         filebrowserBrowseUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile', | ||||
|         filebrowserImageBrowseUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile?type=Images', | ||||
|         filebrowserUploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile?command=QuickUpload&type=Files', | ||||
|         filebrowserImageUploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile', | ||||
|         imageUploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile', | ||||
|  | ||||
|         fileTools_requestHeaders: { | ||||
|           'Authorization': 'Bearer ' + getToken() | ||||
|         }, | ||||
|         image2_alignClasses: ['image-align-left', 'image-align-center', 'image-align-right'], | ||||
|         image2_disableResizer: true, | ||||
|         removeButtons: 'PasteFromWord' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     editorData: { | ||||
|       get() { | ||||
|         return this.modelValue | ||||
|       }, | ||||
|       set(value) { | ||||
|         console.log(value) | ||||
|         this.$emit('update:modelValue', value) | ||||
|       } | ||||
|     }, | ||||
|     editorData2: { | ||||
|       get() { | ||||
|         return this.content | ||||
|  | ||||
|       }, | ||||
|       set(value) { | ||||
|         this.$emit('change', value) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     // editorData(val1) { | ||||
|     //   console.log(val1) | ||||
|     // } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getScript() | ||||
|   }, | ||||
|   methods: { | ||||
|     getScript() { | ||||
|       const script = document.createElement('script') | ||||
|       script.type = 'text/javascript' | ||||
|       script.src = '/node_modules/ckeditor4/ckeditor.js' | ||||
|       document.getElementsByTagName('head')[0].appendChild(script) | ||||
|     }, | ||||
|     logEvent: function(eventName, event) { | ||||
|       const _this = this | ||||
|       // console.log(event) | ||||
|       // 上传请求 | ||||
|       event.on( 'fileUploadRequest', async evt => { | ||||
|         console.log(evt) | ||||
|         var fileLoader = evt.data.fileLoader; | ||||
|         // let formData = new FormData(); | ||||
|         // let xhr = fileLoader.xhr; | ||||
|         // xhr.setRequestHeader( 'Authorization', 'Bearer ' + getToken() ); | ||||
|         // xhr.open( 'POST', fileLoader.uploadUrl, true ); | ||||
|         // formData.append( 'multipartFile', fileLoader.file); | ||||
|         // fileLoader.xhr.send( formData ); | ||||
|  | ||||
|  | ||||
|         // 测试 | ||||
|           const xhr_ = new XMLHttpRequest() | ||||
|           xhr_.onreadystatechange=function() | ||||
|           { | ||||
|               if (xhr_.readyState==4 && xhr_.status==200) | ||||
|               { | ||||
|                 // console.log(xhr_) | ||||
|                 _this.img_url = xhr_.response.data.full_path | ||||
|                 // var data = evt.data; | ||||
|                 // data.url = res_url | ||||
|                 // 用官方的方法进行访问 | ||||
|                 let xhr = fileLoader.xhr; | ||||
|                 xhr.open( 'POST', fileLoader.uploadUrl, true ); | ||||
|                 xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) | ||||
|                 let formData = new FormData(); | ||||
|                 formData.append( 'multipartFile', fileLoader.file); | ||||
|                 fileLoader.xhr.send( formData ); | ||||
|               } | ||||
|           } | ||||
|           xhr_.open('POST', fileLoader.uploadUrl, true) | ||||
|           xhr_.setRequestHeader('Authorization', 'Bearer ' + getToken()) | ||||
|           xhr_.responseType = 'json' | ||||
|  | ||||
|           const data = new FormData(); | ||||
|           // 上传参数就根据后端的处理而设置了 | ||||
|           data.append( 'file', fileLoader.file ); | ||||
|           xhr_.send(data); | ||||
|  | ||||
|         // 测试结束 | ||||
|  | ||||
|         // Prevented the default behavior. | ||||
|         evt.stop() | ||||
|       }) | ||||
|       // 回调 | ||||
|       event.on( 'fileUploadResponse', async evt => { | ||||
|         console.log(evt) | ||||
|         evt.stop(); | ||||
|         evt.data.url = _this.img_url | ||||
|         // var data = evt.data; | ||||
|         // let xhr = data.fileLoader.xhr; | ||||
|         // let response = xhr.responseText; | ||||
|         // let imgUrl = JSON.parse(response).data; | ||||
|         // if(!imgUrl){ | ||||
|         //     data.message = imgUrl   // 这是失败alert提示信息 | ||||
|         //     evt.cancel(); | ||||
|         // }else{ | ||||
|         //     data.url = imgUrl   // 返回到“图像信息”那里的URL框里面 | ||||
|         // } | ||||
|       }) | ||||
|       // if (this.events.length > 19) { | ||||
|       //   this.events.pop() | ||||
|       // } | ||||
|       // | ||||
|       // const eventData = { | ||||
|       //   name: eventName, | ||||
|       //   timestamp: this.getCurrentTimestamp() | ||||
|       // } | ||||
|       // | ||||
|       // this.events.unshift(eventData) | ||||
|  | ||||
|       // console.log(eventData.timestamp, eventData.name, event) | ||||
|     }, | ||||
|  | ||||
|     getCurrentTimestamp: function() { | ||||
|       return new Intl.DateTimeFormat('en', { | ||||
|         hour12: false, | ||||
|         hour: '2-digit', | ||||
|         minute: '2-digit', | ||||
|         second: '2-digit' | ||||
|       }).format(new Date()) | ||||
|     }, | ||||
|  | ||||
|     clearEventsLog: function() { | ||||
|       this.events = [] | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <style> | ||||
| .ck-editor__main{ | ||||
|   max-height: 350px; | ||||
|   overflow: scroll; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										53
									
								
								src/components/richText/ckEditor5.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/components/richText/ckEditor5.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| <template> | ||||
|     <div id="editor-box"> | ||||
|         <ckeditor :editor="editor" v-model="value" :config="editorConfig"  @ready="logEvent('ready', $event)"></ckeditor> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script > | ||||
|     // import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; | ||||
|     import ClassicEditor from 'axl-editor'; | ||||
|     import { MyCustomUploadAdapterPlugin } from '@/components/richText/customUploadAdapter' | ||||
|     // import {ref,onMounted } from 'vue' | ||||
|     export default { | ||||
|         name: 'editor-box', | ||||
|         props: ['modelValue','content'], | ||||
|         emits: ['update:modelValue'], | ||||
|         data() { | ||||
|             return { | ||||
|                 editor: ClassicEditor, | ||||
|                 editorData: '<p>Content of the editor.</p>', | ||||
|                 editorConfig: { | ||||
|                     // The configuration of the editor. | ||||
|                   // uploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile?command=QuickUpload&type=Files&responseType=json', | ||||
|                   // simpleUpload:{ | ||||
|                   //     uploadUrl: 'https://apiwx.twzxjy.com/api/v1/public/uploadFile?command=QuickUpload&type=Files&responseType=json', | ||||
|                   // } | ||||
|                   extraPlugins:[MyCustomUploadAdapterPlugin] | ||||
|                 } | ||||
|             }; | ||||
|         }, | ||||
|        computed: { | ||||
|           value: { | ||||
|             get() { | ||||
|               return this.modelValue | ||||
|             }, | ||||
|             set(value) { | ||||
|               this.$emit('update:modelValue', value) | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         methods:{ | ||||
|           logEvent(eventName, event){ | ||||
|             const _this = this | ||||
|             console.log(eventName) | ||||
|             // event.on( 'fileUploadRequest', async evt => { | ||||
|             //   console.log(evt) | ||||
|             // }) | ||||
|           }, | ||||
|         } | ||||
|     } | ||||
|     // const name = ref(ClassicEditor) | ||||
|     // const editorData = ref('<p>Content of the editor.</p>') | ||||
|     // const editorConfig = ref({}) | ||||
| </script> | ||||
							
								
								
									
										146
									
								
								src/components/richText/customUploadAdapter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/components/richText/customUploadAdapter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| /** | ||||
|  * 图片压缩处理,转换为等比的高800px的图像 | ||||
|  * @params file File类型的图片文件 | ||||
|  * @return Promise<file> 返回一个promise,值为一个压缩后的图片文件 | ||||
|  */ | ||||
| import { getToken } from '@/utils/auth' | ||||
| function imgCutdown(file) { | ||||
|   return new Promise((resolve) => { | ||||
|     const render = new FileReader(); | ||||
|     render.onload = function(progress) { | ||||
|       const target = progress.target; | ||||
|       if (!target) return; | ||||
|  | ||||
|       const reuslt = target.result; | ||||
|       if (typeof reuslt === "string") { | ||||
|         const image = new Image(); | ||||
|         image.src = reuslt; | ||||
|         image.onload = function() { | ||||
|           const h = 800; | ||||
|           const rate = h / image.height; | ||||
|           const canvas = document.createElement("canvas"); | ||||
|           const context = canvas.getContext("2d"); | ||||
|           if (!context) return; | ||||
|           canvas.width = image.width * rate; | ||||
|           canvas.height = h; | ||||
|           context.drawImage( | ||||
|             image, | ||||
|             0, | ||||
|             0, | ||||
|             image.width, | ||||
|             image.height, | ||||
|             0, | ||||
|             0, | ||||
|             canvas.width, | ||||
|             canvas.height | ||||
|           ); | ||||
|           canvas.toBlob( | ||||
|             function(b) { | ||||
|               const file = new File([b], "pic", { | ||||
|                 type: "image/jpeg", | ||||
|               }); | ||||
|               resolve(file); | ||||
|             }, | ||||
|             "image/jpeg", | ||||
|             0.5 | ||||
|           ); | ||||
|         }; | ||||
|       } | ||||
|     }; | ||||
|     render.readAsDataURL(file); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| // 上传图片的地址,我这里使用的是vue的环境变量,也可以直接写死 | ||||
| // const uploadUrl = `${process.env.VUE_APP_HOST}image/upload.do`; | ||||
| // const uploadUrl = `https://192.168.1.23:8000/api/v1/public/uploadFile` | ||||
| const uploadUrl = `https://apiwx.twzxjy.com/api/v1/public/uploadFile` | ||||
|  | ||||
| // 自定义适配器类 | ||||
| class MyUploadAdapter { | ||||
|   constructor(loader) { | ||||
|     this.loader = loader | ||||
|   } | ||||
|  | ||||
|   upload() { | ||||
|     return this.loader.file.then( | ||||
|       (file) => | ||||
|         new Promise((resolve, reject) => { | ||||
|           this._initRequest(); | ||||
|           this._initListeners(resolve, reject, file); | ||||
|           this._sendRequest(file); | ||||
|         }) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   abort() { | ||||
|     if (this.xhr) { | ||||
|       this.xhr.abort(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   _initRequest() { | ||||
|     const xhr = (this.xhr = new XMLHttpRequest()) | ||||
|  | ||||
|     xhr.open('POST', uploadUrl, true) | ||||
|     xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) | ||||
|     xhr.responseType = 'json' | ||||
|   } | ||||
|  | ||||
|   _initListeners(resolve, reject, file) { | ||||
|     const xhr = this.xhr | ||||
|     const loader = this.loader | ||||
|     const genericErrorText = `Couldn't upload file: ${file.name}.` | ||||
|  | ||||
|     xhr.addEventListener('error', () => reject(genericErrorText)) | ||||
|     xhr.addEventListener('abort', () => reject()) | ||||
|     xhr.addEventListener('load', () => { | ||||
|       const response = xhr.response | ||||
|  | ||||
|       if (!response || response.error) { | ||||
|         return reject( | ||||
|           response && response.error ? response.error.message : genericErrorText | ||||
|         ) | ||||
|       } | ||||
|       console.log(response) | ||||
|  | ||||
|       resolve({ | ||||
|         default: response.data.path, | ||||
|       }) | ||||
|     }) | ||||
|  | ||||
|     if (xhr.upload) { | ||||
|       xhr.upload.addEventListener('progress', (evt) => { | ||||
|         if (evt.lengthComputable) { | ||||
|           loader.uploadTotal = evt.total | ||||
|           loader.uploaded = evt.loaded | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async _sendRequest(file) { | ||||
|     const data = new FormData(); | ||||
| 	// 判断如果上传图片大于1M,则进行压缩处理 | ||||
|     // if (file.size > 1000 * 1024) { | ||||
|     //   file = await imgCutdown(file); | ||||
|     // } | ||||
|  | ||||
| 	// 上传参数就根据后端的处理而设置了 | ||||
|     // data.append("file", file); | ||||
|     // data.append("name", file.name); | ||||
|     // data.append("group", "pic"); | ||||
|     data.append( 'file', file ); | ||||
|     this.xhr.send(data); | ||||
|   } | ||||
| } | ||||
|  | ||||
| function MyCustomUploadAdapterPlugin(editor) { | ||||
|   editor.plugins.get("FileRepository").createUploadAdapter = (loader) => { | ||||
|     return new MyUploadAdapter(loader); | ||||
|   }; | ||||
| } | ||||
| export { | ||||
|     MyUploadAdapter, | ||||
|     MyCustomUploadAdapterPlugin | ||||
| } | ||||
| @@ -3,56 +3,15 @@ | ||||
|  */ | ||||
|  | ||||
| const config = { | ||||
|     appName: 'Gin-Vue-Admin', | ||||
|     appLogo: 'https://www.gin-vue-admin.com/img/logo.png', | ||||
|     appName: '嚯奖学吧', | ||||
|     appLogo: 'src/assets/logo.png', | ||||
|     showViteLogo: true | ||||
| } | ||||
|  | ||||
| export const viteLogo = (env) => { | ||||
|     if (config.showViteLogo) { | ||||
|         const chalk = require('chalk') | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 欢迎使用Gin-Vue-Admin,开源地址:https://github.com/flipped-aurora/gin-vue-admin` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 当前版本:v2.5.5` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 加群方式:微信:shouzi_1994 QQ群:622360840` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> GVA讨论社区:https://support.qq.com/products/371961` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 插件市场:https://plugin.gin-vue-admin.com` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 默认自动化文档地址:http://127.0.0.1:${env.VITE_SERVER_PORT}/swagger/index.html` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 默认前端文件运行地址:http://127.0.0.1:${env.VITE_CLI_PORT}` | ||||
|             ) | ||||
|         ) | ||||
|         console.log( | ||||
|             chalk.green( | ||||
|                 `> 如果项目让您获得了收益,希望您能请团队喝杯可乐:https://www.gin-vue-admin.com/coffee/index.html` | ||||
|             ) | ||||
|         ) | ||||
|         console.log('\n') | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default config | ||||
| export default config | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import auth from '@/directive/auth' | ||||
| import { store } from '@/pinia' | ||||
| import App from './App.vue' | ||||
| import { initDom } from './utils/positionToCode' | ||||
| import CKEditor from '@ckeditor/ckeditor5-vue' | ||||
| initDom() | ||||
| /** | ||||
|  * @description 导入加载进度条,防止首屏加载时间过长,用户等待 | ||||
| @@ -31,6 +32,7 @@ const app = createApp(App) | ||||
| app.config.productionTip = false | ||||
|  | ||||
| app | ||||
|   .use(CKEditor) | ||||
|   .use(run) | ||||
|   .use(store) | ||||
|   .use(auth) | ||||
|   | ||||
| @@ -16,7 +16,7 @@ $icon-arrow-size-aside:12px; | ||||
| $width-submenu-aside:55px; | ||||
| $height-aside-tilte:60px; | ||||
| $height-aside-img:30px; | ||||
| $width-aside-img:30px; | ||||
| $width-aside-img:50px; | ||||
| // header | ||||
| $height-header: 60px; | ||||
| // nav-scroll | ||||
| @@ -33,4 +33,4 @@ $color-table-thead:#262626; | ||||
| $height-car:68px; | ||||
| // mobile | ||||
| $padding-xs: 5px; | ||||
| $margin-xs: 5px; | ||||
| $margin-xs: 5px; | ||||
|   | ||||
| @@ -565,7 +565,7 @@ li { | ||||
|             justify-content: center; | ||||
|             .logoimg { | ||||
|                 width: $width-aside-img; | ||||
|                 height: $height-aside-img; | ||||
|                 //height: $height-aside-img; | ||||
|                 background: #fff; | ||||
|                 border-radius: 50%; | ||||
|                 padding: 3px; | ||||
| @@ -1223,4 +1223,4 @@ $mainHight: 100vh; | ||||
|  | ||||
| .justify-content-flex-end { | ||||
|     justify-content: flex-end; | ||||
| } | ||||
| } | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/utils/auth.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/utils/auth.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| import Cookies from 'js-cookie' | ||||
|  | ||||
| const TokenKey = 'Admin-Token' | ||||
|  | ||||
| export function getToken() { | ||||
|   return Cookies.get(TokenKey) | ||||
| } | ||||
|  | ||||
| export function setToken(token) { | ||||
|   return Cookies.set(TokenKey, token) | ||||
| } | ||||
|  | ||||
| export function removeToken() { | ||||
|   return Cookies.remove(TokenKey) | ||||
| } | ||||
							
								
								
									
										206
									
								
								src/utils/city.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/utils/city.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| [ | ||||
|     { | ||||
|         "ProID": 1, | ||||
|         "name": "北京市", | ||||
|         "ProSort": 1, | ||||
|         "ProRemark": "直辖市" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 2, | ||||
|         "name": "天津市", | ||||
|         "ProSort": 2, | ||||
|         "ProRemark": "直辖市" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 3, | ||||
|         "name": "河北省", | ||||
|         "ProSort": 5, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 4, | ||||
|         "name": "山西省", | ||||
|         "ProSort": 6, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 5, | ||||
|         "name": "内蒙古自治区", | ||||
|         "ProSort": 32, | ||||
|         "ProRemark": "自治区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 6, | ||||
|         "name": "辽宁省", | ||||
|         "ProSort": 8, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 7, | ||||
|         "name": "吉林省", | ||||
|         "ProSort": 9, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 8, | ||||
|         "name": "黑龙江省", | ||||
|         "ProSort": 10, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 9, | ||||
|         "name": "上海市", | ||||
|         "ProSort": 3, | ||||
|         "ProRemark": "直辖市" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 10, | ||||
|         "name": "江苏省", | ||||
|         "ProSort": 11, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 11, | ||||
|         "name": "浙江省", | ||||
|         "ProSort": 12, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 12, | ||||
|         "name": "安徽省", | ||||
|         "ProSort": 13, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 13, | ||||
|         "name": "福建省", | ||||
|         "ProSort": 14, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 14, | ||||
|         "name": "江西省", | ||||
|         "ProSort": 15, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 15, | ||||
|         "name": "山东省", | ||||
|         "ProSort": 16, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 16, | ||||
|         "name": "河南省", | ||||
|         "ProSort": 17, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 17, | ||||
|         "name": "湖北省", | ||||
|         "ProSort": 18, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 18, | ||||
|         "name": "湖南省", | ||||
|         "ProSort": 19, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 19, | ||||
|         "name": "广东省", | ||||
|         "ProSort": 20, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 20, | ||||
|         "name": "海南省", | ||||
|         "ProSort": 24, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 21, | ||||
|         "name": "广西壮族自治区", | ||||
|         "ProSort": 28, | ||||
|         "ProRemark": "自治区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 22, | ||||
|         "name": "甘肃省", | ||||
|         "ProSort": 21, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 23, | ||||
|         "name": "陕西省", | ||||
|         "ProSort": 27, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 24, | ||||
|         "name": "新疆维吾尔自治区", | ||||
|         "ProSort": 31, | ||||
|         "ProRemark": "自治区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 25, | ||||
|         "name": "青海省", | ||||
|         "ProSort": 26, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 26, | ||||
|         "name": "宁夏回族自治区", | ||||
|         "ProSort": 30, | ||||
|         "ProRemark": "自治区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 27, | ||||
|         "name": "重庆市", | ||||
|         "ProSort": 4, | ||||
|         "ProRemark": "直辖市" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 28, | ||||
|         "name": "四川省", | ||||
|         "ProSort": 22, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 29, | ||||
|         "name": "贵州省", | ||||
|         "ProSort": 23, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 30, | ||||
|         "name": "云南省", | ||||
|         "ProSort": 25, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 31, | ||||
|         "name": "西藏自治区", | ||||
|         "ProSort": 29, | ||||
|         "ProRemark": "自治区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 32, | ||||
|         "name": "台湾省", | ||||
|         "ProSort": 7, | ||||
|         "ProRemark": "省份" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 33, | ||||
|         "name": "澳门特别行政区", | ||||
|         "ProSort": 33, | ||||
|         "ProRemark": "特别行政区" | ||||
|     }, | ||||
|     { | ||||
|         "ProID": 34, | ||||
|         "name": "香港特别行政区", | ||||
|         "ProSort": 34, | ||||
|         "ProRemark": "特别行政区" | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										123
									
								
								src/utils/custom.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/utils/custom.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| import cityList from '@/utils/city.json'; | ||||
| const custom = { | ||||
|   getStdSubject: (data) => { // 获取标准类型格式 | ||||
|     let arr= [] | ||||
|     for(let item of data) { | ||||
|       // item.label = item.name | ||||
|       if(item.children){ | ||||
|         arr.push(...custom.getStdSubject(item.children)) | ||||
|       } | ||||
|       else{ | ||||
|         arr.push(item) | ||||
|       } | ||||
|     } | ||||
|     return arr | ||||
|   }, | ||||
|   getExercisesTypeList() { | ||||
|     return [ | ||||
|       { | ||||
|         label: '单选题', | ||||
|         value2:'single', | ||||
|         value:1 | ||||
|       }, | ||||
|       { | ||||
|         label: '多选题', | ||||
|         value2:'mutil', | ||||
|         value:2 | ||||
|       }, | ||||
|       { | ||||
|         label: '判断题', | ||||
|         value2:'judge', | ||||
|         value:3 | ||||
|       }, | ||||
|       { | ||||
|         label: '填空题', | ||||
|         value2:'application', | ||||
|         value:4 | ||||
|       }, | ||||
|       { | ||||
|         label: '选填题', | ||||
|         value2:'application', | ||||
|         value:5 | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   getExercisesTypeName(type) { | ||||
|     let name = '' | ||||
|     switch (type){ | ||||
|       case 1: | ||||
|         name = '单选题'; | ||||
|         break; | ||||
|       case 2: | ||||
|         name = '多选题'; | ||||
|         break; | ||||
|       case 3: | ||||
|         name = '判断题'; | ||||
|         break; | ||||
|       case 4: | ||||
|         name = '填空题'; | ||||
|         break; | ||||
|       case 5: | ||||
|         name = '选填题'; | ||||
|         break; | ||||
|     } | ||||
|     return name | ||||
|   }, | ||||
|   getProvinceName(province) { | ||||
|     if(province < 0 || !province) return '' | ||||
|     return cityList[province].name | ||||
|   }, | ||||
|   getExamGroupType() { | ||||
|     return [ | ||||
|       { | ||||
|         name:'1', | ||||
|         value:1 | ||||
|       }, | ||||
|       { | ||||
|         name:'10', | ||||
|         value:10 | ||||
|       },{ | ||||
|         name:'100', | ||||
|         value:100 | ||||
|       },{ | ||||
|         name:'1000', | ||||
|         value:1000 | ||||
|       }, | ||||
|       { | ||||
|         name:'1万', | ||||
|         value:10000 | ||||
|       }, | ||||
|       { | ||||
|         name:'10万', | ||||
|         value:100000 | ||||
|       }, | ||||
|       { | ||||
|         name:'100万', | ||||
|         value:1000000 | ||||
|       }, | ||||
|       { | ||||
|         name:'1000万', | ||||
|         value:10000000 | ||||
|       }, | ||||
|     ] | ||||
|   }, | ||||
|   timestampToDate(stamp) { // 时间戳转日期 | ||||
|       var time = new Date(stamp); | ||||
|       var y = time.getFullYear(); | ||||
|       var m = time.getMonth()+1; | ||||
|       var d = time.getDate(); | ||||
|       const date = `${y}-${m}-${d}` | ||||
|       // console.log(date) | ||||
|     return date | ||||
|   }, | ||||
|   getSTdPerson(num) { | ||||
|     const flag = 10000 | ||||
|     if(num<flag) { | ||||
|       return num | ||||
|     } | ||||
|     else{ | ||||
|       return num/flag+'万' | ||||
|     } | ||||
|   } | ||||
| } | ||||
| export default custom | ||||
							
								
								
									
										431
									
								
								src/utils/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										431
									
								
								src/utils/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,431 @@ | ||||
| /** | ||||
|  * Created by PanJiaChen on 16/11/18. | ||||
|  */ | ||||
|  | ||||
| import OSS from 'ali-oss' | ||||
|  | ||||
| /** | ||||
|  * Parse the time to string | ||||
|  * @param {(Object|string|number)} time | ||||
|  * @param {string} cFormat | ||||
|  * @returns {string | null} | ||||
|  */ | ||||
| export function parseTime(time, cFormat) { | ||||
|   if (arguments.length === 0) { | ||||
|     return null | ||||
|   } | ||||
|  | ||||
|   const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' | ||||
|   let date | ||||
|   if (typeof time === 'object') { | ||||
|     date = time | ||||
|   } else { | ||||
|     if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { | ||||
|       time = parseInt(time) | ||||
|     } | ||||
|     if ((typeof time === 'number') && (time.toString().length === 10)) { | ||||
|       time = time * 1000 | ||||
|     } | ||||
|     date = new Date(time) | ||||
|   } | ||||
|   const formatObj = { | ||||
|     y: date.getFullYear(), | ||||
|     m: date.getMonth() + 1, | ||||
|     d: date.getDate(), | ||||
|     h: date.getHours(), | ||||
|     i: date.getMinutes(), | ||||
|     s: date.getSeconds(), | ||||
|     a: date.getDay() | ||||
|   } | ||||
|   const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { | ||||
|     const value = formatObj[key] | ||||
|     // Note: getDay() returns 0 on Sunday | ||||
|     if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } | ||||
|     return value.toString().padStart(2, '0') | ||||
|   }) | ||||
|   if (time_str.indexOf('01-01-01') > -1) { | ||||
|     return '-' | ||||
|   } | ||||
|   return time_str | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {number} time | ||||
|  * @param {string} option | ||||
|  * @returns {string} | ||||
|  */ | ||||
| export function formatTime(time, option) { | ||||
|   if (('' + time).length === 10) { | ||||
|     time = parseInt(time) * 1000 | ||||
|   } else { | ||||
|     time = +time | ||||
|   } | ||||
|   const d = new Date(time) | ||||
|   const now = Date.now() | ||||
|  | ||||
|   const diff = (now - d) / 1000 | ||||
|  | ||||
|   if (diff < 30) { | ||||
|     return '刚刚' | ||||
|   } else if (diff < 3600) { | ||||
|     // less 1 hour | ||||
|     return Math.ceil(diff / 60) + '分钟前' | ||||
|   } else if (diff < 3600 * 24) { | ||||
|     return Math.ceil(diff / 3600) + '小时前' | ||||
|   } else if (diff < 3600 * 24 * 2) { | ||||
|     return '1天前' | ||||
|   } | ||||
|   if (option) { | ||||
|     return parseTime(time, option) | ||||
|   } else { | ||||
|     return ( | ||||
|       d.getMonth() + | ||||
|       1 + | ||||
|       '月' + | ||||
|       d.getDate() + | ||||
|       '日' + | ||||
|       d.getHours() + | ||||
|       '时' + | ||||
|       d.getMinutes() + | ||||
|       '分' | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {string} url | ||||
|  * @returns {Object} | ||||
|  */ | ||||
| export function getQueryObject(url) { | ||||
|   url = url == null ? window.location.href : url | ||||
|   const search = url.substring(url.lastIndexOf('?') + 1) | ||||
|   const obj = {} | ||||
|   const reg = /([^?&=]+)=([^?&=]*)/g | ||||
|   search.replace(reg, (rs, $1, $2) => { | ||||
|     const name = decodeURIComponent($1) | ||||
|     let val = decodeURIComponent($2) | ||||
|     val = String(val) | ||||
|     obj[name] = val | ||||
|     return rs | ||||
|   }) | ||||
|   return obj | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {string} input value | ||||
|  * @returns {number} output value | ||||
|  */ | ||||
| export function byteLength(str) { | ||||
|   // returns the byte length of an utf8 string | ||||
|   let s = str.length | ||||
|   for (var i = str.length - 1; i >= 0; i--) { | ||||
|     const code = str.charCodeAt(i) | ||||
|     if (code > 0x7f && code <= 0x7ff) s++ | ||||
|     else if (code > 0x7ff && code <= 0xffff) s += 2 | ||||
|     if (code >= 0xDC00 && code <= 0xDFFF) i-- | ||||
|   } | ||||
|   return s | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {Array} actual | ||||
|  * @returns {Array} | ||||
|  */ | ||||
| export function cleanArray(actual) { | ||||
|   const newArray = [] | ||||
|   for (let i = 0; i < actual.length; i++) { | ||||
|     if (actual[i]) { | ||||
|       newArray.push(actual[i]) | ||||
|     } | ||||
|   } | ||||
|   return newArray | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {Object} json | ||||
|  * @returns {Array} | ||||
|  */ | ||||
| export function param(json) { | ||||
|   if (!json) return '' | ||||
|   return cleanArray( | ||||
|     Object.keys(json).map(key => { | ||||
|       if (json[key] === undefined) return '' | ||||
|       return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) | ||||
|     }) | ||||
|   ).join('&') | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {string} url | ||||
|  * @returns {Object} | ||||
|  */ | ||||
| export function param2Obj(url) { | ||||
|   const search = url.split('?')[1] | ||||
|   if (!search) { | ||||
|     return {} | ||||
|   } | ||||
|   return JSON.parse( | ||||
|     '{"' + | ||||
|     decodeURIComponent(search) | ||||
|       .replace(/"/g, '\\"') | ||||
|       .replace(/&/g, '","') | ||||
|       .replace(/=/g, '":"') | ||||
|       .replace(/\+/g, ' ') + | ||||
|     '"}' | ||||
|   ) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {string} val | ||||
|  * @returns {string} | ||||
|  */ | ||||
| export function html2Text(val) { | ||||
|   const div = document.createElement('div') | ||||
|   div.innerHTML = val | ||||
|   return div.textContent || div.innerText | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Merges two objects, giving the last one precedence | ||||
|  * @param {Object} target | ||||
|  * @param {(Object|Array)} source | ||||
|  * @returns {Object} | ||||
|  */ | ||||
| export function objectMerge(target, source) { | ||||
|   if (typeof target !== 'object') { | ||||
|     target = {} | ||||
|   } | ||||
|   if (Array.isArray(source)) { | ||||
|     return source.slice() | ||||
|   } | ||||
|   Object.keys(source).forEach(property => { | ||||
|     const sourceProperty = source[property] | ||||
|     if (typeof sourceProperty === 'object') { | ||||
|       target[property] = objectMerge(target[property], sourceProperty) | ||||
|     } else { | ||||
|       target[property] = sourceProperty | ||||
|     } | ||||
|   }) | ||||
|   return target | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {HTMLElement} element | ||||
|  * @param {string} className | ||||
|  */ | ||||
| export function toggleClass(element, className) { | ||||
|   if (!element || !className) { | ||||
|     return | ||||
|   } | ||||
|   let classString = element.className | ||||
|   const nameIndex = classString.indexOf(className) | ||||
|   if (nameIndex === -1) { | ||||
|     classString += '' + className | ||||
|   } else { | ||||
|     classString = | ||||
|       classString.substr(0, nameIndex) + | ||||
|       classString.substr(nameIndex + className.length) | ||||
|   } | ||||
|   element.className = classString | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {string} type | ||||
|  * @returns {Date} | ||||
|  */ | ||||
| export function getTime(type) { | ||||
|   if (type === 'start') { | ||||
|     return new Date().getTime() - 3600 * 1000 * 24 * 90 | ||||
|   } else { | ||||
|     return new Date(new Date().toDateString()) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {Function} func | ||||
|  * @param {number} wait | ||||
|  * @param {boolean} immediate | ||||
|  * @return {*} | ||||
|  */ | ||||
| export function debounce(func, wait, immediate) { | ||||
|   let timeout, args, context, timestamp, result | ||||
|  | ||||
|   const later = function() { | ||||
|     // 据上一次触发时间间隔 | ||||
|     const last = +new Date() - timestamp | ||||
|  | ||||
|     // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait | ||||
|     if (last < wait && last > 0) { | ||||
|       timeout = setTimeout(later, wait - last) | ||||
|     } else { | ||||
|       timeout = null | ||||
|       // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 | ||||
|       if (!immediate) { | ||||
|         result = func.apply(context, args) | ||||
|         if (!timeout) context = args = null | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return function(...args) { | ||||
|     context = this | ||||
|     timestamp = +new Date() | ||||
|     const callNow = immediate && !timeout | ||||
|     // 如果延时不存在,重新设定延时 | ||||
|     if (!timeout) timeout = setTimeout(later, wait) | ||||
|     if (callNow) { | ||||
|       result = func.apply(context, args) | ||||
|       context = args = null | ||||
|     } | ||||
|  | ||||
|     return result | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This is just a simple version of deep copy | ||||
|  * Has a lot of edge cases bug | ||||
|  * If you want to use a perfect deep copy, use lodash's _.cloneDeep | ||||
|  * @param {Object} source | ||||
|  * @returns {Object} | ||||
|  */ | ||||
| export function deepClone(source) { | ||||
|   if (!source && typeof source !== 'object') { | ||||
|     throw new Error('error arguments', 'deepClone') | ||||
|   } | ||||
|   const targetObj = source.constructor === Array ? [] : {} | ||||
|   Object.keys(source).forEach(keys => { | ||||
|     if (source[keys] && typeof source[keys] === 'object') { | ||||
|       targetObj[keys] = deepClone(source[keys]) | ||||
|     } else { | ||||
|       targetObj[keys] = source[keys] | ||||
|     } | ||||
|   }) | ||||
|   return targetObj | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {Array} arr | ||||
|  * @returns {Array} | ||||
|  */ | ||||
| export function uniqueArr(arr) { | ||||
|   return Array.from(new Set(arr)) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @returns {string} | ||||
|  */ | ||||
| export function createUniqueString() { | ||||
|   const timestamp = +new Date() + '' | ||||
|   const randomNum = parseInt((1 + Math.random()) * 65536) + '' | ||||
|   return (+(randomNum + timestamp)).toString(32) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if an element has a class | ||||
|  * @param {HTMLElement} elm | ||||
|  * @param {string} cls | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| export function hasClass(ele, cls) { | ||||
|   return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Add class to element | ||||
|  * @param {HTMLElement} elm | ||||
|  * @param {string} cls | ||||
|  */ | ||||
| export function addClass(ele, cls) { | ||||
|   if (!hasClass(ele, cls)) ele.className += ' ' + cls | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Remove class from element | ||||
|  * @param {HTMLElement} elm | ||||
|  * @param {string} cls | ||||
|  */ | ||||
| export function removeClass(ele, cls) { | ||||
|   if (hasClass(ele, cls)) { | ||||
|     const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') | ||||
|     ele.className = ele.className.replace(reg, ' ') | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param {Array} filterVal | ||||
|  * @param {Object} jsonData | ||||
|  * @returns {string} | ||||
|  */ | ||||
| export function formatJson(filterVal, jsonData) { | ||||
|   return jsonData.map(v => filterVal.map(j => { | ||||
|     if (j === 'timestamp') { | ||||
|       return parseTime(v[j]) | ||||
|     } else { | ||||
|       return v[j] | ||||
|     } | ||||
|   })) | ||||
| } | ||||
|  | ||||
| // 格式化价格 | ||||
| export function prices(n, type = 'except', per = 100) { | ||||
|   if (!n) return '0.00' | ||||
|   return type === 'multiply' ? (n * per) : `${n / per}`.includes('.') ? (n / per) : `${n / per}.00` | ||||
| } | ||||
|  | ||||
| export function beforeUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 0.5 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     this.$message.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     this.$message.error('上传头像图片大小不能超过 500k!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
|  | ||||
| export function formateCardNumber(str) { | ||||
|   if (!str) return '-' | ||||
|   if (str.length < 8) { | ||||
|     return str | ||||
|   } | ||||
|   const leftString = str.substring(0, 4) | ||||
|   const rightString = str.substring(str.length - 4) | ||||
|   return `${leftString}***${rightString}` | ||||
| } | ||||
|  | ||||
| export const formatNumber = (str, decimals = 2) => `${parseFloat(str.toFixed(decimals)).toLocaleString()}` | ||||
|  | ||||
| // 拍平数组 | ||||
| export function flatten(arr) { | ||||
|   if (!arr) return [] | ||||
|   let arr1 = [] | ||||
|   arr.forEach((val) => { | ||||
|     arr1.push(val) | ||||
|     if (val?.children) { | ||||
|       arr1 = arr1.concat(flatten(val.children)) | ||||
|     } | ||||
|   }) | ||||
|   return arr1 | ||||
| } | ||||
|  | ||||
| export function clients() { | ||||
|   let client = {} | ||||
|   client = new OSS({ | ||||
|     endpoint: 'oss-cn-chengdu.aliyuncs.com', | ||||
|     accessKeyId: 'LTAI5tGUFScGh9qdB8j7vKo1', | ||||
|     accessKeySecret: 'XhBPsJ3fom9sE4yjTQAqwwVEw2nqac', | ||||
|     bucket: 'gwjxb', | ||||
|     timeout: 10 * 60 * 1000 | ||||
|   }) | ||||
|   return client | ||||
| } | ||||
|  | ||||
| export function getNowDate() { | ||||
|   const date = new Date() | ||||
|   const year = date.getFullYear() // 年 | ||||
|   const month = date.getMonth() + 1 // 月 | ||||
|   const day = date.getDate() | ||||
|   return `${year}/${month}/${day}` | ||||
| } | ||||
							
								
								
									
										452
									
								
								src/view/auctionManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										452
									
								
								src/view/auctionManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,452 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/integral' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   key:'', | ||||
|   status:'', | ||||
|   sort:'', | ||||
|   current_page:1 | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'报名中', | ||||
|       value:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'取消', | ||||
|       value:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'结束', | ||||
|       value:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| const auction_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getAuctionList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getAuctionList() { | ||||
|   const res = await api.getAuctionList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.list | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getAuctionList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     key:'', | ||||
|     status:'', | ||||
|     sort:'', | ||||
|     current_page:1 | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = auction_ids.value | ||||
|   const res = await api.delAucitonData({ ids:auction_ids.value }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getAuctionList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   auction_ids.value = val.map((item) => { | ||||
|       return item.id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.current_page = val | ||||
|   getAuctionList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getAuctionList() | ||||
| } | ||||
| // function viewTeacherFunc(row) { // 查看详情 | ||||
| //   router.push({name:'teacherDetail',params:{id:row.teacher_info_id}}) | ||||
| // } | ||||
| function getStateName(row) { | ||||
|   let name = '' | ||||
|   switch(row.status) { | ||||
|     case 1: | ||||
|       // 检查是否过期 | ||||
|       if(row.end_time < (Date.parse(new Date()))) { // 已过期 | ||||
|         name = '已结束'; | ||||
|       } | ||||
|       else{ | ||||
|         name = '报名中'; | ||||
|       } | ||||
|       break; | ||||
|     case 2: | ||||
|       name = '已取消'; | ||||
|       break; | ||||
|     case 0: | ||||
|       name = '已取消'; | ||||
|       break; | ||||
|     case 3: | ||||
|       name = '已结束'; | ||||
|       break; | ||||
|   } | ||||
|   return name | ||||
| } | ||||
|  | ||||
| // 新增 & 编辑相关 ================ | ||||
| const popupVisible = ref(false) | ||||
| const popupTitle = ref('') | ||||
| const auctionForm = ref({}) | ||||
| const auctionFormRules = ref({ | ||||
|   product_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }], | ||||
|   market_value:[{ required: true, message: '请输入市场价格', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式',trigger: 'blur' }], | ||||
|   in_point:[{ required: true, message: '请输入门票积分', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式' }], | ||||
|   full_member:[{ required: true, message: '请输入满员人数', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式' }], | ||||
|   end_time:[{ required: true, message: '请输入截止时间', trigger: 'blur' }], | ||||
|   begin_time:[{ required: true, message: '请输入开始时间', trigger: 'blur' }], | ||||
|   product_cover:[{ required: true, message: '请选择商品封面', trigger: 'blur' }], | ||||
| }) | ||||
| const auctionFormRef = ref(null) | ||||
| function openDialog() { | ||||
|   auctionForm.value = {} | ||||
|   popupTitle.value = '新增竞拍' | ||||
|   popupVisible.value = true | ||||
| } | ||||
| function editAuctionFunc(row) { | ||||
|   popupTitle.value = '编辑竞拍' | ||||
|   popupVisible.value = true | ||||
|   auctionForm.value = row | ||||
| } | ||||
| function delFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     console.log(1) | ||||
|     const res = await api.delAucitonData({ | ||||
|           ids:[row.id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getAuctionList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function cancelClick() { | ||||
|   popupVisible.value = false | ||||
| } | ||||
| async function confirmClick() { //提交竞拍 | ||||
|   submitForm(auctionFormRef.value) | ||||
| } | ||||
| async function submitForm(formEl) { | ||||
|   if (!formEl) return | ||||
|   await formEl.validate((valid, fields) => { | ||||
|     if (valid) { // 验证通过 | ||||
|       // console.log('submit!') | ||||
|       saveData() | ||||
|     } else { | ||||
|       // console.log('请填写完整信息!', fields) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| async function saveData() { | ||||
|   const params = { | ||||
|     ...auctionForm.value | ||||
|   } | ||||
|   let func = '' | ||||
|   if(params.id) { // 编辑 | ||||
|     func = 'editAucitonData' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func = 'addAucitonData' | ||||
|   } | ||||
|   // console.log(params);return | ||||
|   const res = await api[func](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     getAuctionList() | ||||
|     cancelClick() | ||||
|   } | ||||
| } | ||||
| function handleAvatarSuccess(res) { // 图片上传回调 | ||||
|   console.log(res) | ||||
|   auctionForm.value[file_type.value[file_type_index]] = res.data.file.url | ||||
|  | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| const file_type = ref(['product_cover','product_introduce']) | ||||
| let file_type_index = 0 | ||||
| function fileChange(index) { | ||||
|   console.log(index) | ||||
|   file_type_index = index | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="关键字"> | ||||
|           <el-input v-model="queryParams.key" placeholder="根据关键字进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!auction_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="center" label="ID"  prop="id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="商品名称" prop="product_name" /> | ||||
|         <el-table-column align="center" label="商品图片"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.product_cover" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="市场价值(元)" min-width="150" prop="market_value" /> | ||||
|         <el-table-column align="center" label="门票积分"  prop="in_point" /> | ||||
|         <el-table-column align="center" label="满员人数"  prop="full_member" /> | ||||
|         <el-table-column align="center" label="发布日期" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.timestampToDate(scope.row.begin_time)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="截止日期" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.timestampToDate(scope.row.end_time)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="已参与人数" min-width="150" prop="in_member" /> | ||||
|         <el-table-column align="center" label="最高积分" prop="most_point" /> | ||||
|         <el-table-column align="center" label="状态"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editAuctionFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="delFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.current_page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!-- 新增&编辑 窗口--> | ||||
|     <el-drawer | ||||
|       v-model="popupVisible" | ||||
|       :title="popupTitle" | ||||
|       direction="rtl" | ||||
|       size="50%" | ||||
|     > | ||||
|       <el-form ref="auctionFormRef" class="form-box" :model="auctionForm" :rules="auctionFormRules" label-width="80px"> | ||||
|         <el-form-item label="商品名称" prop="product_name"> | ||||
|           <el-input v-model="auctionForm.product_name" placeholder="请输入商品名称" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="奖品封面" prop="product_cover"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             @click="fileChange(0)" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="auctionForm.product_cover" :src="auctionForm.product_cover" class="img-container" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="市场价格"  prop="market_value"> | ||||
|           <el-input v-model.number="auctionForm.market_value" placeholder="请输入市场价格" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item prop="in_point" label="门票积分" > | ||||
|           <el-input v-model.number="auctionForm.in_point" placeholder="请输入门票积分" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item prop="full_member" label="满员人数" > | ||||
|           <el-input v-model.number="auctionForm.full_member" placeholder="请输入满员人数" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="开始日期" prop="begin_time" > | ||||
|           <el-date-picker | ||||
|             v-model="auctionForm.begin_time" | ||||
|             type="datetime" | ||||
|             placeholder="开始日期" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="截止日期" prop="end_time" > | ||||
|           <el-date-picker | ||||
|             v-model="auctionForm.end_time" | ||||
|             type="datetime" | ||||
|             placeholder="截止日期" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="奖品详情" prop="product_introduce"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             @click="fileChange(1)" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="auctionForm.product_introduce" :src="auctionForm.product_introduce" class="img-container" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="启用状态" prop="status"> | ||||
|           <el-switch v-model="auctionForm.status" :active-value="1" :inactive-value="2" active-text="启用" inactive-text="禁用" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|       </el-form> | ||||
|        <template #footer> | ||||
|           <div style="flex: auto"> | ||||
|             <el-button @click="cancelClick">取消</el-button> | ||||
|             <el-button type="primary" @click="confirmClick">确定</el-button> | ||||
|           </div> | ||||
|        </template> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .form-box{ | ||||
|     padding: 10px; | ||||
|   } | ||||
|   .img-container{ | ||||
|     width: 200px; | ||||
|     height: 150px; | ||||
|   } | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										273
									
								
								src/view/course/addCourse/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								src/view/course/addCourse/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,273 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import _ from 'lodash' | ||||
| import api from '@/api/course' | ||||
| import com_api from '@/api/common' | ||||
| import custom from '@/utils/custom' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted,provide  } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| import chapterCom from '../components/chapter.vue' | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const course_id = ref(0) | ||||
| const active = ref(0) | ||||
| const form = ref({status:1,is_boutique:-1,is_audition:-1}) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const subjectList = ref([]) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }], | ||||
|   subject: [{ required: true, message: '请选择课程科目', trigger: 'change' }], | ||||
|   price: [{ required: true, message: '请输入课程价格', trigger: 'blur' }] | ||||
| }) | ||||
| const ruleFormRef = ref(null) | ||||
| const chapter_info = ref([]) | ||||
| const current_subject = ref('') | ||||
| const isChange = ref(false) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   course_id.value = route.params.course_id || 0 | ||||
|   if(course_id.value) { | ||||
|     getCourseInfo() | ||||
|   } | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getCourseInfo() { // 获取课程信息 | ||||
|   const res = await api.getCourse({id:course_id.value}) | ||||
|   if(res.code === 0) { | ||||
|     chapter_info.value = res.data.course_ware_json | ||||
|     res.data.course.price /=100 | ||||
|     form.value = res.data.course | ||||
|   } | ||||
| } | ||||
| function stepChangeFunc(type) { | ||||
|   switch (type) { | ||||
|     case 1: // 上一步 | ||||
|       active.value -=1 | ||||
|       break; | ||||
|     case 2: // 下一步 | ||||
|         if(active.value == 0) { // 保存第一步的信息 | ||||
|           console.log(isChange.value) | ||||
|           if(isChange.value){ | ||||
|             submitForm(ruleFormRef.value) | ||||
|           } | ||||
|           else{ | ||||
|             active.value += 1 | ||||
|           } | ||||
|         } | ||||
|         else{ | ||||
|           active.value +=1 | ||||
|         } | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| const submitForm = async (formEl) => { | ||||
|   if (!formEl) return | ||||
|   await formEl.validate((valid, fields) => { | ||||
|     if (valid) { | ||||
|       console.log('submit!') | ||||
|       saveStep1() | ||||
|     } else { | ||||
|       // console.log('error submit!', fields) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| async function saveStep1() { | ||||
|   form.value.course_category_id = subjectList.value.filter((item,i) => { | ||||
|       return item.name === form.value.subject | ||||
|     })[0].id | ||||
|   form.value.price = parseFloat(form.value.price)<0?0:form.value.price | ||||
|   let params = { | ||||
|     step1:{ | ||||
|       ...form.value | ||||
|     } | ||||
|   } | ||||
|   params.step1.price = parseFloat(params.step1.price)*100 | ||||
|   let func_name ='' | ||||
|   if(course_id.value) { // 编辑 | ||||
|     params.course_id = parseInt(course_id.value) | ||||
|     func_name = 'editCourse' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func_name = 'addCourse' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     active.value += 1 | ||||
|     course_id.value = res.data | ||||
|     current_subject.value = form.value.subject | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: '操作成功!' | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await api.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| async function uploadAction(file){//图片上传 非oss | ||||
| 		    file.status = 'uploading'; | ||||
|         file.message = '上传中...'; | ||||
|         //开始上传 | ||||
|         const content = new FormData(); | ||||
|         //上传图片需要转换二进制这里要用到FormData | ||||
|         content.append("file", file.file); | ||||
|         content.append("type", '1'); | ||||
|         const res=await com_api.upload(content); | ||||
|         if(res.code==200){ | ||||
|           file.status = 'done'; | ||||
|           file.message = '上传成功'; | ||||
|           file.url = res.data.full_path; | ||||
|           this.courseForm.cover = file.url | ||||
|         } | ||||
|         else{ | ||||
|           file.status = 'failed'; | ||||
|           file.message = '上传失败'; | ||||
|         } | ||||
|         //重新赋值  img/视频 | ||||
|  | ||||
|         // var val_arr = [] | ||||
|         // for(let item of topicInfo.value[topic_index.value].answer_img_arr){ | ||||
|         //   if(item.uid==file.file.uid){ | ||||
|         //     item.url=file.url | ||||
|         //   } | ||||
|         //   val_arr.push(item.url) | ||||
|         // } | ||||
|         // topicInfo.value[topic_index.value].answer_img = val_arr.join(",") | ||||
|         // const exercises_info = { | ||||
|         //   ...topicInfo.value[topic_index.value], | ||||
|         //   answer_img: topicInfo.value[topic_index.value].answer_img | ||||
|         // } | ||||
|         // card_submit_data(exercises_info) | ||||
|     } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   handlerChange() | ||||
| } | ||||
| function handleIntroSuccess(res) { | ||||
|   form.value.intro = res.data.file.url | ||||
|   handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function onSubmit() { | ||||
|   router.push({name:'courseManage'}) | ||||
| } | ||||
| function handlerChange(e) { | ||||
|   // console.log(e) | ||||
|   isChange.value = true | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    步骤条--> | ||||
|     <div class="gva-search-box"> | ||||
|         <el-steps :active="active" finish-status="success" simple style="margin-bottom: 20px"> | ||||
|           <el-step title="课程信息" /> | ||||
|           <el-step title="添加章节" /> | ||||
|         </el-steps> | ||||
|     </div> | ||||
|     <!--    表单区域--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      step1--> | ||||
|       <el-form ref="ruleFormRef" v-if="active == 0" :model="form" :rules="rules" label-width="120px" style="width: 50%"> | ||||
|         <el-form-item label="课程名称" prop="name"> | ||||
|           <el-input placeholder="请输入课程名称" v-model="form.name" @change="handlerChange" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类" prop="subject"> | ||||
|           <el-select v-model="form.subject" placeholder="请选择" @change="handlerChange"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="价格(元)" prop="price"> | ||||
|           <el-input @change="handlerChange" placeholder="请输入课程价格" type="number" v-model="form.price" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程简介"> | ||||
| <!--          <el-input @change="handlerChange" v-model="form.intro" type="textarea" />--> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleIntroSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.intro" :src="form.intro" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="包含试听">--> | ||||
| <!--          <el-switch @change="handlerChange" v-model="form.is_audition" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  />--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item label="设置精品"> | ||||
|           <el-switch @change="handlerChange" v-model="form.is_boutique" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程状态"> | ||||
|           <el-switch @change="handlerChange" v-model="form.status" active-text="上架" inactive-text="下架" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|         <el-form-item style="display: none"> | ||||
|           <el-button type="primary" @click="submitForm(ruleFormRef)"> | ||||
|             Create | ||||
|           </el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <!--      step2--> | ||||
|       <div class="chapter-part" v-if="active == 1"> | ||||
|         <chapter-com  @reload="getCourseInfo" :chapter_info="chapter_info" :course_id="course_id"/> | ||||
|       </div> | ||||
|       <div class="btn-box" style="text-align: right"> | ||||
|         <el-button v-if="active>0" @click="stepChangeFunc(1)">上一步</el-button> | ||||
|         <el-button v-if="active<1" type="primary" @click="stepChangeFunc(2)">下一步</el-button> | ||||
|         <el-button v-else type="primary" @click="onSubmit">完成</el-button> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .avatar-uploader .avatar { | ||||
|     width: 178px; | ||||
|     height: 178px; | ||||
|     display: block; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										338
									
								
								src/view/course/components/chapter.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								src/view/course/components/chapter.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,338 @@ | ||||
| <script> | ||||
| export default { | ||||
|   name: 'chapterCom', | ||||
|   methods: { | ||||
|  | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import _ from 'lodash' | ||||
| import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import custom from '@/utils/custom' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted,watch } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| import mediaCom from '../components/mediaPool.vue' | ||||
| import exercisesCom from '../components/exercisesPool.vue' | ||||
| import examCom from '../components/examinationPool.vue' | ||||
| const props = defineProps(['course_id','chapter_info']) | ||||
| const emit = defineEmits(['reload']) | ||||
| import UploadCommon from '@/components/upload/common.vue' | ||||
| // 变量 | ||||
| const is_sub = ref(-1) | ||||
| const dialogChapterVisible = ref(false) | ||||
| // const dialogChapterTitle = ref('') | ||||
| const chapterForm = ref({pid:0,sort:0}) | ||||
| const chapterRules = ref({ | ||||
|   name: [{ required: true, message: '请输入章节名称', trigger: 'blur' }] | ||||
| }) | ||||
| const chapter_data = ref([]) | ||||
| const dialogChapterChildVisible = ref(false) | ||||
| const chapterChildForm = ref({sort:0}) | ||||
| const chapterChildRules = ref({ | ||||
|   name: [{ required: true, message: '请输入章节名称', trigger: 'blur' }], | ||||
|   price: [{ required: true, message: '请输入章节价格', trigger: 'blur' }] | ||||
| }) | ||||
| const dialogChapterTitle = ref('') | ||||
| const dialogChapterChildTitle = ref('') | ||||
| // const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const imageCommon = ref('') | ||||
| // const current_chapter = ref({}) // 当前操作的大章节 | ||||
| // const current_chapter_child = ref({}) // 当前操作的子章节 | ||||
| // const chapter_index = ref(0) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   chapter_data.value = props.chapter_info | ||||
| }) | ||||
| watch(props,(old, newProps) => { | ||||
|   chapter_data.value = props.chapter_info | ||||
| }) | ||||
| // 方法 | ||||
| function addChapterFunc() { // 添加大章节 | ||||
|   chapterForm.value = {pid:0,sort:0} | ||||
|   dialogChapterVisible.value = true | ||||
|   dialogChapterTitle.value = '添加大章节' | ||||
| } | ||||
| async function deleteChapterFunc(item) { //删除大章节 | ||||
|   is_sub.value = -1 | ||||
|   delFunc(item.course_chapter_id) | ||||
| } | ||||
| function delFunc(id) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delChapter({ | ||||
|       ids:[id], | ||||
|       course_id:parseInt(props.course_id), | ||||
|       sub:parseInt(is_sub.value) | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       emit('reload') | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function editChapterFunc(item) { //编辑大章节 | ||||
|   chapterForm.value = item | ||||
|   dialogChapterVisible.value = true | ||||
|   dialogChapterTitle.value = '编辑大章节' | ||||
| } | ||||
| function closeChapterDialog() { | ||||
|   dialogChapterVisible.value = false | ||||
| } | ||||
| function closeChapterChildDialog() { | ||||
|   dialogChapterChildVisible.value = false | ||||
|   chapterChildForm.value = {sort:0} | ||||
| } | ||||
| async function enterChapterDialog() { // 提交大章节 | ||||
|   // return | ||||
|   chapterForm.value.sort = parseInt(chapterForm.value.sort) | ||||
|  | ||||
|   const params = { | ||||
|     ...chapterForm.value | ||||
|   } | ||||
|   let func_name = '' | ||||
|   if(chapterForm.value.course_chapter_id) { // 编辑 | ||||
|     func_name = 'editChapter' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func_name = 'addChapter' | ||||
|     params.course_id = parseInt(props.course_id) | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: '操作成功!' | ||||
|     }) | ||||
|     closeChapterDialog() | ||||
|     emit('reload') | ||||
|   } | ||||
| } | ||||
| function addChapterchildFunc(item) { // 打开新增子章节窗口 | ||||
|   dialogChapterChildTitle.value = '新增子章节' | ||||
|   // current_chapter.value = item | ||||
|   chapterChildForm.value = {pid:item.course_chapter_id,sort:0} | ||||
|   dialogChapterChildVisible.value = true | ||||
| } | ||||
| function editChapterChildFunc(item,main_index) { // 打开编辑子章节窗口 | ||||
|   dialogChapterChildTitle.value = '编辑子章节' | ||||
|   // current_chapter.value = chapter_data.value[main_index] | ||||
|   // item.exam_ids =item.exam_id?[item.exam_id]: [] | ||||
|   item.examination_id = item.exam_id | ||||
|   chapterChildForm.value = _.cloneDeep(item) | ||||
|   chapterChildForm.value.price /= 100 | ||||
|   dialogChapterChildVisible.value = true | ||||
| } | ||||
| function deleteChapterChildFunc(item) { // 删除子章节 | ||||
|   is_sub.value = 1 | ||||
|   delFunc(item.course_subsection_id) | ||||
| } | ||||
| async function enterChapterChildDialog() { // 提交小章节 | ||||
|   chapterChildForm.value.sort = parseInt(chapterChildForm.value.sort) | ||||
|   // chapterChildForm.value.price = parseInt(chapterChildForm.value.price*100) | ||||
|   chapterChildForm.value.price = chapterChildForm.value.price*100 | ||||
|   const params = { | ||||
|     ...chapterChildForm.value | ||||
|   } | ||||
|   let func_name = '' | ||||
|   // return | ||||
|   if(chapterChildForm.value.course_subsection_id){ // 编辑 | ||||
|     func_name = 'editChapter' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func_name = 'addChapter' | ||||
|     params.course_id = parseInt(props.course_id) | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: '操作成功!' | ||||
|     }) | ||||
|     closeChapterChildDialog() | ||||
|     emit('reload') | ||||
|   } | ||||
| } | ||||
| function getFilePath(file) { // 获取上传文件之后的地址 | ||||
|   chapterChildForm.value.url = file.url | ||||
|   chapterChildForm.value.url_name = file.url_name | ||||
| } | ||||
| function addExamFunc(data) { | ||||
|   chapterChildForm.value.examination_id = data | ||||
|   chapterChildForm.value.exam_id = data | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <div class="btn-box" style="text-align: right;margin: 10px 0 20px;"> | ||||
|       <el-button type="primary" icon="plus" @click="addChapterFunc">添加章节</el-button> | ||||
|     </div> | ||||
|     <div class="list-box"> | ||||
|       <div class="lb-card" v-for="(item,i) in chapter_data"> | ||||
|         <!--大章节标题--> | ||||
|         <div class="lb-title-part"> | ||||
|           <div class="lbt-title">{{item.name}}</div> | ||||
|           <div class="lbt-btn-box"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editChapterFunc(item)" | ||||
|             /> | ||||
|             <el-button | ||||
|               icon="plus" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="addChapterchildFunc(item)" | ||||
|             /> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="deleteChapterFunc(item)" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--表格数据--> | ||||
|         <div class="lb-table-part" style="margin-bottom: 20px"> | ||||
|           <el-table :data="item.course_sub" > | ||||
|             <el-table-column align="left" label="ID" width="60" prop="course_subsection_id" /> | ||||
|             <el-table-column align="left" label="子章节名称" min-width="60" prop="name" /> | ||||
|             <el-table-column align="left" label="课件名称" min-width="60" prop="url"> | ||||
|               <template #default="scope">{{scope.row.url?scope.row.url:'未上传课件'}}</template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column align="left" label="章节试卷" min-width="60" prop="exam_id"> | ||||
|               <template #default="scope"> | ||||
|                 {{scope.row.exam_id === 0?'未添加习题':scope.row.exam_id}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="章节价格" min-width="60" prop="price"> | ||||
|               <template #default="scope">{{scope.row.price/100}}</template> | ||||
|             </el-table-column> | ||||
|             <!--            <el-table-column align="left" label="是否免费" min-width="60">--> | ||||
|             <!--              <template #default="scope">--> | ||||
|             <!--                {{scope.row.is_free === 1? '是':'否'}}--> | ||||
|             <!--              </template>--> | ||||
|             <!--            </el-table-column>--> | ||||
|             <el-table-column align="left" label="是否展示" min-width="60"> | ||||
|               <template #default="scope"> | ||||
|                 {{scope.row.is_show === 1? '是':'否'}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="操作" min-width="60"> | ||||
|               <template #default="scope"> | ||||
|                 <el-button | ||||
|                   icon="edit" | ||||
|                   size="small" | ||||
|                   type="primary" | ||||
|                   link | ||||
|                   @click="editChapterChildFunc(scope.row)" | ||||
|                 >编辑</el-button> | ||||
|                 <el-button | ||||
|                   icon="delete" | ||||
|                   size="small" | ||||
|                   type="primary" | ||||
|                   link | ||||
|                   @click="deleteChapterChildFunc(scope.row)" | ||||
|                 >删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|  | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!-- 添加/编辑 大章节窗口--> | ||||
|     <el-dialog v-model="dialogChapterVisible" :before-close="closeChapterDialog" :title="dialogChapterTitle"> | ||||
|       <el-form ref="apiForm" :model="chapterForm" :rules="chapterRules" label-width="80px"> | ||||
|         <el-form-item label="章节名称" prop="name"> | ||||
|           <el-input v-model="chapterForm.name" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="章节排序" prop="sort"> | ||||
|           <el-input v-model="chapterForm.sort" placeholder="输入整数,排序越小越靠前展示" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="是否免费" prop="is_free"> | ||||
|           <el-switch v-model="chapterForm.is_free" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="是否展示" prop="is_show"> | ||||
|           <el-switch v-model="chapterForm.is_show" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeChapterDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterChapterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <!-- 添加小章节窗口--> | ||||
|     <el-dialog v-model="dialogChapterChildVisible" :before-close="closeChapterChildDialog" :title="dialogChapterChildTitle"> | ||||
|       <el-form ref="apiForm" :model="chapterChildForm" :rules="chapterChildRules" label-width="80px"> | ||||
|         <el-form-item label="章节名称" prop="name"> | ||||
|           <el-input v-model="chapterChildForm.name" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="上传课件"> | ||||
|           <!--          <upload-common--> | ||||
|           <!--            v-model:imageCommon="imageCommon"--> | ||||
|           <!--            class="upload-btn"--> | ||||
|           <!--            @on-success="getFilePath"--> | ||||
|           <!--          />--> | ||||
|           <media-com @on-success="getFilePath" :url_name="chapterChildForm.url_name" /> | ||||
|           <!--          <el-button size="small" type="primary" @click="openExercisesWinFunc">点击上传</el-button>--> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="试卷管理"> | ||||
|           <!--          <el-button size="small" @click="chooseChapterChildExercises">添加习题</el-button>--> | ||||
|           <exam-com @addFunc="addExamFunc" :seleted_id="chapterChildForm.exam_id" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="章节价格" prop="price"> | ||||
|           <el-input type="number" v-model="chapterChildForm.price" placeholder="输入章节价格" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="章节排序" prop="sort"> | ||||
|           <el-input v-model="chapterChildForm.sort" placeholder="输入整数,排序越小越靠前展示" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="是否免费" prop="is_free"> | ||||
|           <el-switch v-model="chapterChildForm.is_free" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="是否展示" prop="is_show"> | ||||
|           <el-switch v-model="chapterChildForm.is_show" active-text="是" inactive-text="否" :active-value="1" :inactive-value="-1"  /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeChapterChildDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterChapterChildDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .lbt-title{ | ||||
|     margin-right: 20px; | ||||
|     font-size: 18px; | ||||
|   } | ||||
|   .lb-title-part{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										246
									
								
								src/view/course/components/examinationPool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								src/view/course/components/examinationPool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,246 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import api from '@/api/examination' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| import {formatDate} from '@/utils/format' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name','seleted_id']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_exam_id.value = val1.seleted_id || '' | ||||
| }) | ||||
| // 变量 | ||||
| const selected_exam_id = ref(props.seleted_id || '') | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   // subject:'', | ||||
|   status:'', | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| // const exam_ids = ref([]) | ||||
| const exam_id = ref(null) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| // console.log(subjectList.value) | ||||
| // const current_subject_str = inject('current_subject') | ||||
| // const current_subject = ref(null) | ||||
| // watch(current_subject_str,(val1,val2) => { | ||||
| //   console.log(val1) | ||||
| //   queryParams.value.subject = getSubjectId(val1) | ||||
| //   console.log(queryParams.value.subject) | ||||
| // }) | ||||
| // queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getExaminationList() | ||||
| }) | ||||
| // 方法 | ||||
| function getSubjectId(str) { | ||||
|   // console.log(str) | ||||
|   let s_id = null | ||||
|   for(let item of subjectList.value) { | ||||
|     if(item.name === str) { | ||||
|       s_id = item.id | ||||
|     } | ||||
|   } | ||||
|   return s_id | ||||
| } | ||||
| async function getExaminationList() { | ||||
|   const res = await api.getExaminationList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getExaminationList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getExaminationList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     subject:'', | ||||
|     status:'', | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function addFunc() { | ||||
|   // const list = exam_ids.value.map((item,i) => { | ||||
|   //   return item.exam.exam_id | ||||
|   // }) | ||||
|   // console.log(list) | ||||
|   emit('addFunc',exam_id.value) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   // console.log(selected_exam_id.value) | ||||
|   if(!selected_exam_id.value) { | ||||
|     multipleTableRef.value.setCurrentRow() | ||||
|     return | ||||
|   } | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_exam_id.value == row.exam.exam_id) { | ||||
|         // multipleTableRef.value.toggleRowSelection(row, true) | ||||
|         multipleTableRef.value.setCurrentRow(row) | ||||
|       } | ||||
|       // else{ | ||||
|         // multipleTableRef.value.toggleRowSelection(row, false) | ||||
|         // multipleTableRef.value.setCurrentRow() | ||||
|       // } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
|  | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '上架' | ||||
|       break; | ||||
|     case -1: | ||||
|         str = '下架' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleChooseChange(row) { | ||||
|   if(row) { | ||||
|     exam_id.value = row.exam.exam_id | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="!selected_exam_id" size="small" @click="chooseChapterChildExercises">添加试卷</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="试卷库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="试卷名称"> | ||||
|               <el-input v-model="queryParams.name" placeholder="根据试卷名称进行查询" /> | ||||
|             </el-form-item> | ||||
| <!--            <el-form-item label="试卷分类">--> | ||||
| <!--              <el-select v-model="queryParams.subject" clearable placeholder="请选择">--> | ||||
| <!--                <el-option--> | ||||
| <!--                  v-for="item in subjectList"--> | ||||
| <!--                  :key="item.id"--> | ||||
| <!--                  :label="item.name"--> | ||||
| <!--                  :value="item.name"--> | ||||
| <!--                />--> | ||||
| <!--              </el-select>--> | ||||
| <!--            </el-form-item>--> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef" row-key="exam.exam_id" :data="tableData" highlight-current-row @current-change="handleChooseChange"> | ||||
| <!--            <el-table-column--> | ||||
| <!--              type="selection"--> | ||||
| <!--              width="55"--> | ||||
| <!--              reserve-selection="true"--> | ||||
| <!--            />--> | ||||
|             <el-table-column align="center" label="ID" min-width="60" prop="exam.exam_id" sortable="custom" /> | ||||
|             <el-table-column align="center" label="试卷名称" min-width="150" prop="exam.name" /> | ||||
|             <el-table-column align="center" label="科目" min-width="150" prop="exam.subject" /> | ||||
|             <el-table-column align="center" label="封面" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <img class="e-img" :src="scope.row.exam.cover" alt=""> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="状态" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div>{{getStateName(scope.row.exam.status)}}</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column label="销量"> | ||||
|               <template #default="scope"> | ||||
|                 <div>{{scope.row.exam.sale}}份</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="组数" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div>{{scope.row.exam_types.length}}组</div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="创建时间" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 {{formatDate(scope.row.exam.CreatedAt)}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										203
									
								
								src/view/course/components/exercisesPool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								src/view/course/components/exercisesPool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import api from '@/api/exercises' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name','seleted_arr']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_question_ids.value = val2.seleted_arr || [] | ||||
| }) | ||||
| // 变量 | ||||
| const selected_question_ids = ref(props.seleted_arr || []) | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   content:'', | ||||
|   subject:'', | ||||
|   type:'', | ||||
|   teacherId:0 | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const question_ids = ref([]) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| const current_subject = inject('current_subject') | ||||
| queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getExercisesList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getExercisesList() { | ||||
|   const res = await api.getExercisesList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getExercisesList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getExercisesList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     type:'', | ||||
|     subject:'', | ||||
|     teacherId:0 | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   question_ids.value = val | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   // console.log(JSON.parse(row.question)) | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function addFunc() { | ||||
|   // console.log(question_ids.value) | ||||
|   const list = question_ids.value.map((item,i) => { | ||||
|     return item.question_id | ||||
|   }) | ||||
|   // console.log(list) | ||||
|   emit('addFunc',list) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
|  | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_question_ids.value.includes(row.question_id)) { | ||||
|         multipleTableRef.value.toggleRowSelection(row, true) | ||||
|       }else{ | ||||
|         multipleTableRef.value.toggleRowSelection(row, false) | ||||
|       } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="selected_question_ids.length==0" size="small" @click="chooseChapterChildExercises">添加习题</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看(已选{{selected_question_ids.length}}道题)</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="习题库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="题目"> | ||||
|               <el-input v-model="queryParams.content" placeholder="请输入" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="课程分类"> | ||||
|               <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in subjectList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.name" | ||||
|                   :value="item.name" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="题目类型"> | ||||
|               <el-select v-model="queryParams.type" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in typeList" | ||||
|                   :key="item.value" | ||||
|                   :label="item.label" | ||||
|                   :value="item.value" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef" row-key="question_id" :data="tableData" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column | ||||
|               type="selection" | ||||
|               width="55" | ||||
|               reserve-selection="true" | ||||
|             /> | ||||
|             <el-table-column align="left" label="ID" min-width="60" prop="question_id" sortable="custom" /> | ||||
|             <el-table-column align="left" label="题型" min-width="150" prop="name" > | ||||
|               <template #default="scope"> | ||||
|                 {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|             <el-table-column align="left" label="题目" min-width="150" > | ||||
|               <template #default="scope"> | ||||
|                 <div v-html="getExercisesName(scope.row)"></div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="创建者" min-width="150" prop="teacher_id" /> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										152
									
								
								src/view/course/components/mediaPool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								src/view/course/components/mediaPool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import custom from '@/utils/custom' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted,watch,inject  } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name']) | ||||
| const emit = defineEmits(['on-success']) | ||||
| import { clients, getNowDate } from '@/utils' | ||||
| import { getToken } from '@/utils/auth' | ||||
| // 变量 | ||||
| const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   pageIndex:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   subject:'' | ||||
| }) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| const current_subject = inject('current_subject') | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
| }) | ||||
|  | ||||
| // 方法 | ||||
| function openExercisesWinFunc() { | ||||
|   drawer.value = true | ||||
| } | ||||
| function onSubmit() { | ||||
|  | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'' | ||||
|   } | ||||
| } | ||||
| async function httpUpload(file) { // 上传oss | ||||
|   console.log(file) | ||||
|       // this.$set(this.chapterTable.sel, 'percentage', 0) | ||||
|       // this.$set(this.chapterTable.sel, 'loading', true) | ||||
|       const client = clients() | ||||
|       // 判断扩展名 | ||||
|       const tmpcnt = file.file.name.lastIndexOf('.') | ||||
|       const exname = file.file.name.substring(tmpcnt + 1) | ||||
|       const imgUrl = 'http://gwjxb.oss-cn-chengdu.aliyuncs.com' | ||||
|       const fileName = `static/uploadfile/${getNowDate()}/${file.file.uid}.${exname}` | ||||
|       await client.multipartUpload(fileName, file.file, { | ||||
|         progress: (p, cpt, res) => { | ||||
|           // 获取分片上传进度、断点和返回值。 | ||||
|           // this.$set( | ||||
|           //   this.chapterTable.sel, | ||||
|           //   'percentage', | ||||
|           //   (Math.floor(p * 100) / 100) * 100 | ||||
|           // ) | ||||
|           // if (p === 1) { | ||||
|           //   this.$set(this.chapterTable.sel, 'loading', false) | ||||
|           // } | ||||
|         }, | ||||
|         parallel: 5, // 并发上传的分片数量 | ||||
|         partSize: 1024 * 1024 * 20, | ||||
|         // headers, | ||||
|         // 指定meta参数,自定义Object的元信息。通过head接口可以获取到Object的meta数据。 | ||||
|         meta: { | ||||
|           year: 2020, | ||||
|           people: 'test' | ||||
|         }, | ||||
|         mime: file.type // 上传文件类型 | ||||
|       }) | ||||
|       // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。 | ||||
|       const head = await client.head(fileName) | ||||
|       if (head.status === 200) { | ||||
|         // 上传成功之后添加媒体库 | ||||
|         // this.addDepotFun(`${imgUrl}/${fileName}`, file.file.name) | ||||
|         // 数据赋值 | ||||
|         const params = { | ||||
|           url:`${imgUrl}/${fileName}`, | ||||
|           url_name:file.file.name | ||||
|         } | ||||
|         // console.log(params) | ||||
|         emit('on-success',params) | ||||
|         // this.$set(this.chapterTable.sel, 'url', `${imgUrl}/${fileName}`) | ||||
|         // this.$set(this.chapterTable.sel, 'url_name', file.file.name) | ||||
|       } | ||||
|     } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button size="small" type="primary" @click="openExercisesWinFunc">点击上传</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="媒体库" size="50%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="课程名称"> | ||||
|               <el-input v-model="queryParams.name" placeholder="根据课程名称进行查询" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="课程分类"> | ||||
|               <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in subjectList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-upload | ||||
|                 :headers="headers" | ||||
|                 class="upload-demo" | ||||
|                 action | ||||
|                 :http-request="httpUpload" | ||||
|                 :show-file-list="false" | ||||
|               > | ||||
|                 <el-button | ||||
|                   size="small" | ||||
|                   type="text" | ||||
|                 >普通上传</el-button> | ||||
|               </el-upload> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|  | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										301
									
								
								src/view/course/courseCategory/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								src/view/course/courseCategory/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,301 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/course' | ||||
| // import custom from '@/utils/custom' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| // 变量 | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   keyword:'' | ||||
| }) | ||||
| const total = ref(0) | ||||
| // const dataList = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const dialogFormVisible = ref(false) | ||||
| const tableData =ref([]) | ||||
| const dialogTitle = ref('') | ||||
| const type = ref('') | ||||
| const form = ref({ | ||||
|     name: '', | ||||
|     parent_id: 0, | ||||
|     level: 1, | ||||
|     sort: 0, | ||||
|     is_elite:-1 | ||||
|   }) | ||||
|  | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入名称', trigger: 'blur' }] | ||||
| }) | ||||
| const categoryForm = ref({}) | ||||
| const tree_val = ref(null) | ||||
| // 生命周期 | ||||
| // getSubject() | ||||
| onMounted(() => { | ||||
|   getSubjectList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getSubjectList() { | ||||
|   const res = await api.getSubjectList(queryParams.value) | ||||
|   subjectList.value = res.data.records | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     subjectList.value = addTreeFormatSubject(subjectList.value) | ||||
|     // console.log(subjectList.value) | ||||
|   } | ||||
| } | ||||
| function addTreeFormatSubject(data) { | ||||
|   if(!data) { | ||||
|     return [] | ||||
|   } | ||||
|   data.map( item => { | ||||
|       item.label = item.name | ||||
|       item.value = item.id | ||||
|       if(item.level === 3) { | ||||
|         item.disabled = true | ||||
|       } | ||||
|       if(item.children) { | ||||
|         addTreeFormatSubject(item.children) | ||||
|       } | ||||
|   }) | ||||
|   return data | ||||
| } | ||||
| function onSubmit() { | ||||
|   getSubjectList() | ||||
| } | ||||
| // 排序 | ||||
| // const sortChange = ({ prop, order }) => { | ||||
| //   if (prop) { | ||||
| //     if (prop === 'ID') { | ||||
| //       prop = 'id' | ||||
| //     } | ||||
| //     queryParams.value.orderKey = toSQLLine(prop) | ||||
| //     queryParams.value.desc = order === 'descending' | ||||
| //   } | ||||
| //   getSubjectList() | ||||
| // } | ||||
| // 批量操作 | ||||
| const handleSelectionChange = (val) => { | ||||
|   apis.value = val | ||||
| } | ||||
| function editApiFunc(row) { | ||||
|   for(let prop in form.value) { | ||||
|     if(row[prop]){ | ||||
|       form.value[prop] = row[prop] | ||||
|     } | ||||
|   } | ||||
|   form.value.id = row.id | ||||
|   // return | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delSubject({ | ||||
|           ids:[row.id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       // if (tableData.value.length === 1 && page.value > 1) { | ||||
|       //   page.value-- | ||||
|       // } | ||||
|       getSubjectList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function openDialog(key) { | ||||
|   switch (key) { | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增类型' | ||||
|       break | ||||
|     case 'edit': | ||||
|       dialogTitle.value = '编辑类型' | ||||
|       break | ||||
|     default: | ||||
|       break | ||||
|   } | ||||
|   type.value = key | ||||
|   dialogFormVisible.value = true | ||||
| } | ||||
| const closeDialog = () => { | ||||
|   initForm() | ||||
|   dialogFormVisible.value = false | ||||
| } | ||||
| const initForm = () => { | ||||
|   categoryForm.value.resetFields() | ||||
|   form.value = { | ||||
|     name: '', | ||||
|     parent_id: 0, | ||||
|     level: 1, | ||||
|     sort: 0, | ||||
|     is_elite:-1 | ||||
|   } | ||||
| } | ||||
| function tree_select_func(e) { | ||||
|   form.value.level = findLevel(subjectList.value,e) | ||||
| } | ||||
| function findLevel(data,val){ | ||||
|   let l_id = 0 | ||||
|   for(let i =0;i<data.length;i++) { | ||||
|     if(data[i].id === val) { | ||||
|         l_id = parseInt(data[i].level)+1 | ||||
|         break; | ||||
|     } | ||||
|     else{ | ||||
|         if(data[i].children && l_id == 0) { | ||||
|           l_id = findLevel(data[i].children,val) | ||||
|         } | ||||
|     } | ||||
|   } | ||||
|   return l_id | ||||
| } | ||||
| async function enterDialog() { // 确认创建或修改 | ||||
|   let func_name = '' | ||||
|   if(type.value === 'add') { | ||||
|     func_name = 'addSubject' | ||||
|   } | ||||
|   else{ | ||||
|     func_name = 'editSubject' | ||||
|   } | ||||
|   form.value.sort = parseInt(form.value.sort) | ||||
|   // return | ||||
|   const res = await api[func_name](form.value) | ||||
|   if(res.code === 0 ){ | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: '操作成功!' | ||||
|     }) | ||||
|     getSubjectList() | ||||
|     closeDialog() | ||||
|   } | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     keyword:'' | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getSubjectList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getSubjectList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="类型名称"> | ||||
|           <el-input v-model="queryParams.keyword" placeholder="类型名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|       </div> | ||||
|       <el-table | ||||
|         :data="subjectList" | ||||
|         style="width: 100%; margin-bottom: 20px" | ||||
|         row-key="id" | ||||
|         border | ||||
|         default-expand-all | ||||
|       > | ||||
|         <el-table-column prop="name" label="类型名称" /> | ||||
|         <el-table-column prop="level" label="等级" /> | ||||
|         <el-table-column prop="parent_id" label="父级id" /> | ||||
|         <el-table-column label="首页推荐" > | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.is_elite == 1?'是':'否'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" > | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editApiFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.pageIndex" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--新增、编辑 窗口--> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <!-- <warning-bar title="新增API,需要在角色管理内配置权限才可使用" />--> | ||||
|       <el-form ref="categoryForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="父级类型" prop="path"> | ||||
|           <el-tree-select @change="tree_select_func" check-strictly v-model="form.parent_id" :data="subjectList" :render-after-expand="false" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="名称" prop="path"> | ||||
|           <el-input v-model="form.name" placeholder="请输入类型名称" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="排序" prop="path"> | ||||
|           <el-input type="number" v-model="form.sort" placeholder="排序越小,展示越靠前" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="首页推荐" prop="method"> | ||||
|           <el-switch v-model="form.is_elite" :active-value="1" :inactive-value="-1" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										271
									
								
								src/view/course/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								src/view/course/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,271 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'', | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const course_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const course_id = ref(0) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getCourseList() | ||||
|   getSubject() | ||||
| }) | ||||
| // 方法 | ||||
| async function getCourseList() { | ||||
|   const res = await api.getCourseList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await api.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|     // console.log(subjectList.value) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getCourseList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增课程' | ||||
|       break; | ||||
|     case 'edit': | ||||
|       params.course_id = course_id.value | ||||
|       dialogTitle.value = '编辑课程' | ||||
|       break; | ||||
|   } | ||||
|   router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   console.log(course_ids.value) | ||||
|   const ids = course_ids.value.map(item => item.course_id) | ||||
|   const res = await api.delCourse({ ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getCourseList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   // console.log(val) | ||||
|   course_ids.value = val | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   course_id.value = row.course_id | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteCourseFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delCourse({ | ||||
|           ids:[row.course_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       // if (tableData.value.length === 1 && page.value > 1) { | ||||
|       //   page.value-- | ||||
|       // } | ||||
|       getCourseList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getCourseList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getCourseList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
| } | ||||
| function enterDialog() { | ||||
|  | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{course_id:row.course_id}}) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="课程名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据课程名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!course_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="left" label="id" min-width="60" prop="course_id" sortable="custom" /> | ||||
|         <el-table-column align="left" label="名称" min-width="150" prop="name" /> | ||||
|         <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="价格" min-width="150" prop="price"> | ||||
|           <template #default="scope">{{scope.row.price/100}}</template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="状态" min-width="150" prop="status"> | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.status == 1?'上架':scope.row.status == 2?'待审核':scope.row.status == 3?'通过':scope.row.status == 4?'未通过':'下架'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="是否精品" min-width="150" prop="is_boutique" /> | ||||
|         <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewCourseFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editCourseFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteCourseFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.pageIndex" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|  | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="课程名称" prop="name"> | ||||
|           <el-input v-model="form.name" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程简介" prop="introduction"> | ||||
|           <el-input v-model="form.introduction" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										146
									
								
								src/view/course/viewCourse/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/view/course/viewCourse/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/course' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const course_id = ref(0) | ||||
| const courseData = ref({}) | ||||
| const baseInfo = ref({}) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   course_id.value = route.params.course_id | ||||
|   getCourse() | ||||
| }) | ||||
| //方法 | ||||
| async function getCourse() { // 获取课程信息 | ||||
|   const res = await api.getCourse({id:course_id.value}) | ||||
|   if(res.code === 0) { | ||||
|     courseData.value = res.data | ||||
|     baseInfo.value = res.data.course | ||||
|     // console.log(res.data.course) | ||||
|   } | ||||
| } | ||||
| function downloadChapterChildFunc(item) { // 点击下载 | ||||
|   // console.log(item) | ||||
|  | ||||
|   window.open(row.url) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseinfoBox"> | ||||
|         <div class="base-card course-name"> | ||||
|           <div class="bc-left" style="font-size: 18px">课程名称:</div> | ||||
|           <div class="bc-right" style="font-size: 18px">{{courseData.name}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">课程名称:</div> | ||||
|           <div class="bc-right">{{baseInfo.name}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">课程科目:</div> | ||||
|           <div class="bc-right">{{baseInfo.subject}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">课程状态:</div> | ||||
|           <div class="bc-right">{{baseInfo.status === 1?'上架':'下架'}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">课程价格:</div> | ||||
|           <div class="bc-right">{{baseInfo.price}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">教师姓名:</div> | ||||
|           <div class="bc-right"></div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">创建时间:</div> | ||||
|           <div class="bc-right">{{baseInfo.CreatedAt}}</div> | ||||
|         </div> | ||||
|         <div class="base-card"> | ||||
|           <div class="bc-left">课程简介:</div> | ||||
|           <div class="bc-right">{{baseInfo.intro}}</div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    章节信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="list-box"> | ||||
|         <div class="lb-card" v-for="(item,i) in courseData.course_ware_json"> | ||||
|           <!--大章节标题--> | ||||
|           <div class="lb-title-part"> | ||||
|             <div class="lbt-title">{{item.name}}</div> | ||||
|           </div> | ||||
|           <!--表格数据--> | ||||
|           <div class="lb-table-part" style="margin-bottom: 20px"> | ||||
|             <el-table :data="item.children" > | ||||
|               <el-table-column align="left" label="id" width="60" prop="id" /> | ||||
|               <el-table-column align="left" label="子章节名称" min-width="60" prop="name" /> | ||||
|               <el-table-column align="left" label="课件名称" min-width="60"> | ||||
|                 <template #default="scope"> | ||||
|                   {{scope.row.url_name === ''?'未上传课件':scope.row.url_name}} | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="left" label="章节习题" min-width="60" prop="is_contain_exercise"> | ||||
|                 <template #default="scope"> | ||||
|                   {{scope.row.is_contain_exercise === 0?'未添加习题':scope.row.is_contain_exercise}} | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="left" label="是否免费" min-width="60"> | ||||
|                 <template #default="scope"> | ||||
|                   {{scope.row.is_free === 1? '是':'否'}} | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="left" label="是否展示" min-width="60"> | ||||
|                 <template #default="scope"> | ||||
|                   {{scope.row.is_show === 1? '是':'否'}} | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="left" label="操作" min-width="60"> | ||||
|                 <template #default="scope"> | ||||
|                   <el-button v-if="scope.row.url" | ||||
|                     icon="edit" | ||||
|                     size="small" | ||||
|                     type="primary" | ||||
|                     link | ||||
|                     @click="downloadChapterChildFunc(scope.row)" | ||||
|                   >下载</el-button> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|             </el-table> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
| .lbt-title{ | ||||
|   margin-right: 20px; | ||||
|   font-size: 18px; | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
| .base-card{ | ||||
|   display: flex; | ||||
|   float: left; | ||||
|   white-space: nowrap; | ||||
|   width: 33%; | ||||
|   padding: 10px 0px; | ||||
|   color: gray; | ||||
| } | ||||
| .course-name{ | ||||
|   font-weight: 900; | ||||
|   font-size: 18px !important; | ||||
|   width: 100%; | ||||
|   color:black | ||||
| } | ||||
| .baseinfoBox{ | ||||
|   overflow: hidden; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										155
									
								
								src/view/dealDetailManage/auctionDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/view/dealDetailManage/auctionDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // import * as echarts from 'echarts'; | ||||
| // 变量 | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   user_id:0, | ||||
|   type:'', // 是否中奖 | ||||
|   time:'', // 抽经时间 | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const total = ref(0) | ||||
| const typeList = ref([ | ||||
|   { | ||||
|     name:'已中奖', | ||||
|     value:1 | ||||
|   }, | ||||
|   { | ||||
|     name:'未中奖', | ||||
|     value:2 | ||||
|   } | ||||
| ]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getAuctionDetailList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getAuctionDetailList() { | ||||
|   const res = await api.getAuctionDetailList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getAuctionDetailList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     user_id:0, | ||||
|     type:'', // 是否中奖 | ||||
|     time:'', // 抽经时间 | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getAuctionDetailList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getAuctionDetailList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|  | ||||
|         <el-form-item label="是否中奖"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in typeList" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="竞拍时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.last_time" | ||||
|             type="date" | ||||
|             placeholder="竞拍时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="竞拍时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="竞拍编号" min-width="150" prop="name"> | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="竞拍奖品" min-width="150" prop="subject" /> | ||||
| <!--        <el-table-column align="left" label="选择号数" min-width="150" prop="teacher_id" />--> | ||||
|         <el-table-column align="left" label="参与人数" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="是否获奖" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="竞拍消费" min-width="150" prop="status" /> | ||||
|       </el-table> | ||||
|       <!--      分页--> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										151
									
								
								src/view/dealDetailManage/dealDetailMoney.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/view/dealDetailManage/dealDetailMoney.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| // import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   type:'', | ||||
|   deal_time:'' | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const total = ref(0) | ||||
| const dealTypeList = ref([ | ||||
|   { | ||||
|     name:'课程', | ||||
|     value:1 | ||||
|   },{ | ||||
|     name:'测试', | ||||
|     value:2 | ||||
|   }, | ||||
| ]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getDealMoneyList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getDealMoneyList() { | ||||
|   const res = await api.getDealMoneyList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getDealMoneyList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     type:'', | ||||
|     deal_time:'' | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getDealMoneyList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getDealMoneyList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="交易类别"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in dealTypeList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="交易时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.deal_time" | ||||
|             type="date" | ||||
|             placeholder="交易时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="交易单号" min-width="150" prop="question_id" /> | ||||
|         <el-table-column align="left" label="类别" min-width="150" prop="name" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="交易时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="交易方式" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="交易详情" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="交易金额" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="资产余额" min-width="150" prop="teacher_id" /> | ||||
|  | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										149
									
								
								src/view/dealDetailManage/dealDetailPoint.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/view/dealDetailManage/dealDetailPoint.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| // import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   type:'', | ||||
|   deal_time:'' | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const total = ref(0) | ||||
| const dealTypeList = ref([ | ||||
|   { | ||||
|     name:'课程', | ||||
|     value:1 | ||||
|   },{ | ||||
|     name:'测试', | ||||
|     value:2 | ||||
|   }, | ||||
| ]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getDealPointList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getDealPointList() { | ||||
|   const res = await api.getDealPointList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getDealPointList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     type:'', | ||||
|     deal_time:'' | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getDealPointList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getDealPointList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="交易类别"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in dealTypeList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="交易时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.deal_time" | ||||
|             type="date" | ||||
|             placeholder="交易时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="交易单号" min-width="150" prop="question_id" /> | ||||
|         <el-table-column align="left" label="交易类型" min-width="150" prop="name" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="交易时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="交易详情" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="交易积分" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="积分余额" min-width="150" prop="teacher_id" /> | ||||
|  | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										220
									
								
								src/view/dealDetailManage/learningDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								src/view/dealDetailManage/learningDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import _ from 'lodash' | ||||
| import {ref,onMounted } from 'vue' | ||||
| // import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import * as echarts from 'echarts'; | ||||
| // 变量 | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   user_id:0, | ||||
|   last_time:'', | ||||
|   subject:'' | ||||
|  | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     page:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| // const deleteVisible = ref(false) | ||||
| // const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| // const dialogFormVisible = ref(false) | ||||
| // const dialogTitle = ref('') | ||||
| // const form =ref({}) | ||||
| // const rules = ref({ | ||||
| //   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| // }) | ||||
| // const question_id = ref(0) | ||||
| // const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| // const dealTypeList = ref([ | ||||
| //   { | ||||
| //     name:'课程', | ||||
| //     value:1 | ||||
| //   },{ | ||||
| //     name:'测试', | ||||
| //     value:2 | ||||
| //   }, | ||||
| // ]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getLearningDetailList() | ||||
|   getSubject() | ||||
|   initChart() | ||||
| }) | ||||
| // 方法 | ||||
| function initChart() { // echart | ||||
|   const myChart = echarts.init(document.getElementById('myEcharts')); | ||||
|   const option = ref({ | ||||
|     tooltip: { | ||||
|       trigger: 'axis', | ||||
|       axisPointer: { | ||||
|         type: 'shadow' | ||||
|       } | ||||
|     }, | ||||
|     grid: { | ||||
|       left: '3%', | ||||
|       right: '4%', | ||||
|       bottom: '3%', | ||||
|       containLabel: true | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], | ||||
|       axisTick: { | ||||
|         alignWithLabel: true | ||||
|       } | ||||
|     }, | ||||
|     yAxis: { | ||||
|       type: 'value' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         data: [120, 200, 150, 80, 70, 110, 130], | ||||
|         type: 'bar', | ||||
|         name: '学习时长(分钟)', | ||||
|         barWidth: '60%', | ||||
|       } | ||||
|     ] | ||||
|   }); | ||||
|   option.value && myChart.setOption(option.value); | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|     // console.log(subjectList.value) | ||||
|   } | ||||
| } | ||||
| async function getLearningDetailList() { | ||||
|   const res = await api.getLearningDetailList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getLearningDetailList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     user_id:0, | ||||
|     last_time:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| // const handleSelectionChange = (val) => { | ||||
| //   question_ids.value = val | ||||
| // } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getLearningDetailList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getLearningDetailList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|  | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="最后学习时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.last_time" | ||||
|             type="date" | ||||
|             placeholder="最后学习时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="ID"  prop="course_id" /> | ||||
|         <el-table-column align="left" label="最后学习时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="科目" min-width="150" prop="name"> | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="课程" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="学习时长" min-width="150" prop="teacher_id" /> | ||||
|  | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|     <!--    echart--> | ||||
|     <div class="echarts-box gva-table-box" style="margin-top: 20px"> | ||||
|       <div class="report-title">学习报告:</div> | ||||
|       <div id="myEcharts" :style="{ width: '900px', height: '300px',margin: '0 auto' }"></div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										155
									
								
								src/view/dealDetailManage/raffleDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/view/dealDetailManage/raffleDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // import * as echarts from 'echarts'; | ||||
| // 变量 | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   user_id:0, | ||||
|   type:'', // 是否中奖 | ||||
|   time:'', // 抽经时间 | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const total = ref(0) | ||||
| const typeList = ref([ | ||||
|   { | ||||
|     name:'已中奖', | ||||
|     value:1 | ||||
|   }, | ||||
|   { | ||||
|     name:'未中奖', | ||||
|     value:2 | ||||
|   } | ||||
| ]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getRaffleDetailList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getRaffleDetailList() { | ||||
|   const res = await api.getRaffleDetailList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getRaffleDetailList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     user_id:0, | ||||
|     type:'', // 是否中奖 | ||||
|     time:'', // 抽经时间 | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getRaffleDetailList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getRaffleDetailList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|  | ||||
|         <el-form-item label="是否中奖"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in typeList" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="抽奖时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.last_time" | ||||
|             type="date" | ||||
|             placeholder="抽奖时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="抽奖时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="抽奖编号" min-width="150" prop="name"> | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="抽奖奖品" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="选择号数" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="参与人数" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="是否获奖" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="抽奖消费" min-width="150" prop="status" /> | ||||
|       </el-table> | ||||
|       <!--      分页--> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								src/view/dealDetailManage/testDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/view/dealDetailManage/testDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import _ from 'lodash' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   user_id:0, | ||||
|   last_time:'', | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     page:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const total = ref(0) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // getTestDetailList() | ||||
|   getSubject() | ||||
| }) | ||||
| // 方法 | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|     // console.log(subjectList.value) | ||||
|   } | ||||
| } | ||||
| async function getTestDetailList() { | ||||
|   const res = await api.getTestDetailList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getTestDetailList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     user_id:0, | ||||
|     last_time:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getTestDetailList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getTestDetailList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|  | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="测试时间"> | ||||
|            <el-date-picker class="oi-item" style="margin-left:5px" | ||||
|             v-model="queryParams.last_time" | ||||
|             type="date" | ||||
|             placeholder="测试时间" | ||||
|             format="YYYY-MM-DD" | ||||
|             value-format="x" | ||||
|            /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData"> | ||||
|         <el-table-column align="left" label="ID"  prop="course_id" /> | ||||
|         <el-table-column align="left" label="测试时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="科目" min-width="150" prop="name"> | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="课程" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="测试用时/限时" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="测试状态" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="测试名次" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="测试消费" min-width="150" prop="status" /> | ||||
|         <el-table-column align="left" label="测试收益" min-width="150" prop="status" /> | ||||
|       </el-table> | ||||
|       <!--      分页--> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										465
									
								
								src/view/drawManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								src/view/drawManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,465 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/integral' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   key:'', | ||||
|   status:'', | ||||
|   sort:'', | ||||
|   current_page:1, | ||||
|   loading_egg:'' | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'报名中', | ||||
|       value:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'取消', | ||||
|       value:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'结束', | ||||
|       value:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| const draw_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getDrawList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getDrawList() { | ||||
|   const res = await api.getDrawList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.list | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getDrawList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     key:'', | ||||
|     status:'', | ||||
|     sort:'', | ||||
|     current_page:1 | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = draw_ids.value | ||||
|   const res = await api.delDrawData({ ids:draw_ids.value }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getDrawList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   draw_ids.value = val.map((item) => { | ||||
|       return item.id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.current_page = val | ||||
|   getDrawList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getDrawList() | ||||
| } | ||||
| // function viewTeacherFunc(row) { // 查看详情 | ||||
| //   router.push({name:'teacherDetail',params:{id:row.teacher_info_id}}) | ||||
| // } | ||||
| function getStateName(row) { | ||||
|   let name = '' | ||||
|   switch(row.status) { | ||||
|     case 1: | ||||
|       // 检查是否过期 | ||||
|       if(row.end_time < (Date.parse(new Date()))) { // 已过期 | ||||
|         name = '已结束'; | ||||
|       } | ||||
|       else{ | ||||
|         name = '报名中'; | ||||
|       } | ||||
|       break; | ||||
|     case 2: | ||||
|       name = '已取消'; | ||||
|       break; | ||||
|     case 0: | ||||
|       name = '已取消'; | ||||
|       break; | ||||
|     case 3: | ||||
|       name = '已结束'; | ||||
|       break; | ||||
|   } | ||||
|   return name | ||||
| } | ||||
|  | ||||
| // 新增 & 编辑相关 ================ | ||||
| const popupVisible = ref(false) | ||||
| const popupTitle = ref('') | ||||
| const drawForm = ref({}) | ||||
| const drawFormRules = ref({ | ||||
|   product_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }], | ||||
|   market_value:[{ required: true, message: '请输入市场价格', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式',trigger: 'blur' }], | ||||
|   in_point:[{ required: true, message: '请输入参与积分', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式' }], | ||||
|   full_member:[{ required: true, message: '请输入满员人数', trigger: 'blur'}, | ||||
|   { type: 'number', message: '请输入正确的格式' }], | ||||
|   end_time:[{ required: true, message: '请输入截止时间', trigger: 'blur' }], | ||||
|   begin_time:[{ required: true, message: '请输入开始时间', trigger: 'blur' }], | ||||
|   product_cover:[{ required: true, message: '请选择商品封面', trigger: 'blur' }], | ||||
| }) | ||||
| const drawFormRef = ref(null) | ||||
| function openDialog() { | ||||
|   drawForm.value = {} | ||||
|   popupTitle.value = '新增竞拍' | ||||
|   popupVisible.value = true | ||||
| } | ||||
| function editDrawFunc(row) { | ||||
|   popupTitle.value = '编辑竞拍' | ||||
|   popupVisible.value = true | ||||
|   drawForm.value = row | ||||
| } | ||||
| function delFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     console.log(1) | ||||
|     const res = await api.delDrawData({ | ||||
|           ids:[row.id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getDrawList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function cancelClick() { | ||||
|   popupVisible.value = false | ||||
| } | ||||
| async function confirmClick() { //提交竞拍 | ||||
|   submitForm(drawFormRef.value) | ||||
| } | ||||
| async function submitForm(formEl) { | ||||
|   if (!formEl) return | ||||
|   await formEl.validate((valid, fields) => { | ||||
|     if (valid) { // 验证通过 | ||||
|       // console.log('submit!') | ||||
|       saveData() | ||||
|     } else { | ||||
|       // console.log('请填写完整信息!', fields) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| async function saveData() { | ||||
|   const params = { | ||||
|     ...drawForm.value | ||||
|   } | ||||
|   let func = '' | ||||
|   if(params.id) { // 编辑 | ||||
|     func = 'editDrawData' | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     func = 'addDrawData' | ||||
|   } | ||||
|   // console.log(params);return | ||||
|   const res = await api[func](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     getDrawList() | ||||
|     cancelClick() | ||||
|   } | ||||
| } | ||||
| function handleAvatarSuccess(res) { // 图片上传回调 | ||||
|   console.log(res) | ||||
|   drawForm.value[file_type.value[file_type_index]] = res.data.file.url | ||||
|  | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| const file_type = ref(['product_cover','product_introduce']) | ||||
| let file_type_index = 0 | ||||
| function fileChange(index) { | ||||
|   console.log(index) | ||||
|   file_type_index = index | ||||
| } | ||||
| function loadingEggChange() { | ||||
|   console.log(drawForm.value) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="关键字"> | ||||
|           <el-input v-model="queryParams.key" placeholder="根据关键字进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!draw_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="center" label="ID"  prop="id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="商品名称" prop="product_name" /> | ||||
|         <el-table-column align="center" label="商品图片"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.product_cover" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="市场价值(元)" min-width="150" prop="market_value" /> | ||||
|         <el-table-column align="center" label="参与积分"  prop="in_point" /> | ||||
|         <el-table-column align="center" label="满员人数"  prop="full_member" /> | ||||
|         <el-table-column align="center" label="发布日期" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.timestampToDate(scope.row.begin_time)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="截止日期" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.timestampToDate(scope.row.end_time)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|  | ||||
|         <el-table-column align="center" label="已参与人数" min-width="150" prop="in_member" /> | ||||
|         <el-table-column align="center" label="奖品装蛋" min-width="150" prop="loading_egg" > | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.loading_egg?'是':'否'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
| <!--        <el-table-column align="center" label="最高积分" prop="most_point" />--> | ||||
|         <el-table-column align="center" label="状态"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editDrawFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="delFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.current_page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!-- 新增&编辑 窗口--> | ||||
|     <el-drawer | ||||
|       v-model="popupVisible" | ||||
|       :title="popupTitle" | ||||
|       direction="rtl" | ||||
|       size="50%" | ||||
|     > | ||||
|       <el-form ref="drawFormRef" class="form-box" :model="drawForm" :rules="drawFormRules" label-width="80px"> | ||||
|         <el-form-item label="商品名称" prop="product_name"> | ||||
|           <el-input v-model="drawForm.product_name" placeholder="请输入商品名称" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="奖品封面" prop="product_cover"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             @click="fileChange(0)" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="drawForm.product_cover" :src="drawForm.product_cover" class="img-container" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="市场价格"  prop="market_value"> | ||||
|           <el-input v-model.number="drawForm.market_value" placeholder="请输入市场价格" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item prop="in_point" label="参与积分" > | ||||
|           <el-input v-model.number="drawForm.in_point" placeholder="请输入参与积分" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item prop="full_member" label="满员人数" > | ||||
|           <el-input v-model.number="drawForm.full_member" placeholder="请输入满员人数" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="开始日期" prop="begin_time" > | ||||
|           <el-date-picker | ||||
|             v-model="drawForm.begin_time" | ||||
|             type="datetime" | ||||
|             placeholder="开始日期" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="截止日期" prop="end_time" > | ||||
|           <el-date-picker | ||||
|             v-model="drawForm.end_time" | ||||
|             type="datetime" | ||||
|             placeholder="截止日期" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="奖品装蛋" > | ||||
|           <el-switch @change="loadingEggChange" v-model="drawForm.loading_egg" active-text="是" inactive-text="否" :active-value="true" inactive-value="false"  /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="奖品详情" prop="product_introduce"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             @click="fileChange(1)" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="drawForm.product_introduce" :src="drawForm.product_introduce" class="img-container" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="启用状态" prop="status"> | ||||
|           <el-switch v-model="drawForm.status" :active-value="1" :inactive-value="2" active-text="启用" inactive-text="禁用" /> | ||||
|         </el-form-item> | ||||
|  | ||||
|       </el-form> | ||||
|        <template #footer> | ||||
|           <div style="flex: auto"> | ||||
|             <el-button @click="cancelClick">取消</el-button> | ||||
|             <el-button type="primary" @click="confirmClick">确定</el-button> | ||||
|           </div> | ||||
|        </template> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .form-box{ | ||||
|     padding: 10px; | ||||
|   } | ||||
|   .img-container{ | ||||
|     width: 200px; | ||||
|     height: 150px; | ||||
|   } | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										228
									
								
								src/view/examinationManage/components/coursePool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								src/view/examinationManage/components/coursePool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,228 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import api from '@/api/course' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['url_name','seleted_arr']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   selected_course_ids.value = val1.seleted_arr || [] | ||||
| }) | ||||
| // 变量 | ||||
| const selected_course_ids = ref(props.seleted_arr || []) | ||||
|  | ||||
| // const headers = ref({ Authorization: 'Bearer ' + getToken() }) | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   subject:'', | ||||
|   status:'', | ||||
| }) | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const course_ids = ref([]) | ||||
| // 生命周期 | ||||
| const subjectList = inject('subjectList') | ||||
| // console.log(subjectList.value) | ||||
| // const current_subject =getSubjectId(inject('current_subject')) | ||||
| const current_subject_str = inject('current_subject') | ||||
| const current_subject = ref(null) | ||||
| watch(current_subject_str,(val1,val2) => { | ||||
|   console.log(val1) | ||||
|   queryParams.value.subject = getSubjectId(val1) | ||||
|   console.log(queryParams.value.subject) | ||||
| }) | ||||
| // queryParams.value.subject = current_subject | ||||
| onMounted(() => { | ||||
|   // console.log(headers.value) | ||||
|   // getCourseList() | ||||
| }) | ||||
| // 方法 | ||||
| function getSubjectId(str) { | ||||
|   // console.log(str) | ||||
|   let s_id = null | ||||
|   for(let item of subjectList.value) { | ||||
|     if(item.name === str) { | ||||
|       s_id = item.id | ||||
|     } | ||||
|   } | ||||
|   return s_id | ||||
| } | ||||
| async function getCourseList() { | ||||
|   const res = await api.getCourseList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     await nextTick() | ||||
|     toggleSelection(tableData.value) | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   drawer.value = true | ||||
|   // getCourseList() | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getCourseList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     subject:'', | ||||
|     status:'', | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   course_ids.value = val | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getCourseList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getCourseList() | ||||
| } | ||||
| function addFunc() { | ||||
|   const list = course_ids.value.map((item,i) => { | ||||
|     return item.course_id | ||||
|   }) | ||||
|   emit('addFunc',list) | ||||
|   drawer.value = false | ||||
| } | ||||
| const multipleTableRef = ref(null) | ||||
| const toggleSelection = (rows) => { // 判断是否被选中 | ||||
|   if (rows) { | ||||
|     rows.forEach((row) => { | ||||
|       if(selected_course_ids.value.length>0 && selected_course_ids.value.includes(row.course_id)) { | ||||
|         multipleTableRef.value.toggleRowSelection(row, true) | ||||
|       } | ||||
|       else{ | ||||
|         multipleTableRef.value.toggleRowSelection(row, false) | ||||
|       } | ||||
|     }) | ||||
|   } else { | ||||
|     multipleTableRef.value.clearSelection() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{course_id:row.course_id}}) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="selected_course_ids.length==0" size="small" @click="chooseChapterChildExercises">添加课程</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看(已选{{selected_course_ids.length}}门课程)</el-button> | ||||
|     <div v-if="url_name">{{url_name}}</div> | ||||
|     <el-drawer v-model="drawer" title="课程库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!--      搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="课程名称"> | ||||
|               <el-input v-model="queryParams.name" placeholder="根据课程名称进行查询" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="课程分类"> | ||||
|               <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in subjectList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef" row-key="course_id" :data="tableData" @selection-change="handleSelectionChange"> | ||||
|             <el-table-column | ||||
|               type="selection" | ||||
|               width="55" | ||||
|               reserve-selection="true" | ||||
|             /> | ||||
|             <el-table-column align="left" label="id" min-width="60" prop="course_id" sortable="custom" /> | ||||
|             <el-table-column align="left" label="名称" min-width="150" prop="name" /> | ||||
|             <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|             <el-table-column align="left" label="价格" min-width="150" prop="price" /> | ||||
|             <el-table-column align="left" label="状态" min-width="150" prop="status"> | ||||
|               <template #default="scope"> | ||||
|                 {{scope.row.status == 1?'上架':scope.row.status == 2?'待审核':scope.row.status == 3?'通过':scope.row.status == 4?'未通过':'下架'}} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="是否精品" min-width="150" prop="is_boutique" /> | ||||
|             <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|               <template #default="scope"> | ||||
|                 <el-button | ||||
|                   icon="view" | ||||
|                   size="small" | ||||
|                   type="primary" | ||||
|                   link | ||||
|                   @click="viewCourseFunc(scope.row)" | ||||
|                 >查看</el-button> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="edit"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="primary"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="editCourseFunc(scope.row)"--> | ||||
| <!--                >编辑</el-button>--> | ||||
| <!--                <el-button--> | ||||
| <!--                  icon="delete"--> | ||||
| <!--                  size="small"--> | ||||
| <!--                  type="danger"--> | ||||
| <!--                  link--> | ||||
| <!--                  @click="deleteCourseFunc(scope.row)"--> | ||||
| <!--                >删除</el-button>--> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" icon="plus" @click="addFunc">添加</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										406
									
								
								src/view/examinationManage/components/groupPool.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								src/view/examinationManage/components/groupPool.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,406 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| // import api from '@/api/course' | ||||
| // import com_api from '@/api/common' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import _ from "lodash" | ||||
| import api from '@/api/examination' | ||||
| import { ref, onMounted, watch, inject, nextTick } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // import chapterCom from '../components/chapter.vue' | ||||
| const props = defineProps(['exam_types','exam_id']) | ||||
| const emit = defineEmits(['addFunc']) | ||||
| // const history_num = ref('') | ||||
| // import { clients, getNowDate } from '@/utils' | ||||
| import custom from '@/utils/custom' | ||||
| // import { getToken } from '@/utils/auth' | ||||
| // 监听 | ||||
| watch(props,(val1,val2) => { | ||||
|   has_exam_types.value = _.cloneDeep(val1.exam_types) || [] | ||||
|   queryParams.value.examId = val1.exam_id | ||||
| }) | ||||
| // 变量 | ||||
| const has_exam_types = ref(_.cloneDeep(props.exam_types) || []) | ||||
|  | ||||
| const drawer = ref(false) | ||||
| const queryParams =ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   term:'', | ||||
|   persons:'', | ||||
|   examId:'' | ||||
| }) | ||||
| const tableData =ref([]) | ||||
| const total = ref(0) | ||||
| const dfVisible = ref(false) | ||||
| const type_list = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   queryParams.value.examId = props.exam_id | ||||
|   getExamGroupList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getExamGroupList() { | ||||
|   const res = await api.getExamGroupList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     type_list.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|     console.log('子组件获取行为') | ||||
|     if(type_list.value.length==0) { | ||||
|        type_list.value = _.cloneDeep(has_exam_types.value) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| function chooseChapterChildExercises() { | ||||
|   has_exam_types.value = _.cloneDeep(props.exam_types) || [] | ||||
|   drawer.value = true | ||||
|   onSubmit() | ||||
| } | ||||
| function onSubmit() { | ||||
|   queryParams.value.page = 1 | ||||
|   getExamGroupList() | ||||
| } | ||||
| function onReset() { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     subject:'', | ||||
|     status:'', | ||||
|   } | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExamGroupList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExamGroupList() | ||||
| } | ||||
|  | ||||
| const multipleTableRef = ref(null) | ||||
| function closeDf() { | ||||
|   gform.value = {} | ||||
|   dfVisible.value = false | ||||
| } | ||||
| // 新增组别 | ||||
| const rules = ref({ | ||||
|   persons: [{ required: true, message: '请输入报名人数', trigger: 'blur' }] | ||||
| }) | ||||
| const gform = ref({}) | ||||
| const times = ref(1) | ||||
| const dlTitle = ref('新增组别') | ||||
| function addWindow() { | ||||
|   edit_flag.value = false | ||||
|   openWindow() | ||||
| } | ||||
| function openWindow() { | ||||
|   dfVisible.value = true | ||||
| } | ||||
| function oFunc(val) { | ||||
|   if(times.value+val<1 || times.value+val>9) { | ||||
|     return | ||||
|   } | ||||
|   else{ | ||||
|     times.value+=val | ||||
|   } | ||||
| } | ||||
| function checkFunc(row) { // 检查合法性 | ||||
|   let flag = true | ||||
|   for(let item of has_exam_types.value) { | ||||
|       if(item.persons == row.persons) { // 相同人数(级别) | ||||
|         if( item.expiry_date > Date.parse(new Date())) { // 没有过期 | ||||
|           flag = false | ||||
|         } | ||||
|       } | ||||
|   } | ||||
|   return flag | ||||
| } | ||||
| function assigntTermFunc() { // 赋值期数 | ||||
|   let term = 1 | ||||
|   for(let item of has_exam_types.value) { | ||||
|       if(item.persons == gform.value.persons) { // 相同人数(级别) | ||||
|         term++ | ||||
|       } | ||||
|   } | ||||
|   return term | ||||
| } | ||||
| function enterDb() { // 确认新增/编辑 | ||||
|   if(edit_flag.value) { // 编辑 | ||||
|  | ||||
|   } | ||||
|   else{ // 新增 | ||||
|     // let f = checkFunc(gform.value) | ||||
|     // if(!f) { // 有相同人数且没有过期,无法再次创建 | ||||
|     //   ElMessage.error('该级别组数已存在!') | ||||
|     //   return | ||||
|     // } | ||||
|   } | ||||
|   if(!edit_flag.value) { // 新增 | ||||
|     gform.value.term = assigntTermFunc() | ||||
|     // 添加临时id | ||||
|     gform.value.temp_id = Date.parse(new Date()) | ||||
|     has_exam_types.value.push(_.cloneDeep(gform.value)) | ||||
|     type_list.value.push(_.cloneDeep(gform.value)) | ||||
|   } | ||||
|   else{ // 编辑 | ||||
|     if(gform.value.temp_id) { // 临时数据编辑 | ||||
|       for(let i=0; i<has_exam_types.value.length;i++ ) { | ||||
|         if(has_exam_types.value[i].temp_id && has_exam_types.value[i].temp_id === gform.value.temp_id) { | ||||
|             has_exam_types.value[i] = _.cloneDeep(gform.value) | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|       for(let i=0; i<type_list.value.length;i++ ) { | ||||
|         if(type_list.value[i].temp_id && type_list.value[i].temp_id === gform.value.temp_id) { | ||||
|             type_list.value[i] = _.cloneDeep(gform.value) | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     else{ // 根据id编辑 | ||||
|       for(let i=0; i<has_exam_types.value.length;i++ ) { | ||||
|         if(has_exam_types.value[i].exam_id === gform.value.exam_id) { | ||||
|             has_exam_types.value[i] = _.cloneDeep(gform.value) | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|       for(let i=0; i<type_list.value.length;i++ ) { | ||||
|         if(type_list.value[i].exam_id === gform.value.exam_id) { | ||||
|             type_list.value[i] = _.cloneDeep(gform.value) | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   closeDf() | ||||
| } | ||||
| function addFunc() { // 确认提交 | ||||
|   emit('addFunc',has_exam_types.value) | ||||
|   drawer.value = false | ||||
| } | ||||
| function changeFunc() { | ||||
|   gform.value.first = gform.value.persons | ||||
|   gform.value.second = gform.value.persons*0.04 | ||||
|   gform.value.third = gform.value.persons*0.01 | ||||
| } | ||||
| const edit_flag = ref(false) | ||||
| function editGroupFunc(row) { | ||||
|   dlTitle.value = '编辑组别' | ||||
|   edit_flag.value = true | ||||
|   gform.value = _.cloneDeep(row) | ||||
|   openWindow() | ||||
| } | ||||
| function delGroupFunc(row) { // 删除组别 | ||||
|   let del_index = -1 | ||||
|   for(let i=0;i<has_exam_types.value.length;i++) { | ||||
|     if(has_exam_types.value[i].exam_type_id === row.exam_type_id) { | ||||
|       del_index = i; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   has_exam_types.value.splice(del_index,1) | ||||
|   // 当前展示列表== | ||||
|   let del_index2 = -1 | ||||
|   for(let i=0;i<type_list.value.length;i++) { | ||||
|     if(type_list.value[i].exam_type_id === row.exam_type_id) { | ||||
|         del_index2 = i; | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|   type_list.value.splice(del_index2,1) | ||||
| } | ||||
| function close_draw() { | ||||
|   has_exam_types.value = _.cloneDeep(props.exam_types) || [] | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <el-button v-if="has_exam_types.length==0" size="small" @click="chooseChapterChildExercises">添加组别</el-button> | ||||
|     <el-button v-else size="small" @click="chooseChapterChildExercises" type="plain">点击查看(已发布{{has_exam_types.length}}组)</el-button> | ||||
|     <el-drawer v-model="drawer" @close="close_draw" title="组别库" size="60%"> | ||||
|       <div class="drawer-section"> | ||||
|         <!-- 搜索框--> | ||||
|         <div class="search-box gva-btn-list"> | ||||
|           <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|             <el-form-item label="分组历史"> | ||||
|               <el-input type="number" v-model="queryParams.term" placeholder="请输入分组历史期数" /> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="组别分类"> | ||||
|               <el-select v-model="queryParams.persons" clearable placeholder="请选择"> | ||||
|                 <el-option | ||||
|                   v-for="item in custom.getExamGroupType()" | ||||
|                   :key="item.value" | ||||
|                   :label="item.name" | ||||
|                   :value="item.value" | ||||
|                 /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|               <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|               <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|               <el-button size="small" type="primary" icon="plus" @click="addWindow">新增</el-button> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </div> | ||||
|         <!--      数据列表--> | ||||
|         <div class="list-box"> | ||||
|           <el-table ref="multipleTableRef"  :data="type_list"> | ||||
|             <el-table-column align="left" label="人数级别" min-width="150" prop="persons"> | ||||
|               <template #default="scope">{{custom.getSTdPerson(scope.row.persons)}}</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="截止时间" min-width="150" prop="expiry_date"> | ||||
|               <template #default="scope">{{custom.timestampToDate(scope.row.expiry_date)}}</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="公开时间" min-width="150" prop="public_date"> | ||||
|               <template #default="scope">{{custom.timestampToDate(scope.row.public_date)}}</template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="版本" min-width="150" prop="status"> | ||||
|               <template #default="scope"> | ||||
|                 第{{scope.row.term}}期 | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="left" label="报名人数" min-width="150" prop="enroll_num" /> | ||||
|             <el-table-column align="left" label="提交人数" min-width="150" prop="finish_num" /> | ||||
|             <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|               <template #default="scope"> | ||||
|                 <el-button | ||||
|                   icon="edit" | ||||
|                   size="small" | ||||
|                   type="primary" | ||||
|                   link | ||||
|                   @click="editGroupFunc(scope.row)" | ||||
|                 >编辑</el-button> | ||||
|                 <el-button | ||||
|                   icon="delete" | ||||
|                   size="small" | ||||
|                   type="danger" | ||||
|                   link | ||||
|                   v-if="!checkFunc(scope.row)" | ||||
|                   @click="delGroupFunc(scope.row)" | ||||
|                 >删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|           <div class="gva-pagination"> | ||||
|             <el-pagination | ||||
|               :current-page="queryParams.page" | ||||
|               :page-size="queryParams.pageSize" | ||||
|               :page-sizes="[10, 30, 50, 100]" | ||||
|               :total="total" | ||||
|               layout="total, sizes, prev, pager, next, jumper" | ||||
|               @current-change="handleCurrentChange" | ||||
|               @size-change="handleSizeChange" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <!--  按钮--> | ||||
|         <div class="btn-box" style="text-align: right"> | ||||
|           <el-button size="small" type="primary" @click="addFunc">确认</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-drawer> | ||||
|     <el-dialog v-model="dfVisible" :before-close="closeDf" :title="dlTitle"> | ||||
|       <el-form ref="apiForm" :model="gform" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="报名人数" > | ||||
|           <el-select @change="changeFunc" v-model="gform.persons" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in custom.getExamGroupType()" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|           <div class="more-info-text" v-if="gform.persons"> | ||||
|             第一名:{{gform.first}}元;第二名:{{gform.second}}元;第三名:{{gform.third}}元。(*满员参加的情况下) | ||||
|           </div> | ||||
| <!--          <div class="operator-box" >--> | ||||
| <!--            <div class="ob-btn ob-reduce" @click="oFunc(-1)">--> | ||||
| <!--              <el-icon color="#000"><Minus /></el-icon>--> | ||||
| <!--            </div>--> | ||||
| <!--            <div class="ob-input">--> | ||||
| <!--              {{times}}--> | ||||
| <!--            </div>--> | ||||
| <!--            <div class="ob-btn ob-add" @click="oFunc(1)">--> | ||||
| <!--              <el-icon color="#000"><Plus /></el-icon>--> | ||||
| <!--            </div>--> | ||||
| <!--          </div>--> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="截止时间" > | ||||
| <!--          <el-date-picker class="oi-item" style="margin-left:5px"--> | ||||
| <!--            v-model="gform.expiry_date"--> | ||||
| <!--            type="date"--> | ||||
| <!--            placeholder="截至日期"--> | ||||
| <!--            format="YYYY-MM-DD"--> | ||||
| <!--            value-format="x"--> | ||||
| <!--          />--> | ||||
|           <el-date-picker | ||||
|             v-model="gform.expiry_date" | ||||
|             type="datetime" | ||||
|             placeholder="截至日期" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="公开时间" > | ||||
| <!--          <el-date-picker class="oi-item" style="margin-left:5px"--> | ||||
| <!--            v-model="gform.public_date"--> | ||||
| <!--            type="date"--> | ||||
| <!--            placeholder="截至日期"--> | ||||
| <!--            format="YYYY-MM-DD"--> | ||||
| <!--            value-format="x"--> | ||||
| <!--          />--> | ||||
|           <el-date-picker | ||||
|             v-model="gform.public_date" | ||||
|             type="datetime" | ||||
|             placeholder="公开时间" | ||||
|             format="YYYY-MM-DD HH:mm:ss" | ||||
|             value-format="x" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDf">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDb">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style> | ||||
| .el-form-item{ | ||||
|     margin-bottom: 18px !important; | ||||
|   } | ||||
| </style> | ||||
| <style lang="scss" scoped> | ||||
|   .more-info-text{ | ||||
|     color: gray; | ||||
|     font-size: 12px; | ||||
|     margin: 0 10px; | ||||
|   } | ||||
|   .operator-box{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     border: 1px solid #dfdfdf; | ||||
|     border-radius: 5px; | ||||
|     margin-left: 10px; | ||||
|     .ob-btn{ | ||||
|       padding: 0 5px; | ||||
|       background: #dfdfdf; | ||||
|       cursor: pointer; | ||||
|     } | ||||
|     .ob-input{ | ||||
|       padding: 0 10px; | ||||
|     } | ||||
|   } | ||||
|   .drawer-section{ | ||||
|     padding: 10px; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										481
									
								
								src/view/examinationManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								src/view/examinationManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,481 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/examination' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import coursePool from './components/coursePool.vue' | ||||
| import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import groupPool from './components/groupPool.vue' | ||||
|  | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   teacherId:0, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'', | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| const price_props = ['first','second','third','price'] | ||||
| const exam_type_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getExaminationList() | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| const std_group = ref({ | ||||
|   persons:'', | ||||
|   expiry_date:'', | ||||
|   public_date:'', | ||||
|   first:'', | ||||
|   second:'', | ||||
|   third:'' | ||||
| }) | ||||
| // 方法 | ||||
| async function getExaminationList() { | ||||
|   const res = await api.getExaminationList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getExaminationList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getExaminationList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam.exam_id | ||||
|   }) | ||||
| } | ||||
| const exam_id = ref(null) | ||||
| function editCourseFunc(row) { | ||||
|   // row.exam.course_ids = JSON.parse(row.exam.course_ids) | ||||
|   // row.exam.question_ids = JSON.parse(row.exam.question_ids) | ||||
|   exam_id.value = row.exam.exam_id | ||||
|   form.value = _.cloneDeep(row.exam) | ||||
|   form.value.course_ids = JSON.parse(row.exam.course_ids) | ||||
|   form.value.question_ids = JSON.parse(row.exam.question_ids) | ||||
|   form.value.price = Number(form.value.price)/100 | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     for(let prop in item) { | ||||
|       if(price_props.includes(prop)) { | ||||
|           item[prop] /= 100 | ||||
|       } | ||||
|     } | ||||
|     return item | ||||
|   }) | ||||
|   // console.log(form.value) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getExaminationList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExaminationList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     for(let prop in item) { | ||||
|       if(Object.keys(std_group.value).includes(prop)) { | ||||
|         item[prop] = Number(item[prop]) | ||||
|         if(price_props.includes(prop)) { | ||||
|           item[prop] *= 100 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return item | ||||
|   }) | ||||
|   // console.log(form.value) | ||||
|   form.value.price = Number(form.value.price )*100 | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   // return | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getExaminationList() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{question_id:row.question_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push(_.cloneDeep(std_group.value)) | ||||
| } | ||||
| function delet_func(i) { | ||||
|   exam_types.value.splice(i,1) | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '上架' | ||||
|       break; | ||||
|     case -1: | ||||
|         str = '下架' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| function addGroupFunc(data) { | ||||
|   console.log("父组件行为") | ||||
|   exam_types.value = _.clone(data) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="试卷名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据试卷名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!exam_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="center" label="ID" min-width="60" prop="exam.exam_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="试卷名称" min-width="150" prop="exam.name" /> | ||||
|         <el-table-column align="center" label="科目" min-width="150" prop="exam.subject" /> | ||||
|         <el-table-column align="center" label="封面" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <img class="e-img" :src="scope.row.exam.cover" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="状态" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row.exam.status)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="销量"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.exam.sale}}份</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="组数" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.exam_types.length}}组</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="创建时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.exam.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editCourseFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteExamFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="试卷名称" > | ||||
|           <el-input v-model="form.name" placeholder="请输入试卷名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" @change="changeSubjectFunc" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar avatar-uploader-img" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试时长" > | ||||
|           <el-input type="number" v-model="form.duration" placeholder="请输入测试时长(分钟)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试价格" > | ||||
|           <el-input type="number" v-model="form.price" placeholder="请输入测试价格(元)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试组别" > | ||||
|           <groupPool @addFunc="addGroupFunc" :exam_types="exam_types" :exam_id="form.exam_id" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="添加习题" > | ||||
|           <exercisesPool @addFunc="addExercisesFunc" :seleted_arr="form.question_ids" /> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="适用课程" >--> | ||||
| <!--          <coursePool @addFunc="addCourseFunc" :seleted_arr="form.course_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item label="受否上架" > | ||||
|           <el-switch | ||||
|             v-model="form.status" | ||||
|             active-text="上架" | ||||
|             inactive-text="下架" | ||||
|             :active-value="1" | ||||
|             :inactive-value="-1" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-uploader-img{ | ||||
|     width: 178px; | ||||
|     height: 178px; | ||||
|   } | ||||
|   .avatar-uploader{ | ||||
|  | ||||
|   } | ||||
|   .rb-item{ | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     border-bottom: 1px solid #ebebeb; | ||||
|     margin-bottom: 10px; | ||||
|     .oi-row{ | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       margin-bottom: 10px; | ||||
|       .oi-item{ | ||||
|         //color: red; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										397
									
								
								src/view/exercisesManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								src/view/exercisesManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,397 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/exercises' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import _ from 'lodash' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import ckEditor from '@/components/richText/ckEditor5.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   teacherId:0, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   type:'', | ||||
|   subject:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     page:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const options = ref([]) // 答案选项数组 | ||||
| const question_form = ref({ | ||||
|   options:[], | ||||
|   answer:'', | ||||
|   title:'' | ||||
| }) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getExercisesList() | ||||
|   getSubject() | ||||
| }) | ||||
| // 方法 | ||||
| async function getExercisesList() { | ||||
|   const res = await api.getExercisesList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getExercisesList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     page:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增习题' | ||||
|       form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑习题' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = question_ids.value.map(item => item.question_id) | ||||
|   const res = await api.delExercises({ question_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getExercisesList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   question_ids.value = val | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   form.value = _.cloneDeep(row) | ||||
|   question_id.value = form.value.question_id | ||||
|   content.value = JSON.parse(form.value.question).title | ||||
|   question_form.value = JSON.parse(form.value.question) | ||||
|   if(!question_form.value.options) { | ||||
|     question_form.value.options = [] | ||||
|   } | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteCourseFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExercises({ | ||||
|           question_ids:[row.question_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getExercisesList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getExercisesList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   question_form.value = { | ||||
|     options:[], | ||||
|     answer:'', | ||||
|     title:'' | ||||
|   } | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.score = parseInt(form.value.score) | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.question = JSON.stringify(question_form.value) | ||||
|   let func_name = 'addExercises' | ||||
|   if(form.value.question_id) { // 编辑 | ||||
|       func_name = 'editExercises' | ||||
|   } | ||||
|   const res = await api[func_name](form.value) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     // deleteVisible.value = false | ||||
|     closeDialog() | ||||
|     getExercisesList() | ||||
|   } | ||||
| } | ||||
| function viewCourseFunc(row) { // 查看课程 | ||||
|   router.push({name:'viewCourse',params:{question_id:row.question_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   // for(let i=0 ;i<std_options_title.value.length;i++) { | ||||
|   //     if(!options.value.has(std_options_title.value[i])) { | ||||
|   //       options.value.set(std_options_title.value[i],'') | ||||
|   //       break; | ||||
|   //     } | ||||
|   // } | ||||
|  | ||||
|   for(let i=0 ;i<std_options_title.value.length;i++) { | ||||
|     let has_flag = false | ||||
|     for(let item of question_form.value.options){ | ||||
|       if(item.name === std_options_title.value[i]) { | ||||
|         has_flag = true | ||||
|       } | ||||
|     } | ||||
|     if(!has_flag) { | ||||
|       let data = { | ||||
|         name:std_options_title.value[i], | ||||
|         value: '' | ||||
|       } | ||||
|       question_form.value.options.push(data) | ||||
|       break | ||||
|     } | ||||
|   } | ||||
| } | ||||
| function delet_func(item) { | ||||
|   question_form.value.options.pop() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="题目名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据题目名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="课程分类"> | ||||
|           <el-select v-model="queryParams.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题型"> | ||||
|           <el-select v-model="queryParams.type" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in typeList" | ||||
|               :key="item.value" | ||||
|               :label="item.label" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!question_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="left" label="ID" min-width="60" prop="question_id" sortable="custom" /> | ||||
|         <el-table-column align="left" label="题型" min-width="150" prop="name" > | ||||
|           <template #default="scope"> | ||||
|             {{custom.getExercisesTypeName(scope.row.type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="科目" min-width="150" prop="subject" /> | ||||
|         <el-table-column align="left" label="题目" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             <!--            {{getExercisesName(scope.row)}}--> | ||||
|             <div v-html="getExercisesName(scope.row)"></div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="创建者" min-width="150" prop="teacher_id" /> | ||||
|         <el-table-column align="left" label="创建时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editCourseFunc(scope.row)" | ||||
|             >编辑</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteCourseFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题型" prop="type"> | ||||
|           <el-select v-model="form.type" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in typeList" | ||||
|               :key="item.value" | ||||
|               :label="item.label" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题目内容" > | ||||
|           <ckEditor v-model="question_form.title" style="width:100%" :content="question_form.title" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="分值" > | ||||
|           <el-input type="number" v-model="form.score" placeholder="请输入分值" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="答案" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="question_form" v-for="(item,i) in question_form.options"> | ||||
|               <view>{{item.name}}</view> | ||||
|               <ckEditor v-model="item.value" :content="item.value" style="margin-left:5px;width:100%" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == question_form.options.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加答案</el-button> | ||||
|           </view> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="正确答案" > | ||||
|           <el-input v-model="question_form.answer" placeholder="请输入正确答案(如,选择题:A或A-B;填空题直接填值)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="题目解析" > | ||||
| <!--          <el-input v-model="form.analysis" placeholder="请输入题目解析" />--> | ||||
|           <ckEditor v-model="form.resolve" style="width:100%" :content="form.resolve"  /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										293
									
								
								src/view/integralManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								src/view/integralManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/integral' | ||||
| // import capi from '@/api/course' | ||||
| // import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   status:'', | ||||
|   province:'' | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| import cityList from '@/utils/city.json'; | ||||
| // const cityList = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getIntegralList() | ||||
| }) | ||||
| const stateList = ref([ | ||||
|   { | ||||
|     name:'正常', | ||||
|     value:1 | ||||
|   }, | ||||
|   { | ||||
|     name:'冻结', | ||||
|     value:2 | ||||
|   } | ||||
| ]) | ||||
| // 方法 | ||||
| async function getIntegralList() { | ||||
|   const res = await api.getIntegralList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getIntegralList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getIntegralList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam_id | ||||
|   }) | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getIntegralList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getIntegralList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getIntegralList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getIntegralList() | ||||
|   } | ||||
| } | ||||
| function viewOrderFunc(row) { // 查看订单 | ||||
|   router.push({name:'viewOrder',params:{order_id:row.order_id}}) | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '正常' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '冻结' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="状态"> | ||||
|           <el-select v-model="queryParams.status" filterable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in stateList" | ||||
|               :key="item.value" | ||||
|               :label="item.name" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="所属区域"> | ||||
|           <el-select v-model="queryParams.province" filterable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in cityList" | ||||
|               :key="item.ProID" | ||||
|               :label="item.name" | ||||
|               :value="item.ProID" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="point_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="姓名"  prop="nickname" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="所属区域" prop="province" /> | ||||
|         <el-table-column align="center" label="剩余积分" prop="balance" /> | ||||
|         <el-table-column align="center" label="累计积分" prop="total" /> | ||||
|         <el-table-column align="center" label="邀请好友(分)" min-width="150" prop="invite" /> | ||||
|         <el-table-column align="center" label="购买课程(分)" min-width="150" prop="course" /> | ||||
|         <el-table-column align="center" label="累计消费(分)" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="抽奖(分)" prop="raffle" /> | ||||
|         <el-table-column align="center" label="竞拍(分)" prop="bidding" /> | ||||
|         <el-table-column align="center" label="状态"  > | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row.status)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="提交时间" min-width="200" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewOrderFunc(scope.row)" | ||||
|             >冻结</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteExamFunc(scope.row)" | ||||
|             >解冻</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										313
									
								
								src/view/lbtManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								src/view/lbtManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/lbt' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| import {ref,onMounted } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| const dialogFormVisible = ref(false) | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| import {parseTime} from '@/utils' | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10 | ||||
| }) | ||||
| const deleteVisible = ref(false) | ||||
| const lbt_ids = ref([]) | ||||
| const dialogTitle = ref('') | ||||
| const form = ref({status:'1'}) | ||||
| const lbtType_options = ref([ | ||||
|   { | ||||
|     label:'首页', | ||||
|     value:'1' | ||||
|   } | ||||
| ]) | ||||
| const rules = ref({ | ||||
|   lbtName: [{ required: true, message: '请输入名称', trigger: 'blur' }], | ||||
|   lbtUrl: [{ required: true, message: '请选择素材', trigger: 'blur' }], | ||||
|   lbtSkipUrl:[{ required: true, message: '请填写跳转链接', trigger: 'blur' }], | ||||
|   lbtType:[{ required: true, message: '请选择展示位置', trigger: 'blur' }] | ||||
| }) | ||||
| const ruleFormRef = ref(null) | ||||
| const tableData = ref([]) | ||||
| const total = ref(0) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getLbtList() | ||||
| }) | ||||
| // 方法 | ||||
| async function getLbtList() { | ||||
|   const res = await api.getLbtManageList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   dialogFormVisible.value = true | ||||
|   switch (type) { | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增轮播图' | ||||
|       break; | ||||
|     case 'edit': | ||||
|       dialogTitle.value = '编辑轮播图' | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = lbt_ids.value.map(item => item.banner_id) | ||||
|   const res = await api.delLbt({ ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getLbtList() | ||||
|   } | ||||
| } | ||||
| function closeDialog() { | ||||
|   dialogFormVisible.value = false | ||||
|   form.value = {status:'1'} | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   console.log(res) | ||||
|   form.value.lbtUrl = res.data.file.url | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function enterDialog() { | ||||
|   console.log(form.value) | ||||
|   submitForm(ruleFormRef.value) | ||||
| } | ||||
| const submitForm = async (formEl) => { | ||||
|   if (!formEl) return | ||||
|   await formEl.validate((valid, fields) => { | ||||
|     if (valid) { | ||||
|       console.log('submit!') | ||||
|       saveForm() | ||||
|     } else { | ||||
|       // console.log('error submit!', fields) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| async function saveForm() { | ||||
|   let func_name = '' | ||||
|   if(form.value.banner_id){ // 编辑 | ||||
|     func_name = 'editLbtManage' | ||||
|   } | ||||
|   else{ | ||||
|     func_name = 'addLbtManage' | ||||
|   } | ||||
|   form.value.status = parseInt(form.value.status) | ||||
|   form.value.lbtSkipUrlType = parseInt(form.value.lbtSkipUrlType) | ||||
|   form.value.lbtType = parseInt(form.value.lbtType) | ||||
|   const res = await api[func_name](form.value) | ||||
|   if(res.code === 0) | ||||
|   { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '操作成功!' | ||||
|       }) | ||||
|     getLbtList() | ||||
|     closeDialog() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   lbt_ids.value = val | ||||
| } | ||||
| function editLbtFunc(item) { | ||||
|   form.value = item | ||||
|   openDialog('edit') | ||||
| } | ||||
| function delLbtFunc(item) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     console.log(1) | ||||
|     const res = await api.delLbt({ | ||||
|           ids:[item.banner_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       // if (tableData.value.length === 1 && page.value > 1) { | ||||
|       //   page.value-- | ||||
|       // } | ||||
|       getLbtList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.page = val | ||||
|   getLbtList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getLbtList() | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|           <template #reference> | ||||
|             <el-button icon="delete" size="small" type="danger" :disabled="!lbt_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button> | ||||
|           </template> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column | ||||
|           type="selection" | ||||
|           width="55" | ||||
|         /> | ||||
|         <el-table-column align="left" label="名称" min-width="150" prop="lbtName" /> | ||||
|         <el-table-column align="left" label="缩略图" min-width="150" prop="lbtUrl"> | ||||
|           <template #default="scope"> | ||||
|             <img class="lbt-thumb" :src="scope.row.lbtUrl" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="是否启用" min-width="150" prop="status" > | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.status == '1'?'启用':'禁用'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="说明" min-width="150" prop="lbtIntroduction" /> | ||||
|         <el-table-column align="left" label="更新时间" min-width="150" prop="UpdatedAt"> | ||||
|           <template #default="scope"> | ||||
|             {{parseTime(scope.row.UpdatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="left" label="操作" min-width="150" prop="status"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="editLbtFunc(scope.row)" | ||||
|             >修改</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="delLbtFunc(scope.row)" | ||||
|             >删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--新增、编辑 窗口--> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="名称" prop="lbtName"> | ||||
|           <el-input v-model="form.lbtName" placeholder="请输入名称" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="素材" prop="lbtUrl"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.lbtUrl" :src="form.lbtUrl" class="img-container" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="说明" prop="lbtIntroduction"> | ||||
|           <el-input v-model="form.lbtIntroduction" placeholder="说明" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="链接状态" prop="method"> | ||||
|           <el-switch v-model="form.lbtSkipUrlType" :active-value="1" :inactive-value="2" active-text="外链" inactive-text="内链" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="链接地址" prop="lbtSkipUrl"> | ||||
|           <el-input v-model="form.lbtSkipUrl" placeholder="链接地址" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="启用状态" prop="status"> | ||||
|           <el-switch v-model="form.status" :active-value="1" :inactive-value="2" active-text="启用" inactive-text="禁用" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="展示位置" prop="lbtType"> | ||||
|           <el-select v-model="form.lbtType" class="m-2" placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in lbtType_options" | ||||
|               :key="item.value" | ||||
|               :label="item.label" | ||||
|               :value="item.value" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item style="display: none"> | ||||
|           <el-button type="primary" @click="submitForm(ruleFormRef)"> | ||||
|             Create | ||||
|           </el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped> | ||||
| .img-container{ | ||||
|   width: 200px; | ||||
|   height: 150px; | ||||
| } | ||||
|   .gva-btn-list{ | ||||
|     justify-content: end; | ||||
|   } | ||||
|   .lbt-thumb{ | ||||
|     width: 100px; | ||||
|     height: 50px; | ||||
|   } | ||||
| </style> | ||||
| @@ -67,12 +67,12 @@ | ||||
|             </div> | ||||
|           </el-form-item> | ||||
|           <el-form-item> | ||||
|             <el-button | ||||
|               type="primary" | ||||
|               style="width: 46%" | ||||
|               size="large" | ||||
|               @click="checkInit" | ||||
|             >前往初始化</el-button> | ||||
| <!--            <el-button--> | ||||
| <!--              type="primary"--> | ||||
| <!--              style="width: 46%"--> | ||||
| <!--              size="large"--> | ||||
| <!--              @click="checkInit"--> | ||||
| <!--            >前往初始化</el-button>--> | ||||
|             <el-button | ||||
|               type="primary" | ||||
|               size="large" | ||||
|   | ||||
							
								
								
									
										316
									
								
								src/view/marketManage/assistantList/assistantDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								src/view/marketManage/assistantList/assistantDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,316 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/market' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const assistantInfo = ref({}) | ||||
| const imgs = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getAssistantDetail() | ||||
| }) | ||||
| // funstions | ||||
| async function getAssistantDetail() { | ||||
|   const res = await api.getAssistantDetail({id:route.params.id}) | ||||
|   if(res.code === 0) { | ||||
|     assistantInfo.value = res.data | ||||
|     // let teacher_cert = JSON.parse(res.data.teacher_cert) | ||||
|     // let skill_cert = JSON.parse(res.data.skill_cert) | ||||
|     // imgs.value = [...skill_cert,...teacher_cert] | ||||
|     // console.log(imgs.value) | ||||
|   } | ||||
| } | ||||
| const tip_text = ref('') | ||||
| const dialogVisible = ref(false) | ||||
| const a_type = ref(0) | ||||
| function actionFunc(type) { | ||||
|   dialogVisible.value = true | ||||
|   a_type.value = type | ||||
|   switch (type){ | ||||
|     case 3: | ||||
|       tip_text.value = '是否同意该助教申请?'; | ||||
|       break; | ||||
|     case 2: | ||||
|       tip_text.value = '是否拒绝该助教申请?'; | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| async function actionOk() { // 确认提交 | ||||
|   const res = await api.teacherOperator({ | ||||
|     teacher_id:assistantInfo.value.user_id, | ||||
|     status:a_type.value | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     getAssistantDetail() | ||||
|   } | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '待审核' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已拒绝' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已同意' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     助教详情 | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseInfo-box"> | ||||
|         <div class="bb-item"> | ||||
|           <img class="avatar" :src="assistantInfo.avatar" alt=""> | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           昵称:{{assistantInfo.nickname}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           ID:{{assistantInfo.user_id}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           注册时间:{{formatDate(assistantInfo.created_at)}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           身份:助教 | ||||
|         </div> | ||||
| <!--        <div class="bb-item">--> | ||||
| <!--          邀请人数:105人--> | ||||
| <!--        </div>--> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    详细信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="detail-info-box"> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">身份证号码:</div> | ||||
|             <div class="di-right">{{assistantInfo.id_card}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">手机号码:</div> | ||||
|             <div class="di-right">{{assistantInfo.phone}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">邀请人姓名:</div> | ||||
|             <div class="di-right">{{assistantInfo.invite_nickname}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">邀请人ID号:</div> | ||||
|             <div class="di-right">{{assistantInfo.invite_id}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">邀请人数:</div> | ||||
|             <div class="di-right">{{assistantInfo.invite_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">有效人数:</div> | ||||
|             <div class="di-right">{{assistantInfo.valid_num}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">管理学员:</div> | ||||
|             <div class="di-right">{{assistantInfo.student_num}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">课程订单:</div> | ||||
|             <div class="di-right">{{assistantInfo.course_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">课程收益:</div> | ||||
|             <div class="di-right">{{assistantInfo.course_income}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">试卷订单:</div> | ||||
|             <div class="di-right">{{assistantInfo.exam_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">试卷收益:</div> | ||||
|             <div class="di-right">{{assistantInfo.exam_income}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">推荐老师:</div> | ||||
|             <div class="di-right">{{assistantInfo.teacher_num}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
| <!--        <div class="dib-row">--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">授课总订单:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">授课总收益:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--        </div>--> | ||||
| <!--        <div class="dib-row">--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">试卷总订单:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">试卷总收益:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--        </div>--> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">推荐助教:</div> | ||||
|             <div class="di-right">{{assistantInfo.assistant_num}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
| <!--        <div class="dib-row">--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">课程总订单:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">课程总收益:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--        </div>--> | ||||
| <!--        <div class="dib-row">--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">试卷总订单:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--          <div class="dib-item">--> | ||||
| <!--            <div class="di-left">试卷总收益:</div>--> | ||||
| <!--            <div class="di-right">{{assistantInfo.assistant_info?.num}}</div>--> | ||||
| <!--          </div>--> | ||||
| <!--        </div>--> | ||||
|  | ||||
|       </div> | ||||
|       <!--    操作区域--> | ||||
|       <div class="action-box" v-if="assistantInfo.status == 1"> | ||||
|         <div class="a-btn approved" @click="actionFunc(3)">同意</div> | ||||
|         <div class="a-btn refuse" @click="actionFunc(2)">拒绝</div> | ||||
|       </div> | ||||
|       <div class="action-box" v-else> | ||||
|         <div class="state-text" :class="{'reuse-text':assistantInfo.status == 2}">{{getStateName(assistantInfo.status)}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog | ||||
|       v-model="dialogVisible" | ||||
|       title="操作提醒" | ||||
|       width="30%" | ||||
|     > | ||||
|       <span>{{tip_text}}</span> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="actionOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .action-box{ | ||||
|     display: flex; | ||||
|     margin-top: 20px; | ||||
|     justify-content: center; | ||||
|     .a-btn{ | ||||
|       background: rgb(60, 106, 112); | ||||
|       color: white; | ||||
|       padding: 10px 50px; | ||||
|       cursor: pointer; | ||||
|       margin: 10px; | ||||
|           border-radius: 5px; | ||||
|     } | ||||
|     .approved{ | ||||
|  | ||||
|     } | ||||
|     .refuse{ | ||||
|       background: white !important; | ||||
|       color:rgb(60, 106, 112) !important; | ||||
|       border: 1px solid rgb(60, 106, 112) !important; | ||||
|     } | ||||
|   } | ||||
|   /*基本信息*/ | ||||
|   .gva-search-box{ | ||||
|     .baseInfo-box{ | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       //justify-content: space-around; | ||||
|       .bb-item{ | ||||
|         margin: 10px 20px; | ||||
|         .avatar{ | ||||
|           width: 50px; | ||||
|           height: 50px; | ||||
|           border-radius: 50%; | ||||
|           border: 1px solid #cdcdcd; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /*详细信息*/ | ||||
|   .text{ | ||||
|     color: red !important; | ||||
|   } | ||||
|   .state-text{ | ||||
|     font-size: 15px; | ||||
|     color: gray; | ||||
|   } | ||||
|   .gva-table-box{ | ||||
|     .detail-info-box{ | ||||
|       .dib-row{ | ||||
|         overflow: hidden; | ||||
|         .link-item{ | ||||
|           color: #3C6A70 !important; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         .dib-item{ | ||||
|           //color: gray; | ||||
|           padding: 10px 0; | ||||
|           display: flex; | ||||
|           float: left; | ||||
|           margin-right: 30px; | ||||
|           .di-left{ | ||||
|           } | ||||
|           .img-css{ | ||||
|             width: 100px; | ||||
|             height: 100px; | ||||
|             margin: 0 10px 10px 0; | ||||
|             cursor: pointer; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										303
									
								
								src/view/marketManage/assistantList/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								src/view/marketManage/assistantList/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/market' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| // const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'', | ||||
|   province:'' | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'申请中', | ||||
|       id:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'拒绝', | ||||
|       id:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'同意', | ||||
|       id:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| // const dialogFormVisible = ref(false) | ||||
| // const dialogTitle = ref('') | ||||
| // const form =ref({}) | ||||
| // const rules = ref({ | ||||
| //   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| // }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const teacher_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getAssistantList() | ||||
| }) | ||||
| // provide('subjectList', subjectList) | ||||
| // provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getAssistantList() { | ||||
|   const res = await api.getAssistantList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| // async function getSubject(){ // 获取课程分类 | ||||
| //   const res = await capi.getSubjectList(subjectParams.value) | ||||
| //   if(res.code === 0) { | ||||
| //     subjectList.value = custom.getStdSubject(res.data.records) | ||||
| //   } | ||||
| // } | ||||
| function onSubmit() { | ||||
|   getAssistantList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = teacher_ids.value | ||||
|   const res = await api.delExamination({ teacher_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getAssistantList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   teacher_ids.value = val.map((item) => { | ||||
|       return item.teacher_info_id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getAssistantList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getAssistantList() | ||||
| } | ||||
| function viewAssistantFunc(row) { // 查看详情 | ||||
|   router.push({name:'assistantDetail',params:{id:row.user_id}}) | ||||
| } | ||||
| //审核相关 | ||||
| const p_visible = ref(false) | ||||
| const pFormRules = ref({ | ||||
|   desc: [{ required: true, message: '请输入说明', trigger: 'blur' }] | ||||
| }) | ||||
| const p_type = ref(null); // 审核类型 | ||||
| const pForm = ref({}) | ||||
| const teacher_id = ref(0) | ||||
| const p_title = ref('') | ||||
| function processFunc(row,state) { // 审核 | ||||
|   p_type.value = state | ||||
|   p_visible.value = true | ||||
|   teacher_id.value = row.user_id | ||||
|   if(state === 3) { //同意 | ||||
|     p_title.value = '审核同意' | ||||
|   } | ||||
|   else if(state === 2) { // 拒绝 | ||||
|     p_title.value = '审核拒绝' | ||||
|   } | ||||
| } | ||||
| function close_pv(){ | ||||
|   p_visible.value = false | ||||
| } | ||||
| async function pOk() { // 审核提交 | ||||
|   const res = await api.teacherOperator({ | ||||
|     teacher_id:teacher_id.value, | ||||
|     status:p_type.value, | ||||
|     desc:pForm.value.desc | ||||
|   }) | ||||
|   ElMessage({ | ||||
|     type: 'success', | ||||
|     message: res.data.msg | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     close_pv() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="助教名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据助教名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="助教状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="user_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="头像"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.avatar" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" min-width="150" label="姓名" prop="nickname" /> | ||||
|         <el-table-column align="center" label="申请时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.created_at)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150"> | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.province>-1?cityList[scope.row.province].name:'无'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
| <!--        <el-table-column align="center" label="管理学员" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="课程订单" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="收益" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="试卷订单" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="收益" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="推荐老师" prop="invite_id" />--> | ||||
| <!--        <el-table-column align="center" label="收益" prop="invite_id" />--> | ||||
|  | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewAssistantFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="processFunc(scope.row,2)" | ||||
|             >同意</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="processFunc(scope.row,3)" | ||||
|             >拒绝</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    审核窗口--> | ||||
|     <el-dialog | ||||
|       v-model="p_visible" | ||||
|       :title="p_title" | ||||
|       width="30%" | ||||
|       :before-close="close_pv" | ||||
|     > | ||||
|       <el-form ref="apiForm" :model="pForm" :rules="pFormRules" label-width="80px"> | ||||
|         <el-form-item label="审核说明" prop="name"> | ||||
|           <el-input v-model="pForm.desc" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="p_visible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="pOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										237
									
								
								src/view/marketManage/managerList/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								src/view/marketManage/managerList/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/market' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 地区 | ||||
| import cityList from '@/utils/city.json' | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| // const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   key:'', | ||||
|   province:'' | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'申请中', | ||||
|       id:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'拒绝', | ||||
|       id:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'同意', | ||||
|       id:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| // const dialogFormVisible = ref(false) | ||||
| // const dialogTitle = ref('') | ||||
| // const form =ref({}) | ||||
| // const rules = ref({ | ||||
| //   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| // }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const teacher_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getManagerList() | ||||
| }) | ||||
| // provide('subjectList', subjectList) | ||||
| // provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getManagerList() { | ||||
|   const res = await api.getManagerList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| // async function getSubject(){ // 获取课程分类 | ||||
| //   const res = await capi.getSubjectList(subjectParams.value) | ||||
| //   if(res.code === 0) { | ||||
| //     subjectList.value = custom.getStdSubject(res.data.records) | ||||
| //   } | ||||
| // } | ||||
| function onSubmit() { | ||||
|   getManagerList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = teacher_ids.value | ||||
|   const res = await api.delExamination({ teacher_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getManagerList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   teacher_ids.value = val.map((item) => { | ||||
|       return item.teacher_info_id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getManagerList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getManagerList() | ||||
| } | ||||
| function viewManagerFunc(row) { // 查看详情 | ||||
|   router.push({name:'managerDetail',params:{id:row.user_id}}) | ||||
| } | ||||
|  | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="主管名称"> | ||||
|           <el-input v-model="queryParams.key" placeholder="根据主管名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="管辖区域"> | ||||
|           <el-select v-model="queryParams.province" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="(item,index) in cityList" | ||||
|               :key="item.ProID" | ||||
|               :label="item.name" | ||||
|               :value="index" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="user_id" sortable="custom" /> | ||||
|         <el-table-column align="center" min-width="150" label="姓名" prop="nickname" /> | ||||
|  | ||||
|         <el-table-column align="center" label="开通时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="负责区域" min-width="150"> | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.province>-1?cityList[scope.row.province].name:'无'}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="域内市场助教" prop="assistant_num" /> | ||||
|         <el-table-column align="center" label="域内市场学员" prop="student_num" /> | ||||
|         <el-table-column align="center" label="课程订单" prop="course_num" /> | ||||
|         <el-table-column align="center" label="佣金" prop="course_income" /> | ||||
|         <el-table-column align="center" label="试卷订单" prop="exam_num" /> | ||||
|         <el-table-column align="center" label="佣金" prop="exam_income" /> | ||||
|  | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewManagerFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="processFunc(scope.row,3)" | ||||
|             >关闭</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!-- 新增&编辑 窗口-->git | ||||
|  | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										249
									
								
								src/view/marketManage/managerList/managerDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/view/marketManage/managerList/managerDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/market' | ||||
| // import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 地区 | ||||
| import cityList from '@/utils/city.json' | ||||
| // 变量 | ||||
| const managerInfo = ref({}) | ||||
| const imgs = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getManagerDetail() | ||||
| }) | ||||
| // funstions | ||||
| async function getManagerDetail() { | ||||
|   const res = await api.getManagerDetail({managerId:route.params.id}) | ||||
|   if(res.code === 0) { | ||||
|     managerInfo.value = res.data | ||||
|     // let teacher_cert = JSON.parse(res.data.teacher_cert) | ||||
|     // let skill_cert = JSON.parse(res.data.skill_cert) | ||||
|     // imgs.value = [...skill_cert,...teacher_cert] | ||||
|     // console.log(imgs.value) | ||||
|   } | ||||
| } | ||||
| const tip_text = ref('') | ||||
| const dialogVisible = ref(false) | ||||
| const a_type = ref(0) | ||||
| function actionFunc(type) { | ||||
|   dialogVisible.value = true | ||||
|   a_type.value = type | ||||
|   switch (type){ | ||||
|     case 3: | ||||
|       tip_text.value = '是否同意该助教申请?'; | ||||
|       break; | ||||
|     case 2: | ||||
|       tip_text.value = '是否拒绝该助教申请?'; | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| async function actionOk() { // 确认提交 | ||||
|   const res = await api.teacherOperator({ | ||||
|     teacher_id:managerInfo.value.user_id, | ||||
|     status:a_type.value | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     getManagerDetail() | ||||
|   } | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '待审核' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已拒绝' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已同意' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     助教详情 | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseInfo-box"> | ||||
|         <div class="bb-item"> | ||||
|           <img class="avatar" :src="managerInfo.avatar" alt=""> | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           昵称:{{managerInfo.nickname}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           ID:{{managerInfo.user_id}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           注册时间:{{formatDate(managerInfo.CreatedAt)}} | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    详细信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="detail-info-box"> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">管理区域:</div> | ||||
|             <div class="di-right">{{managerInfo.province>-1?cityList[managerInfo.province].name:'无'}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">身份证号码:</div> | ||||
|             <div class="di-right">{{managerInfo.id_card}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">手机号码:</div> | ||||
|             <div class="di-right">{{managerInfo.phone}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">域内助教人数:</div> | ||||
|             <div class="di-right">{{managerInfo.assistant_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">域内学员人数:</div> | ||||
|             <div class="di-right">{{managerInfo.student_num}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">课程总订单数:</div> | ||||
|             <div class="di-right">{{managerInfo.course_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">课程总学费:</div> | ||||
|             <div class="di-right">{{managerInfo.course_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">课程总佣金:</div> | ||||
|             <div class="di-right">{{managerInfo.course_income}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">测试总订单数:</div> | ||||
|             <div class="di-right">{{managerInfo.exam_num}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">测试总学费:</div> | ||||
|             <div class="di-right">{{managerInfo.exam_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">测试总佣金:</div> | ||||
|             <div class="di-right">{{managerInfo.exam_income}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog | ||||
|       v-model="dialogVisible" | ||||
|       title="操作提醒" | ||||
|       width="30%" | ||||
|     > | ||||
|       <span>{{tip_text}}</span> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="actionOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .action-box{ | ||||
|     display: flex; | ||||
|     margin-top: 20px; | ||||
|     justify-content: center; | ||||
|     .a-btn{ | ||||
|       background: rgb(60, 106, 112); | ||||
|       color: white; | ||||
|       padding: 10px 50px; | ||||
|       cursor: pointer; | ||||
|       margin: 10px; | ||||
|           border-radius: 5px; | ||||
|     } | ||||
|     .approved{ | ||||
|  | ||||
|     } | ||||
|     .refuse{ | ||||
|       background: white !important; | ||||
|       color:rgb(60, 106, 112) !important; | ||||
|       border: 1px solid rgb(60, 106, 112) !important; | ||||
|     } | ||||
|   } | ||||
|   /*基本信息*/ | ||||
|   .gva-search-box{ | ||||
|     .baseInfo-box{ | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       //justify-content: space-around; | ||||
|       .bb-item{ | ||||
|         margin: 10px 20px; | ||||
|         .avatar{ | ||||
|           width: 50px; | ||||
|           height: 50px; | ||||
|           border-radius: 50%; | ||||
|           border: 1px solid #cdcdcd; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /*详细信息*/ | ||||
|   .text{ | ||||
|     color: red !important; | ||||
|   } | ||||
|   .state-text{ | ||||
|     font-size: 15px; | ||||
|     color: gray; | ||||
|   } | ||||
|   .gva-table-box{ | ||||
|     .detail-info-box{ | ||||
|       .dib-row{ | ||||
|         overflow: hidden; | ||||
|         .link-item{ | ||||
|           color: #3C6A70 !important; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         .dib-item{ | ||||
|           //color: gray; | ||||
|           padding: 10px 0; | ||||
|           display: flex; | ||||
|           float: left; | ||||
|           margin-right: 30px; | ||||
|           .di-left{ | ||||
|           } | ||||
|           .img-css{ | ||||
|             width: 100px; | ||||
|             height: 100px; | ||||
|             margin: 0 10px 10px 0; | ||||
|             cursor: pointer; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										446
									
								
								src/view/orderManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								src/view/orderManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,446 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/order' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   teacherId:0, | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   orderType:0, | ||||
|   nickname:'', | ||||
|   status:0 | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getOrderList() | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getOrderList() { | ||||
|   const res = await api.getOrderList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getOrderList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getOrderList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam_id | ||||
|   }) | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   row.course_ids = JSON.parse(row.course_ids) | ||||
|   row.question_ids = JSON.parse(row.question_ids) | ||||
|  | ||||
|   form.value = row.exam | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     return item.persons | ||||
|   }) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getOrderList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getOrderList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getOrderList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getOrderList() | ||||
|   } | ||||
| } | ||||
| function viewOrderFunc(row) { // 查看订单 | ||||
|   router.push({name:'viewOrder',params:{order_id:row.order_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push('') | ||||
| } | ||||
| function delet_func() { | ||||
|   exam_types.value.pop() | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '未付款' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已付款' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已过期' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| function getTypeName(type) { | ||||
|   let name = "" | ||||
|   switch (type) { | ||||
|     case 1: | ||||
|       name = '课程'; | ||||
|       break; | ||||
|     case 2: | ||||
|       name = '章节'; | ||||
|       break; | ||||
|     case 3: | ||||
|       name = '子章节'; | ||||
|       break; | ||||
|     case 4: | ||||
|       name = '试卷'; | ||||
|       break; | ||||
|   } | ||||
|   return name | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="订单名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据订单名称进行查询" /> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="课程分类">--> | ||||
| <!--          <el-select v-model="queryParams.subject" clearable placeholder="请选择">--> | ||||
| <!--            <el-option--> | ||||
| <!--              v-for="item in subjectList"--> | ||||
| <!--              :key="item.id"--> | ||||
| <!--              :label="item.name"--> | ||||
| <!--              :value="item.name"--> | ||||
| <!--            />--> | ||||
| <!--          </el-select>--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
| <!--        <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button>--> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
| <!--          <template #reference>--> | ||||
| <!--            <el-button icon="delete" size="small" type="danger" :disabled="!exam_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>--> | ||||
| <!--          </template>--> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
| <!--        <el-table-column--> | ||||
| <!--          type="selection"--> | ||||
| <!--          width="55"--> | ||||
| <!--        />--> | ||||
|         <el-table-column align="center" label="ID"  prop="order_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="用户昵称" min-width="150" prop="nickname" /> | ||||
|         <el-table-column align="center" label="用户ID" prop="user_id" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="类型" min-width="150" prop="order_type"> | ||||
|           <template #default="scope"> | ||||
|             {{getTypeName(scope.row.order_type)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="商品名称" min-width="150" prop="name" /> | ||||
|         <el-table-column align="center" label="订单金额" min-width="150" prop="price" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150" prop="province" /> | ||||
|         <el-table-column align="center" label="状态"  > | ||||
|           <template #default="scope"> | ||||
|             <div>{{getStateName(scope.row.status)}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="提交时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewOrderFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
| <!--            <el-button--> | ||||
| <!--              icon="delete"--> | ||||
| <!--              size="small"--> | ||||
| <!--              type="danger"--> | ||||
| <!--              link--> | ||||
| <!--              @click="deleteExamFunc(scope.row)"--> | ||||
| <!--            >删除</el-button>--> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="试卷名称" > | ||||
|           <el-input v-model="form.name" placeholder="请输入试卷名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" @change="changeSubjectFunc" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试时长" > | ||||
|           <el-input type="number" v-model="form.duration" placeholder="请输入测试时长(分钟)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试组别" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="exam_types.length>0" v-for="(item,i) in exam_types"> | ||||
|               <view>{{i+1}}</view> | ||||
|               <el-input type="number" style="margin-left:5px" v-model="exam_types[i]" placeholder="请输入组别人数" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == exam_types.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加组别</el-button> | ||||
|           </view> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="添加习题" >--> | ||||
| <!--          <exercisesPool @addFunc="addExercisesFunc" :seleted_arr="form.question_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
| <!--        <el-form-item label="适用课程" >--> | ||||
| <!--          <coursePool @addFunc="addCourseFunc" :seleted_arr="form.course_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item label="受否上架" > | ||||
|           <el-switch | ||||
|             v-model="form.status" | ||||
|             active-text="上架" | ||||
|             inactive-text="下架" | ||||
|             :active-value="1" | ||||
|             :inactive-value="-1" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								src/view/orderManage/orderDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/view/orderManage/orderDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/order' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| // const order_id = ref(0) | ||||
| const orderInfo = ref({}) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   // console.log(route.params) | ||||
|   // order_id.value = route.params.order_id | ||||
|   getOrderDetail() | ||||
| }) | ||||
| // funstions | ||||
| async function getOrderDetail() { | ||||
|   const res = await api.getOrderDetail({id:route.params.order_id}) | ||||
|   if(res.code === 0) { | ||||
|     orderInfo.value = res.data | ||||
|   } | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '未付款' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已付款' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已过期' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseInfo-box"> | ||||
|         <div class="bd-img"> | ||||
|           <img :src="orderInfo.cover" alt=""> | ||||
|         </div> | ||||
|         <div class="bd-info"> | ||||
|           <div class="bdi-title">{{orderInfo.name}}</div> | ||||
|           <div class="bdi-price">¥{{orderInfo.price}}</div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    章节信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="detail-info-box"> | ||||
|         <div class="dib-item di-title"> | ||||
|           用户信息 | ||||
|         </div> | ||||
|         <div class="dib-item"> | ||||
|           <div class="di-left">用户名称:</div> | ||||
|           <div class="di-right">{{orderInfo.nickname}}</div> | ||||
|         </div> | ||||
|         <div class="dib-item"> | ||||
|           <div class="di-left">用户手机:</div> | ||||
|           <div class="di-right">{{orderInfo.phone}}</div> | ||||
|         </div> | ||||
|         <div class="dib-item di-title"> | ||||
|           订单信息 | ||||
|         </div> | ||||
|         <div class="dib-item"> | ||||
|           <div class="di-left">订单编号:</div> | ||||
|           <div class="di-right">{{orderInfo.order_id}}</div> | ||||
|         </div> | ||||
|         <div class="dib-item"> | ||||
|           <div class="di-left">提交时间:</div> | ||||
|           <div class="di-right">{{formatDate(orderInfo.CreatedAt)}}</div> | ||||
|         </div> | ||||
|         <div class="dib-item"> | ||||
|           <div class="di-left">订单状态:</div> | ||||
|           <div class="di-right">{{getStateName(orderInfo.status)}}</div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <!--    操作区域--> | ||||
| <!--      <div class="action-box">--> | ||||
| <!--        <div class="pay-btn">去付款</div>--> | ||||
| <!--      </div>--> | ||||
|     </div> | ||||
|  | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .action-box{ | ||||
|     display: flex; | ||||
|     margin-top: 20px; | ||||
|     .pay-btn{ | ||||
|       background: rgb(60, 106, 112); | ||||
|       color: white; | ||||
|       padding: 10px 50px; | ||||
|       cursor: pointer; | ||||
|     } | ||||
|   } | ||||
|   /*章节信息*/ | ||||
|   .gva-search-box{ | ||||
|     .baseInfo-box{ | ||||
|       display: flex; | ||||
|       .bd-img{ | ||||
|         img{ | ||||
|           width: 200px; | ||||
|           height: 100px; | ||||
|         } | ||||
|         margin-right: 10px; | ||||
|       } | ||||
|       .bd-info{ | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         justify-content: space-around; | ||||
|         .bdi-title,.bdi-price{ | ||||
|           font-weight: 900; | ||||
|           font-size: 18px; | ||||
|         } | ||||
|         .bdi-title{ | ||||
|           margin-bottom: 20px; | ||||
|         } | ||||
|         .bdi-price{ | ||||
|  | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /*章节信息*/ | ||||
|   .gva-table-box{ | ||||
|     .detail-info-box{ | ||||
|       .dib-item{ | ||||
|         color: gray; | ||||
|         padding: 10px 0; | ||||
|         display: flex; | ||||
|         .di-left{ | ||||
|         } | ||||
|       } | ||||
|       .di-title{ | ||||
|         color: black; | ||||
|         font-weight: 900; | ||||
|         font-size: 15px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										305
									
								
								src/view/teacherManage/assistantList/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								src/view/teacherManage/assistantList/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,305 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/teacher' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| // const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'', | ||||
|   province:'' | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'申请中', | ||||
|       id:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'拒绝', | ||||
|       id:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'同意', | ||||
|       id:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| // const dialogFormVisible = ref(false) | ||||
| // const dialogTitle = ref('') | ||||
| // const form =ref({}) | ||||
| // const rules = ref({ | ||||
| //   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| // }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const teacher_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getAssistantList() | ||||
| }) | ||||
| // provide('subjectList', subjectList) | ||||
| // provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getAssistantList() { | ||||
|   const res = await api.getAssistantList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| // async function getSubject(){ // 获取课程分类 | ||||
| //   const res = await capi.getSubjectList(subjectParams.value) | ||||
| //   if(res.code === 0) { | ||||
| //     subjectList.value = custom.getStdSubject(res.data.records) | ||||
| //   } | ||||
| // } | ||||
| function onSubmit() { | ||||
|   getAssistantList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = teacher_ids.value | ||||
|   const res = await api.delExamination({ teacher_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getAssistantList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   teacher_ids.value = val.map((item) => { | ||||
|       return item.teacher_info_id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getAssistantList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getAssistantList() | ||||
| } | ||||
| function viewTeacherFunc(row) { // 查看详情 | ||||
|   router.push({name:'teacherDetail',params:{id:row.teacher_info_id}}) | ||||
| } | ||||
| //审核相关 | ||||
| const p_visible = ref(false) | ||||
| const pFormRules = ref({ | ||||
|   desc: [{ required: true, message: '请输入说明', trigger: 'blur' }] | ||||
| }) | ||||
| const p_type = ref(null); // 审核类型 | ||||
| const pForm = ref({}) | ||||
| const teacher_id = ref(0) | ||||
| const p_title = ref('') | ||||
| function processFunc(row,state) { // 审核 | ||||
|   p_type.value = state | ||||
|   p_visible.value = true | ||||
|   teacher_id.value = row.user_id | ||||
|   if(state === 3) { //同意 | ||||
|     p_title.value = '审核同意' | ||||
|   } | ||||
|   else if(state === 2) { // 拒绝 | ||||
|     p_title.value = '审核拒绝' | ||||
|   } | ||||
| } | ||||
| function close_pv(){ | ||||
|   p_visible.value = false | ||||
| } | ||||
| async function pOk() { // 审核提交 | ||||
|   const res = await api.assistantOperator({ | ||||
|     teacher_id:teacher_id.value, | ||||
|     status:p_type.value, | ||||
|     desc:pForm.value.desc | ||||
|   }) | ||||
|   ElMessage({ | ||||
|     type: 'success', | ||||
|     message: res.data.msg | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     close_pv() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="教师名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据教师名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="教师状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="teacher_info_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="头像"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.avatar" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="姓名" prop="name" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150" prop="province"> | ||||
|           <template #default="scope"> | ||||
|             {{cityList[scope.row.province].name}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="申请时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="推荐人ID" prop="invite_id" /> | ||||
|         <el-table-column align="center" label="授课次数" prop="publish_course" /> | ||||
|         <el-table-column align="center" label="测试次数" prop="publish_exam" /> | ||||
|         <el-table-column align="center" label="累计销售" prop="exam_sale" /> | ||||
|         <el-table-column align="center" label="状态" prop="exam_sale"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.status == 1?'审核中':scope.row.status == 2?'已同意':'已拒绝'}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="审核说明" prop="desc" /> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewTeacherFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="processFunc(scope.row,2)" | ||||
|             >同意</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="processFunc(scope.row,3)" | ||||
|             >拒绝</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    审核窗口--> | ||||
|     <el-dialog | ||||
|       v-model="p_visible" | ||||
|       :title="p_title" | ||||
|       width="30%" | ||||
|       :before-close="close_pv" | ||||
|     > | ||||
|       <el-form ref="apiForm" :model="pForm" :rules="pFormRules" label-width="80px"> | ||||
|         <el-form-item label="审核说明" prop="name"> | ||||
|           <el-input v-model="pForm.desc" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="p_visible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="pOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										21
									
								
								src/view/teacherManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/view/teacherManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <router-view v-slot="{ Component }"> | ||||
|       <transition mode="out-in" name="el-fade-in-linear"> | ||||
|         <keep-alive :include="routerStore.keepAliveRouters"> | ||||
|           <component :is="Component" /> | ||||
|         </keep-alive> | ||||
|       </transition> | ||||
|     </router-view> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'teacherManage' | ||||
| } | ||||
| </script> | ||||
| <script setup> | ||||
| import { useRouterStore } from '@/pinia/modules/router' | ||||
| const routerStore = useRouterStore() | ||||
| </script> | ||||
							
								
								
									
										405
									
								
								src/view/teacherManage/teacherApply/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								src/view/teacherManage/teacherApply/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,405 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/teacher' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:1 | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'申请中', | ||||
|       id:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'拒绝', | ||||
|       id:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'同意', | ||||
|       id:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getTeacherList() | ||||
|   // getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getTeacherList() { | ||||
|   const res = await api.getTeacherList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getTeacherList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getTeacherList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam_id | ||||
|   }) | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   row.course_ids = JSON.parse(row.course_ids) | ||||
|   row.question_ids = JSON.parse(row.question_ids) | ||||
|  | ||||
|   form.value = row.exam | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     return item.persons | ||||
|   }) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getTeacherList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getTeacherList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getTeacherList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getTeacherList() | ||||
|   } | ||||
| } | ||||
| function viewTeacherFunc(row) { // 查看订单 | ||||
|   console.log(row) | ||||
|   router.push({name:'teacherDetail',params:{id:row.teacher_info_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push('') | ||||
| } | ||||
| function delet_func() { | ||||
|   exam_types.value.pop() | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '未付款' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已付款' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已过期' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| function getTypeName(type) { | ||||
|   let name = "" | ||||
|   switch (type) { | ||||
|     case 1: | ||||
|       name = '课程'; | ||||
|       break; | ||||
|     case 2: | ||||
|       name = '章节'; | ||||
|       break; | ||||
|     case 3: | ||||
|       name = '子章节'; | ||||
|       break; | ||||
|     case 4: | ||||
|       name = '试卷'; | ||||
|       break; | ||||
|   } | ||||
|   return name | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="教师名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据教师名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="教师状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="teacher_info_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="头像"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.avatar" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="姓名" prop="name" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150" prop="province"> | ||||
|           <template #default="scope"> | ||||
|             {{cityList[scope.row.province].name}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="申请时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="推荐人ID" prop="invite_id" /> | ||||
|         <el-table-column align="center" label="授课次数" prop="publish_course" /> | ||||
|         <el-table-column align="center" label="测试次数" prop="publish_exam" /> | ||||
|         <el-table-column align="center" label="累计销售" prop="exam_sale" /> | ||||
|         <el-table-column align="center" label="状态" prop="exam_sale"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.status == 1?'查看':scope.row.status == 2?'已拒绝':'已同意'}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewTeacherFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewTeacherFunc(scope.row)" | ||||
|             >同意</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="deleteExamFunc(scope.row)" | ||||
|             >拒绝</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										312
									
								
								src/view/teacherManage/teacherDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/view/teacherManage/teacherDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/teacher' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const teacherInfo = ref({}) | ||||
| const imgs = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getTeacherDetail() | ||||
| }) | ||||
| // funstions | ||||
| async function getTeacherDetail() { | ||||
|   const res = await api.getTeacherDetail({id:route.params.id}) | ||||
|   if(res.code === 0) { | ||||
|     teacherInfo.value = res.data | ||||
|     let teacher_cert = JSON.parse(res.data.teacher_cert) | ||||
|     let skill_cert = JSON.parse(res.data.skill_cert) | ||||
|     imgs.value = [...skill_cert,...teacher_cert] | ||||
|     // console.log(imgs.value) | ||||
|   } | ||||
| } | ||||
| const tip_text = ref('') | ||||
| const dialogVisible = ref(false) | ||||
| const a_type = ref(0) | ||||
| function actionFunc(type) { | ||||
|   dialogVisible.value = true | ||||
|   a_type.value = type | ||||
|   switch (type){ | ||||
|     case 3: | ||||
|       tip_text.value = '是否同意该教师申请?'; | ||||
|       break; | ||||
|     case 2: | ||||
|       tip_text.value = '是否拒绝该教师申请?'; | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| async function actionOk() { // 确认提交 | ||||
|   const res = await api.teacherOperator({ | ||||
|     teacher_id:teacherInfo.value.user_id, | ||||
|     status:a_type.value | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     getTeacherDetail() | ||||
|   } | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '待审核' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已拒绝' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已同意' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseInfo-box"> | ||||
|         <div class="bb-item"> | ||||
|           <img class="avatar" :src="teacherInfo.avatar" alt=""> | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           昵称:{{teacherInfo.name}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           ID:{{teacherInfo.user_id}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           注册时间:{{teacherInfo.CreatedAt}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           身份:教师 | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           邀请人数:105人 | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    章节信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="detail-info-box"> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">身份证号码:</div> | ||||
|             <div class="di-right">{{teacherInfo.id_card}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">手机号码:</div> | ||||
|             <div class="di-right">{{teacherInfo.phone}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">区域:</div> | ||||
|             <div class="di-right">{{teacherInfo.province}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">提交时间:</div> | ||||
|             <div class="di-right">{{formatDate(teacherInfo.CreatedAt)}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">就职单位:</div> | ||||
|             <div class="di-right">重庆大学</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">任职行业:</div> | ||||
|             <div class="di-right">金融</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">余额:</div> | ||||
|             <div class="di-right">{{teacherInfo.balance}}元</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">累计收益:</div> | ||||
|             <div class="di-right">{{teacherInfo.income}}元</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item"> | ||||
|             <div class="di-left">查看交易明细</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">上架课程:</div> | ||||
|             <div class="di-right">{{teacherInfo.publish_course}}门</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item"> | ||||
|             <div class="di-left">查看课程列表</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">上架测试:</div> | ||||
|             <div class="di-right">{{teacherInfo.publish_exam}}份</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item"> | ||||
|             <div class="di-left ">查看试卷列表</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">销售次数(课程):</div> | ||||
|             <div class="di-right">{{teacherInfo.course_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">累计金额:</div> | ||||
|             <div class="di-right">{{teacherInfo.course_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item"> | ||||
|             <div class="di-left">查看学习记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">销售次数(测试):</div> | ||||
|             <div class="di-right">{{teacherInfo.exam_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">累计金额:</div> | ||||
|             <div class="di-right">{{teacherInfo.exam_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item"> | ||||
|             <div class="di-left">查看测试记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row" style="margin-top: 50px"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">资质证书(多张)</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <el-image | ||||
|               v-for="(item,i) in imgs" | ||||
|               class="img-css" | ||||
|               :src="item" | ||||
|               :zoom-rate="1.2" | ||||
|               :preview-src-list="imgs" | ||||
|               :initial-index="4" | ||||
|               fit="cover" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|       </div> | ||||
|       <!--    操作区域--> | ||||
| <!--      <div class="action-box" v-if="teacherInfo.status == 1">--> | ||||
| <!--        <div class="a-btn approved" @click="actionFunc(3)">同意</div>--> | ||||
| <!--        <div class="a-btn refuse" @click="actionFunc(2)">拒绝</div>--> | ||||
| <!--      </div>--> | ||||
| <!--      <div class="action-box" v-else>--> | ||||
| <!--        <div class="state-text" :class="{'reuse-text':teacherInfo.status == 2}">{{getStateName(teacherInfo.status)}}</div>--> | ||||
| <!--      </div>--> | ||||
|             <div class="action-box"> | ||||
|               <div class="state-text" :class="{'reuse-text':teacherInfo.status == 2}">{{getStateName(teacherInfo.status)}}</div> | ||||
|             </div> | ||||
|     </div> | ||||
|     <el-dialog | ||||
|       v-model="dialogVisible" | ||||
|       title="操作提醒" | ||||
|       width="30%" | ||||
|       :before-close="handleClose" | ||||
|     > | ||||
|       <span>{{tip_text}}</span> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="actionOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .action-box{ | ||||
|     display: flex; | ||||
|     margin-top: 20px; | ||||
|     justify-content: center; | ||||
|     .a-btn{ | ||||
|       background: rgb(60, 106, 112); | ||||
|       color: white; | ||||
|       padding: 10px 50px; | ||||
|       cursor: pointer; | ||||
|       margin: 10px; | ||||
|           border-radius: 5px; | ||||
|     } | ||||
|     .approved{ | ||||
|  | ||||
|     } | ||||
|     .refuse{ | ||||
|       background: white !important; | ||||
|       color:rgb(60, 106, 112) !important; | ||||
|       border: 1px solid rgb(60, 106, 112) !important; | ||||
|     } | ||||
|   } | ||||
|   /*基本信息*/ | ||||
|   .gva-search-box{ | ||||
|     .baseInfo-box{ | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       //justify-content: space-around; | ||||
|       .bb-item{ | ||||
|         margin: 10px 20px; | ||||
|         .avatar{ | ||||
|           width: 50px; | ||||
|           height: 50px; | ||||
|           border-radius: 50%; | ||||
|           border: 1px solid #cdcdcd; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /*详细信息*/ | ||||
|   .text{ | ||||
|     color: red !important; | ||||
|   } | ||||
|   .state-text{ | ||||
|     font-size: 15px; | ||||
|     color: gray; | ||||
|   } | ||||
|   .gva-table-box{ | ||||
|     .detail-info-box{ | ||||
|       .dib-row{ | ||||
|         overflow: hidden; | ||||
|         .link-item{ | ||||
|           color: #3C6A70 !important; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         .dib-item{ | ||||
|           //color: gray; | ||||
|           padding: 10px 0; | ||||
|           display: flex; | ||||
|           float: left; | ||||
|           margin-right: 30px; | ||||
|           .di-left{ | ||||
|           } | ||||
|           .img-css{ | ||||
|             width: 100px; | ||||
|             height: 100px; | ||||
|             margin: 0 10px 10px 0; | ||||
|             cursor: pointer; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										304
									
								
								src/view/teacherManage/teacherList/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								src/view/teacherManage/teacherList/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,304 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/teacher' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| import cityList from '@/utils/city.json' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| // const path = ref(import.meta.env.VITE_BASE_API) | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   status:'' | ||||
| }) | ||||
| // const subjectParams = ref({ | ||||
| //     pageIndex:1, | ||||
| //     pageSize:100, | ||||
| // }) | ||||
| const state_arr = ref([ | ||||
|     { | ||||
|       name:'申请中', | ||||
|       id:1 | ||||
|     }, | ||||
|     { | ||||
|       name:'拒绝', | ||||
|       id:2 | ||||
|     }, | ||||
|     { | ||||
|       name:'同意', | ||||
|       id:3 | ||||
|     } | ||||
| ]) | ||||
| const tableData = ref([]) | ||||
| const deleteVisible = ref(false) | ||||
| const total = ref(0) | ||||
| // const dialogFormVisible = ref(false) | ||||
| // const dialogTitle = ref('') | ||||
| // const form =ref({}) | ||||
| // const rules = ref({ | ||||
| //   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| // }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| const teacher_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getTeacherList() | ||||
| }) | ||||
| // provide('subjectList', subjectList) | ||||
| // provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getTeacherList() { | ||||
|   const res = await api.getTeacherList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| // async function getSubject(){ // 获取课程分类 | ||||
| //   const res = await capi.getSubjectList(subjectParams.value) | ||||
| //   if(res.code === 0) { | ||||
| //     subjectList.value = custom.getStdSubject(res.data.records) | ||||
| //   } | ||||
| // } | ||||
| function onSubmit() { | ||||
|   getTeacherList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = teacher_ids.value | ||||
|   const res = await api.delExamination({ teacher_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     deleteVisible.value = false | ||||
|     getTeacherList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   teacher_ids.value = val.map((item) => { | ||||
|       return item.teacher_info_id | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getTeacherList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getTeacherList() | ||||
| } | ||||
| function viewTeacherFunc(row) { // 查看详情 | ||||
|   router.push({name:'teacherDetail',params:{id:row.teacher_info_id}}) | ||||
| } | ||||
| //审核相关 | ||||
| const p_visible = ref(false) | ||||
| const pFormRules = ref({ | ||||
|   desc: [{ required: true, message: '请输入说明', trigger: 'blur' }] | ||||
| }) | ||||
| const p_type = ref(null); // 审核类型 | ||||
| const pForm = ref({}) | ||||
| const teacher_id = ref(0) | ||||
| const p_title = ref('') | ||||
| function processFunc(row,state) { // 审核 | ||||
|   p_type.value = state | ||||
|   p_visible.value = true | ||||
|   teacher_id.value = row.user_id | ||||
|   if(state === 3) { //同意 | ||||
|     p_title.value = '审核同意' | ||||
|   } | ||||
|   else if(state === 2) { // 拒绝 | ||||
|     p_title.value = '审核拒绝' | ||||
|   } | ||||
| } | ||||
| function close_pv(){ | ||||
|   p_visible.value = false | ||||
| } | ||||
| async function pOk() { // 审核提交 | ||||
|   const res = await api.teacherOperator({ | ||||
|     teacher_id:teacher_id.value, | ||||
|     status:p_type.value, | ||||
|     desc:pForm.value.desc | ||||
|   }) | ||||
|   ElMessage({ | ||||
|     type: 'success', | ||||
|     message: res.data.msg | ||||
|   }) | ||||
|   if(res.code === 0) { | ||||
|     close_pv() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="教师名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据教师名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="教师状态"> | ||||
|           <el-select v-model="queryParams.status" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in state_arr" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.id" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column align="center" label="ID"  prop="teacher_info_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="头像"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-box" :src="scope.row.avatar" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="姓名" prop="name" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150" prop="province"> | ||||
|           <template #default="scope"> | ||||
|             {{cityList[scope.row.province].name}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="申请时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="推荐人ID" prop="invite_id" /> | ||||
|         <el-table-column align="center" label="授课次数" prop="publish_course" /> | ||||
|         <el-table-column align="center" label="测试次数" prop="publish_exam" /> | ||||
|         <el-table-column align="center" label="累计销售" prop="exam_sale" /> | ||||
|         <el-table-column align="center" label="状态" prop="exam_sale"> | ||||
|           <template #default="scope"> | ||||
|             <div>{{scope.row.status == 1?'审核中':scope.row.status == 2?'已同意':'已拒绝'}}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="审核说明" prop="desc" /> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="view" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewTeacherFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="processFunc(scope.row,2)" | ||||
|             >同意</el-button> | ||||
|             <el-button v-if="scope.row.status == 1" | ||||
|               icon="delete" | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               @click="processFunc(scope.row,3)" | ||||
|             >拒绝</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    审核窗口--> | ||||
|     <el-dialog | ||||
|       v-model="p_visible" | ||||
|       :title="p_title" | ||||
|       width="30%" | ||||
|       :before-close="close_pv" | ||||
|     > | ||||
|       <el-form ref="apiForm" :model="pForm" :rules="pFormRules" label-width="80px"> | ||||
|         <el-form-item label="审核说明" prop="name"> | ||||
|           <el-input v-model="pForm.desc" autocomplete="off" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <span class="dialog-footer"> | ||||
|           <el-button @click="p_visible = false">取消</el-button> | ||||
|           <el-button type="primary" @click="pOk"> | ||||
|             确定 | ||||
|           </el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-box{ | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     border: 1px solid #dbdbdb; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										451
									
								
								src/view/userManage/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								src/view/userManage/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,451 @@ | ||||
|  | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| import cityList from '@/utils/city.json'; | ||||
| // store | ||||
| import { useUserStore } from '@/pinia/modules/user' | ||||
| const userStore = useUserStore() | ||||
| // 变量 | ||||
| const path = ref(import.meta.env.VITE_BASE_API) | ||||
| // const typeList = custom.getExercisesTypeList() | ||||
| const queryParams = ref({ | ||||
|   page:1, | ||||
|   pageSize:10, | ||||
|   name:'', | ||||
|   province:'' | ||||
| }) | ||||
| const subjectParams = ref({ | ||||
|     pageIndex:1, | ||||
|     pageSize:100, | ||||
| }) | ||||
| const tableData = ref([]) | ||||
| const subjectList = ref([]) | ||||
| const current_subject = ref('') | ||||
| const deleteVisible = ref(false) | ||||
| const question_ids = ref([]) | ||||
| const total = ref(0) | ||||
| const dialogFormVisible = ref(false) | ||||
| const dialogTitle = ref('') | ||||
| const form =ref({}) | ||||
| const rules = ref({ | ||||
|   name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }] | ||||
| }) | ||||
| const question_id = ref(0) | ||||
| const content = ref(null) | ||||
| // const options = ref([]) // 答案选项数组 | ||||
| const exam_types = ref([]) | ||||
| const exam_ids = ref([]) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getUserList() | ||||
|   getSubject() | ||||
| }) | ||||
| provide('subjectList', subjectList) | ||||
| provide('current_subject', current_subject) | ||||
| // 方法 | ||||
| async function getUserList() { | ||||
|   const res = await api.getUserList(queryParams.value) | ||||
|   if(res.code === 0) { | ||||
|     tableData.value = res.data.records | ||||
|     total.value = res.data.total | ||||
|   } | ||||
| } | ||||
| async function getSubject(){ // 获取课程分类 | ||||
|   const res = await capi.getSubjectList(subjectParams.value) | ||||
|   if(res.code === 0) { | ||||
|     subjectList.value = custom.getStdSubject(res.data.records) | ||||
|   } | ||||
| } | ||||
| function onSubmit() { | ||||
|   getUserList() | ||||
| } | ||||
| const onReset = () => { | ||||
|   queryParams.value = { | ||||
|     pageIndex:1, | ||||
|     pageSize:10, | ||||
|     name:'', | ||||
|     status:'', | ||||
|     subject:'' | ||||
|   } | ||||
| } | ||||
| function openDialog(type) { | ||||
|   // let params = {} | ||||
|   switch (type){ | ||||
|     case 'add': | ||||
|       dialogTitle.value = '新增试卷' | ||||
|         form.value = {} | ||||
|       break; | ||||
|     case 'edit': | ||||
|       // params.question_id = question_id.value | ||||
|       dialogTitle.value = '编辑试卷' | ||||
|       break; | ||||
|   } | ||||
|   dialogFormVisible.value = true | ||||
|   // router.push({name:'addCourse',params}) | ||||
| } | ||||
| async function onDelete() { | ||||
|   const ids = exam_ids.value | ||||
|   const res = await api.delExamination({ exam_ids:ids }) | ||||
|   if (res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     // if (tableData.value.length === ids.length && page.value > 1) { | ||||
|     //   page.value-- | ||||
|     // } | ||||
|     deleteVisible.value = false | ||||
|     getUserList() | ||||
|   } | ||||
| } | ||||
| const handleSelectionChange = (val) => { | ||||
|   exam_ids.value = val.map((item) => { | ||||
|       return item.exam_id | ||||
|   }) | ||||
| } | ||||
| function editCourseFunc(row) { | ||||
|   row.course_ids = JSON.parse(row.course_ids) | ||||
|   row.question_ids = JSON.parse(row.question_ids) | ||||
|  | ||||
|   form.value = row.exam | ||||
|   exam_types.value = row.exam_types.map((item) => { | ||||
|     return item.persons | ||||
|   }) | ||||
|   current_subject.value = form.value.subject | ||||
|   openDialog('edit') | ||||
| } | ||||
| function deleteExamFunc(row) { | ||||
|   ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|   .then(async() => { | ||||
|     const res = await api.delExamination({ | ||||
|           exam_ids:[row.exam_id] | ||||
|     }) | ||||
|     if (res.code === 0) { | ||||
|       ElMessage({ | ||||
|         type: 'success', | ||||
|         message: '删除成功!' | ||||
|       }) | ||||
|       getUserList() | ||||
|     } | ||||
|   },() => { | ||||
|   }) | ||||
| } | ||||
| function handleCurrentChange(val) { | ||||
|   queryParams.value.pageIndex = val | ||||
|   getUserList() | ||||
| } | ||||
| function handleSizeChange(val) { | ||||
|   queryParams.value.pageSize = val | ||||
|   getUserList() | ||||
| } | ||||
| function closeDialog(){ | ||||
|   dialogFormVisible.value = false | ||||
|   exam_types.value = [] | ||||
|   form.value = {} | ||||
| } | ||||
| async function enterDialog() { // 提交 | ||||
|   form.value.teacher_id = 0 | ||||
|   form.value.exam_type = exam_types.value.map((item) => { | ||||
|     return item = parseInt(item) | ||||
|   }) | ||||
|   form.value.duration = parseInt(form.value.duration) | ||||
|   // return | ||||
|   const params = { | ||||
|     ...form.value | ||||
|   } | ||||
|   params.question_ids = JSON.stringify(form.value.question_ids) | ||||
|   params.course_ids = JSON.stringify(form.value.course_ids) | ||||
|   let func_name = 'addExamination' | ||||
|   if(form.value.exam_id) { // 编辑 | ||||
|     func_name = 'editExamination' | ||||
|   } | ||||
|   const res = await api[func_name](params) | ||||
|   if(res.code === 0) { | ||||
|     ElMessage({ | ||||
|       type: 'success', | ||||
|       message: res.msg | ||||
|     }) | ||||
|     closeDialog() | ||||
|     getUserList() | ||||
|   } | ||||
| } | ||||
| function viewUserFunc(row) { // 查看订单 | ||||
|   router.push({name:'viewUserManage',params:{id:row.user_id}}) | ||||
| } | ||||
| function getExercisesName(row) { | ||||
|   return JSON.parse(row.question).title | ||||
| } | ||||
| // const std_options_title = ref(['A','B','C','D','E','F']) | ||||
| function addOptionFunc() { | ||||
|   exam_types.value.push('') | ||||
| } | ||||
| function delet_func() { | ||||
|   exam_types.value.pop() | ||||
| } | ||||
| function getStateName(state) { | ||||
|   let str = '' | ||||
|   switch (state){ | ||||
|     case 1: | ||||
|         str = '未付款' | ||||
|       break; | ||||
|     case 2: | ||||
|         str = '已付款' | ||||
|       break; | ||||
|     case 3: | ||||
|         str = '已过期' | ||||
|       break; | ||||
|   } | ||||
|   return str | ||||
| } | ||||
| function handleAvatarSuccess(res) { | ||||
|   form.value.cover = res.data.file.url | ||||
|   // handlerChange() | ||||
| } | ||||
| function beforeAvatarUpload(file) { | ||||
|   const isLt05M = file.size / 1024 / 1024 < 20 | ||||
|   const isJPG = file.type.indexOf('image/') === -1 | ||||
|   if (isJPG) { | ||||
|     ElMessage.error('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件') | ||||
|   } | ||||
|   if (!isLt05M) { | ||||
|     ElMessage.error('上传头像图片大小不能超过 2M!') | ||||
|   } | ||||
|   return !isJPG && isLt05M | ||||
| } | ||||
| function changeSubjectFunc(e) { | ||||
|   current_subject.value = e | ||||
| } | ||||
| function addExercisesFunc(data) { | ||||
|   form.value.question_ids = data | ||||
| } | ||||
| function addCourseFunc(data) { | ||||
|   form.value.course_ids = data | ||||
| } | ||||
| function getTypeName(type) { | ||||
|   let name = "" | ||||
|   switch (type) { | ||||
|     case 1: | ||||
|       name = '课程'; | ||||
|       break; | ||||
|     case 2: | ||||
|       name = '章节'; | ||||
|       break; | ||||
|     case 3: | ||||
|       name = '子章节'; | ||||
|       break; | ||||
|     case 4: | ||||
|       name = '试卷'; | ||||
|       break; | ||||
|   } | ||||
|   return name | ||||
| } | ||||
| function getProvinceName(province) { | ||||
|   if(province < 0) return '' | ||||
|   return cityList[province].name | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    搜索框--> | ||||
|     <div class="gva-search-box"> | ||||
|       <el-form ref="searchForm" :inline="true" :model="queryParams"> | ||||
|         <el-form-item label="用户名称"> | ||||
|           <el-input v-model="queryParams.name" placeholder="根据用户名称进行查询" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="区域"> | ||||
|           <el-select v-model="queryParams.province" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in cityList" | ||||
|               :key="item.ProID" | ||||
|               :label="item.name" | ||||
|               :value="item.ProID" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item> | ||||
|           <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button> | ||||
|           <el-button size="small" icon="refresh" @click="onReset">重置</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <!--    表格数据--> | ||||
|     <div class="gva-table-box"> | ||||
|       <!--      批量操作--> | ||||
|       <div class="gva-btn-list"> | ||||
| <!--        <el-button size="small" type="primary" icon="plus" @click="openDialog('add')">新增</el-button>--> | ||||
|         <el-popover v-model="deleteVisible" placement="top" width="160"> | ||||
|           <p>确定要删除吗?</p> | ||||
|           <div style="text-align: right; margin-top: 8px;"> | ||||
|             <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button> | ||||
|             <el-button size="small" type="primary" @click="onDelete">确定</el-button> | ||||
|           </div> | ||||
| <!--          <template #reference>--> | ||||
| <!--            <el-button icon="delete" size="small" type="danger" :disabled="!exam_ids.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>--> | ||||
| <!--          </template>--> | ||||
|         </el-popover> | ||||
|       </div> | ||||
|       <!--      数据列表--> | ||||
|       <el-table :data="tableData" @selection-change="handleSelectionChange"> | ||||
| <!--        <el-table-column--> | ||||
| <!--          type="selection"--> | ||||
| <!--          width="55"--> | ||||
| <!--        />--> | ||||
|         <el-table-column align="center" label="ID"  prop="user_id" sortable="custom" /> | ||||
|         <el-table-column align="center" label="头像" min-width="150"> | ||||
|           <template #default="scope"> | ||||
|             <img class="avatar-css" :src="scope.row.avatar" alt=""> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="姓名" prop="nickname" /> | ||||
|         <el-table-column align="center" label="手机号" min-width="150" prop="phone" /> | ||||
|         <el-table-column align="center" label="身份" min-width="150" prop="order_type"> | ||||
|           <template #default="scope"> | ||||
|             {{scope.row.idCard}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="所属区域" min-width="150"> | ||||
|           <template #default="scope"> | ||||
|             {{getProvinceName(scope.row.province)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|          <el-table-column align="center" label="推荐人ID" min-width="150" prop="invite_id" /> | ||||
|         <el-table-column align="center" label="报课次数" min-width="150" prop="name" /> | ||||
|         <el-table-column align="center" label="测试次数" min-width="150" prop="price" /> | ||||
|         <el-table-column align="center" label="累计金额" min-width="150" prop="balance" /> | ||||
|         <el-table-column align="center" label="注册时间" min-width="150" > | ||||
|           <template #default="scope"> | ||||
|             {{formatDate(scope.row.CreatedAt)}} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" fixed="right" label="操作" width="200"> | ||||
|           <template #default="scope"> | ||||
|             <el-button | ||||
|               icon="edit" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="viewUserFunc(scope.row)" | ||||
|             >查看</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <div class="gva-pagination"> | ||||
|         <el-pagination | ||||
|           :current-page="queryParams.page" | ||||
|           :page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 30, 50, 100]" | ||||
|           :total="total" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @current-change="handleCurrentChange" | ||||
|           @size-change="handleSizeChange" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle"> | ||||
|       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="试卷名称" > | ||||
|           <el-input v-model="form.name" placeholder="请输入试卷名称" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="科目" prop="subject"> | ||||
|           <el-select v-model="form.subject" @change="changeSubjectFunc" clearable placeholder="请选择"> | ||||
|             <el-option | ||||
|               v-for="item in subjectList" | ||||
|               :key="item.id" | ||||
|               :label="item.name" | ||||
|               :value="item.name" | ||||
|             /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="封面"> | ||||
|           <el-upload | ||||
|             class="avatar-uploader" | ||||
|             :action="`${path}/fileUploadAndDownload/upload`" | ||||
|             :headers="{ 'x-token': userStore.token }" | ||||
|             :show-file-list="false" | ||||
|             :on-success="handleAvatarSuccess" | ||||
|             :before-upload="beforeAvatarUpload" | ||||
|           > | ||||
|             <img v-if="form.cover" :src="form.cover" class="avatar" /> | ||||
|             <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | ||||
|           </el-upload> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试时长" > | ||||
|           <el-input type="number" v-model="form.duration" placeholder="请输入测试时长(分钟)" /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="测试组别" > | ||||
|           <!--          <el-input v-model="form.score" placeholder="请输入分值" />--> | ||||
|           <view class="options-box"> | ||||
|             <view class="option-item" v-if="exam_types.length>0" v-for="(item,i) in exam_types"> | ||||
|               <view>{{i+1}}</view> | ||||
|               <el-input type="number" style="margin-left:5px" v-model="exam_types[i]" placeholder="请输入组别人数" /> | ||||
|               <el-icon style="margin-left: 5px;cursor: pointer" v-if="(i+1) == exam_types.length" @click="delet_func(item)"><Delete /></el-icon> | ||||
|             </view> | ||||
|             <el-button @click="addOptionFunc">添加组别</el-button> | ||||
|           </view> | ||||
|         </el-form-item> | ||||
| <!--        <el-form-item label="添加习题" >--> | ||||
| <!--          <exercisesPool @addFunc="addExercisesFunc" :seleted_arr="form.question_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
| <!--        <el-form-item label="适用课程" >--> | ||||
| <!--          <coursePool @addFunc="addCourseFunc" :seleted_arr="form.course_ids" />--> | ||||
| <!--        </el-form-item>--> | ||||
|         <el-form-item label="受否上架" > | ||||
|           <el-switch | ||||
|             v-model="form.status" | ||||
|             active-text="上架" | ||||
|             inactive-text="下架" | ||||
|             :active-value="1" | ||||
|             :inactive-value="-1" | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button size="small" @click="closeDialog">取 消</el-button> | ||||
|           <el-button size="small" type="primary" @click="enterDialog">确 定</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .avatar-css{ | ||||
|     height: 100px; | ||||
|     width: 150px; | ||||
|   } | ||||
|   .e-img{ | ||||
|     width: 150px; | ||||
|     height: 100px; | ||||
|   } | ||||
|   .option-item{ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin-bottom: 10px; | ||||
|   } | ||||
|   .button-box { | ||||
|     padding: 10px 20px; | ||||
|     .el-button { | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .warning { | ||||
|     color: #dc143c; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										256
									
								
								src/view/userManage/view.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								src/view/userManage/view.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | ||||
| <script setup> | ||||
| // 引入依赖 | ||||
| import api from '@/api/userManage' | ||||
| import capi from '@/api/course' | ||||
| import custom from '@/utils/custom' | ||||
| import {formatDate} from '@/utils/format' | ||||
| // import { toSQLLine } from '@/utils/stringFun' | ||||
| // import WarningBar from '@/components/warningBar/warningBar.vue' | ||||
| // import coursePool from './components/coursePool.vue' | ||||
| // import exercisesPool from '@/view/course/components/exercisesPool.vue' | ||||
| import {ref,onMounted,provide } from 'vue' | ||||
| import { ElMessage, ElMessageBox } from 'element-plus' | ||||
| import { useRouter, useRoute } from 'vue-router' | ||||
| const router = useRouter() | ||||
| const route = useRoute() | ||||
| // 变量 | ||||
| const userManageInfo = ref({}) | ||||
| const imgs = ref([]) | ||||
| const detail_type = ref({ | ||||
|   dealDetailMoney:'dealDetailMoney', | ||||
|   dealDetailPoint:'dealDetailPoint', | ||||
|   learningDetail:'learningDetail', | ||||
|   testDetail:'testDetail', | ||||
|   auctionDetail:'auctionDetail',// 竞拍 | ||||
|   raffleDetail:'raffleDetail',// 抽奖 | ||||
| }) | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getUserDetail() | ||||
| }) | ||||
| // funstions | ||||
| async function getUserDetail() { | ||||
|   const res = await api.viewUser({id:route.params.id}) | ||||
|   if(res.code === 0) { | ||||
|     userManageInfo.value = res.data.user | ||||
|     // let teacher_cert = JSON.parse(res.data.teacher_cert) | ||||
|     // let skill_cert = JSON.parse(res.data.skill_cert) | ||||
|     // imgs.value = [...skill_cert,...teacher_cert] | ||||
|     // console.log(imgs.value) | ||||
|   } | ||||
| } | ||||
| function toDealDetail(type) { | ||||
|   // let url = '' | ||||
|   // switch (type){ | ||||
|   //   case detail_type.value.dealDetailMoney: | ||||
|   //       url = 'dealDetailMoney'; | ||||
|   //       break; | ||||
|   //   case 2: | ||||
|   //       url = 'dealDetailPoint'; | ||||
|   //       break; | ||||
|   // } | ||||
|   router.push({name:type,params:{user_id:route.params.id}}) | ||||
| } | ||||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <!--    基本信息--> | ||||
|     <div class="gva-search-box"> | ||||
|       <div class="baseInfo-box"> | ||||
|         <div class="bb-item"> | ||||
|           <img class="avatar" :src="userManageInfo.avatar" alt=""> | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           昵称:{{userManageInfo.nickname}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           ID:{{userManageInfo.user_id}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           注册时间:{{userManageInfo.CreatedAt}} | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           身份:教师 | ||||
|         </div> | ||||
|         <div class="bb-item"> | ||||
|           邀请人数:105人 | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <!--    章节信息--> | ||||
|     <div class="gva-table-box"> | ||||
|       <div class="detail-info-box"> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">身份证号码:</div> | ||||
|             <div class="di-right">{{userManageInfo.id_card}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">手机号码:</div> | ||||
|             <div class="di-right">{{userManageInfo.phone}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">区域:</div> | ||||
|             <div class="di-right">{{custom.getProvinceName(userManageInfo.province)}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">余额:</div> | ||||
|             <div class="di-right">{{userManageInfo.balance}}元</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.dealDetailMoney)"> | ||||
|             <div class="di-left">查看交易明细</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">积分:</div> | ||||
|             <div class="di-right">{{userManageInfo.points}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.dealDetailPoint)"> | ||||
|             <div class="di-left">查看交易明细</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">报课次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.course_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">累计消费金额:</div> | ||||
|             <div class="di-right">{{userManageInfo.course_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.learningDetail)"> | ||||
|             <div class="di-left">查看学习记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">测试次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">累计金额:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_income}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.testDetail)"> | ||||
|             <div class="di-left">查看测试记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">抽奖次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">中奖次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_income}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.raffleDetail)"> | ||||
|             <div class="di-left">查看抽奖记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">竞拍次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_sale}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">中奖次数:</div> | ||||
|             <div class="di-right">{{userManageInfo.exam_income}}次</div> | ||||
|           </div> | ||||
|           <div class="dib-item link-item" @click="toDealDetail(detail_type.auctionDetail)"> | ||||
|             <div class="di-left">查看竞拍记录</div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="dib-row"> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">邀请人姓名:</div> | ||||
|             <div class="di-right">{{userManageInfo.invite_id}}</div> | ||||
|           </div> | ||||
|           <div class="dib-item"> | ||||
|             <div class="di-left">邀请人姓名ID:</div> | ||||
|             <div class="di-right">{{userManageInfo.invite_id}}</div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <style scoped lang="scss"> | ||||
|   .action-box{ | ||||
|     display: flex; | ||||
|     margin-top: 20px; | ||||
|     justify-content: center; | ||||
|     .a-btn{ | ||||
|       background: rgb(60, 106, 112); | ||||
|       color: white; | ||||
|       padding: 10px 50px; | ||||
|       cursor: pointer; | ||||
|       margin: 10px; | ||||
|           border-radius: 5px; | ||||
|     } | ||||
|     .approved{ | ||||
|  | ||||
|     } | ||||
|     .refuse{ | ||||
|       background: white !important; | ||||
|       color:rgb(60, 106, 112) !important; | ||||
|       border: 1px solid rgb(60, 106, 112) !important; | ||||
|     } | ||||
|   } | ||||
|   /*基本信息*/ | ||||
|   .gva-search-box{ | ||||
|     .baseInfo-box{ | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       //justify-content: space-around; | ||||
|       .bb-item{ | ||||
|         margin: 10px 20px; | ||||
|         .avatar{ | ||||
|           width: 50px; | ||||
|           height: 50px; | ||||
|           border-radius: 50%; | ||||
|           border: 1px solid #cdcdcd; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /*详细信息*/ | ||||
|   .text{ | ||||
|     color: red !important; | ||||
|   } | ||||
|   .state-text{ | ||||
|     font-size: 15px; | ||||
|     color: gray; | ||||
|   } | ||||
|   .gva-table-box{ | ||||
|     .detail-info-box{ | ||||
|       .dib-row{ | ||||
|         overflow: hidden; | ||||
|         .link-item{ | ||||
|           color: #3C6A70 !important; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         .dib-item{ | ||||
|           //color: gray; | ||||
|           padding: 10px 0; | ||||
|           display: flex; | ||||
|           float: left; | ||||
|           margin-right: 30px; | ||||
|           .di-left{ | ||||
|           } | ||||
|           .img-css{ | ||||
|             width: 100px; | ||||
|             height: 100px; | ||||
|             margin: 0 10px 10px 0; | ||||
|             cursor: pointer; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -59,7 +59,10 @@ export default ({ | ||||
|       open: true, | ||||
|       port: process.env.VITE_CLI_PORT, | ||||
|       proxy: { | ||||
|         // 把key的路径代理到target位置 | ||||
|         // | ||||
|  | ||||
|  | ||||
|  | ||||
|         // detail: https://cli.vuejs.org/config/#devserver-proxy | ||||
|         [process.env.VITE_BASE_API]: { // 需要代理的路径   例如 '/api' | ||||
|           target: `${process.env.VITE_BASE_PATH}:${process.env.VITE_SERVER_PORT}/`, // 代理到 目标路径 | ||||
|   | ||||
							
								
								
									
										9497
									
								
								yarn-error.log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9497
									
								
								yarn-error.log
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user