This commit is contained in:
chengdandan 2024-06-24 15:24:41 +08:00
commit 30e21b71fb
81 changed files with 20229 additions and 0 deletions

5
.editorconfig Normal file
View File

@ -0,0 +1,5 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

4
.env Normal file
View File

@ -0,0 +1,4 @@
# 基本环境
VITE_APP_NAME=''
# 基本请求地址
VITE_BASE_URL=''

4
.env.production Normal file
View File

@ -0,0 +1,4 @@
# 基本环境
VITE_APP_NAME=''
# 基本请求地址
VITE_BASE_URL=''

36
.eslintrc.cjs Normal file
View File

@ -0,0 +1,36 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'standard',
'plugin:vue/vue3-essential'
],
overrides: [
{
env: {
node: true
},
files: [
'.eslintrc.{js,cjs}'
],
parserOptions: {
sourceType: 'script'
}
}
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'vue'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/multi-word-component-names': 'off'
}
}

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).

14
babel.config.js Normal file
View File

@ -0,0 +1,14 @@
{
'plugins'[
[
'import',
{
libraryName: 'element-plus',
customStyleName: (name) => {
// 注意:这里需要确保你的样式文件名是 `style.css`,否则需要进行相应调整
return `element-plus/lib/theme-chalk/${name}.css`
}
}
]
]
}

BIN
imgurl/培训@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
imgurl/学员.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
imgurl/考试@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
imgurl/课程@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

15
index.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>LKJCpowerSupplyOfficeSimulationSystem</title>
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_4490429_ym69s57vxr.css">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

5203
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

38
package.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "databoard",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "vite build",
"build:production": "vite build --mode production",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
"dev": "vite",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.6.7",
"echarts": "^5.5.0",
"element-plus": "^2.5.6",
"font-awesome": "^4.7.0",
"jsencrypt": "^3.3.2",
"pinia": "^2.1.7",
"vue": "^3.4.15",
"vue-router": "^4.2.5",
"vue3-seamless-scroll": "^2.0.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.3",
"babel-plugin-import": "^1.13.8",
"eslint": "^8.57.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.22.0",
"file-loader": "^6.2.0",
"sass": "~1.26.5",
"sass-loader": "^13.3.2",
"vite": "^5.1.0"
},
"type": "module"
}

1
public/vite.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 111 KiB

11
src/App.vue Normal file
View File

@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<router-view />
</template>
<style scoped>
@import url('@/assets/fonts/index.css');
@import "assets/fonts/FontIcon/iconfont.css";
</style>

6
src/api/IPManagement.js Normal file
View File

@ -0,0 +1,6 @@
import { get } from '@/api/request.js'
// 成绩查询列表
export const apiGetRoomIPList = (params) => {
return get('/api/GetRoomIPList', params)
}

44
src/api/LearningQuery.js Normal file
View File

@ -0,0 +1,44 @@
import { get, post,upload} from "@/api/request.js";
// 学习查询列表
export const apiGetLearnList = (params) => {
return get("/api/GetStudyList", params);
};
// 学习情况查询接口
export const apiGetStudyRecordList = (params) => {
return get("/api/GetStudyRecordList", params);
};
// 添加评语
export const apiGetCommentList = (params) => {
return post("/api/Comment", params);
};
// 新增学习接口
export const apiGetAddStudyList = (params) => {
return post("/api/AddStudy", params);
};
// 删除学习接口
export const apiDeleteStudyList = (params) => {
return get("/api/DeleteStudy", params);
};
// 发布接口
export const apiReleaseStudyList = (params) => {
return get("/api/ReleaseStudy", params);
};
// 上传文件接口
export const apiUploadList = (url,params) => {
return upload('/api/Upload'+url, params);
};
// 新增学习接口
export const apiAddStudyList = (params) => {
return post('/api/AddStudy', params);
};
//编辑保存
export const apiGetEditStudyList = (params) => {
return post('/api/EditStudy', params);
};
//编辑学习接口
export const apiGetStudyDetailsList = (params) => {
return get('/api/GetStudyDetails', params);
};

6
src/api/LoginRecord.js Normal file
View File

@ -0,0 +1,6 @@
import { get } from '@/api/request.js'
// 成绩查询列表
export const apiGetLoginLogList = (params) => {
return get('/api/GetLoginLogList', params)
}

View File

@ -0,0 +1,10 @@
import { get } from '@/api/request.js'
// 实训新增列表
export const apiGetTrainList = (params) => {
return get('/api/GetTrainList', params)
}
// 删除
export const DeleteTrain = (params) => {
return get('/api/DeleteTrain', params)
}

39
src/api/ScoreInquiry.js Normal file
View File

@ -0,0 +1,39 @@
import { get,post,download } from '@/api/request.js'
// 成绩查询列表
export const apiGetAchievementList = (params) => {
return get('/api/GetAchievementList', params)
}
//获取考试接口(用于下拉框)
export const apiGetExamDown = (params) => {
return get('/api/GetExamDown', params)
}
//删除
export const DeleteAchievement = (params) => {
return post('/api/DeleteAchievement', params)
}
//导出成绩接口
export const ExportAchievement = (params) => {
return download('/api/ExportAchievement', params)
}
//导出单个成绩接口
export const ExportIndividualGrades = (params) => {
return download('/api/ExportIndividualGrades', params)
}
//考试成绩导出接口
export const ExportAchievementDetails = (params) => {
return download('/api/ExportAchievementDetails', params)
}
//获取视频回放接口
export const GetVideoPlaybackList = (params) => {
return get('/api/GetVideoPlaybackList', params)
}
//获取成绩详情接口
export const GetAchievementDetails = (params) => {
return get('/api/GetAchievementDetails', params)
}

50
src/api/UserManagement.js Normal file
View File

@ -0,0 +1,50 @@
import { get,post,download,downloadPost,uploadFile } from '@/api/request.js'
// 查询列表
export const apiGetUserList = (params) => {
return get('/api/GetUserList', params)
}
// 新增
export const apiAddUser = (params) => {
return post('/api/AddUser', params)
}
// 获取用户信息
export const apiGetUserDetails = (params) => {
return get('/api/GetUserDetails', params)
}
// 编辑用户
export const apiEditUser = (params) => {
return post('/api/EditUser', params)
}
// 编辑用户密码
export const apiEditUserMim = (params) => {
return post('/api/EditUserMim', params)
}
// 删除
export const apiDeleteUser = (params) => {
return get('/api/DeleteUser', params)
}
// 导入
export const apiImportUser = (params) => {
return uploadFile('/api/ImportUser', params)
}
// 导出
export const apiExportUser = (params) => {
return downloadPost('/api/ExportUser', params)
}
// 下载模板
export const apiDownloadTemplate = (params) => {
return download('/api/DownloadTemplate', params)
}
//获取所在市、工作单位、部门、工作岗位
export const apiGetField = (params) => {
return get('/api/GetField', params)
}
//重置所有考生密码接口
export const apiResetUserMim = (params) => {
return get('/api/ResetUserMim', params)
}

21
src/api/analysisManage.js Normal file
View File

@ -0,0 +1,21 @@
import { get } from "@/api/request.js";
export const apiGetAllDataList = (params) => {
return get("/api/GetAllData", params);
};
//
export const apiGetStudyList = (params) => {
return get("/api/GetStudy", params);
};
export const apiGetTrainList = (params) => {
return get("/api/GetTrain", params);
};
export const apiGetTrainFaultList = (params) => {
return get("/api/GetTrainFaultType", params);
};
export const apiGetEndExamList = (params) => {
return get("/api/GetEndExam", params);
};

108
src/api/index.js Normal file
View File

@ -0,0 +1,108 @@
import { get, post, download, uploadFile } from './request'
// 登录
export const apiLogin = (params) => {
return post('/api/Login', params)
}
// 成绩管理列表
export const GetStarterList = (params) => {
return get('/api/GetStarterList', params)
}
// 成绩管理列表
export const GetModelList = (params) => {
return get('/api/GetModelList', params)
}
// 获取单条数据
export const GetModelDetails = (params) => {
return get('/api/GetModelDetails', params)
}
// 新增成绩管理列表
export const AddExam = (params) => {
return post('/api/AddExam', params)
}
// 编辑成绩管理列表
export const EditExamList = (params) => {
return post('/api/EditExam', params)
}
// 编辑器树结构
export const GetFaultTree = (params) => {
return get('/api/GetFaultTree', params)
}
// 编辑器-场景编辑
export const apiGetFaultList = (params) => {
return get('/api/GetFaultList', params)
}
export const SaveFault = (params) => {
return post('/api/SaveFault', params)
}
export const InitFault = (params) => {
return get('/api/InitFault', params)
}
// 编辑器-工具器
export const apiGetTools = (params) => {
return get('/api/GetTools', params)
}
export const SaveTools = (params) => {
return post('/api/SaveTools', params)
}
// 编辑器-操作票
export const apiGetOperationTicket = (params) => {
return get('/api/GetOperationTicket', params)
}
export const SaveOperationTicket = (params) => {
return post('/api/SaveOperationTicket', params)
}
export const ApiCopyExam = (params) => {
return get('/api/CopyExam', params)
}
export const DeleteExam = (params) => {
return get('/api/DeleteExam', params)
}
export const ApiReleaseExam = (params) => {
return get('/api/ReleaseExam', params)
}
export const ApiRevokeReleaseExam = (params) => {
return get('/api/RevokeReleaseExam', params)
}
export const ApiFinishedExam = (params) => {
return get('/api/FinishedExam', params)
}
export const ApiDownloadExamm = (params) => {
return download('/api/DownloadExam', params)
}
export const ApiGetExamRosterList = (params) => {
return get('/api/GetExamRosterList', params)
}
export const ApiGetAddExamRosterListt = (params) => {
return get('/api/AddExamRosterList', params)
}
export const ApiAddExamRoster = (params) => {
return post('/api/AddExamRoster', params)
}
export const GetScene = (params) => {
return get('/api/GetScene', params)
}
export const GetPlatformArea = (params) => {
return get('/api/GetPlatformArea', params)
}
export const GetLine = (params) => {
return get('/api/GetLine', params)
}
export const EditExam = (params) => {
return post('/api/EditExam', params)
}
export const GetExamDetails = (params) => {
return get('/api/GetExamDetails', params)
}
export const DeleteExamRoster = (params) => {
return get('/api/DeleteExamRoster', params)
}
export const apiUpload = (url, params) => {
return uploadFile('/api/ImportExam', params)
}

98
src/api/request.js Normal file
View File

@ -0,0 +1,98 @@
import axios from 'axios'
// import { useRouter } from 'vue-router'
// 带cookie请求
axios.defaults.headers.post['Content-Type'] = 'application/json'
const http = axios.create({
// baseURL: 'http://admin.umayle.com'
baseURL: `${import.meta.env.VITE_BASE_URL}`
})
// request 请求拦截器 - 请求之前headers加sid
http.interceptors.request.use(
config => {
if (config.url.indexOf('/login') < 0 && localStorage.getItem('token')) {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
}
// 每次发送请求之前检测都vuex存有token,那么都要放在请求头发送给服务器
return config
},
err => {
return err
}
)
// const router = useRouter()
// // response 错误统一处理
http.interceptors.response.use(
res => {
return res.data
},
err => {
console.log('接口访问失败')
// localStorage.removeItem('token')
// router.push('/Login')
return err
}
)
// 封装请求的api
const callapi = (method = 'GET', url, data = {}) => {
const params = method === 'GET' ? data : {}
const body = ['POST', 'PUT', 'PATCH'].includes(method) ? data : {}
const options = { method, url, params, data: body }
return http(options)
}
export const upload = (url, file) => {
return new Promise((resolve, reject) => {
http
.post(url, file, {
headers: { 'Content-Type': 'multipart/form-data' }
})
.then((res) => {
resolve(res.data)
})
.catch((err) => {
reject(err.data)
})
})
}
export const uploadFile = (url, file) => {
return new Promise((resolve, reject) => {
http
.post(url, file, {
headers: { 'Content-Type': 'multipart/form-data' }
})
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
export const download = (url, data = {}, method = 'GET') => {
const params = method === 'GET' ? data : {}
const body = ['POST', 'PUT', 'PATCH'].includes(method) ? data : {}
const options = { method, url, params, data: body, responseType: 'blob' }
console.log(options, 'options--')
return http(options)
}
// 导出
export const downloadPost = (url, data = {}, method = 'POST') => {
const params = method === 'GET' ? data : {}
const body = ['POST', 'PUT', 'PATCH'].includes(method) ? data : {}
const options = { method, url, params, data: body, responseType: 'blob' }
console.log(options, 'options--')
return http(options)
}
// 封装GET请求函数
export const get = (url, data) => callapi('GET', url, data)
export const post = (url, data) => callapi('POST', url, data)
export const put = (url, data) => callapi('PUT', url, data)
export const deleteapi = (url, data) => callapi('DELETE', url, data)
export const patchApi = (url, data) => callapi('PATCH', url, data)

105
src/api/trainList.js Normal file
View File

@ -0,0 +1,105 @@
import { get, post, download, uploadFile } from './request'
// 登录
export const apiLogin = (params) => {
return post('/api/Login', params)
}
// 成绩管理列表
export const GetTrainList = (params) => {
return get('/api/GetTrainList', params)
}
// 新增成绩管理列表
export const AddTrain = (params) => {
return post('/api/AddTrain', params)
}
// 编辑成绩管理列表
export const EditExamList = (params) => {
return post('/api/EditExam', params)
}
// 编辑器树结构
export const GetFaultTree = (params) => {
return get('/api/GetFaultTree', params)
}
// 编辑器-场景编辑
export const apiGetTrainFaultList = (params) => {
return get('/api/GetTrainFaultList', params)
}
export const SaveFault = (params) => {
return post('/api/SaveTrainFault', params)
}
export const InitFault = (params) => {
return get('/api/InitTrainFault', params)
}
// 编辑器-工具器
export const apiGetTrainTools = (params) => {
return get('/api/GetTrainTools', params)
}
export const SaveTools = (params) => {
return post('/api/SaveTrainTools', params)
}
// 编辑器-操作票
export const apiGetOperationTicket = (params) => {
return get('/api/GetTrainOperationTicket', params)
}
export const SaveOperationTicket = (params) => {
return post('/api/SaveTrainOperationTicket', params)
}
export const CopyTrain = (params) => {
return get('/api/CopyTrain', params)
}
export const DeleteTrain = (params) => {
return get('/api/DeleteTrain', params)
}
export const ApiReleaseTrain = (params) => {
return get('/api/ReleaseTrain', params)
}
export const ApiRevokeReleaseExam = (params) => {
return get('/api/RevokeReleaseExam', params)
}
export const ApiFinishedExam = (params) => {
return get('/api/FinishedExam', params)
}
export const ApiDownloadExamm = (params) => {
return download('/api/DownloadExam', params)
}
export const ApiGetExamRosterList = (params) => {
return get('/api/GetExamRosterList', params)
}
export const ApiGetAddExamRosterListt = (params) => {
return get('/api/AddExamRosterList', params)
}
export const ApiAddExamRoster = (params) => {
return post('/api/AddExamRoster', params)
}
export const GetScene = (params) => {
return get('/api/GetScene', params)
}
export const GetPlatformArea = (params) => {
return get('/api/GetPlatformArea', params)
}
export const GetLine = (params) => {
return get('/api/GetLine', params)
}
export const EditTrain = (params) => {
return post('/api/EditTrain', params)
}
export const GetTrainDetails = (params) => {
return get('/api/GetTrainDetails', params)
}
export const DeleteExamRoster = (params) => {
return get('/api/DeleteExamRoster', params)
}
export const apiUpload = (url,params) => {
return uploadFile('/api/ImportExam', params)
}
// 上传文件接口
export const apiUploadList = (url,params) => {
return upload('/api/Upload'+url, params);
};

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,333 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4490429" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe61d;</span>
<div class="name">分析管理</div>
<div class="code-name">&amp;#xe61d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6d2;</span>
<div class="name">实训管理</div>
<div class="code-name">&amp;#xe6d2;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe821;</span>
<div class="name">学习管理</div>
<div class="code-name">&amp;#xe821;</div>
</li>
<!-- 新增客户端管理 -->
<li class="dib">
<span class="icon iconfont">&#xe821;</span>
<div class="name">客户端管理</div>
<div class="code-name">&amp;#xe821;</div>
</li>
<!-- 新增客户端管理 end-->
<li class="dib">
<span class="icon iconfont">&#xe601;</span>
<div class="name">grade</div>
<div class="code-name">&amp;#xe601;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe602;</span>
<div class="name">exam</div>
<div class="code-name">&amp;#xe602;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe603;</span>
<div class="name">system</div>
<div class="code-name">&amp;#xe603;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1716193171193') format('woff2'),
url('iconfont.woff?t=1716193171193') format('woff'),
url('iconfont.ttf?t=1716193171193') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-fenxiguanli"></span>
<div class="name">
分析管理
</div>
<div class="code-name">.icon-fenxiguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shixunguanli"></span>
<div class="name">
实训管理
</div>
<div class="code-name">.icon-shixunguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xuexiguanli"></span>
<div class="name">
学习管理
</div>
<div class="code-name">.icon-xuexiguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chengji"></span>
<div class="name">
grade
</div>
<div class="code-name">.icon-chengji
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-kaoshi"></span>
<div class="name">
exam
</div>
<div class="code-name">.icon-kaoshi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-xitong"></span>
<div class="name">
system
</div>
<div class="code-name">.icon-xitong
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-fenxiguanli"></use>
</svg>
<div class="name">分析管理</div>
<div class="code-name">#icon-fenxiguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shixunguanli"></use>
</svg>
<div class="name">实训管理</div>
<div class="code-name">#icon-shixunguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xuexiguanli"></use>
</svg>
<div class="name">学习管理</div>
<div class="code-name">#icon-xuexiguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chengji"></use>
</svg>
<div class="name">grade</div>
<div class="code-name">#icon-chengji</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-kaoshi"></use>
</svg>
<div class="name">exam</div>
<div class="code-name">#icon-kaoshi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-xitong"></use>
</svg>
<div class="name">system</div>
<div class="code-name">#icon-xitong</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -0,0 +1,39 @@
@font-face {
font-family: "iconfont"; /* Project id 4490429 */
src: url('iconfont.woff2?t=1716193171193') format('woff2'),
url('iconfont.woff?t=1716193171193') format('woff'),
url('iconfont.ttf?t=1716193171193') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-fenxiguanli:before {
content: "\e61d";
}
.icon-shixunguanli:before {
content: "\e6d2";
}
.icon-xuexiguanli:before {
content: "\e821";
}
.icon-chengji:before {
content: "\e601";
}
.icon-kaoshi:before {
content: "\e602";
}
.icon-xitong:before {
content: "\e603";
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,60 @@
{
"id": "4490429",
"name": "LKJC",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "9096254",
"name": "分析管理",
"font_class": "fenxiguanli",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "11101584",
"name": "实训管理",
"font_class": "shixunguanli",
"unicode": "e6d2",
"unicode_decimal": 59090
},
{
"icon_id": "36656926",
"name": "学习管理",
"font_class": "xuexiguanli",
"unicode": "e821",
"unicode_decimal": 59425
},
//
{
"icon_id": "36656927",
"name": "客户端管理",
"font_class": "kehuduanguanli",
"unicode": "e821",
"unicode_decimal": 59427
},
// end
{
"icon_id": "39758479",
"name": "grade",
"font_class": "chengji",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "39758508",
"name": "exam",
"font_class": "kaoshi",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "39758529",
"name": "system",
"font_class": "xitong",
"unicode": "e603",
"unicode_decimal": 58883
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
@font-face {
font-family: 'Microsoft-YaHei';
src: url('./msyh.ttc') format('truetype');
}
@font-face {
font-family: 'D-DIN-Bold';
src: url('./D-DIN-Bold.otf') format('opentype');
}
@font-face {
font-family: 'DouyinSansBold';
src: url('./DouyinSansBold.otf') format('opentype');
}

BIN
src/assets/fonts/msyh.ttc Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
src/assets/login/Login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

BIN
src/assets/menu/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
src/assets/menu/exam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/menu/grade.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/assets/menu/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
src/assets/menu/reset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

BIN
src/assets/menu/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
src/assets/menu/toLead.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

19
src/common/js/public.js Normal file
View File

@ -0,0 +1,19 @@
export const updateCountdown = (targetDate) => {
if (!targetDate) {
targetDate = new Date().getFullYear()
}
const targetTime = new Date(targetDate + '-12-31').getTime()
const currentDate = new Date().getTime()
const timeRemaining = targetTime - currentDate
const days = Math.floor(timeRemaining / (1000 * 60 * 60 * 24))
const hours = Math.floor((timeRemaining % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
const minutes = Math.floor((timeRemaining % (1000 * 60 * 60)) / (1000 * 60))
const seconds = Math.floor((timeRemaining % (1000 * 60)) / 1000)
return [days, hours, minutes, seconds]
}
export const getImgName = (imagePath) => {
// const imagePath = 'http://admin.umayle.com/upload/userphoto/郑亚丽.jpg' // 假设这是图片路径
return imagePath.split('/').pop()
}

76
src/layout/Tab.vue Normal file
View File

@ -0,0 +1,76 @@
<template lang="">
<div class="tag-list">
<el-tag v-for="(tag,index) in tagsList" :key="tag.name" closable :class="{'isActive':tagsActiveIndex===index}"
@click="tagClick(tag,index)" @close="tagClose(index)">
{{ tag.name }}
</el-tag>
</div>
</template>
<script setup>
import { useRoute, useRouter } from 'vue-router'
import { watch, ref } from 'vue'
const route = useRoute()
const router = useRouter()
const tagsList = ref([])
const tagsActiveIndex = ref(1)
const tagClick = (item, index) => {
router.push(item.path)
tagsActiveIndex.value = index
}
const tagClose = (index) => {
const _path = tagsList.value[tagsActiveIndex.value].path
tagsList.value.splice(index, 1)
if (tagsActiveIndex.value === index) {
tagsActiveIndex.value = index > 0 ? index - 1 : 1
router.push(tagsList.value[tagsActiveIndex.value].path)
} else {
const hasIndex = tagsList.value.findIndex((v) => v.path === _path)
tagsActiveIndex.value = hasIndex
}
}
watch(
() => route,
(newValue, oldValue) => {
const hasIndex = tagsList.value.findIndex((v) => v.path === newValue.path)
if (hasIndex < 0 && newValue.meta.title !== '') {
tagsList.value.push({
name: newValue.meta.title,
path: newValue.path
})
tagsActiveIndex.value = tagsList.value.length - 1
} else {
// tagsActiveIndex.value = hasIndex;
}
},
{ immediate: true, deep: true }
)
</script>
<style lang="scss" scoped>
.tag-list {
.el-tag{
background: rgba(69, 85, 82, 0.10);
color:rgba(69, 85, 82, 1);
margin-right: 10px;
cursor: pointer;
&.isActive {
background: rgba(69, 85, 82, 0.10);
color:rgba(69, 85, 82, 1);
::v-deep{
.el-icon{
color:rgba(69, 85, 82, 1);
}
}
}
}
}
:deep(.el-tag__close){
color:rgba(69, 85, 82, 1) !important;
}
:deep(.el-tag__close:hover){
background-color: transparent !important;
}
</style>

232
src/layout/index.vue Normal file
View File

@ -0,0 +1,232 @@
<script setup>
import { ref } from 'vue'
import { ArrowDown } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import mock from '@/router/menu/index.js'
import Tab from './Tab.vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// import useUserStore from '@/store/index.js'
// const userStore = useUserStore()
//
const isCollapse = ref(false)
const handleOpen = (key, keyPath) => {
console.log(key, keyPath)
}
const handleClose = (key, keyPath) => {
console.log(key, keyPath)
}
// 退
function loginOut () {
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
router.push('/Login')
})
}
</script>
<template>
<section class="common-layout">
<el-container class="layout">
<el-header>
<el-header>
<!-- <img src="../assets/menu/logo.png" alt=""/> -->
<div class="Administrator">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
超级管理员
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="loginOut">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-header>
</el-header>
<el-container class="ContainerConent">
<el-aside>
<aside>
<div class="Sidebar">
<el-menu
default-active="0"
class="el-menu-vertical-demo"
:collapse="isCollapse"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item :index="String(0)" @click="$router.push(mock[0].path)">
<template #title>
<i :class="['iconfont', mock[0].meta.icon]"></i>
<span>{{ mock[0].meta.title }}</span>
</template>
</el-menu-item>
<el-menu-item :index="String(1)" @click="$router.push(mock[1].path)">
<template #title>
<i :class="['iconfont', mock[1].meta.icon]"></i>
<span>{{ mock[1].meta.title }}</span>
</template>
</el-menu-item>
<!-- <el-sub-menu index="2">
<template #title>
<i :class="['iconfont', mock[2].meta.icon]"></i>
<span>{{ mock[2].meta.title }}</span>
</template>
<el-menu-item v-for="(subItem, subIndex) in mock[2].children" :key="subIndex" :index="String('subIndex' + subIndex)" @click="$router.push(subItem.path)">
{{ subItem.meta.title }}
</el-menu-item>
</el-sub-menu> -->
<!-- <el-sub-menu index="3">
<template #title>
<i :class="['iconfont', mock[3].meta.icon]"></i>
<span>{{ mock[3].meta.title }}</span>
</template>
<el-menu-item v-for="(digitem, digIndex) in mock[3].children" :key="digIndex" :index="String('digIndex' + digIndex)" @click="$router.push(digitem.path)">
{{ digitem.meta.title }}
</el-menu-item>
</el-sub-menu> -->
<!-- <el-menu-item :index="String(4)" @click="$router.push(mock[4].path)">
<template #title>
<i :class="['iconfont', mock[4].meta.icon]"></i>
<span>{{ mock[4].meta.title }}</span>
</template>
</el-menu-item> -->
<!-- <el-menu-item :index="String(5)" @click="$router.push(mock[5].path)">
<template #title>
<i :class="['iconfont', mock[5].meta.icon]"></i>
<span>{{ mock[5].meta.title }}</span>
</template>
</el-menu-item> -->
<!-- 客户端管理 -->
<!-- <el-sub-menu index="6">
<template #title>
<i :class="['iconfont', mock[6].meta.icon]"></i>
<span>{{ mock[6].meta.title }}</span>
</template>
<el-menu-item v-for="(figItem, figIndex) in mock[6].children" :key="figIndex" :index="String('figIndex' + figIndex)" @click="$router.push(figItem.path)">
{{ figItem.meta.title }}
</el-menu-item>
</el-sub-menu> -->
<!-- 客户端管理end -->
</el-menu>
</div>
</aside>
</el-aside>
<el-container class="mainContent">
<div class="Tool">
<Tab></Tab>
</div>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</el-container>
</section>
</template>
<style scoped lang="scss">
.common-layout{
width: 100vw;
height: 100vh;
overflow: hidden;
}
.layout{
width: 100%;
height: 100%;
}
.el-menu{
border: none;
}
.el-header {
width: 100%;
height: 60px;
background-color: white;
padding: 0;
img {
width: 126px;
height: 37px;
margin-top: 12px;
margin-left: 16px;
}
}
.ContainerConent{
width: 100%;
height: calc(100% - 60px);
background-color: rgba(246, 249, 248, 1);
}
.el-aside{
width: 200px;
height: 100%;
background-color: #fff;
}
.mainContent{
width: 100%;
height: 100%;
display: block;
padding:17px 20px;
}
.Tool{
width: 100%;
height: 24px;
.el-tabs{
width: 100%;
height: 24px;
}
:deep(.el-tabs__header){
border:none !important;
}
:deep(.el-tabs__item ){
width: 88px;
height: 24px;
background-color: rgba(69, 85, 82, 0.10);
}
}
.el-main{
padding: 0;
height: calc(100% - 34px);
width: 100%;
margin-top:16px ;
overflow: hidden;
}
.el-menu-item.is-active{
color: #0D867F;
}
.iconfont{
margin-right: 16px;
}
.Administrator{
float: right;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 40px;
cursor: pointer;
}
:deep(.el-dropdown-link){
border: none!important;
}
:deep(.el-dropdown-link){
border: none!important;
}
:deep(.example-showcase .el-dropdown-link) {
cursor: pointer;
color: var(--el-color-primary);
display: flex;
align-items: center;
}
</style>

12
src/main.js Normal file
View File

@ -0,0 +1,12 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import 'element-plus/dist/index.css'
import ElementPlus from 'element-plus'
import zhCN from 'element-plus/dist/locale/zh-cn.mjs' // 引入中文
import './style/reset.css'
import './assets/fonts/index.css'
import store from '@/store'
import vue3SeamlessScroll from 'vue3-seamless-scroll'
createApp(App).use(router).use(store).use(vue3SeamlessScroll).use(ElementPlus, { locale: zhCN }).mount('#app')

240
src/router/index.js Normal file
View File

@ -0,0 +1,240 @@
import { createRouter, createWebHashHistory } from 'vue-router'
// 引入其他组件...
const routes = [
{
path: '/',
name: '',
redirect: '/home'
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/index.vue')
},
{
path: '/map',
name: 'map',
component: () => import('@/views/map/index.vue')
},
{
path: '/home',
name: 'Home',
component: () => import('@/layout/index.vue'),
redirect: '/home',
children: [
{
path: '/home',
component: () => import('@/views/home/index.vue'),
meta: { sort: 1, title: '测试', icon: '' }
},
{
path: '/ExaminationManagement',
component: () => import('@/views/ExaminationManagement/index.vue'),
meta: { sort: 1, title: '考试管理', icon: '' }
}
// {
// path: '/ScoreInquiry',
// component: () => import('@/views/ScoreInquiry/index.vue'),
// meta: { sort: 2, title: '成绩查询', icon: '' }
// },
// {
// path: '/TrainingManage',
// component: () => import('@/views/TrainingManage/index.vue'),
// meta: { sort: 5, title: '实训管理11', icon: '' }
// },
// {
// path: '/AnalyticalManagement',
// component: () => import('@/views/AnalyticalManagement/index.vue'),
// meta: { sort: 6, title: '分析管理', icon: '' }
// },
// {
// path: '/SystemManagement',
// // component: () => import('@/views/ScoreInquiry/index.vue'),
// meta: { sort: 3, title: '系统管理', icon: '' },
// children: [
// {
// path: '/UserManagement',
// component: () => import('@/views/SystemManagement/UserManagement/index.vue'),
// meta: { title: '用户管理', icon: '' }
// },
// {
// path: '/IPManagement',
// component: () => import('@/views/SystemManagement/IPManagement/index.vue'),
// meta: { title: '考场IP管理', icon: '' }
// },
// {
// path: '/LoginRecord',
// component: () => import('@/views/SystemManagement/LoginRecord/index.vue'),
// meta: { title: '考场登录日志', icon: '' }
// }
// ]
// },
// {
// path: '/LearninManagement',
// meta: { sort: 4, title: '学习管理', icon: '' },
// children: [
// {
// path: '/LearningQuery',
// component: () => import('@/views/LearninManagement/LearningQuery/index.vue'),
// meta: { title: '学习查询', icon: '' }
// },
// {
// path: '/NewLearning',
// component: () => import('@/views/LearninManagement/NewLearning/index.vue'),
// meta: { title: '学习新增', icon: '' }
// }
//
// ]
// },
// {
// path: '/TrainingManagement',
// component: () => import('@/views/TrainingManagement/index.vue'),
// meta: { sort: 5, title: '实训管理', icon: '' }
// },
// {
// path: '/TrainingManage',
// component: () => import('@/views/TrainingManage/index.vue'),
// meta: { sort: 5, title: '实训管理11', icon: '' }
// },
// {
// path: '/PracticalManage',
// component: () => import('@/views/PracticalManage/index.vue'),
// meta: { sort: 5, title: '实训管理', icon: '' }
// },
//
// 客户端管理
// {
// path: '/ClientManagement',
// meta: { sort: 7, title: '客户端管理', icon: '' },
// children: [
// {
//
// path: '/LineTools',
// component: () => import('@/views/ClientManagement/LineTools/index.vue'),
// meta: { title: '巡线工具器', icon: '' }
// },
// {
// path: '/TroubleShooting',
// component: () => import('@/views/ClientManagement/TroubleShooting/index.vue'),
// meta: { title: '排故工具器', icon: '' }
// },
// {
// path: '/PowerFail',
// component: () => import('@/views/ClientManagement/PowerFail/index.vue'),
// meta: { title: '停电操作票', icon: '' }
// },
// {
// path: '/PowerGet',
// component: () => import('@/views/ClientManagement/PowerGet/index.vue'),
// meta: { title: '送电操作票', icon: '' }
// },
// {
// path: '/DistributionBox',
// component: () => import('@/views/ClientManagement/DistributionBox/index.vue'),
// meta: { title: '配电箱', icon: '' }
// }, {
// path: '/TowerOne',
// component: () => import('@/views/ClientManagement/TowerOne/index.vue'),
// meta: { title: '杆塔1', icon: '' }
// }, {
// path: '/TowerTwo',
// component: () => import('@/views/ClientManagement/TowerTwo/index.vue'),
// meta: { title: '杆塔2', icon: '' }
// }, {
// path: '/TowerThree',
// component: () => import('@/views/ClientManagement/TowerThree/index.vue'),
// meta: { title: '杆塔3', icon: '' }
// }, {
// path: '/TowerFour',
// component: () => import('@/views/ClientManagement/TowerFour/index.vue'),
// meta: { title: '杆塔4', icon: '' }
// }, {
// path: '/TowerFive',
// component: () => import('@/views/ClientManagement/TowerFive/index.vue'),
// meta: { title: '杆塔5', icon: '' }
// }, {
// path: '/TowerSix',
// component: () => import('@/views/ClientManagement/TowerSix/index.vue'),
// meta: { title: '杆塔6', icon: '' }
// }, {
// path: '/TowerSeven',
// component: () => import('@/views/ClientManagement/TowerSeven/index.vue'),
// meta: { title: '杆塔7', icon: '' }
// }, {
// path: '/LineStop',
// component: () => import('@/views/ClientManagement/LineStop/index.vue'),
// meta: { title: '线档', icon: '' }
// }
// ]
// },
// // 客户端管理end
// {
// path: '/EditorMacros',
// component: () => import('@/views/ExaminationManagement/EditorMacros/index.vue'),
// meta: { title: '', icon: '' },
// redirect: '/SceneEditing',
// children: [
// {
// path: '/SceneEditing',
// component: () => import('@/views/ExaminationManagement/EditorMacros/SceneEditing.vue')
// },
// {
// path: '/LinePatrol',
// component: () => import('@/views/ExaminationManagement/EditorMacros/LinePatrol.vue')
// },
// {
// path: '/Troubleshoot',
// component: () => import('@/views/ExaminationManagement/EditorMacros/Troubleshoot.vue')
// },
// {
// path: '/Powercut',
// component: () => import('@/views/ExaminationManagement/EditorMacros/Powercut.vue')
// },
// {
// path: '/DeliveryCurrent',
// component: () => import('@/views/ExaminationManagement/EditorMacros/DeliveryCurrent.vue')
// }
// ]
// },
// // 实训管理
// {
// path: '/EditortrainMacros',
// component: () => import('@/views/PracticalManage/EditortrainMacros/index.vue'),
// meta: { title: '', icon: '' },
// redirect: '/TrainEditing',
// children: [
// {
// path: '/TrainEditing',
// component: () => import('@/views/PracticalManage/EditortrainMacros/TrainEditing.vue')
// },
// {
// path: '/LinePatrol',
// component: () => import('@/views/PracticalManage/EditortrainMacros/LinePatrol.vue')
// },
// {
// path: '/Troubleshoot',
// component: () => import('@/views/PracticalManage/EditortrainMacros/Troubleshoot.vue')
// },
// {
// path: '/Powercut',
// component: () => import('@/views/PracticalManage/EditortrainMacros/Powercut.vue')
// },
// {
// path: '/DeliveryCurrent',
// component: () => import('@/views/PracticalManage/EditortrainMacros/DeliveryCurrent.vue')
// }
// ]
// }
]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router

121
src/router/menu/index.js Normal file
View File

@ -0,0 +1,121 @@
// import {ref} from "vue";
export default [
{
path: 'ExaminationManagement',
meta: { sort: 1, title: '启动器管理', icon: 'icon-kaoshi' }
},
{
path: 'home',
meta: { sort: 1, title: '模型管理', icon: 'icon-chengji' }
}
// {
// path: 'ScoreInquiry',
// meta: { sort: 2, title: '成绩查询', icon: 'icon-chengji' }
// },
// {
// path: 'SystemManagement',
// meta: { sort: 3, title: '系统管理', icon: 'icon-xitong' },
// children: [
// {
// path: 'UserManagement',
// meta: { title: '用户管理', icon: '' }
// },
// {
// path: 'IPManagement',
// meta: { title: '考场IP管理', icon: '' }
// },
// {
// path: 'LoginRecord',
// meta: { title: '考场登录日志', icon: '' }
// }
// ]
// },
// {
// path: 'LearninManagement',
// meta: { sort: 4, title: '学习管理', icon: 'icon-chengji' },
// children: [
// {
// path: 'NewLearning',
// meta: { title: '学习新增', icon: '' }
// },
// {
// path: 'LearningQuery',
// meta: { title: '学习查询', icon: '' }
// }
//
// ]
// },
//
// path: 'TrainingManage',
// meta: { sort: 5, title: '实训管理11', icon: 'icon-chengji' }
// },
// {
// path: 'PracticalManage',
// meta: { sort: 5, title: '实训管理', icon: 'icon-chengji' }
// },
// {
// path: 'AnalyticalManagement',
// meta: { sort: 6, title: '分析管理', icon: 'icon-chengji' }
// }
// {
// path: 'ClientManagement',
// meta: { sort: 7, title: '客户端管理', icon: 'icon-chengji' },
// children: [
// {
// path: 'LineTools',
// component: () => import('@/views/ClientManagement/LineTools/index.vue'),
// meta: { title: '巡线工具器', icon: '' }
// }, {
// path: '/TroubleShooting',
// component: () => import('@/views/ClientManagement/TroubleShooting/index.vue'),
// meta: { title: '排故工具器', icon: '' }
// }, {
// path: '/PowerFail',
// component: () => import('@/views/ClientManagement/PowerFail/index.vue'),
// meta: { title: '停电操作票', icon: '' }
// }, {
// path: '/PowerGet',
// component: () => import('@/views/ClientManagement/PowerGet/index.vue'),
// meta: { title: '送电操作票', icon: '' }
// }, {
// path: '/DistributionBox',
// component: () => import('@/views/ClientManagement/DistributionBox/index.vue'),
// meta: { title: '配电箱', icon: '' }
// }, {
// path: '/TowerOne',
// component: () => import('@/views/ClientManagement/TowerOne/index.vue'),
// meta: { title: '杆塔1', icon: '' }
// }, {
// path: '/TowerTwo',
// component: () => import('@/views/ClientManagement/TowerTwo/index.vue'),
// meta: { title: '杆塔2', icon: '' }
// }, {
// path: '/TowerThree',
// component: () => import('@/views/ClientManagement/TowerThree/index.vue'),
// meta: { title: '杆塔3', icon: '' }
// }, {
// path: '/TowerFour',
// component: () => import('@/views/ClientManagement/TowerFour/index.vue'),
// meta: { title: '杆塔4', icon: '' }
// }, {
// path: '/TowerFive',
// component: () => import('@/views/ClientManagement/TowerFive/index.vue'),
// meta: { title: '杆塔5', icon: '' }
// }, {
// path: '/TowerSix',
// component: () => import('@/views/ClientManagement/TowerSix/index.vue'),
// meta: { title: '杆塔6', icon: '' }
// }, {
// path: '/TowerSeven',
// component: () => import('@/views/ClientManagement/TowerSeven/index.vue'),
// meta: { title: '杆塔7', icon: '' }
// }, {
// path: '/LineStop',
// component: () => import('@/views/ClientManagement/LineStop/index.vue'),
// meta: { title: '线档', icon: '' }
// }
// ]
// }
]

3
src/store/index.js Normal file
View File

@ -0,0 +1,3 @@
import { createPinia } from 'pinia'
const store = createPinia()
export default store

142
src/style/reset.css Normal file
View File

@ -0,0 +1,142 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
box-sizing: border-box;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
width: 100vw;
height: 100vh;
font-family: "Microsoft YaHei", "PingFangSC-Regular", "Helvetica Neue",
"Helvetica", "Hiragino Sans GB", "SimSun", "sans-serif";
font-size: 14px;
overflow: hidden;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
#app {
width: 100%;
height: 100%;
overflow: hidden;
}

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '送电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus"
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '巡线'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '停电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus";
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '排故'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.SelectToolList
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div class="section">
<div class="ScorePoints">
<div class="title">
<img src="../../../assets/menu/exam.png" alt=""/>
<p>考试名称编辑器</p>
</div>
<div class="TestScore">
<div class="fractionalValue" >
<div class="user-name" v-for="scoreItem in scoreList" :key="scoreItem.id">
<span class="designation">{{scoreItem.designation}}:</span>
<span class="score">{{scoreItem.score}}</span>
<el-divider direction="vertical"></el-divider>
</div>
</div>
<div class="totalPoints">
<div class="score">100</div>
<p class="explain">总分</p>
</div>
</div>
</div>
<div class="editorContent">
<div class="actionBar">
<div class="operatingButton">
<el-button :style="{color: tabAct === 1 ? '#0d867f' : ''}" @click="selTabs(1)">场景编辑</el-button>
<el-button :style="{color: tabAct === 2 ? '#0d867f' : ''}" @click="selTabs(2)">巡线工具器</el-button>
<el-button :style="{color: tabAct === 3 ? '#0d867f' : ''}" @click="selTabs(3)">排故工具器</el-button>
<el-button :style="{color: tabAct === 4 ? '#0d867f' : ''}" @click="selTabs(4)">停电操作票</el-button>
<el-button :style="{color: tabAct === 5 ? '#0d867f' : ''}" @click="selTabs(5)">送电操作票</el-button>
</div>
</div>
<div class="operating">
<!-- <router-view></router-view>-->
<SceneEditing v-if="tabAct === 1" :ExamId="ExamId"></SceneEditing>
<LinePatrol v-else-if="tabAct === 2" :ExamId="ExamId"></LinePatrol>
<Troubleshoot v-else-if="tabAct === 3" :ExamId="ExamId"></Troubleshoot>
<Powercut v-else-if="tabAct === 4" :ExamId="ExamId"></Powercut>
<DeliveryCurrent v-else-if="tabAct === 5" :ExamId="ExamId"></DeliveryCurrent>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import SceneEditing from './SceneEditing.vue'
import LinePatrol from './LinePatrol.vue'
import Troubleshoot from './Troubleshoot.vue'
import Powercut from './Powercut.vue'
import DeliveryCurrent from './DeliveryCurrent.vue'
const route = useRoute()
const ExamId = ref(route.query.ExamId)
const scoreList = ([
{ designation: '巡检工器具分值', score: '3' },
{ designation: '排故工器具分值', score: ' 3' },
{ designation: '停电操作票填写分值', score: '5' },
{ designation: '送电操作票填写分值', score: '5' },
{ designation: '停电操作票步骤分值', score: '5' },
{ designation: '送电操作票步骤分值', score: '3' },
{ designation: '时间分分值', score: '5' },
{ designation: '缺陷查找、缺陷处理、缺陷分类分值', score: '69' }
])
const tabAct = ref(1)
const selTabs = (v) => {
console.log(v,'v--')
tabAct.value = Number(v)
}
const router = useRouter()
const sceneButton = () => {
router.push('/SceneEditing') //
}
const linePatrolButton = () => {
router.push('/LinePatrol')//
}
const troubleshootButton = () => {
router.push('/Troubleshoot') //
}
const powercutButton = () => {
router.push('/Powercut') //
}
const deliveryButton = () => {
router.push('/DeliveryCurrent') //
}
</script>
<style scoped lang="scss">
.section{
width: 100%;
height: 100%;
background-color: #fff;
}
.ScorePoints{
height: 174px;
border-radius: 6px 6px 0 0;
margin:0 20px;
border-bottom: 1px solid #F2F3F5;
overflow: hidden;
.title{
margin-top: 20px;
display: flex;
margin-bottom: 22px;
font-family: Microsoft-YaHei;
img{
width: 28px;
height: 28px;
}
p{
font-weight: 400;
font-size: 20px;
color: #1D2129;
line-height: 28px;
}
}
.TestScore{
height: 86px;
background: #F2F3F5;
border-radius: 4px 4px 4px 4px;
justify-content: space-between;
display: flex;
}
.fractionalValue{
display: flex;
height: 100%;
flex-wrap: wrap;
padding-top: 16px;
.user-name{
margin-left: 18px;
white-space: nowrap;
.designation{
font-weight: 400;
font-size: 14px;
color: #1D2129;
}
.score{
margin-right: 18px;
margin-left:8px;
font-weight: 700;
font-size: 14px;
color: #0D867F;
line-height: 21px;
}
.el-divider--vertical{
margin: 0;
height: 19px;
border-left:1px solid rgba(29, 33, 41, 0.50);
}
}
.user-name:nth-child(10){
.el-divider--vertical{
display: none;
}
}
}
.totalPoints{
margin-right: 16px;
margin-left: 27px;
.score{
width: 58px;
height: 54px;
background-image: url("../../../assets/menu/grade.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin-top: 10px;
position: relative;
padding:10px 15px 0;
font-family: D-DIN-Bold;
font-weight: 700;
font-size: 24px;
color: #FF6565;
line-height: 26px;
}
.explain{
width: 100%;
text-align: center;
font-weight: 400;
font-size: 12px;
color: #1D2129;
}
}
}
.editorContent{
width: 100%;
height: calc(100% - 174px);
// height: calc(100% - 12px);//
//background-color: #55a532;
}
.actionBar{
width: 100%;
height: 68px;
background: #FFFFFF;
box-shadow: 0 4px 3px 0 rgba(0,0,0,0.03);
display: flex;
align-items: center;
margin-bottom: 5px;
.operatingButton{
margin-left: 20px;
.el-button{
margin-right: 14px;
width: 88px;
height: 28px;
border: none;
font-weight: 500;
font-size: 14px;
color: #455552;
line-height: 21px;
}
.el-button:hover{
color: #455552;
}
.el-button:focus{
background-color: #E7F9F8;
font-weight: 500;
font-size: 14px;
color: #0D867F;
}
}
}
.operating{
width: 100%;
height: calc(100% - 68px);
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '送电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus"
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '巡线'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '停电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus";
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '排故'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.SelectToolList
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div class="section">
<div class="ScorePoints">
<div class="title">
<img src="../../../assets/menu/exam.png" alt=""/>
<p>考试名称编辑器</p>
</div>
<div class="TestScore">
<div class="fractionalValue" >
<div class="user-name" v-for="scoreItem in scoreList" :key="scoreItem.id">
<span class="designation">{{scoreItem.designation}}:</span>
<span class="score">{{scoreItem.score}}</span>
<el-divider direction="vertical"></el-divider>
</div>
</div>
<div class="totalPoints">
<div class="score">100</div>
<p class="explain">总分</p>
</div>
</div>
</div>
<div class="editorContent">
<div class="actionBar">
<div class="operatingButton">
<el-button :style="{color: tabAct === 1 ? '#0d867f' : ''}" @click="selTabs(1)">场景编辑</el-button>
<el-button :style="{color: tabAct === 2 ? '#0d867f' : ''}" @click="selTabs(2)">巡线工具器</el-button>
<el-button :style="{color: tabAct === 3 ? '#0d867f' : ''}" @click="selTabs(3)">排故工具器</el-button>
<el-button :style="{color: tabAct === 4 ? '#0d867f' : ''}" @click="selTabs(4)">停电操作票</el-button>
<el-button :style="{color: tabAct === 5 ? '#0d867f' : ''}" @click="selTabs(5)">送电操作票</el-button>
</div>
</div>
<div class="operating">
<!-- <router-view></router-view>-->
<SceneEditing v-if="tabAct === 1" :ExamId="ExamId"></SceneEditing>
<LinePatrol v-else-if="tabAct === 2" :ExamId="ExamId"></LinePatrol>
<Troubleshoot v-else-if="tabAct === 3" :ExamId="ExamId"></Troubleshoot>
<Powercut v-else-if="tabAct === 4" :ExamId="ExamId"></Powercut>
<DeliveryCurrent v-else-if="tabAct === 5" :ExamId="ExamId"></DeliveryCurrent>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import SceneEditing from './SceneEditing.vue'
import LinePatrol from './LinePatrol.vue'
import Troubleshoot from './Troubleshoot.vue'
import Powercut from './Powercut.vue'
import DeliveryCurrent from './DeliveryCurrent.vue'
const route = useRoute()
const ExamId = ref(route.query.ExamId)
const scoreList = ([
{ designation: '巡检工器具分值', score: '3' },
{ designation: '排故工器具分值', score: ' 3' },
{ designation: '停电操作票填写分值', score: '5' },
{ designation: '送电操作票填写分值', score: '5' },
{ designation: '停电操作票步骤分值', score: '5' },
{ designation: '送电操作票步骤分值', score: '3' },
{ designation: '时间分分值', score: '5' },
{ designation: '缺陷查找、缺陷处理、缺陷分类分值', score: '69' }
])
const tabAct = ref(1)
const selTabs = (v) => {
console.log(v,'v--')
tabAct.value = Number(v)
}
const router = useRouter()
const sceneButton = () => {
router.push('/SceneEditing') //
}
const linePatrolButton = () => {
router.push('/LinePatrol')//
}
const troubleshootButton = () => {
router.push('/Troubleshoot') //
}
const powercutButton = () => {
router.push('/Powercut') //
}
const deliveryButton = () => {
router.push('/DeliveryCurrent') //
}
</script>
<style scoped lang="scss">
.section{
width: 100%;
height: 100%;
background-color: #fff;
}
.ScorePoints{
height: 174px;
border-radius: 6px 6px 0 0;
margin:0 20px;
border-bottom: 1px solid #F2F3F5;
overflow: hidden;
.title{
margin-top: 20px;
display: flex;
margin-bottom: 22px;
font-family: Microsoft-YaHei;
img{
width: 28px;
height: 28px;
}
p{
font-weight: 400;
font-size: 20px;
color: #1D2129;
line-height: 28px;
}
}
.TestScore{
height: 86px;
background: #F2F3F5;
border-radius: 4px 4px 4px 4px;
justify-content: space-between;
display: flex;
}
.fractionalValue{
display: flex;
height: 100%;
flex-wrap: wrap;
padding-top: 16px;
.user-name{
margin-left: 18px;
white-space: nowrap;
.designation{
font-weight: 400;
font-size: 14px;
color: #1D2129;
}
.score{
margin-right: 18px;
margin-left:8px;
font-weight: 700;
font-size: 14px;
color: #0D867F;
line-height: 21px;
}
.el-divider--vertical{
margin: 0;
height: 19px;
border-left:1px solid rgba(29, 33, 41, 0.50);
}
}
.user-name:nth-child(10){
.el-divider--vertical{
display: none;
}
}
}
.totalPoints{
margin-right: 16px;
margin-left: 27px;
.score{
width: 58px;
height: 54px;
background-image: url("../../../assets/menu/grade.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin-top: 10px;
position: relative;
padding:10px 15px 0;
font-family: D-DIN-Bold;
font-weight: 700;
font-size: 24px;
color: #FF6565;
line-height: 26px;
}
.explain{
width: 100%;
text-align: center;
font-weight: 400;
font-size: 12px;
color: #1D2129;
}
}
}
.editorContent{
width: 100%;
height: calc(100% - 174px);
// height: calc(100% - 12px);//
//background-color: #55a532;
}
.actionBar{
width: 100%;
height: 68px;
background: #FFFFFF;
box-shadow: 0 4px 3px 0 rgba(0,0,0,0.03);
display: flex;
align-items: center;
margin-bottom: 5px;
.operatingButton{
margin-left: 20px;
.el-button{
margin-right: 14px;
width: 88px;
height: 28px;
border: none;
font-weight: 500;
font-size: 14px;
color: #455552;
line-height: 21px;
}
.el-button:hover{
color: #455552;
}
.el-button:focus{
background-color: #E7F9F8;
font-weight: 500;
font-size: 14px;
color: #0D867F;
}
}
}
.operating{
width: 100%;
height: calc(100% - 68px);
}
</style>

864
src/views/home/index.vue Normal file
View File

@ -0,0 +1,864 @@
<template>
<div class="PageContent">
<div class="WebToolbar">
<div class="FormComponent">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="企业名称">
<el-input
v-model="formInline.EnterpriseName"
placeholder="请输入企业编码"
clearable
/>
</el-form-item>
<el-form-item label="企业编码">
<el-input
v-model="formInline.EnterpriseCode"
placeholder="请输入企业编码"
clearable
/>
</el-form-item>
<el-form-item label="模型名称">
<el-input
v-model="formInline.ModelName"
placeholder="请输入模型名称"
clearable
/>
</el-form-item>
</el-form>
</div>
<div class="ButtonAssembly">
<el-button style="color: #fff" @click="queryData()">
<img src="../../assets/menu/search.png" alt="" />
<span>查询</span>
</el-button>
<el-button style="color: #1d2129" @click="resetFormInline">
<img src="../../assets/menu/reset.png" alt="" />
<span>重置</span>
</el-button>
</div>
</div>
<div class="Tabulation">
<div class="actionBar">
<h1>考试列表</h1>
<div class="Worktop">
<el-button @click="goToAboutPage">编辑器</el-button>
<el-button @click="handleReleaseExam">发布</el-button>
<el-button @click="handleRevokeReleaseExam">撤销发布</el-button>
<el-button @click="handleFinishedExam">考试结束</el-button>
<el-button @click="handleExamination">考试名单</el-button>
<el-button class="BlueBack" @click="handleCreate">
<img src="../../assets/menu/Increased.png" alt="" />
<span>新增</span>
</el-button>
<el-button class="BlueBack" @click="dialogToLead = true">
<img src="../../assets/menu/toLead.png" alt="" />
<span>导入</span>
</el-button>
<el-button class="Delete">
<img src="../../assets/menu/delete.png" alt="" />
<span>删除</span>
</el-button>
</div>
</div>
<div class="ExaminationForm">
<el-table
ref="multipleTableRef"
:data="tableData"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" />
<el-table-column label="序号" type="index" :index="indexMethod" width="60px"/>
<el-table-column property="EnterpriseName" label="企业名称" />
<el-table-column property="EnterpriseCode" label="企业编码" />
<el-table-column property="DistrictCode" label="关区代码" />
<el-table-column property="ModelName" label="模型名称" />
<el-table-column property="VersionNumber" label="版本号" />
<el-table-column property="MapLongitude" label="地图经度" />
<el-table-column property="MapLatitude" label="地图纬度" />
<el-table-column property="TrainingSize" label="模型包大小" />
<el-table-column property="ModelResources" label="模型包资源地址" />
<el-table-column property="UpdateTime" label="最新更新时间" />
<el-table-column property="" label="操作">
<template #default="{row}">
<span class="user-name" @click="handleEdit(row)" >编辑</span>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page="InlineForm.PageIndex"
:page-size="InlineForm.PageSize"
:small="small"
:disabled="disabled"
:background="background"
layout="total, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<!--新增弹框-->
<el-dialog
v-model="dialogFormVisible"
title="编辑模型"
width="1050"
center
@close="closeDialog"
>
<el-form ref="formRef" :model="form" :rules="state.rules" :inline="true" :label-width="formLabelWidth">
<el-form-item label="企业编号:" prop="ExamName">
<el-input v-model="form.ExamName" />
</el-form-item>
<el-form-item
label="企业名称:"
class="demo-form-scene"
>
<el-input v-model="form.ExamName" />
</el-form-item>
<el-form-item label="模型名称:" >
<el-input v-model="form.ExamName" />
</el-form-item>
<el-form-item label="版本号:" >
<el-input v-model="form.ExamName" />
</el-form-item>
<el-form-item label="地图经度:" >
<el-input v-model="form.ExaminationDuration" autocomplete="off" />
</el-form-item>
<el-form-item label="地图纬度:">
<el-input v-model="form.IncomingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
<el-form-item label="模型包大小:">
<el-input v-model="form.OutgoingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
<el-form-item label="模型包资源:">
<el-input v-model="form.OutgoingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
<el-form-item label="更新时间:">
<el-input v-model="form.OutgoingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">
取消
</el-button>
<el-button @click="submit" type="primary">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import {
GetModelList,
AddExam,
EditExam,
GetModelDetails,
EditExamList,
DeleteExam,
GetScene,
GetPlatformArea,
GetLine,
ApiReleaseExam,
ApiRevokeReleaseExam,
ApiFinishedExam,
ApiCopyExam,
ApiDownloadExamm,
ApiGetExamRosterList,
DeleteExamRoster,
ApiGetAddExamRosterListt,
ApiAddExamRoster,
apiUpload
} from '@/api/index.js'
const formInline = reactive({
EnterpriseName: '',
EnterpriseCode: '',
ModelName: '',
PageIndex: 1,
PageSize: 10
})
const resetFormInline = () => {
formInline.EnterpriseName = ''
formInline.EnterpriseCode = ''
formInline.ModelName = ''
getTable()
// for (const key in formInline) {
// if ( key !== 'PageIndex' || key !== 'PageIndex' ) formInline[key] = ''
// }
}
//
const indexMethod = (index) => {
return index + 1
}
//
const formRef = ref(null)
const dialogFormVisible = ref(false)
function handleCreate () {
dialogFormVisible.value = true
}
const formLabelWidth = '150px'
const value1 = ref('')
const value2 = ref('')
const state = reactive({
rules: {},
scenemList: [],
platformAreaList: [],
lineList: []
})
const form = reactive({
EnterpriseName: '',
DistrictCode: '',
ModelName: '',
VersionNumber: '',
MapLongitude: '',
MapLatitude: '',
Trainingsize: '',
ModelResources: '',
UpdateTime: ''
// WorkOrderContent: '',
// BackgroundInformation: '',
// StartExamTime: '',
// EndExamTime: '',
// Type: ''
})
//
onMounted(() => {
getTable()
// addTable()
GetScene().then(res => {
state.scenemList = res.data
console.log(res.data, 'res.data--')
})
GetPlatformArea({
SceneId: 'eab5920509b011ed844e7cd30a92bb1c'
}).then(res => state.platformAreaList = res.data)
GetLine({
PlatformAreaId: '28f0723409b111ed844e7cd30a92bb1c'
}).then(res => state.lineList = res.data)
})
//
const total = ref(0)
const tableData = ref([])
const queryData = () => {
formInline.PageIndex = 1
getTable()
}
const getTable = async () => {
try {
const { code, data } = await GetModelList({
...formInline
})
if (code === 0) {
console.log('data', data)
total.value = data.total
tableData.value = data.list
} else {
total.value = 0
tableData.value = []
}
} catch (error) {}
}
const multipleTableRef = ref()
const multipleSelection = ref([])
const handleSelectionChange = (val) => {
if (val.length > 1) {
multipleTableRef.value.clearSelection()
multipleTableRef.value.toggleRowSelection(val.pop())
} else {
// this.currentRow = val.pop();
multipleSelection.value = val
}
}
const textarea = ref('')
const small = ref(false)
const background = ref(false)
const disabled = ref(false)
//
const InlineForm = reactive({
PageIndex: 1,
PageSize: 10
})
const handleSizeChange = (val) => {
console.log(`${val} items per page`)
formInline.PageSize = val
getTable()
}
const handleCurrentChange = (val) => {
console.log(`current page: ${val}`)
formInline.PageIndex = val
getTable()
}
const ExamId = ref('')
const handleEdit = async (row) => {
const res = await GetModelDetails({ EnterpriseCode: row.EnterpriseCode })
console.log(res.data, 'res--')
for (const key in form) {
form[key] = res.data[key]
}
// ExamId.value = res.data.ExamId
dialogFormVisible.value = true
}
const handleCopy = (row) => {
ApiCopyExam({ ExamId: row.ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
//
const handleDelete = (row) => {
console.log(row.ExamId, 'row--')
ElMessageBox.confirm('确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
DeleteExam({ ExamId: row.ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
//
const submit = () => {
formRef.value.validate(async (valid) => {
console.log(form, 'from--')
if (valid) {
const obj = state.platformAreaList.find(v => v.PlatformAreaId == form.PlatformAreaId)
console.log(obj, 'obj--')
if (ExamId.value) {
EditExam({
...form,
PlatformArea: obj?.PlatformAreaName || '',
ExamId: ExamId.value
}).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
closeDialog()
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
} else {
form.Type = '考试'
AddExam({
...form,
PlatformArea: obj?.PlatformAreaName || ''
}).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
closeDialog()
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
}
})
}
//
const closeDialog = () => {
for (const key in form) {
form[key] = ''
}
ExamId.value = ''
dialogFormVisible.value = false
}
//
const router = useRouter()
const goToAboutPage = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
router.push(`/EditorMacros?ExamId=${multipleSelection.value[0].ExamId}`) //
}
//
const EditFormVisible = ref(false)
const EditExamtableData = ref()
const handleUpdate = async () => {
EditFormVisible.value = true
const data = await EditExamList()
console.log(data.data, 'data')
}
//
const handleReleaseExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要发布吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiReleaseExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const handleRevokeReleaseExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要撤销发布吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiRevokeReleaseExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const handleFinishedExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要考试结束吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiFinishedExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const dialogTabular = ref(false)
const stateA = reactive({
total: 0,
examRosterList: [],
queryForm: {
Name: '',
Account: '',
PageIndex: 1,
PageSize: 10
}
})
const handleExamination = async () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
getExamination()
getAddExamRosterListt()
dialogTabular.value = true
}
const getExamination = async () => {
console.log(stateA.queryForm, ' stateA.queryForm--')
const res = await ApiGetExamRosterList({
ExamId: multipleSelection.value[0].ExamId,
// ExamId: '048dd77b0a734856a86153e2feaa1d1d',
...stateA.queryForm
})
dialogTabular.value = true
stateA.examRosterList = res.data?.list || []
stateA.total = res.data?.total
console.log(res, 'res--ApiGetExamRosterList')
}
//
const handleCancel = (row) => {
console.log(row.ExamUsersId, 'row--')
ElMessageBox.confirm('确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
DeleteExamRoster({ ExamUsersId: row.ExamUsersId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
getExamination()
getAddExamRosterListt()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const dialogExamination = ref(false)
const rosterSelection = ref([])
const handleSelChange = (val) => {
console.log(val, 'val--')
rosterSelection.value = val
}
const stateB = reactive({
total: 0,
examRosterList: [],
queryForm: {
Name: '',
Account: '',
PageIndex: 1,
PageSize: 10
}
})
const handleCurrentChangeB = (val) => {
stateB.queryForm.PageIndex = val
getAddExamRosterListt()
}
const getAddExamRosterListt = async () => {
console.log(stateA.queryForm, ' stateA.queryForm--')
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
const res = await ApiGetAddExamRosterListt({
ExamId: multipleSelection.value[0].ExamId,
// ExamId: '048dd77b0a734856a86153e2feaa1d1d',
...stateB.queryForm
})
dialogTabular.value = true
stateB.examRosterList = res.data?.list || []
stateB.total = res.data?.total
console.log(res, 'res--ApiGetExamRosterList')
}
const addExamRoster = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ApiAddExamRoster({
ExamId: multipleSelection.value[0].ExamId,
UserIdList: rosterSelection.value.map(item => item.UserId)
}).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
getExamination()
getAddExamRosterListt()
dialogExamination.value = false
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
//
const dialogToLead = ref(false)
const uploadRef = ref()
const handleExceed = (files) => {
// submitUpload(files[0])
uploadRef.value.clearFiles()
nextTick(() => {
uploadRef.value.handleStart(files[0])
})
}
const handleChange = (uploadFile) => {
console.log(uploadFile, 'uploadFile')
// submitUpload(uploadFile.raw)
}
const submitUpload = () => {
uploadRef.value.submit()
}
const toUpload = (param) => {
if (!uploadRef.value) return ElMessage.error('请先上传文件')
const formData = new FormData()
formData.append('Files', param.file)
apiUpload('', formData).then((res) => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '上传成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
</script>
<style scoped lang="scss">
.PageContent {
width: 100%;
height: 100%;
}
.WebToolbar {
width: 100%;
height: 72px;
background-color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
:deep(.el-form-item__content) {
width: 256px !important;
height: 32px !important;
}
:deep(.el-input) {
width: 256px !important;
}
:deep(.el-select) {
width: 256px !important;
}
:deep(.el-form-item__label) {
color: #666 !important;
}
}
.ButtonAssembly {
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.el-button:nth-child(1) {
background-color: #0d867f;
}
.el-button:nth-child(2) {
background-color: #f2f3f5;
}
}
.Tabulation {
width: 100%;
height: calc(100% - 72px);
background-color: #fff;
margin-top: 14px;
padding: 20px;
.actionBar {
display: flex;
justify-content: space-between;
h1 {
font-weight: 500;
font-size: 20px;
color: #1d2129;
line-height: 28px;
font-family: Microsoft YaHei, Microsoft YaHei;
}
}
.Worktop {
.el-button {
border: 1px solid #0d867f;
font-weight: 400;
font-size: 14px;
color: #0d867f;
}
.el-button:hover {
background-color: transparent;
}
.BlueBack {
background: #0d867f;
border-radius: 2px 2px 2px 2px;
font-weight: 400;
font-size: 14px;
color: #ffffff;
line-height: 22px;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.BlueBack:hover {
background-color: #0d867f;
}
.Delete {
background: #f2f3f5;
border-radius: 2px 2px 2px 2px;
font-weight: 400;
font-size: 14px;
color: #1d2129;
line-height: 22px;
border: none;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.Delete:hover {
background-color: #f2f3f5;
}
}
.ExaminationForm {
margin-top: 16px;
background-color: #0077aa;
}
.el-table tr {
height: 41px;
}
.el-table td {
height: 41px;
}
:deep(th) {
background-color: #e5e6eb;
}
}
.el-pagination {
float: right;
background-color: #fff !important;
margin-top: 18px;
}
:deep(.el-pager li.is-active) {
background-color: #e7f9f8 !important;
font-weight: 400;
color: #0d867f !important;
}
:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
background-color: #e7f9f8 !important;
}
:deep(.el-select) {
width: 280px !important;
}
:deep(.el-input) {
width: 280px !important;
}
.example {
margin-left: 20px;
color: red;
}
.backInformation {
:deep(.el-input) {
width: 280px !important;
height: 120px !important;
}
}
.dialog-footer {
width: 100%;
text-align: center;
}
:deep(.el-textarea__inner) {
width: 280px !important;
}
.user-name,.register{
cursor: pointer;
}
.functionalUnit{
margin-left: 20px;
display: flex;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
color: #fff;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.el-button:nth-child(1) {
background-color: #2192ba;
}
.el-button:nth-child(2) {
background-color: #17c85f;
}
}
.TabularTitle{
font-size: 14px;
color: #747272;
font-weight: bold;
margin-bottom: 10px;
}
.pagination{
width: 100%;
height:30px;
:deep(.el-pagination){
margin-top: 9px!important;
}
}
.addSlip{
.el-button{
border: none;
background-color: #0077aa;
margin-top: 8px;
color: #fff;
}
:deep(.el-pagination){
margin-top: 8px!important;
}
}
.ml-3{
margin-left: 20px;
}
</style>

198
src/views/login/index.vue Normal file
View File

@ -0,0 +1,198 @@
<template>
<div class="loginPage">
<div class="loginLayout">
<div class="Login-content">
<div class="loginTitle">
<!-- <img src="../../assets/login/Login-logo.png" alt="" /> -->
<p>后台管理系统</p>
</div>
<div class="loginInput">
<p>欢迎登录</p>
<div class="login_from">
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
class="demo-ruleForm"
:size="formSize"
status-icon
>
<el-form-item label="" prop="login_name">
<el-input
v-model="ruleForm.login_name"
placeholder="请输入账号"
:prefix-icon="User"
/>
</el-form-item>
<el-form-item label="" prop="password">
<el-input
type="password"
v-model="ruleForm.password"
placeholder="请输入密码"
:prefix-icon="Lock"
/>
</el-form-item>
<el-button @click="handleLogin">登录</el-button>
</el-form>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { User, Lock } from '@element-plus/icons-vue'
import { apiLogin } from '@/api/index.js'
import JSEncrypt from 'jsencrypt'
//
const formSize = ref('default')
const ruleFormRef = ref()
const ruleForm = reactive({
login_name: '',
password: ''
})
const encryptor = ref(null)
onMounted(() => {
encryptor.value = new JSEncrypt() //
const pubKey =
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2TEstfATFdDWntbJTCPer9FOdwTRe58Vjy9T238/uUQYyoTHClfQCCKnys4elHCE0D0B7D/k2hK9U+xu1hWv1v4lH+n+t5duNVGq3sa5+pOq8j1ztec3W+wlcFgplYJq78XBYGYDbyfhmu5KeDeImsiccwnq3WvigfZYPbTvGv2YsqXDpTp+/s0hQsrYeATr2MuhiBhQGynLUvKCEcWvd/GNByMxJdJwl0k+IZW+DiCDmNX9Qwj23HF7U+Om7jEZC+Li/j2MHA5C4eEtVzgVC4VZETVOIcLv/UDufnAlneTJK2Exo+4YFEg9S1shpqUz9shSBl8JF9DM2a3KKmxc4wIDAQAB'
encryptor.value.setPublicKey(pubKey)
})
const router = useRouter()
const handleLogin = async () => {
const rsaPassWord = encryptor.value.encrypt(ruleForm.password) //
try {
const response = await apiLogin({
login_name: ruleForm.login_name,
password: rsaPassWord
})
if (response.code === 0) {
console.log(response.data, 'response.data')
// token
localStorage.setItem('token', response.data.token)
localStorage.setItem('ReviewerId', response.data.user_id)
localStorage.setItem('Reviewer', response.data.real_name)
await router.push('/ExaminationManagement')
} else {
//
alert('密码错误')
}
} catch (error) {
//
alert('请求失败')
}
}
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
const passLength = value.length
if (passLength < 5 || passLength > 20) {
callback(new Error('密码长度为5-20'))
} else {
callback()
}
}
}
const rules = reactive({
password: [
{ required: true, trigger: 'blur', message: '请输入密码' },
{ validator: validatePass, trigger: 'blur' }
]
})
</script>
<style scoped lang="scss">
.loginPage {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.loginLayout {
width: 100%;
height: 100%;
background: url("../../assets/login/Login.png") no-repeat;
background-size: 100% 100%;
display: flex;
align-items: center;
justify-content: center;
}
.loginTitle {
display: flex;
justify-content: center;
margin-bottom: 36px;
img {
width: 60px;
height: 60px;
margin-right: 24px;
}
p {
height: 46px;
line-height: 46px;
font-family: DouyinSansBold;
font-weight: 700;
font-size: 38px;
color: #0d867f;
margin-top: 11px;
letter-spacing: 1px;
}
}
.loginInput {
width: 506px;
height: 402px;
background: #fdfffd;
box-shadow: 0 0 12px 0 rgba(160, 194, 182, 0.29);
border-radius: 10px 10px 10px 10px;
padding: 0 63px;
overflow: hidden;
p {
width: 100%;
text-align: center;
font-weight: 400;
font-size: 20px;
color: #333333;
line-height: 30px;
margin-top: 50px;
margin-bottom: 52px;
}
.el-button {
width: 380px;
height: 50px;
background: #0d867f;
border: none;
border-radius: 2px 2px 2px 2px;
font-weight: 400;
font-size: 16px;
color: #ffffff;
line-height: 24px;
}
}
.login_from {
.el-input {
height: 50px;
border: 1px solid rgba(13, 134, 127, 1);
}
.el-form-item--default {
margin-bottom: 30px;
}
:deep(.el-input__wrapper) {
border-radius: 0 !important;
box-shadow: none !important;
}
:deep(.el-input__wrapper:hover) {
box-shadow: none !important;
}
}
:deep(.el-input) {
--el-input-focus-border-color: transparent !important;
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '送电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus"
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '巡线'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<div class="powerFailure">
<div class="failureMain">
<div class="operate" v-for="(operateItem, index) in operateList" :key="index">
<span class="rank">{{ operateItem.SerialNumber}}:</span>
<el-input class="name" v-model="operateItem.Content"></el-input>
</div>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {apiGetOperationTicket, SaveOperationTicket} from '@/api/index.js'
import {ElMessage} from "element-plus";
const operateList = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const c = {
Type: '停电',
ExamId
}
const initFour = async () => {
try {
const res = await apiGetOperationTicket(c)
operateList.value = res.data
console.log(res, ' res')
} catch (error) {
console.error(error)
}
}
const handleSave = async () => {
console.log(operateList.value,'operateList--')
const res = await SaveOperationTicket({
...c,
Data: operateList.value.map(item => {
return {
OperationTicketId: item.OperationTicketId,
SerialNumber: item.SerialNumber,
Content: item.Content
}
})
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.powerFailure{
width: 100%;
height: 100%;
}
.failureMain{
padding: 16px 280px 0;
overflow-y: auto;
height: calc(100% - 94px);
}
.operate{
display: flex;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.rank{
width: 30px;
height: 21px;
font-weight: 350;
font-size: 14px;
color: #666666;
line-height: 32px;
margin-right: 10px;
text-align: center;
}
.name{
flex: 1;
background: #F5F7F6;
font-weight: 350;
font-size: 14px;
color: #1D2927;
line-height: 32px;
padding-left: 12px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
<template>
<div class="LinePatrolMain">
<div class="checkMain">
<el-checkbox-group v-model="checkList" >
<el-checkbox
v-for="(item, index) in checkItems"
:key="index"
:label="item.ToolId"
:value="{
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId: item.ThreeToolId
}"
>
{{item.ToolName}}
</el-checkbox>
</el-checkbox-group>
</div>
<div class='settingUp'>
<div class='maintain'>
<el-button @click="handleSave">保存</el-button>
<el-button>重置</el-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, defineProps } from 'vue'
import { apiGetTools, SaveTools } from '@/api/index.js'
import { ElMessage } from "element-plus";
const checkList = ref([])
const checkItems = ref([]) // refAPI
const { ExamId } = defineProps(['ExamId'])
onMounted(() => {
initFour()
})
const b = {
ExamId,
Type: '排故'
}
const initFour = async () => {
const res = await apiGetTools(b)
checkItems.value = res.data.ToolList // APIcheckItems
checkList.value = res.data.SelectToolList
checkList.value = res.data.ToolList.map(item => {
if (res.data.SelectToolList.includes(item.ToolId)) {
return {
ToolId: item.ToolId,
ToolType: item.ToolType,
ToolName: item.ToolName,
ThreeToolId:item.ThreeToolId
}
}
}).filter(item => item)
}
const handleSave = async () => {
console.log(checkList.value, 'handleSave--')
const res = await SaveTools({
...b,
Data: checkList.value
})
if (res.code === 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
} else {
ElMessage.error(res?.data || '操作失敗')
}
}
</script>
<style scoped lang="scss">
.LinePatrolMain{
width: 100%;
height: 100%;
padding-top: 24px;
}
.el-checkbox__label{
font-weight: 400;
font-size: 14px;
color: #1D2129;
line-height: 21px;
}
:deep(.el-checkbox__input.is-checked .el-checkbox__inner){
background-color: #0D867F !important;
border-color:#0D867F;
}
:deep(.el-checkbox__input.is-checked+.el-checkbox__label){
color: #1D2129 !important;
}
.el-checkbox__inner:hover{
border-color:transparent;
}
.checkMain{
height: calc(100% - 94px);
padding: 0 38px;
}
.settingUp{
width: 100%;
height: 94px;
border-top: 3px solid rgba(246, 249, 248, 1);
}
.maintain{
float: right;
margin-right: 20px;
margin-top: 42px;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
}
.el-button:nth-child(1) {
background: #0d867f;
color: #ffffff;
}
.el-button:nth-child(2) {
background: #f2f3f5;
color: #1d2129;
}
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div class="section">
<div class="ScorePoints">
<div class="title">
<img src="../../../assets/menu/exam.png" alt=""/>
<p>考试名称编辑器</p>
</div>
<div class="TestScore">
<div class="fractionalValue" >
<div class="user-name" v-for="scoreItem in scoreList" :key="scoreItem.id">
<span class="designation">{{scoreItem.designation}}:</span>
<span class="score">{{scoreItem.score}}</span>
<el-divider direction="vertical"></el-divider>
</div>
</div>
<div class="totalPoints">
<div class="score">100</div>
<p class="explain">总分</p>
</div>
</div>
</div>
<div class="editorContent">
<div class="actionBar">
<div class="operatingButton">
<el-button :style="{color: tabAct === 1 ? '#0d867f' : ''}" @click="selTabs(1)">场景编辑</el-button>
<el-button :style="{color: tabAct === 2 ? '#0d867f' : ''}" @click="selTabs(2)">巡线工具器</el-button>
<el-button :style="{color: tabAct === 3 ? '#0d867f' : ''}" @click="selTabs(3)">排故工具器</el-button>
<el-button :style="{color: tabAct === 4 ? '#0d867f' : ''}" @click="selTabs(4)">停电操作票</el-button>
<el-button :style="{color: tabAct === 5 ? '#0d867f' : ''}" @click="selTabs(5)">送电操作票</el-button>
</div>
</div>
<div class="operating">
<!-- <router-view></router-view>-->
<SceneEditing v-if="tabAct === 1" :ExamId="ExamId"></SceneEditing>
<LinePatrol v-else-if="tabAct === 2" :ExamId="ExamId"></LinePatrol>
<Troubleshoot v-else-if="tabAct === 3" :ExamId="ExamId"></Troubleshoot>
<Powercut v-else-if="tabAct === 4" :ExamId="ExamId"></Powercut>
<DeliveryCurrent v-else-if="tabAct === 5" :ExamId="ExamId"></DeliveryCurrent>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import SceneEditing from './SceneEditing.vue'
import LinePatrol from './LinePatrol.vue'
import Troubleshoot from './Troubleshoot.vue'
import Powercut from './Powercut.vue'
import DeliveryCurrent from './DeliveryCurrent.vue'
const route = useRoute()
const ExamId = ref(route.query.ExamId)
const scoreList = ([
{ designation: '巡检工器具分值', score: '3' },
{ designation: '排故工器具分值', score: ' 3' },
{ designation: '停电操作票填写分值', score: '5' },
{ designation: '送电操作票填写分值', score: '5' },
{ designation: '停电操作票步骤分值', score: '5' },
{ designation: '送电操作票步骤分值', score: '3' },
{ designation: '时间分分值', score: '5' },
{ designation: '缺陷查找、缺陷处理、缺陷分类分值', score: '69' }
])
const tabAct = ref(1)
const selTabs = (v) => {
console.log(v,'v--')
tabAct.value = Number(v)
}
const router = useRouter()
const sceneButton = () => {
router.push('/SceneEditing') //
}
const linePatrolButton = () => {
router.push('/LinePatrol')//
}
const troubleshootButton = () => {
router.push('/Troubleshoot') //
}
const powercutButton = () => {
router.push('/Powercut') //
}
const deliveryButton = () => {
router.push('/DeliveryCurrent') //
}
</script>
<style scoped lang="scss">
.section{
width: 100%;
height: 100%;
background-color: #fff;
}
.ScorePoints{
height: 174px;
border-radius: 6px 6px 0 0;
margin:0 20px;
border-bottom: 1px solid #F2F3F5;
overflow: hidden;
.title{
margin-top: 20px;
display: flex;
margin-bottom: 22px;
font-family: Microsoft-YaHei;
img{
width: 28px;
height: 28px;
}
p{
font-weight: 400;
font-size: 20px;
color: #1D2129;
line-height: 28px;
}
}
.TestScore{
height: 86px;
background: #F2F3F5;
border-radius: 4px 4px 4px 4px;
justify-content: space-between;
display: flex;
}
.fractionalValue{
display: flex;
height: 100%;
flex-wrap: wrap;
padding-top: 16px;
.user-name{
margin-left: 18px;
white-space: nowrap;
.designation{
font-weight: 400;
font-size: 14px;
color: #1D2129;
}
.score{
margin-right: 18px;
margin-left:8px;
font-weight: 700;
font-size: 14px;
color: #0D867F;
line-height: 21px;
}
.el-divider--vertical{
margin: 0;
height: 19px;
border-left:1px solid rgba(29, 33, 41, 0.50);
}
}
.user-name:nth-child(10){
.el-divider--vertical{
display: none;
}
}
}
.totalPoints{
margin-right: 16px;
margin-left: 27px;
.score{
width: 58px;
height: 54px;
background-image: url("../../../assets/menu/grade.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin-top: 10px;
position: relative;
padding:10px 15px 0;
font-family: D-DIN-Bold;
font-weight: 700;
font-size: 24px;
color: #FF6565;
line-height: 26px;
}
.explain{
width: 100%;
text-align: center;
font-weight: 400;
font-size: 12px;
color: #1D2129;
}
}
}
.editorContent{
width: 100%;
height: calc(100% - 174px);
// height: calc(100% - 12px);//
//background-color: #55a532;
}
.actionBar{
width: 100%;
height: 68px;
background: #FFFFFF;
box-shadow: 0 4px 3px 0 rgba(0,0,0,0.03);
display: flex;
align-items: center;
margin-bottom: 5px;
.operatingButton{
margin-left: 20px;
.el-button{
margin-right: 14px;
width: 88px;
height: 28px;
border: none;
font-weight: 500;
font-size: 14px;
color: #455552;
line-height: 21px;
}
.el-button:hover{
color: #455552;
}
.el-button:focus{
background-color: #E7F9F8;
font-weight: 500;
font-size: 14px;
color: #0D867F;
}
}
}
.operating{
width: 100%;
height: calc(100% - 68px);
}
</style>

923
src/views/map/index.vue Normal file
View File

@ -0,0 +1,923 @@
<template>
<div class="PageContent">
<div class="WebToolbar">
<div class="FormComponent">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="企业名称">
<el-input
v-model="formInline.EnterpriseName"
placeholder="请输入企业编码"
clearable
/>
</el-form-item>
<el-form-item label="企业编码">
<el-input
v-model="formInline.EnterpriseCode"
placeholder="请输入企业编码"
clearable
/>
</el-form-item>
<el-form-item label="模型名称">
<el-input
v-model="formInline.ModelName"
placeholder="请输入模型名称"
clearable
/>
</el-form-item>
</el-form>
</div>
<div class="ButtonAssembly">
<el-button style="color: #fff" @click="queryData()">
<img src="../../assets/menu/search.png" alt="" />
<span>查询</span>
</el-button>
<el-button style="color: #1d2129" @click="resetFormInline">
<img src="../../assets/menu/reset.png" alt="" />
<span>重置</span>
</el-button>
</div>
</div>
<div class="Tabulation">
<div class="actionBar">
<h1>考试列表</h1>
<div class="Worktop">
<el-button @click="goToAboutPage">编辑器</el-button>
<el-button @click="handleReleaseExam">发布</el-button>
<el-button @click="handleRevokeReleaseExam">撤销发布</el-button>
<el-button @click="handleFinishedExam">考试结束</el-button>
<el-button @click="handleExamination">考试名单</el-button>
<el-button class="BlueBack" @click="handleCreate">
<img src="../../assets/menu/Increased.png" alt="" />
<span>新增</span>
</el-button>
<el-button class="BlueBack" @click="dialogToLead = true">
<img src="../../assets/menu/toLead.png" alt="" />
<span>导入</span>
</el-button>
<el-button class="Delete">
<img src="../../assets/menu/delete.png" alt="" />
<span>删除</span>
</el-button>
</div>
</div>
<div class="ExaminationForm">
<el-table
ref="multipleTableRef"
:data="tableData"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" />
<el-table-column label="序号" type="index" :index="indexMethod" width="60px"/>
<el-table-column property="EnterpriseName" label="企业名称" />
<el-table-column property="EnterpriseCode" label="企业编码" />
<el-table-column property="DistrictCode" label="关区代码" />
<el-table-column property="ModelName" label="模型名称" />
<el-table-column property="VersionNumber" label="版本号" />
<el-table-column property="MapLongitude" label="地图经度" />
<el-table-column property="MapLatitude" label="地图纬度" />
<el-table-column property="TrainingSize" label="模型包大小" />
<el-table-column property="ModelResources" label="模型包资源地址" />
<el-table-column property="UpdateTime" label="最新更新时间" />
<el-table-column property="" label="操作">
<template #default="{row}">
<span class="user-name" @click="handleEdit(row)" >编辑</span>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page="InlineForm.PageIndex"
:page-size="InlineForm.PageSize"
:small="small"
:disabled="disabled"
:background="background"
layout="total, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<!--新增弹框-->
<el-dialog
v-model="dialogFormVisible"
title="编辑模型"
width="1050"
center
@close="closeDialog"
>
<el-form ref="formRef" :model="form" :rules="state.rules" :inline="true" :label-width="formLabelWidth">
<el-form-item label="考试名称:" prop="ExamName">
<el-input v-model="form.ExamName" />
</el-form-item>
<el-form-item
label="场景:"
class="demo-form-scene"
>
<el-select v-model="form.SceneId" placeholder="请选择场景">
<el-option
v-for="(item,i) in state.scenemList"
:key="i"
:value="item.SceneId"
:label="item.SceneName"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="开始考试时间:"
class="el-form-end"
>
<el-date-picker
v-model="form.StartExamTime"
type="datetime"
placeholder="请选择时间">
</el-date-picker>
</el-form-item>
<el-form-item
label="结束考试时间:"
class="el-form-end"
>
<el-date-picker v-model="form.EndExamTime" type="datetime" placeholder="请选择时间" />
</el-form-item>
<el-form-item label="台区:" >
<el-select v-model="form.PlatformAreaId" placeholder="请选择台区">
<el-option
v-for="(item,i) in state.platformAreaList"
:key="i"
:value="item.PlatformAreaId"
:label="item.PlatformAreaName"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="线路:" >
<el-select v-model="form.LineId" placeholder="请选择线路">
<el-option
v-for="(item,i) in state.lineList"
:key="i"
:value="item.LineId"
:label="item.LineName"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="巡线日期:"
class="el-form-end"
>
<el-date-picker v-model="form.LinePatrolDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择时间" />
</el-form-item>
<el-form-item label="处理日期:" >
<el-date-picker v-model="form.HandleDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择时间" />
</el-form-item>
<el-form-item
label="工单内容:"
class="backInformation"
>
<el-input
v-model="form.WorkOrderContent"
style="width: 240px"
:rows="12"
type="textarea"
placeholder=""
/>
</el-form-item>
<el-form-item label="背景资料:" label-width="192px" >
<el-input
v-model="form.BackgroundInformation"
style="width: 240px"
:rows="12"
type="textarea"
placeholder=""
/>
</el-form-item>
<el-form-item label="考试时长:" >
<el-input v-model="form.ExaminationDuration" autocomplete="off" />
</el-form-item>
<el-form-item label="411电缆型号及长度">
<el-input v-model="form.IncomingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
<el-form-item label="411电缆型号及长度">
<el-input v-model="form.OutgoingLineModelLength" autocomplete="off" />
<span class="example">示例YJV22-4*95/12</span>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">
取消
</el-button>
<el-button @click="submit" type="primary">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import {
GetModelList,
AddExam,
EditExam,
GetModelDetails,
EditExamList,
DeleteExam,
GetScene,
GetPlatformArea,
GetLine,
ApiReleaseExam,
ApiRevokeReleaseExam,
ApiFinishedExam,
ApiCopyExam,
ApiDownloadExamm,
ApiGetExamRosterList,
DeleteExamRoster,
ApiGetAddExamRosterListt,
ApiAddExamRoster,
apiUpload
} from '@/api/index.js'
const formInline = reactive({
EnterpriseName: '',
EnterpriseCode: '',
ModelName: '',
PageIndex: 1,
PageSize: 10
})
const resetFormInline = () => {
formInline.EnterpriseName = ''
formInline.EnterpriseCode = ''
formInline.ModelName = ''
getTable()
// for (const key in formInline) {
// if ( key !== 'PageIndex' || key !== 'PageIndex' ) formInline[key] = ''
// }
}
//
const indexMethod = (index) => {
return index + 1
}
//
const formRef = ref(null)
const dialogFormVisible = ref(false)
function handleCreate () {
dialogFormVisible.value = true
}
const formLabelWidth = '150px'
const value1 = ref('')
const value2 = ref('')
const state = reactive({
rules: {},
scenemList: [],
platformAreaList: [],
lineList: []
})
const form = reactive({
EnterpriseName: '',
DistrictCode: '',
ModelName: '',
VersionNumber: '',
MapLongitude: '',
MapLatitude: '',
Trainingsize: '',
ModelResources: '',
UpdateTime: ''
// WorkOrderContent: '',
// BackgroundInformation: '',
// StartExamTime: '',
// EndExamTime: '',
// Type: ''
})
//
onMounted(() => {
getTable()
// addTable()
GetScene().then(res => {
state.scenemList = res.data
console.log(res.data, 'res.data--')
})
GetPlatformArea({
SceneId: 'eab5920509b011ed844e7cd30a92bb1c'
}).then(res => state.platformAreaList = res.data)
GetLine({
PlatformAreaId: '28f0723409b111ed844e7cd30a92bb1c'
}).then(res => state.lineList = res.data)
})
//
const total = ref(0)
const tableData = ref([])
const queryData = () => {
formInline.PageIndex = 1
getTable()
}
const getTable = async () => {
try {
const { code, data } = await GetModelList({
...formInline
})
if (code === 0) {
console.log('data', data)
total.value = data.total
tableData.value = data.list
} else {
total.value = 0
tableData.value = []
}
} catch (error) {}
}
const multipleTableRef = ref()
const multipleSelection = ref([])
const handleSelectionChange = (val) => {
if (val.length > 1) {
multipleTableRef.value.clearSelection()
multipleTableRef.value.toggleRowSelection(val.pop())
} else {
// this.currentRow = val.pop();
multipleSelection.value = val
}
}
const textarea = ref('')
const small = ref(false)
const background = ref(false)
const disabled = ref(false)
//
const InlineForm = reactive({
PageIndex: 1,
PageSize: 10
})
const handleSizeChange = (val) => {
console.log(`${val} items per page`)
formInline.PageSize = val
getTable()
}
const handleCurrentChange = (val) => {
console.log(`current page: ${val}`)
formInline.PageIndex = val
getTable()
}
const ExamId = ref('')
const handleEdit = async (row) => {
const res = await GetModelDetails({ EnterpriseCode: row.EnterpriseCode })
console.log(res.data, 'res--')
for (const key in form) {
form[key] = res.data[key]
}
// ExamId.value = res.data.ExamId
dialogFormVisible.value = true
}
const handleCopy = (row) => {
ApiCopyExam({ ExamId: row.ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
//
const handleDelete = (row) => {
console.log(row.ExamId, 'row--')
ElMessageBox.confirm('确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
DeleteExam({ ExamId: row.ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
//
const submit = () => {
formRef.value.validate(async (valid) => {
console.log(form, 'from--')
if (valid) {
const obj = state.platformAreaList.find(v => v.PlatformAreaId == form.PlatformAreaId)
console.log(obj, 'obj--')
if (ExamId.value) {
EditExam({
...form,
PlatformArea: obj?.PlatformAreaName || '',
ExamId: ExamId.value
}).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
closeDialog()
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
} else {
form.Type = '考试'
AddExam({
...form,
PlatformArea: obj?.PlatformAreaName || ''
}).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功.',
type: 'success'
})
closeDialog()
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
}
})
}
//
const closeDialog = () => {
for (const key in form) {
form[key] = ''
}
ExamId.value = ''
dialogFormVisible.value = false
}
//
const router = useRouter()
const goToAboutPage = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
router.push(`/EditorMacros?ExamId=${multipleSelection.value[0].ExamId}`) //
}
//
const EditFormVisible = ref(false)
const EditExamtableData = ref()
const handleUpdate = async () => {
EditFormVisible.value = true
const data = await EditExamList()
console.log(data.data, 'data')
}
//
const handleReleaseExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要发布吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiReleaseExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code == 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const handleRevokeReleaseExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要撤销发布吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiRevokeReleaseExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const handleFinishedExam = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ElMessageBox.confirm('确定要考试结束吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
ApiFinishedExam({ ExamId: multipleSelection.value[0].ExamId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const dialogTabular = ref(false)
const stateA = reactive({
total: 0,
examRosterList: [],
queryForm: {
Name: '',
Account: '',
PageIndex: 1,
PageSize: 10
}
})
const handleExamination = async () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
getExamination()
getAddExamRosterListt()
dialogTabular.value = true
}
const getExamination = async () => {
console.log(stateA.queryForm, ' stateA.queryForm--')
const res = await ApiGetExamRosterList({
ExamId: multipleSelection.value[0].ExamId,
// ExamId: '048dd77b0a734856a86153e2feaa1d1d',
...stateA.queryForm
})
dialogTabular.value = true
stateA.examRosterList = res.data?.list || []
stateA.total = res.data?.total
console.log(res, 'res--ApiGetExamRosterList')
}
//
const handleCancel = (row) => {
console.log(row.ExamUsersId, 'row--')
ElMessageBox.confirm('确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
DeleteExamRoster({ ExamUsersId: row.ExamUsersId }).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
getExamination()
getAddExamRosterListt()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
})
}
//
const dialogExamination = ref(false)
const rosterSelection = ref([])
const handleSelChange = (val) => {
console.log(val, 'val--')
rosterSelection.value = val
}
const stateB = reactive({
total: 0,
examRosterList: [],
queryForm: {
Name: '',
Account: '',
PageIndex: 1,
PageSize: 10
}
})
const handleCurrentChangeB = (val) => {
stateB.queryForm.PageIndex = val
getAddExamRosterListt()
}
const getAddExamRosterListt = async () => {
console.log(stateA.queryForm, ' stateA.queryForm--')
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
const res = await ApiGetAddExamRosterListt({
ExamId: multipleSelection.value[0].ExamId,
// ExamId: '048dd77b0a734856a86153e2feaa1d1d',
...stateB.queryForm
})
dialogTabular.value = true
stateB.examRosterList = res.data?.list || []
stateB.total = res.data?.total
console.log(res, 'res--ApiGetExamRosterList')
}
const addExamRoster = () => {
if (multipleSelection.value?.length === 0) return ElMessage.error('请先选择')
ApiAddExamRoster({
ExamId: multipleSelection.value[0].ExamId,
UserIdList: rosterSelection.value.map(item => item.UserId)
}).then(res => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '操作成功',
type: 'success'
})
getExamination()
getAddExamRosterListt()
dialogExamination.value = false
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
//
const dialogToLead = ref(false)
const uploadRef = ref()
const handleExceed = (files) => {
// submitUpload(files[0])
uploadRef.value.clearFiles()
nextTick(() => {
uploadRef.value.handleStart(files[0])
})
}
const handleChange = (uploadFile) => {
console.log(uploadFile, 'uploadFile')
// submitUpload(uploadFile.raw)
}
const submitUpload = () => {
uploadRef.value.submit()
}
const toUpload = (param) => {
if (!uploadRef.value) return ElMessage.error('请先上传文件')
const formData = new FormData()
formData.append('Files', param.file)
apiUpload('', formData).then((res) => {
console.log(res, 'res--')
if (res.code === 0) {
ElMessage({
message: '上传成功',
type: 'success'
})
queryData()
} else {
ElMessage.error(res?.data || '操作失敗')
}
})
}
</script>
<style scoped lang="scss">
.PageContent {
width: 100%;
height: 100%;
}
.WebToolbar {
width: 100%;
height: 72px;
background-color: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
:deep(.el-form-item__content) {
width: 256px !important;
height: 32px !important;
}
:deep(.el-input) {
width: 256px !important;
}
:deep(.el-select) {
width: 256px !important;
}
:deep(.el-form-item__label) {
color: #666 !important;
}
}
.ButtonAssembly {
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.el-button:nth-child(1) {
background-color: #0d867f;
}
.el-button:nth-child(2) {
background-color: #f2f3f5;
}
}
.Tabulation {
width: 100%;
height: calc(100% - 72px);
background-color: #fff;
margin-top: 14px;
padding: 20px;
.actionBar {
display: flex;
justify-content: space-between;
h1 {
font-weight: 500;
font-size: 20px;
color: #1d2129;
line-height: 28px;
font-family: Microsoft YaHei, Microsoft YaHei;
}
}
.Worktop {
.el-button {
border: 1px solid #0d867f;
font-weight: 400;
font-size: 14px;
color: #0d867f;
}
.el-button:hover {
background-color: transparent;
}
.BlueBack {
background: #0d867f;
border-radius: 2px 2px 2px 2px;
font-weight: 400;
font-size: 14px;
color: #ffffff;
line-height: 22px;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.BlueBack:hover {
background-color: #0d867f;
}
.Delete {
background: #f2f3f5;
border-radius: 2px 2px 2px 2px;
font-weight: 400;
font-size: 14px;
color: #1d2129;
line-height: 22px;
border: none;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.Delete:hover {
background-color: #f2f3f5;
}
}
.ExaminationForm {
margin-top: 16px;
background-color: #0077aa;
}
.el-table tr {
height: 41px;
}
.el-table td {
height: 41px;
}
:deep(th) {
background-color: #e5e6eb;
}
}
.el-pagination {
float: right;
background-color: #fff !important;
margin-top: 18px;
}
:deep(.el-pager li.is-active) {
background-color: #e7f9f8 !important;
font-weight: 400;
color: #0d867f !important;
}
:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
background-color: #e7f9f8 !important;
}
:deep(.el-select) {
width: 280px !important;
}
:deep(.el-input) {
width: 280px !important;
}
.example {
margin-left: 20px;
color: red;
}
.backInformation {
:deep(.el-input) {
width: 280px !important;
height: 120px !important;
}
}
.dialog-footer {
width: 100%;
text-align: center;
}
:deep(.el-textarea__inner) {
width: 280px !important;
}
.user-name,.register{
cursor: pointer;
}
.functionalUnit{
margin-left: 20px;
display: flex;
.el-button {
width: 84px;
height: 32px;
border: none;
font-weight: 400;
font-size: 14px;
border-radius: 2px 2px 2px 2px;
color: #fff;
img {
width: 16px;
height: 16px;
margin-right: 8px;
}
}
.el-button:nth-child(1) {
background-color: #2192ba;
}
.el-button:nth-child(2) {
background-color: #17c85f;
}
}
.TabularTitle{
font-size: 14px;
color: #747272;
font-weight: bold;
margin-bottom: 10px;
}
.pagination{
width: 100%;
height:30px;
:deep(.el-pagination){
margin-top: 9px!important;
}
}
.addSlip{
.el-button{
border: none;
background-color: #0077aa;
margin-top: 8px;
color: #fff;
}
:deep(.el-pagination){
margin-top: 8px!important;
}
}
.ml-3{
margin-left: 20px;
}
</style>

26
vite.config.js Normal file
View File

@ -0,0 +1,26 @@
import { defineConfig } from 'vite'
import { fileURLToPath, URL } from 'node:url'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
base: './',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 8080,
host: '0.0.0.0',
cors: true,
proxy: {
'/api': {
target: 'http://172.16.1.253:4000',
changeOrigin: true
// rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})

View File

@ -0,0 +1,30 @@
// vite.config.js
import { defineConfig } from 'file:///E:/Desktop/Work/LKJCpowerSupplyOfficeSimulationSystem/node_modules/vite/dist/node/index.js'
import { fileURLToPath, URL } from 'node:url'
import vue from 'file:///E:/Desktop/Work/LKJCpowerSupplyOfficeSimulationSystem/node_modules/@vitejs/plugin-vue/dist/index.mjs'
const __vite_injected_original_import_meta_url = 'file:///E:/Desktop/Work/LKJCpowerSupplyOfficeSimulationSystem/vite.config.js'
const vite_config_default = defineConfig({
plugins: [vue()],
base: './',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', __vite_injected_original_import_meta_url))
}
},
server: {
port: 8080,
host: '0.0.0.0',
cors: true,
proxy: {
'/api': {
target: 'http://172.16.1.253:4000',
changeOrigin: true
// rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
export {
vite_config_default as default
}
// # sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxEZXNrdG9wXFxcXFdvcmtcXFxcTEtKQ3Bvd2VyU3VwcGx5T2ZmaWNlU2ltdWxhdGlvblN5c3RlbVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRTpcXFxcRGVza3RvcFxcXFxXb3JrXFxcXExLSkNwb3dlclN1cHBseU9mZmljZVNpbXVsYXRpb25TeXN0ZW1cXFxcdml0ZS5jb25maWcuanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0U6L0Rlc2t0b3AvV29yay9MS0pDcG93ZXJTdXBwbHlPZmZpY2VTaW11bGF0aW9uU3lzdGVtL3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSAnbm9kZTp1cmwnXHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJ1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbdnVlKCldLFxyXG4gIGJhc2U6ICcuLycsXHJcbiAgcmVzb2x2ZToge1xyXG4gICAgYWxpYXM6IHtcclxuICAgICAgJ0AnOiBmaWxlVVJMVG9QYXRoKG5ldyBVUkwoJy4vc3JjJywgaW1wb3J0Lm1ldGEudXJsKSlcclxuICAgIH1cclxuICB9LFxyXG4gIHNlcnZlcjoge1xyXG4gICAgcG9ydDogODA4MCxcclxuICAgIGhvc3Q6ICcwLjAuMC4wJyxcclxuICAgIGNvcnM6IHRydWUsXHJcbiAgICBwcm94eToge1xyXG4gICAgICAnL2FwaSc6IHtcclxuICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTcyLjE2LjEuMjUzOjUwMDAnLFxyXG4gICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZVxyXG4gICAgICAgIC8vIHJld3JpdGU6IChwYXRoKSA9PiBwYXRoLnJlcGxhY2UoL15cXC9hcGkvLCAnJylcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufSlcclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUF5VixTQUFTLG9CQUFvQjtBQUN0WCxTQUFTLGVBQWUsV0FBVztBQUNuQyxPQUFPLFNBQVM7QUFGeU0sSUFBTSwyQ0FBMkM7QUFLMVEsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDMUIsU0FBUyxDQUFDLElBQUksQ0FBQztBQUFBLEVBQ2YsTUFBTTtBQUFBLEVBQ04sU0FBUztBQUFBLElBQ1AsT0FBTztBQUFBLE1BQ0wsS0FBSyxjQUFjLElBQUksSUFBSSxTQUFTLHdDQUFlLENBQUM7QUFBQSxJQUN0RDtBQUFBLEVBQ0Y7QUFBQSxFQUNBLFFBQVE7QUFBQSxJQUNOLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxJQUNOLE9BQU87QUFBQSxNQUNMLFFBQVE7QUFBQSxRQUNOLFFBQVE7QUFBQSxRQUNSLGNBQWM7QUFBQTtBQUFBLE1BRWhCO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=