北斗启航科技教育平台管理系统

This commit is contained in:
2026-03-27 17:33:34 +08:00
commit 86a383e719
150 changed files with 21746 additions and 0 deletions

30
.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

29
README.md Normal file
View File

@@ -0,0 +1,29 @@
# account-manager
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```

49
index.html Normal file
View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en" class="w-h-full">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>北斗启航科技教育平台管理系统</title>
<style>
/* 当屏幕宽度大于或等于3000px时 */
@media (min-width: 3000px) {
html {
font-size: 28px;
}
}
/* 当屏幕宽度在1920px到2999px之间时 */
@media (min-width: 1920px) and (max-width: 2999px) {
html {
font-size: 20px;
}
}
/* 当屏幕宽度在750px到1919px之间时 */
@media (min-width: 750px) and (max-width: 1919px) {
html {
font-size: 14px;
}
}
/* 当屏幕宽度在600px到749px之间时 */
@media (min-width: 600px) and (max-width: 749px) {
html {
font-size: 14px;
}
}
/* 当屏幕宽度小于600px时 */
@media (max-width: 599px) {
html {
font-size: 12px;
}
}
</style>
</head>
<body class="w-h-full">
<div id="app" class="w-h-full text-white"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

8
jsconfig.json Normal file
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

47
package.json Normal file
View File

@@ -0,0 +1,47 @@
{
"name": "account-manager",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port=7012",
"build": "vite build",
"preview": "vite preview --port=7012"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.7",
"core-js": "^3.39.0",
"crypto-js": "^4.2.0",
"echarts": "^5.5.1",
"element-plus": "^2.8.8",
"file-saver": "^2.0.5",
"fingerprintjs2": "^2.1.4",
"jsencrypt": "^3.3.2",
"moment": "^2.30.1",
"node-xlsx": "^0.24.0",
"pinia": "^2.2.6",
"pinia-plugin-persist": "^1.0.0",
"terser": "^5.36.0",
"vue": "^3.5.13",
"vue-echarts": "^7.0.3",
"vue-quill-editor": "^3.0.6",
"vue-router": "^4.5.0",
"vue-vercode": "^1.0.6",
"vue3-slide-verify": "^1.1.5",
"watermark-dom": "^2.3.0",
"xlsx": "^0.18.5",
"zipson": "^0.2.12"
},
"devDependencies": {
"@vitejs/plugin-legacy": "^5.4.3",
"@vitejs/plugin-vue": "^5.2.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.15",
"unplugin-auto-import": "^0.18.5",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.4.11",
"vite-plugin-components": "^0.13.3"
}
}

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

9
src/App.vue Normal file
View File

@@ -0,0 +1,9 @@
<template>
<RouterView />
</template>
<script setup>
import { RouterView } from "vue-router";
</script>
<style scoped></style>

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

@@ -0,0 +1,130 @@
import axios from "axios";
import $url from "./url";
import router from "../router";
import { encrypt } from "../utils/aes";
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if (localStorage.access_token && localStorage.access_token !== "" && localStorage.access_token !== null && localStorage.access_token !== undefined && localStorage.access_token !== NaN) {
if (config.headers) {
config.headers.authorization = localStorage.access_token;
}
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 转到登录页面
const toLogin = () => {
// localStorage.clear();
router.push({ path: '/mlogin' });
};
// 添加响应拦截器
let result = true;
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
if (response.data.code === 200) {
if ("access_token" in response.data) {
localStorage.setItem("access_token", response.data.access_token);
}
if ("refresh_token" in response.data) {
localStorage.setItem("refresh_token", response.data.refresh_token);
}
if ("data" in response.data) {
localStorage.setItem("data", response.data.data);
}
}
// if (response.data.code === 404) {
// localStorage.clear();
// //转到404页面
// router.push({ path: '/404page' });
// }
// if (response.data.code === 402) {
// toLogin();
// }
if (response.data.code === 401 && result) {
result = false;
setTimeout(() => {
result = true;
}, 1000);
let getCode = window.location.href.indexOf('?');
if (getCode != '-1') {
let code = window.location.href.substring(getCode + 1);
const data = {
code: code,
type: encrypt('code')
};
axios.post($url.getToken, data).then((res) => {
if (res.data.code === 200) {
localStorage.setItem("data", res.data.data);
localStorage.setItem("access_token", res.data.access_token);
localStorage.setItem("refresh_token", res.data.refresh_token);
window.location.href = res.data.redirect;
} else {
toLogin();
}
});
} else if(localStorage.loginCode && localStorage.loginCode !== "" && localStorage.loginCode !== null && localStorage.loginCode !== undefined && localStorage.loginCode !== NaN) {
const data = {
code: localStorage.loginCode,
type: encrypt('code')
};
axios.post($url.getToken, data).then((res) => {
if (res.data.code === 200) {
localStorage.setItem("data", res.data.data);
localStorage.setItem("access_token", res.data.access_token);
localStorage.setItem("refresh_token", res.data.refresh_token);
localStorage.removeItem('loginCode');
window.location.href = res.data.redirect;
} else {
toLogin();
}
});
} else if (localStorage.refresh_token && localStorage.refresh_token !== "" && localStorage.refresh_token !== null && localStorage.refresh_token !== undefined && localStorage.refresh_token !== NaN) {
const data = {
code: localStorage.refresh_token,
type: localStorage.data
};
axios.post($url.getToken, data).then((res) => {
console.log(res);
if (res.data.code === 200) {
localStorage.setItem("data", res.data.data);
localStorage.setItem("access_token", res.data.access_token);
localStorage.setItem("refresh_token", res.data.refresh_token);
window.location.reload();
} else {
toLogin();
}
});
} else {
toLogin();
}
}
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
export default {
get(url, query = {}) {
return axios.get(url, {
params: query
});
},
post(url, body) {
return axios.post(url, body);
},
put(url, body) {
return axios.put(url, body);
},
del(url) {
return axios.delete(url);
},
}

163
src/api/url.js Normal file
View File

@@ -0,0 +1,163 @@
export default {
// 退出登录
unLogin: "/authentication/unLogin",
// 获取登录状态
loginStatus: "/authentication/loginStatus",
// 登录请求接口
mlogin: "/authentication/mlogin",
// 用于获取token
getToken: "/authentication/getToken",
// 用于验证token
verify: "/authentication/verify",
// 获取用户基本信息
getUser: "/authentication/getUser",
// 修改用户基本信息
editUser: "/authentication/editUser",
// 修改密码
changePassword: "/authentication/changePassword",
// 获取资源
main: "/accountManager/main",
home: "/accountManager/main/home",
bside: "/accountManager/main/bside",
cside: "/accountManager/main/cside",
contest: "/accountManager/main/contest",
manager: "/accountManager/main/manager",
system: "/accountManager/main/system",
// 注册北斗卡
addBdCard: "/accountManager/addBdCard",
// 查看北斗卡
showBdCard: "/accountManager/showBdCard",
// 编辑北斗卡
editBdCard: "/accountManager/editBdCard",
// 删除北斗卡
deleteBdCard: "/accountManager/deleteBdCard",
// 查看绑定记录
showBindRecord: "/accountManager/showBindRecord",
// 删除绑定记录
deleteBindRecord: "/accountManager/deleteBindRecord",
// 注册公司业务
addBusiness: "/accountManager/addBusiness",
// 查看公司业务
showBusiness: "/accountManager/showBusiness",
// 远程搜索公司业务
SearchBusiness: "/accountManager/SearchBusiness",
// 编辑公司业务
editBusiness: "/accountManager/editBusiness",
// 删除公司业务
deleteBusiness: "/accountManager/deleteBusiness",
// 注册B端用户
addBSide: "/accountManager/addBSide",
// 查看B端用户
showBSide: "/accountManager/showBSide",
// 编辑B端用户
editBSide: "/accountManager/editBSide",
// 删除B端用户
deleteBSide: "/accountManager/deleteBSide",
// 查看C端用户
showCSide: "/accountManager/showCSide",
// 编辑C端用户
editCSide: "/accountManager/editCSide",
// 删除C端用户
deleteCSide: "/accountManager/deleteCSide",
// 注册管理系统用户
addInsiders: "/accountManager/addInsiders",
// 查看管理系统用户
showInsiders: "/accountManager/showInsiders",
// 编辑管理系统用户
editInsiders: "/accountManager/editInsiders",
// 删除管理系统用户
deleteInsiders: "/accountManager/deleteInsiders",
// 注册B端用户单位
addOrganization: "/accountManager/addOrganization",
// 查看B端用户单位
showOrganization: "/accountManager/showOrganization",
// 远程搜索B端用户单位
SearchOrganization: "/accountManager/SearchOrganization",
// 编辑B端用户单位
editOrganization: "/accountManager/editOrganization",
// 删除B端用户单位
deleteOrganization: "/accountManager/deleteOrganization",
// 查看监控记录
showMonitoring: "/accountManager/showMonitoring",
// 删除监控记录
deleteMonitoring: "/accountManager/deleteMonitoring",
// 管理系统检索竞赛 uid
searchContestUid: "/accountManager/searchContestUid",
// 管理系统创建竞赛信息
addContest: "/accountManager/addContest",
// 管理系统查看竞赛信息
showContest: "/accountManager/showContest",
// 管理系统编辑竞赛信息
editContest: "/accountManager/editContest",
// 管理系统删除竞赛信息
delContest: "/accountManager/delContest",
// 管理系统导入选择题
importChoiceTopic: "/accountManager/importChoiceTopic",
// 管理系统创建选择题
addChoiceTopic: "/accountManager/addChoiceTopic",
// 管理系统查看选择题
showChoiceTopic: "/accountManager/showChoiceTopic",
// 管理系统编辑选择题
editChoiceTopic: "/accountManager/editChoiceTopic",
// 管理系统删除选择题
delChoiceTopic: "/accountManager/delChoiceTopic",
// 管理系统导入竞赛账号信息
importAccount: "/accountManager/importAccount",
// 管理系统创建竞赛账号信息
addAccount: "/accountManager/addAccount",
// 管理系统查看竞赛账号信息
showAccount: "/accountManager/showAccount",
// 管理系统编辑竞赛账号信息
editAccount: "/accountManager/editAccount",
// 管理系统删除竞赛账号信息
delAccount: "/accountManager/delAccount",
// 管理系统重置竞赛账号密码
resetAccount: "/accountManager/resetAccount",
// 管理系统查看账号成绩排名
showExamination: "/accountManager/showExamination",
// 管理系统编辑账号成绩排名
editExamination: "/accountManager/editExamination",
// 管理系统删除账号成绩排名
delExamination: "/accountManager/delExamination",
// 管理系统导出账号成绩排名
downloadExamination: "/accountManager/downloadExamination",
// 注册SN号
addSN: "/accountManager/addSN",
// 查看SN号
showSN: "/accountManager/showSN",
// 编辑SN号
editSN: "/accountManager/editSN",
// 删除SN号
deleteSN: "/accountManager/deleteSN",
// 查看SN号绑定记录
showBindSNRecord: "/accountManager/showBindSNRecord",
// 删除SN号绑定记录
deleteBindSNRecord: "/accountManager/deleteBindSNRecord",
// 搜索可分配的SN号
searchAllocationSN: "/accountManager/searchAllocationSN",
// 搜索可分配的单位用户
searchAllocationUser: "/accountManager/searchAllocationUser",
// B端分配SN号
allocationSN: "/accountManager/allocationSN",
// 查看B端SN号分配记录
showAllocationSNRecord: "/accountManager/showAllocationSNRecord",
// 删除B端SN号分配记录
deleteAllocationSNRecord: "/accountManager/deleteAllocationSNRecord",
}

BIN
src/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

1
src/assets/logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 276 B

9
src/assets/main.css Normal file
View File

@@ -0,0 +1,9 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.w-h-full {
@apply w-full h-full m-0 p-0 overflow-hidden;
}
}

BIN
src/assets/qrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -0,0 +1,155 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="SNActive" />
<SingleAdd ref="singleAddRef" v-if="dialogSingleVisible" @addSN="addSN" />
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
@addSN="addSN"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addSN="addSN" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import SNActiveStore from "../../../stores/SN";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const SNActive = SNActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
SNActive.dialogSingleVisible = dialogSingleVisible.value;
SNActive.dialogMultipleVisible = dialogMultipleVisible.value;
SNActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
SNActive.dialogSingleVisible = dialogSingleVisible.value;
SNActive.dialogMultipleVisible = dialogMultipleVisible.value;
SNActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
SNActive.dialogSingleVisible = dialogSingleVisible.value;
SNActive.dialogMultipleVisible = dialogMultipleVisible.value;
SNActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addSN = (requestMsg) => {
requestMsg.forEach((element) => {
element.sn_number = encrypt(String(element.sn_number));
});
const data = { requestMsg };
$http.post($url.addSN, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增SN号成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增SN号失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,82 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
sn_number: {
value: "",
label: "SN号",
}
};
const relatedOptions = [
{
value: "0",
label: "SN号",
disabled: false,
}
];
const emit = defineEmits(["addSN"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
sn_number: item[relatedRules.sn_number.value]
});
}
});
});
});
emit("addSN", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,113 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "SN号1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean,
});
const emit = defineEmits(["addSN"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addSN", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,96 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="SN号" prop="sn_number">
<el-input
clearable
placeholder="请输入卡号"
minlength="8"
maxlength="8"
v-model="ruleForm.sn_number"
@input="filter(ruleForm.sn_number, 'sn_number')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const ruleFormRef = ref(null);
const ruleForm = reactive({
sn_number: ""
});
const formClone = ref({});
const checkLength = (length) => {
return (rule, value) => {
if (!value) return new Error(`请输入${length}位数字`);
else if (value.length !== length) return new Error(`请输入${length}位数字`);
else return true;
};
};
const rules = reactive({
sn_number: [
{ required: true, message: "请输入卡号", trigger: "blur" },
{ validator: checkLength(8), trigger: "blur" },
]
});
const emit = defineEmits(["addSN"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addSN", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,156 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="bdCardMsgActive" />
<SingleAdd ref="singleAddRef" v-if="dialogSingleVisible" @addBdCard="addBdCard" />
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
@addBdCard="addBdCard"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addBdCard="addBdCard" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import bdCardActiveStore from "../../../stores/bdCard";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const bdCardMsgActive = bdCardActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
bdCardMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bdCardMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bdCardMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
bdCardMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bdCardMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bdCardMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
bdCardMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bdCardMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bdCardMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addBdCard = (requestMsg) => {
requestMsg.forEach((element) => {
element.card_id = encrypt(String(element.card_id));
element.card_imsi = encrypt(String(element.card_imsi));
});
const data = { requestMsg };
$http.post($url.addBdCard, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增北斗卡成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增北斗卡失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,92 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
card_id: {
value: "",
label: "卡号",
},
card_imsi: {
value: "",
label: "IMSI号",
},
};
const relatedOptions = [
{
value: "0",
label: "卡号",
disabled: false,
},
{
value: "1",
label: "IMSI号",
disabled: false,
},
];
const emit = defineEmits(["addBdCard"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
card_id: item[relatedRules.card_id.value],
card_imsi: item[relatedRules.card_imsi.value],
});
}
});
});
});
emit("addBdCard", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,113 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean,
});
const emit = defineEmits(["addBdCard"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addBdCard", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,111 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="卡号" prop="card_id">
<el-input
clearable
placeholder="请输入卡号"
minlength="8"
maxlength="8"
v-model="ruleForm.card_id"
@input="filter(ruleForm.card_id, 'card_id')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="IMSI号" prop="card_imsi">
<el-input
clearable
placeholder="请输入IMSI号"
minlength="18"
maxlength="18"
v-model="ruleForm.card_imsi"
@input="filter(ruleForm.card_imsi, 'card_imsi')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const ruleFormRef = ref(null);
const ruleForm = reactive({
card_id: "",
card_imsi: "",
});
const formClone = ref({});
const checkLength = (length) => {
return (rule, value) => {
if (!value) return new Error(`请输入${length}位数字`);
else if (value.length !== length) return new Error(`请输入${length}位数字`);
else return true;
};
};
const rules = reactive({
card_id: [
{ required: true, message: "请输入卡号", trigger: "blur" },
{ validator: checkLength(8), trigger: "blur" },
],
card_imsi: [
{ required: true, message: "请输入IMSI号", trigger: "blur" },
{ validator: checkLength(18), trigger: "blur" },
],
});
const emit = defineEmits(["addBdCard"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addBdCard", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,177 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="bsideMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
:addData="addData"
:createdAt="createdAt"
@addBside="addBside"
@remoteSearch="remoteSearch"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:addData="addData"
:checkNeed="true"
:createdAt="createdAt"
@addBside="addBside"
@remoteSearch="remoteSearch"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addBside="addBside" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import bsideActiveStore from "../../../stores/bside";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const bsideMsgActive = bsideActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
addData: Object,
createdAt: String,
});
const emit = defineEmits(["reloadData", "remoteSearch"]);
const remoteSearch = (data, searchKey, timeBefor, operateType) => {
emit("remoteSearch", data, searchKey, timeBefor, "add", operateType);
};
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
bsideMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bsideMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bsideMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
bsideMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bsideMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bsideMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
bsideMsgActive.dialogSingleVisible = dialogSingleVisible.value;
bsideMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
bsideMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addBside = (requestMsg) => {
requestMsg.forEach((element) => {
element.role = encrypt(String(element.role));
element.account_name = encrypt(String(element.account_name));
element.organization =
element.organization == "" ? "" : encrypt(String(element.organization));
element.user_name = element.user_name == "" ? "" : encrypt(String(element.user_name));
element.phone = element.phone == "" ? "" : encrypt(String(element.phone));
element.msg = element.msg == "" ? "" : encrypt(String(element.msg));
});
const data = { requestMsg };
$http.post($url.addBSide, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增B端用户成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增B端用户失败!");
}
});
};
defineExpose({ dialogVisible, singleAddRef, multipleAddRef });
</script>
<style scoped></style>

View File

@@ -0,0 +1,132 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
role: {
value: "",
label: "账号角色",
},
account_name: {
value: "",
label: "账号名称",
},
organization: {
value: "",
label: "单位uid",
},
user_name: {
value: "",
label: "用户姓名",
},
phone: {
value: "",
label: "用户手机号码",
},
msg: {
value: "",
label: "用户基本信息",
},
};
const relatedOptions = [
{
value: "0",
label: "账号角色",
disabled: false,
},
{
value: "1",
label: "账号名称",
disabled: false,
},
{
value: "2",
label: "单位uid",
disabled: false,
},
{
value: "3",
label: "用户姓名",
disabled: false,
},
{
value: "4",
label: "用户手机号码",
disabled: false,
},
{
value: "5",
label: "用户基本信息",
disabled: false,
},
];
const emit = defineEmits(["addBside"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
role: item[relatedRules.role.value],
account_name: item[relatedRules.account_name.value],
organization: item[relatedRules.organization.value],
user_name: item[relatedRules.user_name.value],
phone: item[relatedRules.phone.value],
msg: item[relatedRules.msg.value],
});
}
});
});
});
emit("addBside", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,121 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox v-model="checked" label="为所有表单进行相同操作" size="large" />
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd
ref="singleAddRef"
:addData="addData"
:createdAt="createdAt"
@remoteSearch="remoteSearch"
/>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
addData: Object,
checkNeed: Boolean,
createdAt: String,
});
const emit = defineEmits(["addBside", "remoteSearch"]);
const remoteSearch = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "multiple");
};
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {
item.ruleForm.role = singleAddRef.value[0].ruleForm.role;
});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addBside", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ singleAddRef, resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,165 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="账号角色" prop="role">
<el-select
clearable
size="small"
placeholder="请选择账号角色"
autocomplete="off"
v-model="ruleForm.role"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号名称" prop="account_name">
<el-input
clearable
placeholder="请输入账号名称"
minlength="8"
maxlength="12"
v-model="ruleForm.account_name"
@input="filter(ruleForm.account_name, 'account_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="用户单位" prop="organization">
<RemoteSearch
ref="remoteSearchRef"
@searchResult="searchResult"
:disabled="false"
searchKey="organization_name"
:timeBefor="createdAt"
@handleSelect="handleSelect"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="用户姓名" prop="user_name">
<el-input
clearable
placeholder="请输入用户姓名"
maxlength="10"
v-model="ruleForm.user_name"
@input="filter(ruleForm.user_name, 'user_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="用户手机号码" prop="phone">
<el-input
clearable
placeholder="请输入用户手机号码"
maxlength="11"
v-model="ruleForm.phone"
@input="filter(ruleForm.phone, 'phone')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="用户基本信息" prop="msg">
<el-input
clearable
placeholder="请输入用户基本信息"
maxlength="200"
v-model="ruleForm.msg"
@input="filter(ruleForm.msg, 'msg')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
import RemoteSearch from "../../search/remoteSearch.vue";
const ruleFormRef = ref(null);
const remoteSearchRef = ref(null);
const ruleForm = reactive({
role: "",
account_name: "",
organization: "",
user_name: "",
phone: "",
msg: "",
});
const props = defineProps({
addData: Object,
createdAt: String,
});
const formClone = ref({});
const rules = reactive({
role: [{ required: true, message: "请选择账号角色", trigger: "blur" }],
account_name: [{ required: true, message: "请输入账号名称", trigger: "blur" }],
});
const emit = defineEmits(["addBside", "remoteSearch"]);
const searchResult = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "single");
};
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
remoteSearchRef.value.clearValue();
};
const handleSelect = () => {
ruleForm.organization = remoteSearchRef.value.keyValue;
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addBside", [formClone.value]);
ruleFormRef.value.resetFields();
remoteSearchRef.value.clearValue();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ remoteSearchRef, resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,179 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="businessMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
:addData="addData"
:createdAt="createdAt"
@addBusiness="addBusiness"
@remoteSearch="remoteSearch"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:addData="addData"
:checkNeed="true"
:createdAt="createdAt"
@addBusiness="addBusiness"
@remoteSearch="remoteSearch"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addBusiness="addBusiness" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import businessActiveStore from "../../../stores/business";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const businessMsgActive = businessActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
addData: Object,
createdAt: String,
});
const emit = defineEmits(["reloadData", "remoteSearch"]);
const remoteSearch = (data, searchKey, timeBefor, operateType) => {
emit("remoteSearch", data, searchKey, timeBefor, "add", operateType);
};
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
businessMsgActive.dialogSingleVisible = dialogSingleVisible.value;
businessMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
businessMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
businessMsgActive.dialogSingleVisible = dialogSingleVisible.value;
businessMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
businessMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
businessMsgActive.dialogSingleVisible = dialogSingleVisible.value;
businessMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
businessMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addBusiness = (requestMsg) => {
requestMsg.forEach((element) => {
element.login_url = encrypt(String(element.login_url));
element.client_url = encrypt(String(element.client_url));
element.temporary_id = encrypt(
element.temporary_id === true ? "true" : String(element.temporary_id)
);
element.name = encrypt(String(element.name));
element.type = encrypt(String(element.type));
element.level = encrypt(String(element.level));
element.status = encrypt(String(element.status));
});
const data = { requestMsg };
$http.post($url.addBusiness, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增公司业务成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增公司业务失败!");
}
});
};
defineExpose({ dialogVisible, singleAddRef, multipleAddRef });
</script>
<style scoped></style>

View File

@@ -0,0 +1,132 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
login_url: {
value: "",
label: "业务登录网址",
},
client_url: {
value: "",
label: "业务网址",
},
name: {
value: "",
label: "业务名称",
},
type: {
value: "",
label: "业务类型",
},
level: {
value: "",
label: "业务等级",
},
status: {
value: "",
label: "业务状态",
},
};
const relatedOptions = [
{
value: "0",
label: "业务登录网址",
disabled: false,
},
{
value: "1",
label: "业务网址",
disabled: false,
},
{
value: "2",
label: "业务名称",
disabled: false,
},
{
value: "3",
label: "业务类型",
disabled: false,
},
{
value: "4",
label: "业务等级",
disabled: false,
},
{
value: "5",
label: "业务状态",
disabled: false,
},
];
const emit = defineEmits(["addBusiness"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
login_url: item[relatedRules.login_url.value],
client_url: item[relatedRules.client_url.value],
name: item[relatedRules.name.value],
type: item[relatedRules.type.value],
level: item[relatedRules.level.value],
status: item[relatedRules.status.value],
});
}
});
});
});
emit("addBusiness", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,137 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd
ref="singleAddRef"
:addData="addData"
:createdAt="createdAt"
@remoteSearch="remoteSearch"
/>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
addData: Object,
checkNeed: Boolean,
createdAt: String,
});
const emit = defineEmits(["addBusiness", "remoteSearch"]);
const remoteSearch = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "multiple");
};
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {
item.ruleForm.type = singleAddRef.value[0].ruleForm.type;
item.ruleForm.level = singleAddRef.value[0].ruleForm.level;
item.ruleForm.status = singleAddRef.value[0].ruleForm.status;
});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (!element.switchChecked) {
if (
element.ruleForm.temporary_id == true ||
element.ruleForm.temporary_id == undefined
) {
result = false;
element.checkedText = true;
}
}
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addBusiness", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ singleAddRef, resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,254 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="业务登录网址" prop="login_url">
<el-input
clearable
placeholder="请输入业务登录网址"
v-model="ruleForm.login_url"
@input="filter(ruleForm.login_url, 'login_url')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务网址" prop="client_url">
<el-input
clearable
placeholder="请输入业务网址"
v-model="ruleForm.client_url"
@input="filter(ruleForm.client_url, 'client_url')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务临时标识" prop="temporary_id">
<el-switch
v-model="switchChecked"
class="ml-2"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
active-text="随机生成业务临时标识"
inactive-text="使用已有业务临时标识"
/>
<div v-if="checkedText">&nbsp;&nbsp;&nbsp;&nbsp;</div>
<div v-if="checkedText" class="text-red-500 font-black">
请搜索并使用业务临时标识
</div>
<RemoteSearch
ref="remoteSearchRef"
@searchResult="searchResult"
:disabled="switchChecked"
searchKey="name"
:timeBefor="createdAt"
@handleSelect="handleSelect"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务名称" prop="name">
<el-input
clearable
placeholder="请输入业务名称"
v-model="ruleForm.name"
@input="filter(ruleForm.name, 'name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务类型" prop="type">
<el-select
clearable
size="small"
placeholder="请选择业务类型"
autocomplete="off"
v-model="ruleForm.type"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务等级" prop="level">
<el-select
clearable
size="small"
placeholder="请选择业务等级"
autocomplete="off"
v-model="ruleForm.level"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.levelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择业务状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive, watch } from "vue";
import { ElMessage } from "element-plus";
import RemoteSearch from "../../search/remoteSearch.vue";
const ruleFormRef = ref(null);
const switchChecked = ref(true);
const checkedText = ref(false);
const remoteSearchRef = ref(null);
const ruleForm = reactive({
login_url: "",
client_url: "",
temporary_id: true,
name: "",
type: "",
level: "",
status: "",
});
const props = defineProps({
addData: Object,
createdAt: String,
});
const formClone = ref({});
const rules = reactive({
login_url: [{ required: true, message: "请输入业务登录网址", trigger: "blur" }],
client_url: [{ required: true, message: "请输入业务网址", trigger: "blur" }],
name: [{ required: true, message: "请输入业务名称", trigger: "blur" }],
});
const emit = defineEmits(["addBusiness", "remoteSearch"]);
const searchResult = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "single");
};
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleSelect = () => {
ruleForm.temporary_id = remoteSearchRef.value.keyValue;
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
remoteSearchRef.value.statusHolder = false;
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
remoteSearchRef.value.clearValue();
switchChecked.value = true;
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (!switchChecked.value) {
if (ruleForm.temporary_id == true || ruleForm.temporary_id == undefined) {
valid = false;
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
remoteSearchRef.value.statusHolder = true;
}
}
if (valid) {
formClone.value = { ...ruleForm };
emit("addBusiness", [formClone.value]);
ruleFormRef.value.resetFields();
remoteSearchRef.value.clearValue();
switchChecked.value = true;
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({
remoteSearchRef,
resetCheckForm,
confirm,
validate,
ruleForm,
formClone,
switchChecked,
checkedText,
});
watch(switchChecked, (value) => {
if (value) {
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
ruleForm.temporary_id = true;
remoteSearchRef.value.clearValue();
} else {
if (remoteSearchRef.value.statusHolder) {
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
}
}
});
watch(ruleForm, (value) => {
if (!switchChecked.value) {
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
remoteSearchRef.value.statusHolder = true;
}
if (value.temporary_id !== true && value.temporary_id !== undefined) {
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,156 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="accountMsgActive" />
<SingleAdd ref="singleAddRef" v-if="dialogSingleVisible" @addAccount="addAccount" />
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
@addAccount="addAccount"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addAccount="addAccount" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import accountActiveStore from "../../../../stores/contest/account";
import $http from "../../../../api/index";
import $url from "../../../../api/url";
import { encrypt } from "../../../../utils/aes";
const accountMsgActive = accountActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
accountMsgActive.dialogSingleVisible = dialogSingleVisible.value;
accountMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
accountMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
accountMsgActive.dialogSingleVisible = dialogSingleVisible.value;
accountMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
accountMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
accountMsgActive.dialogSingleVisible = dialogSingleVisible.value;
accountMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
accountMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addAccount = (requestMsg) => {
requestMsg.forEach((element) => {
element.contest_uid = encrypt(String(element.contest_uid));
element.account_name = encrypt(String(element.account_name));
});
const data = { requestMsg };
$http.post($url.addAccount, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增竞赛账号成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增竞赛账号失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,82 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
account_name: {
value: "",
label: "账号名称",
},
};
const relatedOptions = [
{
value: "0",
label: "账号名称",
disabled: false,
},
];
const emit = defineEmits(["addAccount"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
account_name: item[relatedRules.account_name.value],
});
}
});
});
});
emit("addAccount", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,113 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean,
});
const emit = defineEmits(["addAccount"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addAccount", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,111 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="竞赛uid" prop="contest_uid">
<el-autocomplete
:fetch-suggestions="searchContestUid"
clearable
placeholder="请输入竞赛uid"
v-model="ruleForm.contest_uid"
@input="filter(ruleForm.contest_uid, 'contest_uid')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号名称" prop="account_name">
<el-input
clearable
placeholder="请输入账号名称"
maxlength="20"
v-model="ruleForm.account_name"
@input="filter(ruleForm.account_name, 'account_name')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
import $http from "../../../../api/index";
import $url from "../../../../api/url";
const ruleFormRef = ref(null);
const ruleForm = reactive({
contest_uid: "",
account_name: "",
});
const formClone = ref({});
const searchContestUid = (value, cb) => {
const data = {
contest_uid: value,
};
$http.post($url.searchContestUid, data).then((res) => {
if (res.data.code === 200) {
cb(res.data.data);
} else {
cb([]);
}
});
};
const rules = reactive({
contest_uid: [{ required: true, message: "请输入竞赛uid", trigger: "blur" }],
account_name: [{ required: true, message: "请输入账号名称", trigger: "blur" }],
});
const emit = defineEmits(["addAccount"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addAccount", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,168 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="choiceTopicMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
@addChoiceTopic="addChoiceTopic"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
@addChoiceTopic="addChoiceTopic"
/>
<ExcleAdd
ref="excleAddRef"
v-if="dialogExcleVisible"
@addChoiceTopic="addChoiceTopic"
/>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import choiceTopicActiveStore from "../../../../stores/contest/choiceTopic";
import $http from "../../../../api/index";
import $url from "../../../../api/url";
import { encrypt } from "../../../../utils/aes";
const choiceTopicMsgActive = choiceTopicActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
choiceTopicMsgActive.dialogSingleVisible = dialogSingleVisible.value;
choiceTopicMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
choiceTopicMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
choiceTopicMsgActive.dialogSingleVisible = dialogSingleVisible.value;
choiceTopicMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
choiceTopicMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
choiceTopicMsgActive.dialogSingleVisible = dialogSingleVisible.value;
choiceTopicMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
choiceTopicMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addChoiceTopic = (requestMsg) => {
requestMsg.forEach((element) => {
element.topic = encrypt(String(element.topic));
element.options_a = encrypt(String(element.options_a));
element.options_b = encrypt(String(element.options_b));
element.options_c = encrypt(String(element.options_c));
element.options_d = encrypt(String(element.options_d));
element.answer = encrypt(String(element.answer));
});
const data = { requestMsg };
$http.post($url.addChoiceTopic, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增单选题成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增单选题失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,132 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
topic: {
value: "",
label: "题目",
},
options_a: {
value: "",
label: "选项A",
},
options_b: {
value: "",
label: "选项B",
},
options_c: {
value: "",
label: "选项C",
},
options_d: {
value: "",
label: "选项D",
},
answer: {
value: "",
label: "答案",
},
};
const relatedOptions = [
{
value: "0",
label: "题目",
disabled: false,
},
{
value: "1",
label: "选项A",
disabled: false,
},
{
value: "1",
label: "选项B",
disabled: false,
},
{
value: "1",
label: "选项C",
disabled: false,
},
{
value: "1",
label: "选项D",
disabled: false,
},
{
value: "1",
label: "答案",
disabled: false,
},
];
const emit = defineEmits(["addChoiceTopic"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
topic: item[relatedRules.topic.value],
options_a: item[relatedRules.options_a.value],
options_b: item[relatedRules.options_b.value],
options_c: item[relatedRules.options_c.value],
options_d: item[relatedRules.options_d.value],
answer: item[relatedRules.answer.value],
});
}
});
});
});
emit("addChoiceTopic", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,113 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean,
});
const emit = defineEmits(["addChoiceTopic"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addChoiceTopic", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,133 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="题目" prop="topic">
<el-input
clearable
placeholder="请输入题目"
v-model="ruleForm.topic"
@input="filter(ruleForm.topic, 'topic')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项A" prop="options_a">
<el-input
clearable
placeholder="请输入选项A"
v-model="ruleForm.options_a"
@input="filter(ruleForm.options_a, 'options_a')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项B" prop="options_b">
<el-input
clearable
placeholder="请输入选项B"
v-model="ruleForm.options_b"
@input="filter(ruleForm.options_b, 'options_b')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项C" prop="options_c">
<el-input
clearable
placeholder="请输入选项C"
v-model="ruleForm.options_c"
@input="filter(ruleForm.options_c, 'options_c')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项D" prop="options_d">
<el-input
clearable
placeholder="请输入选项D"
v-model="ruleForm.options_d"
@input="filter(ruleForm.options_d, 'options_d')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="答案" prop="answer">
<el-input
clearable
placeholder="请输入答案"
v-model="ruleForm.answer"
@input="filter(ruleForm.answer, 'answer')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const ruleFormRef = ref(null);
const ruleForm = reactive({
topic: "",
options_a: "",
options_b: "",
options_c: "",
options_d: "",
answer: "",
});
const formClone = ref({});
const rules = reactive({
topic: [{ required: true, message: "请输入题目", trigger: "blur" }],
options_a: [{ required: true, message: "请输入选项A", trigger: "blur" }],
options_b: [{ required: true, message: "请输入选项B", trigger: "blur" }],
options_c: [{ required: true, message: "请输入选项C", trigger: "blur" }],
options_d: [{ required: true, message: "请输入选项D", trigger: "blur" }],
answer: [{ required: true, message: "请输入答案", trigger: "blur" }],
});
const emit = defineEmits(["addChoiceTopic"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addChoiceTopic", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,164 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="contestMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
:addData="addData"
@addContest="addContest"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
:addData="addData"
@addContest="addContest"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addContest="addContest" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import contestActiveStore from "../../../../stores/contest/contest";
import $http from "../../../../api/index";
import $url from "../../../../api/url";
import { encrypt } from "../../../../utils/aes";
const contestMsgActive = contestActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
addData: Object,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
contestMsgActive.dialogSingleVisible = dialogSingleVisible.value;
contestMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
contestMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
contestMsgActive.dialogSingleVisible = dialogSingleVisible.value;
contestMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
contestMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
contestMsgActive.dialogSingleVisible = dialogSingleVisible.value;
contestMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
contestMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addContest = (requestMsg) => {
requestMsg.forEach((element) => {
element.contest_name = encrypt(String(element.contest_name));
element.contest_organizers = encrypt(String(element.contest_organizers));
element.contest_term = encrypt(String(element.contest_term));
});
const data = { requestMsg };
$http.post($url.addContest, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增竞赛成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增竞赛失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,172 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
contest_name: {
value: "",
label: "竞赛名称",
},
contest_organizers: {
value: "",
label: "竞赛主办方",
},
contest_term: {
value: "",
label: "竞赛届数",
},
type: {
value: "",
label: "竞赛类型",
},
online_start: {
value: "",
label: "线上赛开始时间",
},
online_end: {
value: "",
label: "线上赛结束时间",
},
offline_start: {
value: "",
label: "线下赛开始时间",
},
offline_end: {
value: "",
label: "线下赛结束时间",
},
contest_start: {
value: "",
label: "竞赛开始时间",
},
contest_end: {
value: "",
label: "竞赛结束时间",
},
};
const relatedOptions = [
{
value: "0",
label: "竞赛名称",
disabled: false,
},
{
value: "1",
label: "竞赛主办方",
disabled: false,
},
{
value: "2",
label: "竞赛届数",
disabled: false,
},
{
value: "3",
label: "竞赛类型",
disabled: false,
},
{
value: "4",
label: "线上赛开始时间",
disabled: false,
},
{
value: "5",
label: "线上赛结束时间",
disabled: false,
},
{
value: "6",
label: "线下赛开始时间",
disabled: false,
},
{
value: "7",
label: "线下赛结束时间",
disabled: false,
},
{
value: "8",
label: "竞赛开始时间",
disabled: false,
},
{
value: "9",
label: "竞赛结束时间",
disabled: false,
},
];
const emit = defineEmits(["addContest"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
contest_name: item[relatedRules.contest_name.value],
contest_organizers: item[relatedRules.contest_organizers.value],
contest_term: item[relatedRules.contest_term.value],
type: item[relatedRules.type.value],
online_start: item[relatedRules.online_start.value],
online_end: item[relatedRules.online_end.value],
offline_start: item[relatedRules.offline_start.value],
offline_end: item[relatedRules.offline_end.value],
contest_start: item[relatedRules.contest_start.value],
contest_end: item[relatedRules.contest_end.value],
});
}
});
});
});
emit("addContest", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,114 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" :addData="addData" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean,
addData: Object,
});
const emit = defineEmits(["addContest"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addContest", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,227 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="竞赛名称" prop="contest_name">
<el-input
clearable
placeholder="请输入竞赛名称"
v-model="ruleForm.contest_name"
@input="filter(ruleForm.contest_name, 'contest_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛主办方" prop="contest_organizers">
<el-input
clearable
placeholder="请输入竞赛主办方"
v-model="ruleForm.contest_organizers"
@input="filter(ruleForm.contest_organizers, 'contest_organizers')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛届数" prop="contest_term">
<el-input
clearable
placeholder="请输入竞赛届数"
v-model="ruleForm.contest_term"
@input="filter(ruleForm.contest_term, 'contest_term')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛类型" prop="type">
<el-select
clearable
size="small"
placeholder="请选择竞赛类型"
autocomplete="off"
v-model="ruleForm.type"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item label="线上赛起止时间">
<el-col :span="11">
<el-form-item prop="online_start">
<el-date-picker
v-model="ruleForm.online_start"
type="datetime"
placeholder="请选择线上赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="online_end">
<el-date-picker
v-model="ruleForm.online_end"
type="datetime"
placeholder="请选择线上赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="线下赛起止时间">
<el-col :span="11">
<el-form-item prop="offline_start">
<el-date-picker
v-model="ruleForm.offline_start"
type="datetime"
placeholder="请选择线下赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="offline_end">
<el-date-picker
v-model="ruleForm.offline_end"
type="datetime"
placeholder="请选择线下赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="竞赛起止时间">
<el-col :span="11">
<el-form-item prop="contest_start">
<el-date-picker
v-model="ruleForm.contest_start"
type="datetime"
placeholder="请选择竞赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="contest_end">
<el-date-picker
v-model="ruleForm.contest_end"
type="datetime"
placeholder="请选择竞赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const props = defineProps({
addData: Object,
});
const ruleFormRef = ref(null);
const ruleForm = reactive({
contest_name: "",
contest_organizers: "",
contest_term: "",
type: "",
online_start: "",
online_end: "",
offline_start: "",
offline_end: "",
contest_start: "",
contest_end: "",
});
const formClone = ref({});
const rules = reactive({
contest_name: [{ required: true, message: "请输入竞赛名称", trigger: "blur" }],
contest_organizers: [{ required: true, message: "请输入竞赛主办方", trigger: "blur" }],
contest_term: [{ required: true, message: "请输入竞赛届数", trigger: "blur" }],
type: [{ required: true, message: "请选择竞赛类型", trigger: "change" }],
online_start: [
{ type: "date", required: true, message: "线上赛开始时间", trigger: "change" },
],
online_end: [
{ type: "date", required: true, message: "线上赛结束时间", trigger: "change" },
],
offline_start: [
{ type: "date", required: true, message: "线下赛开始时间", trigger: "change" },
],
offline_end: [
{ type: "date", required: true, message: "线下赛结束时间", trigger: "change" },
],
contest_start: [
{ type: "date", required: true, message: "竞赛开始时间", trigger: "change" },
],
contest_end: [
{ type: "date", required: true, message: "竞赛结束时间", trigger: "change" },
],
});
const emit = defineEmits(["addContest"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addContest", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,112 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
role: {
value: "",
label: "账号角色",
},
name: {
value: "",
label: "员工姓名",
},
department: {
value: "",
label: "所属部门",
},
change: {
value: "",
label: "账号信息变更描述",
},
};
const relatedOptions = [
{
value: "0",
label: "账号角色",
disabled: false,
},
{
value: "1",
label: "员工姓名",
disabled: false,
},
{
value: "2",
label: "所属部门",
disabled: false,
},
{
value: "3",
label: "账号信息变更描述",
disabled: false,
},
];
const emit = defineEmits(["addInsiders"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
role: item[relatedRules.role.value],
name: item[relatedRules.name.value],
department: item[relatedRules.department.value],
change: item[relatedRules.change.value],
});
}
});
});
});
emit("addInsiders", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,166 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="insidersMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
:addData="addData"
@addInsiders="addInsiders"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:addData="addData"
:checkNeed="true"
@addInsiders="addInsiders"
/>
<ExcleAdd ref="excleAddRef" v-if="dialogExcleVisible" @addInsiders="addInsiders" />
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import insidersActiveStore from "../../../stores/insiders";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const insidersMsgActive = insidersActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
addData: Object,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
insidersMsgActive.dialogSingleVisible = dialogSingleVisible.value;
insidersMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
insidersMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
insidersMsgActive.dialogSingleVisible = dialogSingleVisible.value;
insidersMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
insidersMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
insidersMsgActive.dialogSingleVisible = dialogSingleVisible.value;
insidersMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
insidersMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addInsiders = (requestMsg) => {
requestMsg.forEach((element) => {
element.role = encrypt(String(element.role));
element.name = encrypt(String(element.name));
element.department =
element.department == "" ? "" : encrypt(String(element.department));
element.change = encrypt(String(element.change));
});
const data = { requestMsg };
$http.post($url.addInsiders, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增公司员工成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增公司员工失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,116 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed">&nbsp;&nbsp;</div>
<el-checkbox
v-if="checkNeed"
v-model="checked"
label="为所有表单进行相同操作"
size="large"
/>
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd ref="singleAddRef" :addData="addData" />
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
addData: Object,
checkNeed: Boolean,
});
const emit = defineEmits(["addInsiders"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {
item.ruleForm.role = singleAddRef.value[0].ruleForm.role;
});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if (checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addInsiders", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if (value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,127 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="账号角色" prop="role">
<el-select
clearable
size="small"
placeholder="请选择账号角色"
autocomplete="off"
v-model="ruleForm.role"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in addData.roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="员工姓名" prop="name">
<el-input
clearable
placeholder="请输入员工姓名"
v-model="ruleForm.name"
@input="filter(ruleForm.name, 'name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="员工所属部门" prop="department">
<el-input
clearable
placeholder="请输入员工所属部门"
v-model="ruleForm.department"
@input="filter(ruleForm.department, 'department')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号信息变更描述" prop="change">
<el-input
clearable
placeholder="请输入账号信息变更描述"
v-model="ruleForm.change"
@input="filter(ruleForm.change, 'change')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const ruleFormRef = ref(null);
const ruleForm = reactive({
role: "",
name: "",
department: "",
change: "",
});
const props = defineProps({
addData: Object,
});
const formClone = ref({});
const rules = reactive({
role: [{ required: true, message: "请选择账号角色", trigger: "blur" }],
name: [{ required: true, message: "请输入员工姓名", trigger: "blur" }],
change: [{ required: true, message: "请输入账号信息变更描述", trigger: "blur" }],
});
const emit = defineEmits(["addInsiders"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addInsiders", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,142 @@
<template>
<UploadFile
ref="uploadFileRef"
:options="options"
:relatedRules="relatedRules"
:relatedOptions="relatedOptions"
/>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import UploadFile from "../../operate/uploadFile.vue";
const uploadFileRef = ref(null);
const formClone = ref([]);
const options = {
limit: 1,
accept: ".xlsx",
action: "",
multiple: false,
listType: "text",
autoUpload: false,
};
const relatedRules = {
organization_name: {
value: "",
label: "单位名称",
},
address: {
value: "",
label: "通信地址",
},
liaison_name: {
value: "",
label: "单位联系人姓名",
},
phone: {
value: "",
label: "联系人手机号码",
},
email: {
value: "",
label: "单位电子邮箱地址",
},
other_information: {
value: "",
label: "其他信息",
},
post_code: {
value: "",
label: "邮政编码",
},
};
const relatedOptions = [
{
value: "0",
label: "单位名称",
disabled: false,
},
{
value: "1",
label: "通信地址",
disabled: false,
},
{
value: "2",
label: "单位联系人姓名",
disabled: false,
},
{
value: "3",
label: "联系人手机号码",
disabled: false,
},
{
value: "4",
label: "单位电子邮箱地址",
disabled: false,
},
{
value: "5",
label: "其他信息",
disabled: false,
},
{
value: "6",
label: "邮政编码",
disabled: false,
},
];
const emit = defineEmits(["addOrganization"]);
const resetCheckForm = () => {
if (!uploadFileRef) return;
uploadFileRef.value.handleExceed();
};
const confirm = async () => {
if (!uploadFileRef) return;
formClone.value = [];
const length = uploadFileRef.value.loadData.length;
if (length == 0) return ElMessage.error("请先上传文件!");
const flag = await uploadFileRef.value.confirm();
if (!flag) return ElMessage.error("请先选择表格关联项!");
ElMessage({
message: `正在上传数据中,请稍等...`,
type: "success",
});
setTimeout(() => {
uploadFileRef.value.loadData.forEach((ExcleForm) => {
ExcleForm.forEach((worksheet) => {
let context = [...worksheet];
context.shift();
context.forEach((item) => {
if (item.length != 0) {
formClone.value.push({
organization_name: item[relatedRules.organization_name.value],
address: item[relatedRules.address.value],
liaison_name: item[relatedRules.liaison_name.value],
phone: item[relatedRules.phone.value],
email: item[relatedRules.email.value],
other_information: item[relatedRules.other_information.value],
post_code: item[relatedRules.post_code.value],
});
}
});
});
});
emit("addOrganization", formClone.value);
}, 3000);
};
defineExpose({ resetCheckForm, confirm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,111 @@
<template>
<div>
<div
style="font-size: 2rem"
class="flex flex-warp justify-center items-center font-bold"
>
<div style="font-size: 1rem">请输入要导入的数据数量:</div>
<el-input-number v-model="singleFormNum" :min="1" :max="10" @change="createForm" />
<div v-if="checkNeed"> &nbsp;&nbsp; </div>
<el-checkbox v-if="checkNeed" v-model="checked" label="为所有表单进行相同操作" size="large" />
</div>
<el-scrollbar max-height="40rem">
<div class="mt-2 border-2 border-gray-300" v-for="item in input">
<div style="font-size: 1.2rem" class="w-full text-center font-bold">
{{ item.label }}
</div>
<SingleAdd
ref="singleAddRef"
/>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { ElMessage } from "element-plus";
import SingleAdd from "./singleAdd.vue";
const singleFormNum = ref(1);
const checked = ref(true);
const input = ref([{ label: "卡1" }]);
const singleAddRef = ref(null);
const formClone = ref([]);
const props = defineProps({
checkNeed: Boolean
});
const emit = defineEmits(["addOrganization"]);
const initData = () => {
setTimeout(() => {
singleAddRef.value.forEach((item) => {
});
}, 0);
};
const createForm = () => {
let difference = Math.abs(singleFormNum.value - input.value.length);
for (let i = 0; i < difference; i++) {
if (singleFormNum.value > input.value.length) {
input.value.push({ label: `卡${input.value.length + 1}` });
} else if (singleFormNum.value < input.value.length) {
input.value.pop();
}
}
if(checked.value) {
initData();
}
};
const resetCheckForm = () => {
if (!singleAddRef) return;
singleAddRef.value.forEach((element) => {
element.resetCheckForm();
});
singleFormNum.value = 1;
createForm();
};
const confirm = () => {
if (!singleAddRef) return;
let valid = true;
formClone.value = [];
singleAddRef.value.forEach((element) => {
element.validate().then((result) => {
if (result) {
formClone.value.push({ ...element.ruleForm });
} else {
valid = result;
}
});
});
setTimeout(() => {
if (valid) {
emit("addOrganization", formClone.value);
singleAddRef.value.forEach((item) => {
item.resetCheckForm();
});
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
}, 0);
};
defineExpose({ resetCheckForm, confirm, formClone });
watch(checked, (value) => {
if(value) {
initData();
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,171 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="resetCheckForm"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ title }}
</div>
<div
@click="resetCheckForm"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<FormTools @showTools="showTools" :dialogObj="organizationMsgActive" />
<SingleAdd
ref="singleAddRef"
v-if="dialogSingleVisible"
@addOrganization="addOrganization"
/>
<MultipleAdd
ref="multipleAddRef"
v-if="dialogMultipleVisible"
:checkNeed="false"
@addOrganization="addOrganization"
/>
<ExcleAdd
ref="excleAddRef"
v-if="dialogExcleVisible"
@addOrganization="addOrganization"
/>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm"> 取消 </el-button>
<el-button style="font-weight: bold" type="primary" @click="confirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import FormTools from "../../operate/formTools.vue";
import SingleAdd from "./singleAdd.vue";
import MultipleAdd from "./multipleAdd.vue";
import ExcleAdd from "./excleAdd.vue";
import organizationActiveStore from "../../../stores/organization";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
const organizationMsgActive = organizationActiveStore();
const dialogVisible = ref(false);
const singleAddRef = ref(null);
const multipleAddRef = ref(null);
const excleAddRef = ref(null);
const dialogSingleVisible = ref(true);
const dialogMultipleVisible = ref(false);
const dialogExcleVisible = ref(false);
const props = defineProps({
title: String,
});
const emit = defineEmits(["reloadData"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
dialogSingleVisible.value = true;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = false;
organizationMsgActive.dialogSingleVisible = dialogSingleVisible.value;
organizationMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
organizationMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "multiple":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = true;
dialogExcleVisible.value = false;
organizationMsgActive.dialogSingleVisible = dialogSingleVisible.value;
organizationMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
organizationMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
case "excle":
dialogSingleVisible.value = false;
dialogMultipleVisible.value = false;
dialogExcleVisible.value = true;
organizationMsgActive.dialogSingleVisible = dialogSingleVisible.value;
organizationMsgActive.dialogMultipleVisible = dialogMultipleVisible.value;
organizationMsgActive.dialogExcleVisible = dialogExcleVisible.value;
break;
default:
break;
}
};
const resetCheckForm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.resetCheckForm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.resetCheckForm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.resetCheckForm();
}
dialogVisible.value = false;
};
const confirm = () => {
if (dialogSingleVisible.value) {
singleAddRef.value.confirm();
} else if (dialogMultipleVisible.value) {
multipleAddRef.value.confirm();
} else if (dialogExcleVisible.value) {
excleAddRef.value.confirm();
}
};
const addOrganization = (requestMsg) => {
requestMsg.forEach((element) => {
element.organization_name = encrypt(String(element.organization_name));
element.address = element.address == "" ? "" : encrypt(String(element.address));
element.liaison_name =
element.liaison_name == "" ? "" : encrypt(String(element.liaison_name));
element.phone = element.phone == "" ? "" : encrypt(String(element.phone));
element.email = element.email == "" ? "" : encrypt(String(element.email));
element.other_information =
element.other_information == "" ? "" : encrypt(String(element.other_information));
element.post_code = element.post_code == "" ? "" : encrypt(String(element.post_code));
});
const data = { requestMsg };
$http.post($url.addOrganization, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
ElMessage({
message: "新增B端单位成功!",
type: "success",
});
emit("reloadData");
} else {
ElMessage.error("新增B端单位失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,137 @@
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="单位名称" prop="organization_name">
<el-input
clearable
placeholder="请输入单位名称"
v-model="ruleForm.organization_name"
@input="filter(ruleForm.organization_name, 'organization_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="通信地址" prop="address">
<el-input
clearable
placeholder="请输入通信地址"
v-model="ruleForm.address"
@input="filter(ruleForm.address, 'address')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="单位联系人姓名" prop="liaison_name">
<el-input
clearable
placeholder="请输入单位联系人姓名"
v-model="ruleForm.liaison_name"
@input="filter(ruleForm.liaison_name, 'liaison_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="联系人电话号码" prop="phone">
<el-input
clearable
placeholder="请输入联系人电话号码"
v-model="ruleForm.phone"
@input="filter(ruleForm.phone, 'phone')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="单位电子邮箱" prop="email">
<el-input
clearable
placeholder="请输入单位电子邮箱"
v-model="ruleForm.email"
@input="filter(ruleForm.email, 'email')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="其他信息" prop="other_information">
<el-input
clearable
placeholder="请输入其他信息"
v-model="ruleForm.other_information"
@input="filter(ruleForm.other_information, 'other_information')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="邮政编码" prop="post_code">
<el-input
clearable
placeholder="请输入邮政编码"
v-model="ruleForm.post_code"
@input="filter(ruleForm.post_code, 'post_code')"
/>
</el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const ruleFormRef = ref(null);
const ruleForm = reactive({
organization_name: "",
address: "",
liaison_name: "",
phone: "",
email: "",
other_information: "",
post_code: "",
});
const formClone = ref({});
const rules = reactive({
organization_name: [{ required: true, message: "请输入单位名称", trigger: "blur" }],
});
const emit = defineEmits(["addOrganization"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const resetCheckForm = () => {
if (!ruleFormRef) return;
ruleFormRef.value.resetFields();
};
const confirm = async () => {
if (!ruleFormRef) return;
await ruleFormRef.value.validate((valid) => {
if (valid) {
formClone.value = { ...ruleForm };
emit("addOrganization", [formClone.value]);
ruleFormRef.value.resetFields();
ElMessage({
message: `提交成功!`,
type: "success",
});
} else {
ElMessage.error("提交失败!");
}
});
};
const validate = () => {
if (!ruleFormRef) return Promise.resolve(false);
return new Promise((resolve) => {
ruleFormRef.value.validate((valid) => {
resolve(valid);
});
});
};
defineExpose({ resetCheckForm, confirm, validate, ruleForm, formClone });
</script>
<style scoped></style>

View File

@@ -0,0 +1,60 @@
<template>
<el-menu
:default-active="activeIndex"
style="background-color: rgb(250 240 210)"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item
v-for="(options, index) in menu"
:key="options.path"
@click="goToPage(options.path, options.id)"
:index="index"
:style="
activeIndex == options.id
? 'background-color: rgb(20 200 200);color: #fff;border-width: 2px;border-bottom-color: rgb(192 38 211);'
: ''
"
>
<el-icon><icon-menu /></el-icon>
<span>{{ options.label }}</span>
</el-menu-item>
</el-menu>
</template>
<script setup>
import { ref, defineProps, onMounted } from "vue";
import { useRouter } from "vue-router";
import activeIndexActiveStore from "../../stores/activeIndex";
const router = useRouter();
const activeIndexActive = activeIndexActiveStore();
const { menu } = defineProps(["menu"]);
const activeIndex = ref(0);
const handleOpen = (key, keyPath) => {
console.log(key, keyPath);
};
const handleClose = (key, keyPath) => {
console.log(key, keyPath);
};
const goToPage = (page, id) => {
activeIndex.value = id;
activeIndexActive.asideActive = id;
router.push({ name: page });
};
onMounted(() => {
if (activeIndexActive.asideActive >= menu.length)
activeIndexActive.asideActive = menu.length - 1;
goToPage(menu[activeIndexActive.asideActive].path, activeIndexActive.asideActive);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,147 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="绑定状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择绑定状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import PasswordOauth from "../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
status: "",
});
const password = ref("");
const rules = reactive({
status: [{ required: true, message: "请选择绑定状态", trigger: "blur" }],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
const requestOperate = () => {
password.value = editPasswordOauthRef.value.ruleForm.password;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
};
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
} else {
ElMessage.error("提交失败!");
}
});
};
defineExpose({ operateDialogVisible, model, ruleForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,147 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="白名单类型" prop="type">
<el-select
clearable
size="small"
placeholder="请选择白名单类型"
autocomplete="off"
v-model="ruleForm.type"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import PasswordOauth from "../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
type: "",
});
const password = ref("");
const rules = reactive({
type: [{ required: true, message: "请选择白名单类型", trigger: "blur" }],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
const requestOperate = () => {
password.value = editPasswordOauthRef.value.ruleForm.password;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
};
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
} else {
ElMessage.error("提交失败!");
}
});
};
defineExpose({ operateDialogVisible, model, ruleForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,204 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="账号状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择账号状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号角色" prop="role">
<el-select
clearable
size="small"
placeholder="请选择账号角色"
autocomplete="off"
v-model="ruleForm.role"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="用户单位" prop="organization">
<RemoteSearch
ref="remoteSearchRef"
@searchResult="searchResult"
:disabled="false"
searchKey="organization_name"
:timeBefor="createdAt"
@handleSelect="handleSelect"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../operate/passwordOauth.vue";
import RemoteSearch from "../search/remoteSearch.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const remoteSearchRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
status: "",
role: "",
organization: "",
});
const password = ref("");
const rules = reactive({});
const props = defineProps({
operateLabel: String,
editData: Object,
createdAt: String,
});
const emit = defineEmits(["requestOperate", "remoteSearch"]);
const searchResult = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "edit");
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
remoteSearchRef.value.clearValue();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
remoteSearchRef.value.clearValue();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// remoteSearchRef.value.clearValue();
// };
const handleSelect = () => {
ruleForm.organization = remoteSearchRef.value.keyValue;
};
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
let FormNull = false;
for (const element in ruleForm) {
if (ruleForm[element] !== "" && ruleForm[element] !== undefined) {
FormNull = true;
}
}
if (valid && FormNull) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
remoteSearchRef.value.clearValue();
} else {
if (!FormNull) {
ElMessage.error("请先编辑数据!");
} else {
ElMessage.error("提交失败!");
}
}
});
};
defineExpose({ remoteSearchRef, model, operateDialogVisible, ruleForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,407 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务随机盐"
prop="salt"
>
<el-switch
v-model="ruleForm.salt"
class="ml-2"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
active-text="更改当前业务随机盐"
inactive-text="保持当前业务随机盐"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务登录网址"
prop="login_url"
>
<el-input
clearable
placeholder="请输入业务登录网址"
v-model="ruleForm.login_url"
@input="filter(ruleForm.login_url, 'login_url')"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务网址"
prop="client_url"
>
<el-input
clearable
placeholder="请输入业务网址"
v-model="ruleForm.client_url"
@input="filter(ruleForm.client_url, 'client_url')"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务临时标识"
prop="temporary_id"
>
<el-switch
v-model="switched"
class="ml-2"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
active-text="更改当前业务临时标识"
inactive-text="保持当前业务临时标识"
@change="switchChange"
/>
<div> &nbsp;&nbsp;&nbsp;&nbsp; </div>
<el-checkbox
:disabled="!switched"
v-model="checked"
label="随机生成业务临时标识"
size="large"
@change="checkedChange"
/>
<div v-if="checkedText"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div v-if="checkedText" class="text-red-500 font-black">
请搜索并使用业务临时标识
</div>
<RemoteSearch
ref="remoteSearchRef"
@searchResult="searchResult"
:disabled="!switched ? true : checked"
searchKey="name"
:timeBefor="ruleForm.created_at"
@handleSelect="handleSelect"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务ID"
prop="client_id"
>
<el-switch
v-model="ruleForm.client_id"
class="ml-2"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
active-text="更改当前业务ID"
inactive-text="保持当前业务ID"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务密钥"
prop="client_secret"
>
<el-switch
v-model="ruleForm.client_secret"
class="ml-2"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
active-text="更改当前业务密钥"
inactive-text="保持当前业务密钥"
/>
</el-form-item>
<el-form-item
v-if="model == 'single' ? true : false"
class="mx-1 font-bold"
label="业务名称"
prop="name"
>
<el-input
clearable
placeholder="请输入业务名称"
v-model="ruleForm.name"
@input="filter(ruleForm.name, 'name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务类型" prop="type">
<el-select
clearable
size="small"
placeholder="请选择业务类型"
autocomplete="off"
v-model="ruleForm.type"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务等级" prop="level">
<el-select
clearable
size="small"
placeholder="请选择业务等级"
autocomplete="off"
v-model="ruleForm.level"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.levelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="业务状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择业务状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import PasswordOauth from "../operate/passwordOauth.vue";
import RemoteSearch from "../search/remoteSearch.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
const editPasswordOauthRef = ref(null);
const switched = ref(false);
const checked = ref(false);
const checkedText = ref(false);
const remoteSearchRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
salt: false,
login_url: "",
client_url: "",
temporary_id: false,
client_id: false,
client_secret: false,
name: "",
type: "",
level: "",
status: "",
created_at: "",
});
const password = ref("");
const rules = reactive({});
const props = defineProps({
operateLabel: String,
editData: Object,
createdAt: String,
});
const emit = defineEmits(["requestOperate", "remoteSearch"]);
const searchResult = (data, searchKey, timeBefor) => {
emit("remoteSearch", data, searchKey, timeBefor, "edit");
};
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const switchChange = (value) => {
if (!value) {
ruleForm.temporary_id = false;
remoteSearchRef.value.clearValue();
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
} else {
if (remoteSearchRef.value.statusHolder) {
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
}
}
}
const checkedChange = (value) => {
if (value) {
ruleForm.temporary_id = true;
remoteSearchRef.value.clearValue();
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
} else {
if (remoteSearchRef.value.statusHolder) {
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
}
}
}
const handleSelect = () => {
ruleForm.temporary_id = remoteSearchRef.value.keyValue;
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
remoteSearchRef.value.statusHolder = false;
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
remoteSearchRef.value.clearValue();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
remoteSearchRef.value.clearValue();
};
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (switched.value ? !checked.value : false) {
if (ruleForm.temporary_id == undefined || ruleForm.temporary_id == false || ruleForm.temporary_id == true ) {
valid = false;
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
remoteSearchRef.value.statusHolder = true;
}
}
if (valid) {
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
} else {
ElMessage.error("提交失败!");
}
});
};
const originForm = (editData, options) => {
ruleForm.login_url = editData.login_url;
ruleForm.client_url = editData.client_url;
ruleForm.name = editData.name;
ruleForm.type = options.typeOptions[editData.type].value;
ruleForm.level = options.levelOptions[editData.level].value;
ruleForm.status = options.statusOptions[editData.status].value;
ruleForm.created_at = editData.origin_createdAt;
};
const requestOperate = () => {
if (switched.value && checked.value) {
ruleForm.temporary_id = "true";
} else if (switched.value && !checked.value) {
ruleForm.temporary_id = remoteSearchRef.value.keyValue;
}
password.value = editPasswordOauthRef.value.ruleForm.password;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
remoteSearchRef.value.clearValue();
};
defineExpose({ remoteSearchRef, operateDialogVisible, model, ruleForm, originForm, password });
watch(ruleForm, (value) => {
if (remoteSearchRef.value) {
if (switched.value && !checked.value) {
checkedText.value = true;
remoteSearchRef.value.selectStyle = "border-width: 2px; border-color: rgb(239 68 68);";
}
if (value.temporary_id !== true && value.temporary_id !== undefined) {
checkedText.value = false;
remoteSearchRef.value.selectStyle = "";
}
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,202 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="竞赛uid" prop="contest_uid">
<el-autocomplete
:fetch-suggestions="searchContestUid"
clearable
placeholder="请输入竞赛uid"
v-model="ruleForm.contest_uid"
@input="filter(ruleForm.contest_uid, 'contest_uid')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号名称" prop="account_name">
<el-input
clearable
placeholder="请输入账号名称"
maxlength="20"
v-model="ruleForm.account_name"
@input="filter(ruleForm.account_name, 'account_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择账号状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import $http from "../../../api/index";
import $url from "../../../api/url";
// import PasswordOauth from "../../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
contest_uid: "",
account_name: "",
status: "",
});
const password = ref("");
const searchContestUid = (value, cb) => {
const data = {
contest_uid: value,
};
$http.post($url.searchContestUid, data).then((res) => {
if (res.data.code === 200) {
cb(res.data.data);
} else {
cb([]);
}
});
};
const rules = reactive({
contest_uid: [{ required: true, message: "请输入竞赛uid", trigger: "blur" }],
account_name: [{ required: true, message: "请输入账号名称", trigger: "blur" }],
status: [{ required: true, message: "请选择账号状态", trigger: "change" }],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
ElMessage.error("提交失败!");
}
});
};
const accountForm = (editData) => {
ruleForm.contest_uid = editData.contest_uid;
ruleForm.account_name = editData.account_name;
ruleForm.status = props.editData.statusOptions[editData.status];
};
defineExpose({ operateDialogVisible, model, ruleForm, accountForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,206 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="题目" prop="topic">
<el-input
clearable
placeholder="请输入题目"
v-model="ruleForm.topic"
@input="filter(ruleForm.topic, 'topic')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项A" prop="options_a">
<el-input
clearable
placeholder="请输入选项A"
v-model="ruleForm.options_a"
@input="filter(ruleForm.options_a, 'options_a')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项B" prop="options_b">
<el-input
clearable
placeholder="请输入选项B"
v-model="ruleForm.options_b"
@input="filter(ruleForm.options_b, 'options_b')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项C" prop="options_c">
<el-input
clearable
placeholder="请输入选项C"
v-model="ruleForm.options_c"
@input="filter(ruleForm.options_c, 'options_c')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="选项D" prop="options_d">
<el-input
clearable
placeholder="请输入选项D"
v-model="ruleForm.options_d"
@input="filter(ruleForm.options_d, 'options_d')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="答案" prop="answer">
<el-input
clearable
placeholder="请输入答案"
v-model="ruleForm.answer"
@input="filter(ruleForm.answer, 'answer')"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
topic: "",
options_a: "",
options_b: "",
options_c: "",
options_d: "",
answer: "",
});
const password = ref("");
const rules = reactive({
topic: [{ required: true, message: "请输入题目", trigger: "blur" }],
options_a: [{ required: true, message: "请输入选项A", trigger: "blur" }],
options_b: [{ required: true, message: "请输入选项B", trigger: "blur" }],
options_c: [{ required: true, message: "请输入选项C", trigger: "blur" }],
options_d: [{ required: true, message: "请输入选项D", trigger: "blur" }],
answer: [{ required: true, message: "请输入答案", trigger: "blur" }],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
ElMessage.error("提交失败!");
}
});
};
const choiceTopicForm = (editData) => {
ruleForm.topic = editData.topic;
ruleForm.options_a = editData.options_a;
ruleForm.options_b = editData.options_b;
ruleForm.options_c = editData.options_c;
ruleForm.options_d = editData.options_d;
ruleForm.answer = editData.answer;
};
defineExpose({ operateDialogVisible, model, ruleForm, choiceTopicForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,322 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="竞赛名称" prop="contest_name">
<el-input
clearable
placeholder="请输入竞赛名称"
v-model="ruleForm.contest_name"
@input="filter(ruleForm.contest_name, 'contest_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛主办方" prop="contest_organizers">
<el-input
clearable
placeholder="请输入竞赛主办方"
v-model="ruleForm.contest_organizers"
@input="filter(ruleForm.contest_organizers, 'contest_organizers')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛届数" prop="contest_term">
<el-input
clearable
placeholder="请输入竞赛届数"
v-model="ruleForm.contest_term"
@input="filter(ruleForm.contest_term, 'contest_term')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="竞赛类型" prop="type">
<el-select
clearable
size="small"
placeholder="请选择竞赛类型"
autocomplete="off"
v-model="ruleForm.type"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="举办状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择举办状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item label="线上赛起止时间">
<el-col :span="11">
<el-form-item prop="online_start">
<el-date-picker
v-model="ruleForm.online_start"
type="datetime"
placeholder="请选择线上赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="online_end">
<el-date-picker
v-model="ruleForm.online_end"
type="datetime"
placeholder="请选择线上赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="线下赛起止时间">
<el-col :span="11">
<el-form-item prop="offline_start">
<el-date-picker
v-model="ruleForm.offline_start"
type="datetime"
placeholder="请选择线下赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="offline_end">
<el-date-picker
v-model="ruleForm.offline_end"
type="datetime"
placeholder="请选择线下赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="竞赛起止时间">
<el-col :span="11">
<el-form-item prop="contest_start">
<el-date-picker
v-model="ruleForm.contest_start"
type="datetime"
placeholder="请选择竞赛开始时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-form-item prop="contest_end">
<el-date-picker
v-model="ruleForm.contest_end"
type="datetime"
placeholder="请选择竞赛结束时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
contest_name: "",
contest_organizers: "",
contest_term: "",
type: "",
status: "",
online_start: "",
online_end: "",
offline_start: "",
offline_end: "",
contest_start: "",
contest_end: "",
});
const password = ref("");
const rules = reactive({
contest_name: [{ required: true, message: "请输入竞赛名称", trigger: "blur" }],
contest_organizers: [{ required: true, message: "请输入竞赛主办方", trigger: "blur" }],
contest_term: [{ required: true, message: "请输入竞赛届数", trigger: "blur" }],
type: [{ required: true, message: "请选择竞赛类型", trigger: "change" }],
status: [{ required: true, message: "请选择举办状态", trigger: "change" }],
online_start: [
{ type: "date", required: true, message: "线上赛开始时间", trigger: "change" },
],
online_end: [
{ type: "date", required: true, message: "线上赛结束时间", trigger: "change" },
],
offline_start: [
{ type: "date", required: true, message: "线下赛开始时间", trigger: "change" },
],
offline_end: [
{ type: "date", required: true, message: "线下赛结束时间", trigger: "change" },
],
contest_start: [
{ type: "date", required: true, message: "竞赛开始时间", trigger: "change" },
],
contest_end: [
{ type: "date", required: true, message: "竞赛结束时间", trigger: "change" },
],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
ElMessage.error("提交失败!");
}
});
};
const contestForm = (editData) => {
ruleForm.contest_name = editData.contest_name;
ruleForm.contest_organizers = editData.contest_organizers;
ruleForm.contest_term = editData.contest_term;
ruleForm.type = props.editData.typeOptions[editData.type];
ruleForm.status = props.editData.statusOptions[editData.status];
ruleForm.online_start = editData.origin_onlineStart;
ruleForm.online_end = editData.origin_onlineEnd;
ruleForm.offline_start = editData.origin_offlineStart;
ruleForm.offline_end = editData.origin_offlineEnd;
ruleForm.contest_start = editData.origin_contestStart;
ruleForm.contest_end = editData.origin_contestEnd;
};
defineExpose({ operateDialogVisible, model, ruleForm, contestForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,151 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="得分" prop="score">
<el-input
clearable
placeholder="请输入得分"
v-model="ruleForm.score"
@input="filter(ruleForm.score, 'score')"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
score: "",
});
const password = ref("");
const rules = reactive({
score: [{ required: true, message: "请输入得分", trigger: "blur" }],
});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
ElMessage.error("提交失败!");
}
});
};
const examinationForm = (editData) => {
ruleForm.score = editData.score;
};
defineExpose({ operateDialogVisible, model, ruleForm, examinationForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,178 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="账号状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择账号状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号角色" prop="role">
<el-select
clearable
size="small"
placeholder="请选择账号角色"
autocomplete="off"
v-model="ruleForm.role"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
status: "",
role: "",
});
const password = ref("");
const rules = reactive({});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
let FormNull = false;
for (const element in ruleForm) {
if (ruleForm[element] !== "" && ruleForm[element] !== undefined) {
FormNull = true;
}
}
if (valid && FormNull) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
if (!FormNull) {
ElMessage.error("请先编辑数据!");
} else {
ElMessage.error("提交失败!");
}
}
});
};
defineExpose({ operateDialogVisible, model, ruleForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,178 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="账号状态" prop="status">
<el-select
clearable
size="small"
placeholder="请选择账号状态"
autocomplete="off"
v-model="ruleForm.status"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="账号角色" prop="role">
<el-select
clearable
size="small"
placeholder="请选择账号角色"
autocomplete="off"
v-model="ruleForm.role"
style="width: 100%; font-size: 1rem"
>
<el-option
v-for="item in editData.roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
class="text-center"
:style="item.style"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
status: "",
role: "",
});
const password = ref("");
const rules = reactive({});
const props = defineProps({
operateLabel: String,
editData: Object,
});
const emit = defineEmits(["requestOperate"]);
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
let FormNull = false;
for (const element in ruleForm) {
if (ruleForm[element] !== "" && ruleForm[element] !== undefined) {
FormNull = true;
}
}
if (valid && FormNull) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
if (!FormNull) {
ElMessage.error("请先编辑数据!");
} else {
ElMessage.error("提交失败!");
}
}
});
};
defineExpose({ operateDialogVisible, model, ruleForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,210 @@
<template>
<div>
<el-dialog
v-model="operateDialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
{{ operateLabel }}
</div>
<div
@click="resetCheckForm(ruleFormRef)"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="单位名称" prop="organization_name">
<el-input
clearable
placeholder="请输入单位名称"
v-model="ruleForm.organization_name"
@input="filter(ruleForm.organization_name, 'organization_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="通信地址" prop="address">
<el-input
clearable
placeholder="请输入通信地址"
v-model="ruleForm.address"
@input="filter(ruleForm.address, 'address')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="单位联系人姓名" prop="liaison_name">
<el-input
clearable
placeholder="请输入单位联系人姓名"
v-model="ruleForm.liaison_name"
@input="filter(ruleForm.liaison_name, 'liaison_name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="联系人手机号码" prop="phone">
<el-input
clearable
placeholder="请输入联系人手机号码"
v-model="ruleForm.phone"
@input="filter(ruleForm.phone, 'phone')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="单位电子邮箱" prop="email">
<el-input
clearable
placeholder="请输入单位电子邮箱"
v-model="ruleForm.email"
@input="filter(ruleForm.email, 'email')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="其他信息" prop="other_information">
<el-input
clearable
placeholder="请输入其他信息"
v-model="ruleForm.other_information"
@input="filter(ruleForm.other_information, 'other_information')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="邮政编码" prop="post_code">
<el-input
clearable
placeholder="请输入邮政编码"
v-model="ruleForm.post_code"
@input="filter(ruleForm.post_code, 'post_code')"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetCheckForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="confirm(ruleFormRef)"
>
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- <PasswordOauth
ref="editPasswordOauthRef"
:operateLabel="operateLabel"
@requestOperate="requestOperate"
/> -->
</div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
// import PasswordOauth from "../operate/passwordOauth.vue";
const operateDialogVisible = ref(false);
const model = ref("single");
const ruleFormRef = ref(null);
// const editPasswordOauthRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
organization_name: "",
address: "",
liaison_name: "",
phone: "",
email: "",
other_information: "",
post_code: "",
});
const password = ref("");
const rules = reactive({
organization_name: [{ required: true, message: "请输入单位名称", trigger: "blur" }],
});
const props = defineProps({
operateLabel: String,
});
const emit = defineEmits(["requestOperate"]);
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const handleClose = () => {
operateDialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetCheckForm = (formEl) => {
operateDialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
// const requestOperate = () => {
// password.value = editPasswordOauthRef.value.ruleForm.password;
// emit("requestOperate");
// operateDialogVisible.value = false;
// formElClone.value.resetFields();
// };
const confirm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
// editPasswordOauthRef.value.operateDialogVisible = true;
formElClone.value = formEl;
emit("requestOperate");
operateDialogVisible.value = false;
formElClone.value.resetFields();
} else {
ElMessage.error("提交失败!");
}
});
};
const originForm = (editData) => {
ruleForm.organization_name = editData.organization_name;
ruleForm.address = editData.address;
ruleForm.liaison_name = editData.liaison_name;
ruleForm.phone = editData.phone;
ruleForm.email = editData.email;
ruleForm.other_information = editData.other_information;
ruleForm.post_code = editData.post_code;
};
defineExpose({ operateDialogVisible, model, ruleForm, originForm, password });
</script>
<style scoped></style>

View File

@@ -0,0 +1,146 @@
<template>
<div>
<div class="bg-fuchsia-200">
<el-dropdown class="flex flex-auto justify-end items-center">
<el-button style="font-weight: bold" type="success" size="small">
账户名: {{ userMsg.name }}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
style="background-color: rgba(56, 188, 248, 0.1)"
@click="editUser"
>
<el-link style="font-weight: bold" :underline="false" type="primary">
账户管理
</el-link>
</el-dropdown-item>
<el-dropdown-item
style="background-color: rgba(56, 188, 248, 0.1)"
@click="changePassword"
>
<el-link style="font-weight: bold" :underline="false" type="primary">
密码管理
</el-link>
</el-dropdown-item>
<el-dropdown-item
style="background-color: rgba(240, 70, 70, 0.1)"
@click="unLogin"
>
<el-link style="font-weight: bold" :underline="false" type="danger">
退出登录
</el-link>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<UserManager @resetData="resetData" ref="userManagerRef" :msg="userMsg" />
<PasswordManager ref="passwordManagerRef" />
</div>
</template>
<script setup>
import { ref, watch, onMounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { ArrowDown } from "@element-plus/icons-vue";
import $http from "../../api/index";
import $url from "../../api/url";
import UserManager from "../manager/userManager.vue";
import PasswordManager from "../manager/changePassword.vue";
const router = useRouter();
const systemManager = ref(false);
const manager = ref(false);
const userManagerRef = ref(null);
const userMsg = ref({});
const passwordManagerRef = ref(null);
const editUser = () => {
if (userManagerRef.value) {
userManagerRef.value.dialogVisible = true;
userManagerRef.value.reset();
}
};
const changePassword = () => {
if (passwordManagerRef.value) {
passwordManagerRef.value.dialogVisible = true;
}
};
const unLogin = () => {
const data = {
uid: localStorage.data,
access_token: localStorage.access_token,
refresh_token: localStorage.refresh_token,
};
$http.post($url.unLogin, data).then((res) => {
localStorage.clear();
if (localStorage.length == 0) {
window.location.reload();
}
});
};
const resetData = () => {
const data = {
uid: localStorage.data,
};
$http.post($url.getUser, data).then((res) => {
if (res.data.code === 200) {
ElMessage({
message: "获取用户信息成功!",
type: "success",
});
userMsg.value = res.data.userData;
if (res.data.userData.role == 9) {
systemManager.value = true;
}
if (res.data.userData.role == 6 || res.data.userData.role == 9) {
manager.value = true;
}
if (res.data.userData.status == 0) {
ElMessage({
showClose: true,
message: "您的账号正在使用默认密码,请尽快进行更改!",
type: "warning",
});
}
if (res.data.userData.status == 2) {
ElMessage({
showClose: true,
message: "您的账号已被封禁,请联系管理员进行申诉!",
type: "error",
});
}
} else {
ElMessage.error("获取用户信息失败!");
if (localStorage.length == 0) {
// window.location.reload();
router.push({ path: '/mlogin' });
}
}
});
};
watch(manager, (value) => {
if (value) {
}
});
onMounted(() => {
setTimeout(() => {
resetData();
}, 200);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,17 @@
<template>
<div>
<img class="cursor-pointer" src="../../assets/logo.png" alt="" @click="goToHome">
</div>
</template>
<script setup>
import { useRouter } from "vue-router";
const router = useRouter();
const goToHome = () => {
router.push({ name: "home" });
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,59 @@
<template>
<div class="w-2/3 h-full flex justify-between items-center bg-teal-400">
<template v-for="options in nav" :key="options.page">
<div
:style="
activeIndex == options.id
? 'background-color: rgb(14 165 233);border-width: 2px;border-bottom-color: rgb(192 38 211);line-height: 5.7rem'
: 'line-height: 5.7rem'
"
class="h-full flex-1 cursor-pointer text-center hover:bg-sky-500"
@click="goToPage(options.page, options.id)"
>
{{ options.label }}
</div>
</template>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import activeIndexActiveStore from "../../stores/activeIndex";
const router = useRouter();
const activeIndexActive = activeIndexActiveStore();
const activeIndex = ref(0);
const nav = [
{ label: "首页", page: "home", id: 0 },
{ label: "工作区", page: "workspace", id: 1 },
{ label: "B端管理", page: "bside", id: 2 },
{ label: "C端管理", page: "cside", id: 3 },
{ label: "竞赛管理", page: "contest", id: 4 },
{ label: "内部管理", page: "insiders", id: 5 },
{ label: "系统设置", page: "system", id: 6 },
];
const handleOpen = (key, keyPath) => {
console.log(key, keyPath);
};
const handleClose = (key, keyPath) => {
console.log(key, keyPath);
};
const goToPage = (page, id) => {
activeIndex.value = id;
activeIndexActive.headerActive = id;
router.push({ name: page });
};
onMounted(() => {
goToPage(nav[activeIndexActive.headerActive].page, activeIndexActive.headerActive);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,8 @@
<template>
<el-text class="mx-1"> Charts </el-text>
</template>
<script setup>
</script>
<style scoped></style>

View File

@@ -0,0 +1,8 @@
<template>
<el-text class="mx-1"> Form </el-text>
</template>
<script setup>
</script>
<style scoped></style>

View File

@@ -0,0 +1,8 @@
<template>
<el-text class="mx-1"> Table </el-text>
</template>
<script setup>
</script>
<style scoped></style>

View File

@@ -0,0 +1,584 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="SNActive" />
<AddNewData newDataLabel="新增SN号" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="100" column-key="sn_number">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchSNKeyRef"
holderText="输入SN号以搜索相关数据"
@search="SNMsg"
/>
<div>
<el-text class="mx-1"> SN号 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="SortSNRef"
activeText="顺序"
inactiveText="倒序"
@search="SNMsg"
/>
</div>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ scope.row.sn_number }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择绑定状态以搜索相关数据"
:options="statusOptions"
@search="SNMsg"
/>
<div>
<el-text class="mx-1"> 绑定状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入绑定用户以搜索相关数据"
@search="SNMsg"
/>
<div>
<el-text class="mx-1"> 绑定用户 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="SNMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="SNMsg"
/>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="SNMsg"
/>
<div>
<el-text class="mx-1"> 绑定状态变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="SNMsg"
/>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="SNActive"
@sizeChangeBack="changePage"
@search="SNMsg"
/>
</div>
</el-card>
<AddSNForm ref="addSNFormRef" title="新增SN号" @reloadData="SNMsg" />
<EditSNForm
ref="editSNFormRef"
operateLabel="编辑SN号"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除SN号"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddSNForm from "../addNewData/SNForm/SNForm.vue";
import EditSNForm from "../editData/SNForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import SNActiveStore from "../../stores/SN";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const SNActive = SNActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑SN号",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除SN号",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchSNKeyRef = ref(null);
const SelectStatusSearchRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const SortSNRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addSNFormRef = ref(null);
const editSNFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
sn_number: "",
status: "",
created_at: "",
updated_at: "",
});
const sortOptions = reactive({
sn_number: false,
created_at: false,
updated_at: false,
});
const tableData = ref([]);
const statusOptions = [
{
value: "0",
label: "未绑定",
style: "color: rgb(20, 200, 200);background-color: rgba(20, 200, 200, 0.1);padding: 0;",
},
{
value: "1",
label: "B端绑定",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "2",
label: "C端绑定",
style: "color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
{
value: "3",
label: "竞赛绑定",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "4",
label: "B端预绑定",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({
statusOptions,
});
const showAddForm = () => {
addSNFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
SNActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
SNActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
SNActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const SNMsg = () => {
judgment(searchOptions, "sn_number", SearchSNKeyRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "sn_number", SortSNRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showSN, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.SNMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
SNActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
SNActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editSNFormRef.value.operateDialogVisible = true;
editSNFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editSN;
model = EditSelectRef.value.model;
password = editSNFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteSN;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editSNFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
SNMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ SNMsg });
watch(searchOptions, (value) => {
SNActive.searchOptions = value;
});
watch(sortOptions, (value) => {
SNActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = SNActive.pageCount;
dialogSearchVisible.value = SNActive.dialogSearchVisible;
dialogSortVisible.value = SNActive.dialogSortVisible;
dialogOperationVisible.value = SNActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.sn_number = SNActive.searchOptions.sn_number;
searchOptions.status = SNActive.searchOptions.status;
searchOptions.created_at = SNActive.searchOptions.created_at;
searchOptions.updated_at = SNActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
sortOptions.sn_number = SNActive.sortOptions.sn_number;
sortOptions.created_at = SNActive.sortOptions.created_at;
sortOptions.updated_at = SNActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
SNMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchSNKeyRef.value.searchMsg = SNActive.searchOptions.sn_number;
SelectStatusSearchRef.value.searchMsg = SNActive.searchOptions.status;
createdDateTimePickerRef.value.created_at =
SNActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
SNActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
SortSNRef.value.searchMsg = SNActive.sortOptions.sn_number;
createdSortDateTimeRef.value.searchMsg = SNActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = SNActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,329 @@
<template>
<div class="card-container">
<div class="top-block">
<div class="info-block">
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>用户ID</span>
</div>
</template>
<div class="unbind-users" :style="{ height: contentBlockHeight + 'px' }">
<el-tag v-show="selectedUser !== ''" type="info" class="sn-tag" effect="dark">
{{ selectedUser }}
</el-tag>
</div>
</el-card>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>SN号</span>
</div>
</template>
<div class="unbind-sn" :style="{ height: contentBlockHeight + 'px' }">
<el-tag
v-for="sn in selectedSNs"
:key="sn"
type="info"
class="sn-tag"
effect="dark"
>
{{ sn }}
</el-tag>
</div>
</el-card>
</div>
<div
class="action-block"
:style="{
height: contentBlockHeight + 'px',
lineHeight: contentBlockHeight / 2 + 'px',
}"
>
<div class="sn-count-label">
用户可管理的SN号数量
<div>
<el-input
v-model.number="snCount"
type="number"
placeholder="输入可绑定的SN数量"
class="sn-count-input"
:min="0"
@change="validateSNCount"
/>
</div>
<el-button class="bind-button" type="primary" @click="allocationSN"
>确认绑定</el-button
>
</div>
</div>
</div>
<div class="content-block" ref="contentBlockRef">
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>未绑定的用户</span>
</div>
</template>
<div class="unbind-users">
<el-tag
v-for="user in unbindUsers"
:key="user"
type="info"
class="user-tag"
:effect="user === selectedUser ? 'dark' : 'plain'"
@click="selectUser(user)"
>
{{ user }}
</el-tag>
</div>
</el-card>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>未绑定的SN号</span>
</div>
</template>
<div class="unbind-sn">
<el-tag
v-for="sn in unbindSN"
:key="sn"
type="info"
class="sn-tag"
:effect="selectedSNs.includes(sn) ? 'dark' : 'plain'"
@click="toggleSelectSN(sn)"
>
{{ sn }}
</el-tag>
</div>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, nextTick } from "vue";
import { ElCard, ElButton, ElTag, ElMessage, ElInput } from "element-plus";
import SNAdminActiveStore from "../../stores/SNAdmin";
import $http from "../../api/index";
import $url from "../../api/url";
const SNAdminActive = SNAdminActiveStore();
const selectedUser = ref("");
const selectedSNs = ref([]);
const snCount = ref(0);
const unbindUsers = ref([]);
const userObj = ref({});
const unbindSN = ref([]);
const contentBlockRef = ref(null);
const contentBlockHeight = ref(0);
const selectUser = (user) => {
selectedUser.value = user;
SNAdminActive.selectedUser = user;
};
const toggleSelectSN = (sn) => {
if (selectedSNs.value.includes(sn)) {
selectedSNs.value = selectedSNs.value.filter((s) => s !== sn);
SNAdminActive.selectedSNs = selectedSNs.value.filter((s) => s !== sn);
} else {
if (selectedSNs.value.length < snCount.value) {
selectedSNs.value.push(sn);
} else {
ElMessage.warning("已达到可绑定的SN号数量上限!");
}
}
};
const validateSNCount = () => {
if (snCount.value < 0) {
snCount.value = 0;
ElMessage.warning("SN号数量不能为负数!");
} else {
if (selectedSNs.value.length > snCount.value) {
snCount.value = selectedSNs.value.length;
ElMessage.warning("已达到可绑定的SN号数量上限!");
}
}
SNAdminActive.snCount = snCount.value;
};
const resetCheckForm = () => {
selectedUser.value = "";
SNAdminActive.selectedUser = "";
selectedSNs.value = [];
SNAdminActive.selectedSNs = [];
snCount.value = 0;
SNAdminActive.snCount = 0;
};
const searchAllocationUser = () => {
$http.get($url.searchAllocationUser).then((res) => {
if (res.data.code === 200) {
res.data.userArr.forEach(element => {
unbindUsers.value.push(element.account_name);
userObj.value[element.account_name] = element.uid;
});
} else {
unbindUsers.value = [];
resetCheckForm();
// ElMessage.error("未查找到相关数据!");
}
});
};
const searchAllocationSN = () => {
$http.get($url.searchAllocationSN).then((res) => {
if (res.data.code === 200) {
res.data.snArr.forEach(element => {
unbindSN.value.push(element.sn_number);
});
} else {
unbindSN.value = [];
resetCheckForm();
// ElMessage.error("未查找到相关数据!");
}
});
};
const allocationSN = () => {
if (selectedUser.value === "" || selectedSNs.value.length === 0) {
ElMessage.warning("请选择用户和SN号!");
return;
}
const data = {
user_uid: userObj.value[selectedUser.value],
length: snCount.value,
sn_set: selectedSNs.value.join(","),
};
$http.post($url.allocationSN, data).then((res) => {
if (res.data.code === 200) {
resetCheckForm();
unbindUsers.value = [];
unbindSN.value = [];
searchAllocationUser();
searchAllocationSN();
ElMessage({
message: "绑定成功!",
type: "success",
});
} else {
ElMessage.error("绑定失败!");
}
});
};
const setContentBlockHeight = async () => {
await nextTick();
if (contentBlockRef.value) {
contentBlockHeight.value = contentBlockRef.value.offsetHeight;
}
};
onMounted(() => {
selectedUser.value = SNAdminActive.selectedUser;
selectedSNs.value = SNAdminActive.selectedSNs;
snCount.value = SNAdminActive.snCount;
setTimeout(() => {
searchAllocationUser();
searchAllocationSN();
setContentBlockHeight();
}, 200);
});
</script>
<style scoped>
.card-container {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.top-block {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 20px;
}
.info-block {
display: flex;
gap: 20px;
width: 100%;
flex: 1;
}
.box-card {
flex: 1;
}
.unbind-users,
.unbind-sn {
display: flex;
flex-wrap: wrap;
gap: 10px;
height: 100%;
align-items: flex-start;
overflow-y: auto;
}
.unbind-users .sn-tag,
.unbind-sn .sn-tag {
margin-bottom: 10px;
cursor: pointer;
}
.user-tag.effect-dark,
.sn-tag.effect-dark {
background-color: #409eff;
color: #fff;
border-color: #409eff;
}
.user-tag.effect-plain:hover,
.sn-tag.effect-plain:hover {
background-color: #ecf5ff;
color: #409eff;
border-color: #d9ecff;
}
.action-block {
color: #000;
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.sn-count-label {
text-align: center;
font-weight: bold;
}
.sn-count-input,
.bind-button {
width: 100%;
max-width: 200px; /* 设置最大宽度,确保文字长度合适 */
}
.content-block {
display: flex;
justify-content: space-between;
gap: 20px;
width: 100%;
}
.card-header {
text-align: center;
font-weight: bold;
}
.unbound-users .el-tag,
.unbound-sn .el-tag {
color: #000; /* 确保文字为黑色 */
}
</style>

View File

@@ -0,0 +1,384 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="allocationSNRecordActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账户名以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="user_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserUidKeyRef"
holderText="输入账户uid以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="length">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchLengthKeyRef"
holderText="输入可管理的SN号数量以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 可管理的SN号数量 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.length }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="sn_set">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchSNKeyRef"
holderText="输入SN号以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> SN号 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.sn_set }}
</div>
<el-button
style="font-size: 1rem; font-weight: bold"
size="small"
type="primary"
plain
@click="showAll(scope.row.sn_set)"
>
查看全部
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="allocationSNRecordActive"
@sizeChangeBack="changePage"
@search="bindSNRecordMsg"
/>
</div>
</el-card>
<DataShow ref="DataShowRef" />
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除SN号分配记录"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import Pagination from "../search/pagination.vue";
import DataShow from "../operate/dataShow.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import allocationSNRecordActiveStore from "../../stores/allocationSNRecord";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const allocationSNRecordActive = allocationSNRecordActiveStore();
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除SN号分配记录",
};
const DelSelectRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SearchUserUidKeyRef = ref(null);
const SearchLengthKeyRef = ref(null);
const SearchSNKeyRef = ref(null);
const PaginationRef = ref(null);
const DataShowRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("del");
const searchOptions = reactive({
account_name: "",
user_uid: "",
length: "",
sn_set: "",
});
const sortOptions = reactive({});
const tableData = ref([]);
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const showAll = (msg) => {
DataShowRef.value.dialogMsg = msg;
DataShowRef.value.dialogVisible = true;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
allocationSNRecordActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
allocationSNRecordActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
allocationSNRecordActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const bindSNRecordMsg = () => {
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "user_uid", SearchUserUidKeyRef.value, "searchMsg");
judgment(searchOptions, "length", SearchLengthKeyRef.value, "searchMsg");
judgment(searchOptions, "sn_set", SearchSNKeyRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showAllocationSNRecord, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.SNAdminMsg;
PaginationRef.value.dataCount = res.data.count;
allocationSNRecordActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
allocationSNRecordActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
delete item.origin_createdAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
delete singleData.origin_createdAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "del") {
operateType = "删除";
url = $url.deleteAllocationSNRecord;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
bindSNRecordMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ bindSNRecordMsg });
watch(searchOptions, (value) => {
allocationSNRecordActive.searchOptions = value;
});
watch(sortOptions, (value) => {
allocationSNRecordActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = allocationSNRecordActive.pageCount;
dialogSearchVisible.value = allocationSNRecordActive.dialogSearchVisible;
dialogSortVisible.value = allocationSNRecordActive.dialogSortVisible;
dialogOperationVisible.value = allocationSNRecordActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.account_name = allocationSNRecordActive.searchOptions.account_name;
searchOptions.user_uid = allocationSNRecordActive.searchOptions.user_uid;
searchOptions.length = allocationSNRecordActive.searchOptions.length;
searchOptions.sn_set = allocationSNRecordActive.searchOptions.sn_set;
}
if (dialogSortVisible.value) {
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
bindSNRecordMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchAccountNameKeyRef.value.searchMsg = allocationSNRecordActive.searchOptions.account_name;
SearchUserUidKeyRef.value.searchMsg = allocationSNRecordActive.searchOptions.user_uid;
SearchLengthKeyRef.value.searchMsg = allocationSNRecordActive.searchOptions.length;
SearchSNKeyRef.value.searchMsg = allocationSNRecordActive.searchOptions.sn_set;
}
if (dialogSortVisible.value) {
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,658 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="bdCardMsgActive" />
<AddNewData newDataLabel="新增北斗卡" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="100" column-key="card_id">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchCardIdKeyRef"
holderText="输入卡号以搜索相关数据"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 卡号 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="SortCardIdRef"
activeText="顺序"
inactiveText="倒序"
@search="bdCardMsg"
/>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.card_id }}
</div>
</template>
</el-table-column>
<el-table-column min-width="160" column-key="card_imsi">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchCardImsiKeyRef"
holderText="输入IMSI号以搜索相关数据"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> IMSI号 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="SortCardImsiRef"
activeText="顺序"
inactiveText="倒序"
@search="bdCardMsg"
/>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.card_imsi }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择白名单类型以搜索相关数据"
:options="typeOptions"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 白名单类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择绑定状态以搜索相关数据"
:options="statusOptions"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 绑定状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入绑定用户以搜索相关数据"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 绑定用户 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bdCardMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="bdCardMsg"
/>
<div>
<el-text class="mx-1"> 绑定状态变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bdCardMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="bdCardMsgActive"
@sizeChangeBack="changePage"
@search="bdCardMsg"
/>
</div>
</el-card>
<AddBdCardForm ref="addBdCardFormRef" title="新增北斗卡" @reloadData="bdCardMsg" />
<EditBdCardForm
ref="editBdCardFormRef"
operateLabel="编辑北斗卡"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除北斗卡"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddBdCardForm from "../addNewData/bdCardForm/bdCardForm.vue";
import EditBdCardForm from "../editData/bdCardForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import bdCardActiveStore from "../../stores/bdCard";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const bdCardMsgActive = bdCardActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑北斗卡",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除北斗卡",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchCardIdKeyRef = ref(null);
const SearchCardImsiKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const SelectStatusSearchRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const SortCardIdRef = ref(null);
const SortCardImsiRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addBdCardFormRef = ref(null);
const editBdCardFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
card_id: "",
card_imsi: "",
type: "",
status: "",
account_name: "",
created_at: "",
updated_at: "",
});
const sortOptions = reactive({
card_id: false,
card_imsi: false,
created_at: false,
updated_at: false,
});
const tableData = ref([]);
const typeOptions = [
{
value: "0",
label: "白名单",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "1",
label: "审核中",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "2",
label: "黑名单",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const statusOptions = [
{
value: "0",
label: "未绑定",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "1",
label: "B端绑定",
style:
"color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "2",
label: "C端绑定",
style:
"color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
{
value: "3",
label: "竞赛绑定",
style:
"color: rgb(20, 200, 200);background-color: rgba(20, 200, 200, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({
typeOptions,
});
const showAddForm = () => {
addBdCardFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
bdCardMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
bdCardMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
bdCardMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const bdCardMsg = () => {
judgment(searchOptions, "card_id", SearchCardIdKeyRef.value, "searchMsg");
judgment(searchOptions, "card_imsi", SearchCardImsiKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "card_id", SortCardIdRef.value, "searchMsg");
judgment(sortOptions, "card_imsi", SortCardImsiRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showBdCard, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.bdCardMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
bdCardMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
bdCardMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editBdCardFormRef.value.operateDialogVisible = true;
editBdCardFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editBdCard;
model = EditSelectRef.value.model;
password = editBdCardFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteBdCard;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg: model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editBdCardFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
bdCardMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ bdCardMsg });
watch(searchOptions, (value) => {
bdCardMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
bdCardMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = bdCardMsgActive.pageCount;
dialogSearchVisible.value = bdCardMsgActive.dialogSearchVisible;
dialogSortVisible.value = bdCardMsgActive.dialogSortVisible;
dialogOperationVisible.value = bdCardMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.card_id = bdCardMsgActive.searchOptions.card_id;
searchOptions.card_imsi = bdCardMsgActive.searchOptions.card_imsi;
searchOptions.type = bdCardMsgActive.searchOptions.type;
searchOptions.status = bdCardMsgActive.searchOptions.status;
searchOptions.account_name = bdCardMsgActive.searchOptions.account_name;
searchOptions.created_at = bdCardMsgActive.searchOptions.created_at;
searchOptions.updated_at = bdCardMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
sortOptions.card_id = bdCardMsgActive.sortOptions.card_id;
sortOptions.card_imsi = bdCardMsgActive.sortOptions.card_imsi;
sortOptions.created_at = bdCardMsgActive.sortOptions.created_at;
sortOptions.updated_at = bdCardMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
bdCardMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchCardIdKeyRef.value.searchMsg = bdCardMsgActive.searchOptions.card_id;
SearchCardImsiKeyRef.value.searchMsg = bdCardMsgActive.searchOptions.card_imsi;
SelectTypeSearchRef.value.searchMsg = bdCardMsgActive.searchOptions.type;
SelectStatusSearchRef.value.searchMsg = bdCardMsgActive.searchOptions.status;
SearchAccountNameKeyRef.value.searchMsg =
bdCardMsgActive.searchOptions.account_name;
createdDateTimePickerRef.value.created_at =
bdCardMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
bdCardMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
SortCardIdRef.value.searchMsg = bdCardMsgActive.sortOptions.card_id;
SortCardImsiRef.value.searchMsg = bdCardMsgActive.sortOptions.card_imsi;
createdSortDateTimeRef.value.searchMsg = bdCardMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = bdCardMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,510 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="bindRecordMsgActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账户名以搜索相关数据"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="side">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectSideSearchRef"
holderText="选择用户类型以搜索相关数据"
:options="sideOptions"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 用户类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(sideOptions, scope.row.side)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(sideOptions, scope.row.side) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="user_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserUidKeyRef"
holderText="输入账户uid以搜索相关数据"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="card_id">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchCardIdKeyRef"
holderText="输入卡号以搜索相关数据"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 卡号 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.card_id }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择操作类型以搜索相关数据"
:options="typeOptions"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 操作类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="bindRecordMsg"
/>
<div>
<el-text class="mx-1"> 记录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bindRecordMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="bindRecordMsgActive"
@sizeChangeBack="changePage"
@search="bindRecordMsg"
/>
</div>
</el-card>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除北斗卡绑定记录"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import bindRecordActiveStore from "../../stores/bindRecord";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const bindRecordMsgActive = bindRecordActiveStore();
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除北斗卡绑定记录",
};
const DelSelectRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SelectSideSearchRef = ref(null);
const SearchUserUidKeyRef = ref(null);
const SearchCardIdKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const createdDateTimePickerRef = ref(null);
const createdSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("del");
const searchOptions = reactive({
account_name: "",
side: "",
user_uid: "",
card_id: "",
type: "",
created_at: "",
});
const sortOptions = reactive({
created_at: false,
});
const tableData = ref([]);
const sideOptions = [
{
value: "0",
label: "B端用户",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "1",
label: "C端用户",
style: "color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
];
const typeOptions = [
{
value: "0",
label: "绑定",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "1",
label: "解绑",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
bindRecordMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
bindRecordMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
bindRecordMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const bindRecordMsg = () => {
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "side", SelectSideSearchRef.value, "searchMsg");
judgment(searchOptions, "user_uid", SearchUserUidKeyRef.value, "searchMsg");
judgment(searchOptions, "card_id", SearchCardIdKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showBindRecord, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.BindRecordMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(0, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
bindRecordMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
bindRecordMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
delete item.origin_createdAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
delete singleData.origin_createdAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "del") {
operateType = "删除";
url = $url.deleteBindRecord;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
bindRecordMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ bindRecordMsg });
watch(searchOptions, (value) => {
bindRecordMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
bindRecordMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = bindRecordMsgActive.pageCount;
dialogSearchVisible.value = bindRecordMsgActive.dialogSearchVisible;
dialogSortVisible.value = bindRecordMsgActive.dialogSortVisible;
dialogOperationVisible.value = bindRecordMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.account_name = bindRecordMsgActive.searchOptions.account_name;
searchOptions.side = bindRecordMsgActive.searchOptions.side;
searchOptions.user_uid = bindRecordMsgActive.searchOptions.user_uid;
searchOptions.card_id = bindRecordMsgActive.searchOptions.card_id;
searchOptions.type = bindRecordMsgActive.searchOptions.type;
searchOptions.created_at = bindRecordMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
sortOptions.created_at = bindRecordMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
bindRecordMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchAccountNameKeyRef.value.searchMsg = bindRecordMsgActive.searchOptions.account_name;
SelectSideSearchRef.value.searchMsg = bindRecordMsgActive.searchOptions.side;
SearchUserUidKeyRef.value.searchMsg = bindRecordMsgActive.searchOptions.user_uid;
SearchCardIdKeyRef.value.searchMsg = bindRecordMsgActive.searchOptions.card_id;
SelectTypeSearchRef.value.searchMsg = bindRecordMsgActive.searchOptions.type;
createdDateTimePickerRef.value.created_at = bindRecordMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = bindRecordMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,515 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="bindSNRecordMsgActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账户名以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="side">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectSideSearchRef"
holderText="选择用户类型以搜索相关数据"
:options="sideOptions"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 用户类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(sideOptions, scope.row.side)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(sideOptions, scope.row.side) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="user_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserUidKeyRef"
holderText="输入账户uid以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 账户uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="sn_number">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchSNKeyRef"
holderText="输入SN号以搜索相关数据"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> SN号 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.sn_number }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择操作类型以搜索相关数据"
:options="typeOptions"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 操作类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="bindSNRecordMsg"
/>
<div>
<el-text class="mx-1"> 记录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bindSNRecordMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="bindSNRecordMsgActive"
@sizeChangeBack="changePage"
@search="bindSNRecordMsg"
/>
</div>
</el-card>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除SN号绑定记录"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import bindSNRecordActiveStore from "../../stores/bindSNRecord";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const bindSNRecordMsgActive = bindSNRecordActiveStore();
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除SN号绑定记录",
};
const DelSelectRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SelectSideSearchRef = ref(null);
const SearchUserUidKeyRef = ref(null);
const SearchSNKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const createdDateTimePickerRef = ref(null);
const createdSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("del");
const searchOptions = reactive({
account_name: "",
side: "",
user_uid: "",
sn_number: "",
type: "",
created_at: "",
});
const sortOptions = reactive({
created_at: false,
});
const tableData = ref([]);
const sideOptions = [
{
value: "0",
label: "B端用户",
style:
"color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "1",
label: "C端用户",
style:
"color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
];
const typeOptions = [
{
value: "0",
label: "绑定",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "1",
label: "解绑",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
bindSNRecordMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
bindSNRecordMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
bindSNRecordMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const bindSNRecordMsg = () => {
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "side", SelectSideSearchRef.value, "searchMsg");
judgment(searchOptions, "user_uid", SearchUserUidKeyRef.value, "searchMsg");
judgment(searchOptions, "sn_number", SearchSNKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showBindSNRecord, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.BindSNRecordMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(0, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
bindSNRecordMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
bindSNRecordMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
delete item.origin_createdAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
delete singleData.origin_createdAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "del") {
operateType = "删除";
url = $url.deleteBindSNRecord;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
bindSNRecordMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ bindSNRecordMsg });
watch(searchOptions, (value) => {
bindSNRecordMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
bindSNRecordMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = bindSNRecordMsgActive.pageCount;
dialogSearchVisible.value = bindSNRecordMsgActive.dialogSearchVisible;
dialogSortVisible.value = bindSNRecordMsgActive.dialogSortVisible;
dialogOperationVisible.value = bindSNRecordMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.account_name = bindSNRecordMsgActive.searchOptions.account_name;
searchOptions.side = bindSNRecordMsgActive.searchOptions.side;
searchOptions.user_uid = bindSNRecordMsgActive.searchOptions.user_uid;
searchOptions.sn_number = bindSNRecordMsgActive.searchOptions.sn_number;
searchOptions.type = bindSNRecordMsgActive.searchOptions.type;
searchOptions.created_at = bindSNRecordMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
sortOptions.created_at = bindSNRecordMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
bindSNRecordMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchAccountNameKeyRef.value.searchMsg =
bindSNRecordMsgActive.searchOptions.account_name;
SelectSideSearchRef.value.searchMsg = bindSNRecordMsgActive.searchOptions.side;
SearchUserUidKeyRef.value.searchMsg = bindSNRecordMsgActive.searchOptions.user_uid;
SearchSNKeyRef.value.searchMsg = bindSNRecordMsgActive.searchOptions.sn_number;
SelectTypeSearchRef.value.searchMsg = bindSNRecordMsgActive.searchOptions.type;
createdDateTimePickerRef.value.created_at =
bindSNRecordMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = bindSNRecordMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,817 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="bsideMsgActive" />
<AddNewData newDataLabel="新增B端用户" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="100" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择账号状态以搜索相关数据"
:options="statusOptions"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 账号状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="role">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectRoleSearchRef"
holderText="选择账号角色以搜索相关数据"
:options="roleOptions"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 账号角色 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(roleOptions, scope.row.role)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(roleOptions, scope.row.role) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账号名称以搜索相关数据"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 账号名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="organization">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOrganizationKeyRef"
holderText="输入单位名称以搜索相关数据"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 单位名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.organization }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="user_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserNameKeyRef"
holderText="输入用户姓名以搜索相关数据"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 用户姓名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="phone">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchPhoneKeyRef"
holderText="输入手机号码以搜索相关数据"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 手机号码 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.phone }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="msg">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchMsgKeyRef"
holderText="输入基本信息以搜索相关数据"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 基本信息 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.msg }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bsideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 账号状态变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bsideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="login_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="loginDateTimePickerRef"
DateTimePicker="loginMsgDateTimePicker"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 上次登录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="loginSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="bsideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.login_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="login_status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectLoginStatusSearchRef"
holderText="选择登录状态以搜索相关数据"
:options="loginStatusOptions"
@search="bsideMsg"
/>
<div>
<el-text class="mx-1"> 登录状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(loginStatusOptions, scope.row.login_status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(loginStatusOptions, scope.row.login_status) }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="bsideMsgActive"
@sizeChangeBack="changePage"
@search="bsideMsg"
/>
</div>
</el-card>
<AddBsideForm
ref="addBsideFormRef"
title="新增B端用户"
:addData="addData"
:createdAt="null"
@reloadData="bsideMsg"
@remoteSearch="remoteSearch"
/>
<EditBsideForm
ref="editBsideFormRef"
operateLabel="编辑B端用户"
:editData="editData"
:createdAt="null"
@requestOperate="requestOperate"
@remoteSearch="remoteSearch"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除B端用户"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddBsideForm from "../addNewData/bsideForm/bsideForm.vue";
import EditBsideForm from "../editData/bsideForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import bsideActiveStore from "../../stores/bside";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const bsideMsgActive = bsideActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑B端用户",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除B端用户",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SelectStatusSearchRef = ref(null);
const SelectRoleSearchRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SearchOrganizationKeyRef = ref(null);
const SearchUserNameKeyRef = ref(null);
const SearchPhoneKeyRef = ref(null);
const SearchMsgKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const loginDateTimePickerRef = ref(null);
const SelectLoginStatusSearchRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const loginSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addBsideFormRef = ref(null);
const editBsideFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
status: "",
role: "",
account_name: "",
organization: "",
user_name: "",
phone: "",
msg: "",
created_at: "",
updated_at: "",
login_at: "",
login_status: "",
});
const sortOptions = reactive({
created_at: false,
updated_at: false,
login_at: false,
});
const tableData = ref([]);
const statusOptions = [
{
value: "0",
label: "默认",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "正在使用",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "封禁",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const roleOptions = [
{
value: "0",
label: "普通用户",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "单位管理员",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
];
const loginStatusOptions = [
{
value: "0",
label: "未登录",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "已登录",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const addData = reactive({
roleOptions,
});
const editData = reactive({
statusOptions,
roleOptions,
});
const showAddForm = () => {
addBsideFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
bsideMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
bsideMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
bsideMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const remoteSearch = (query, key, timeBefor, model, operateType) => {
const data = {
query: query,
key: key,
};
$http.post($url.SearchOrganization, data).then((res) => {
if (res.data.code == 200) {
if (model == "edit") {
res.data.organization.forEach((element) => {
let created_at = moment
.utc(element.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
editBsideFormRef.value.remoteSearchRef.options.push({
value: element.uid,
label: element.organization_name + "------" + created_at,
});
});
} else if (model == "add") {
res.data.organization.forEach((element) => {
let created_at = moment
.utc(element.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
if (operateType == "single") {
addBsideFormRef.value.singleAddRef.remoteSearchRef.options.push({
value: element.uid,
label: element.organization_name + "------" + created_at,
});
} else if (operateType == "multiple") {
addBsideFormRef.value.multipleAddRef.singleAddRef.forEach((item) => {
item.remoteSearchRef.options.push({
value: element.uid,
label: element.organization_name + "------" + created_at,
});
});
}
});
}
} else {
ElMessage.error("无相关数据");
}
});
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const bsideMsg = () => {
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "role", SelectRoleSearchRef.value, "searchMsg");
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "organization", SearchOrganizationKeyRef.value, "searchMsg");
judgment(searchOptions, "user_name", SearchUserNameKeyRef.value, "searchMsg");
judgment(searchOptions, "phone", SearchPhoneKeyRef.value, "searchMsg");
judgment(searchOptions, "msg", SearchMsgKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_at", loginDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_status", SelectLoginStatusSearchRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "login_at", loginSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showBSide, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.BSideMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_loginAt = item.login_at;
item.login_at = moment
.utc(item.login_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
bsideMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
bsideMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
if (item.origin_loginAt) {
item.created_at = item.origin_loginAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.origin_loginAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
singleData.login_at = singleData.origin_loginAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
delete singleData.origin_loginAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editBsideFormRef.value.operateDialogVisible = true;
editBsideFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editBSide;
model = EditSelectRef.value.model;
password = editBsideFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteBSide;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editBsideFormRef.value.ruleForm };
for (const element in data.updateMsg) {
if (data.updateMsg[element] == "") {
delete data.updateMsg[element];
}
}
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
bsideMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ bsideMsg });
watch(searchOptions, (value) => {
bsideMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
bsideMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = bsideMsgActive.pageCount;
dialogSearchVisible.value = bsideMsgActive.dialogSearchVisible;
dialogSortVisible.value = bsideMsgActive.dialogSortVisible;
dialogOperationVisible.value = bsideMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.status = bsideMsgActive.searchOptions.status;
searchOptions.role = bsideMsgActive.searchOptions.role;
searchOptions.account_name = bsideMsgActive.searchOptions.account_name;
searchOptions.organization = bsideMsgActive.searchOptions.organization;
searchOptions.user_name = bsideMsgActive.searchOptions.user_name;
searchOptions.phone = bsideMsgActive.searchOptions.phone;
searchOptions.msg = bsideMsgActive.searchOptions.msg;
searchOptions.created_at = bsideMsgActive.searchOptions.created_at;
searchOptions.updated_at = bsideMsgActive.searchOptions.updated_at;
searchOptions.login_at = bsideMsgActive.searchOptions.login_at;
searchOptions.login_status = bsideMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
sortOptions.created_at = bsideMsgActive.sortOptions.created_at;
sortOptions.updated_at = bsideMsgActive.sortOptions.updated_at;
sortOptions.login_at = bsideMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
bsideMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SelectStatusSearchRef.value.searchMsg = bsideMsgActive.searchOptions.status;
SelectRoleSearchRef.value.searchMsg = bsideMsgActive.searchOptions.role;
SearchAccountNameKeyRef.value.searchMsg = bsideMsgActive.searchOptions.account_name;
SearchOrganizationKeyRef.value.searchMsg =
bsideMsgActive.searchOptions.organization;
SearchUserNameKeyRef.value.searchMsg = bsideMsgActive.searchOptions.user_name;
SearchPhoneKeyRef.value.searchMsg = bsideMsgActive.searchOptions.phone;
SearchMsgKeyRef.value.searchMsg = bsideMsgActive.searchOptions.msg;
createdDateTimePickerRef.value.created_at = bsideMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at = bsideMsgActive.searchOptions.updated_at;
loginDateTimePickerRef.value.login_at = bsideMsgActive.searchOptions.login_at;
SelectLoginStatusSearchRef.value.searchMsg =
bsideMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = bsideMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = bsideMsgActive.sortOptions.updated_at;
loginSortDateTimeRef.value.searchMsg = bsideMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,824 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="businessMsgActive" />
<AddNewData newDataLabel="新增公司业务" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
singleType="single"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="300" column-key="salt">
<template #header>
<div>
<div>
<el-text class="mx-1"> 随机盐值 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.salt }}
</div>
</template>
</el-table-column>
<el-table-column min-width="300" column-key="login_url">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchLoginUrlKeyRef"
holderText="输入业务登录网址以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务登录网址 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.login_url }}
</div>
</template>
</el-table-column>
<el-table-column min-width="300" column-key="client_url">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchClientUrlKeyRef"
holderText="输入业务网址以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务网址 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.client_url }}
</div>
</template>
</el-table-column>
<el-table-column min-width="600" column-key="temporary_id">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchTemporaryIdKeyRef"
holderText="输入业务临时标识以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务临时标识 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.temporary_id }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="client_id">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchClientIdKeyRef"
holderText="输入业务ID以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务ID </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.client_id }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="client_secret">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchClientSecretKeyRef"
holderText="输入业务密钥以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务密钥 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.client_secret }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchNameKeyRef"
holderText="输入业务名称以搜索相关数据"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择业务类型以搜索相关数据"
:options="typeOptions"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="level">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectLevelSearchRef"
holderText="选择业务等级以搜索相关数据"
:options="levelOptions"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务等级 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(levelOptions, scope.row.level)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(levelOptions, scope.row.level) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择业务状态以搜索相关数据"
:options="statusOptions"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务开通时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="businessMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="businessMsg"
/>
<div>
<el-text class="mx-1"> 业务变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="businessMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="businessMsgActive"
@sizeChangeBack="changePage"
@search="businessMsg"
/>
</div>
</el-card>
<AddBusinessForm
ref="addBusinessFormRef"
title="新增公司业务"
:addData="addData"
:createdAt="new Date()"
@reloadData="businessMsg"
@remoteSearch="remoteSearch"
/>
<EditBusinessForm
ref="editBusinessFormRef"
operateLabel="编辑公司业务"
:editData="editData"
:createdAt="tableData.origin_createdAt"
@requestOperate="requestOperate"
@remoteSearch="remoteSearch"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除公司业务"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddBusinessForm from "../addNewData/businessForm/businessForm.vue";
import EditBusinessForm from "../editData/businessForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import businessActiveStore from "../../stores/business";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const businessMsgActive = businessActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑公司业务",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除公司业务",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchLoginUrlKeyRef = ref(null);
const SearchClientUrlKeyRef = ref(null);
const SearchTemporaryIdKeyRef = ref(null);
const SearchClientIdKeyRef = ref(null);
const SearchClientSecretKeyRef = ref(null);
const SearchNameKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const SelectLevelSearchRef = ref(null);
const SelectStatusSearchRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addBusinessFormRef = ref(null);
const editBusinessFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
salt: "",
login_url: "",
client_url: "",
temporary_id: "",
client_id: "",
client_secret: "",
name: "",
type: "",
level: "",
status: "",
created_at: "",
updated_at: "",
});
const sortOptions = reactive({
created_at: false,
updated_at: false,
});
const tableData = ref([]);
const typeOptions = [
{
value: "0",
label: "B端业务",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "1",
label: "C端业务",
style: "color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
{
value: "2",
label: "通用业务",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
];
const levelOptions = [
{
value: "0",
label: "一般",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "重要",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "2",
label: "紧要",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const statusOptions = [
{
value: "0",
label: "未启动",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "已启动",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "已关闭",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const addData = reactive({
typeOptions,
levelOptions,
statusOptions,
});
const editData = reactive({
typeOptions,
levelOptions,
statusOptions,
});
const showAddForm = () => {
addBusinessFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
businessMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
businessMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
businessMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const remoteSearch = (query, key, timeBefor, model, operateType) => {
const data = {
query: query,
key: key,
timeBefor: timeBefor,
};
$http.post($url.SearchBusiness, data).then((res) => {
if (res.data.code == 200) {
if (model == "edit") {
res.data.business.forEach((element) => {
let created_at = moment
.utc(element.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
editBusinessFormRef.value.remoteSearchRef.options.push({
value: element.temporary_id,
label: element.name + "------" + created_at,
});
});
} else if (model == "add") {
res.data.business.forEach((element) => {
let created_at = moment
.utc(element.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
if (operateType == "single") {
addBusinessFormRef.value.singleAddRef.remoteSearchRef.options.push({
value: element.temporary_id,
label: element.name + "------" + created_at,
});
} else if (operateType == "multiple") {
addBusinessFormRef.value.multipleAddRef.singleAddRef.forEach((item) => {
item.remoteSearchRef.options.push({
value: element.temporary_id,
label: element.name + "------" + created_at,
});
});
}
});
}
} else {
ElMessage.error("无相关数据");
}
});
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const businessMsg = () => {
judgment(searchOptions, "login_url", SearchLoginUrlKeyRef.value, "searchMsg");
judgment(searchOptions, "client_url", SearchClientUrlKeyRef.value, "searchMsg");
judgment(searchOptions, "temporary_id", SearchTemporaryIdKeyRef.value, "searchMsg");
judgment(searchOptions, "client_id", SearchClientIdKeyRef.value, "searchMsg");
judgment(searchOptions, "client_secret", SearchClientSecretKeyRef.value, "searchMsg");
judgment(searchOptions, "name", SearchNameKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "level", SelectLevelSearchRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showBusiness, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.BusinessMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
businessMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
businessMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editBusinessFormRef.value.originForm({ ...singleMsg.data }, { ...editData });
editBusinessFormRef.value.operateDialogVisible = true;
editBusinessFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editBusiness;
model = EditSelectRef.value.model;
password = editBusinessFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteBusiness;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editBusinessFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
businessMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ businessMsg });
watch(searchOptions, (value) => {
businessMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
businessMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = businessMsgActive.pageCount;
dialogSearchVisible.value = businessMsgActive.dialogSearchVisible;
dialogSortVisible.value = businessMsgActive.dialogSortVisible;
dialogOperationVisible.value = businessMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.login_url = businessMsgActive.searchOptions.login_url;
searchOptions.client_url = businessMsgActive.searchOptions.client_url;
searchOptions.temporary_id = businessMsgActive.searchOptions.temporary_id;
searchOptions.client_id = businessMsgActive.searchOptions.client_id;
searchOptions.client_secret = businessMsgActive.searchOptions.client_secret;
searchOptions.name = businessMsgActive.searchOptions.name;
searchOptions.type = businessMsgActive.searchOptions.type;
searchOptions.level = businessMsgActive.searchOptions.level;
searchOptions.status = businessMsgActive.searchOptions.status;
searchOptions.created_at = businessMsgActive.searchOptions.created_at;
searchOptions.updated_at = businessMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
sortOptions.created_at = businessMsgActive.sortOptions.created_at;
sortOptions.updated_at = businessMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
businessMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchLoginUrlKeyRef.value.searchMsg = businessMsgActive.searchOptions.login_url;
SearchClientUrlKeyRef.value.searchMsg = businessMsgActive.searchOptions.client_url;
SearchTemporaryIdKeyRef.value.searchMsg =
businessMsgActive.searchOptions.temporary_id;
SearchClientIdKeyRef.value.searchMsg = businessMsgActive.searchOptions.client_id;
SearchClientSecretKeyRef.value.searchMsg =
businessMsgActive.searchOptions.client_secret;
SearchNameKeyRef.value.searchMsg = businessMsgActive.searchOptions.name;
SelectTypeSearchRef.value.searchMsg = businessMsgActive.searchOptions.type;
SelectLevelSearchRef.value.searchMsg = businessMsgActive.searchOptions.level;
SelectStatusSearchRef.value.searchMsg = businessMsgActive.searchOptions.status;
createdDateTimePickerRef.value.created_at =
businessMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
businessMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = businessMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = businessMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,648 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="accountMsgActive" />
<AddNewData newDataLabel="新增比赛账号" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="120" :column-key="重置密码">
<template #header>
<div>
<el-text class="mx-1"> 重置密码 </el-text>
</div>
</template>
<template #default="scope">
<el-button
style="font-weight: bold"
type="warning"
size="small"
plain="true"
@click="showResetDialog(scope.row.uid)"
>
重置密码
</el-button>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUidKeyRef"
holderText="输入账号uid以搜索相关数据"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 账号uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="contest_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchContestUidKeyRef"
holderText="输入竞赛uid以搜索相关数据"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 竞赛uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账号名称以搜索相关数据"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 账号名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择账号状态以搜索相关数据"
:options="statusOptions"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 账号状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="accountMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="login_status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectLoginStatusSearchRef"
holderText="选择登录状态以搜索相关数据"
:options="loginStatusOptions"
@search="accountMsg"
/>
<div>
<el-text class="mx-1"> 登录状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(loginStatusOptions, scope.row.login_status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(loginStatusOptions, scope.row.login_status) }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="accountMsgActive"
@sizeChangeBack="changePage"
@search="accountMsg"
/>
</div>
</el-card>
<AddAccountForm
ref="addAccountFormRef"
title="新增账号信息"
@reloadData="accountMsg"
/>
<EditAccountForm
ref="editAccountFormRef"
operateLabel="编辑账号信息"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除账号信息"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="resetPasswordOauthRef"
operateLabel="重置账号密码"
@requestOperate="resetAccount"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../../operate/tabelTools.vue";
import AddNewData from "../../operate/addNewData.vue";
import TabelSelect from "../../operate/tabelSelect.vue";
import SearchKey from "../../search/searchKey.vue";
import SortSearch from "../../search/sortSearch.vue";
import SelectSearch from "../../search/selectSearch.vue";
import DateTimePicker from "../../search/dateTimePicker.vue";
import Pagination from "../../search/pagination.vue";
import AddAccountForm from "../../addNewData/contest/accountForm/accountForm.vue";
import EditAccountForm from "../../editData/contest/accountForm.vue";
import PasswordOauth from "../../operate/passwordOauth.vue";
import accountActiveStore from "../../../stores/contest/account";
import moment from "moment";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
import { judgment } from "../../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const accountMsgActive = accountActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑账号信息",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除账号信息",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchUidKeyRef = ref(null);
const SearchContestUidKeyRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SelectStatusSearchRef = ref(null);
const createdDateTimePickerRef = ref(null);
const SelectLoginStatusSearchRef = ref(null);
const createdSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addAccountFormRef = ref(null);
const editAccountFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const resetPasswordOauthRef = ref(null);
const resetAccountUid = ref("");
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
uid: "",
contest_uid: "",
account_name: "",
status: "",
created_at: "",
login_status: "",
});
const sortOptions = reactive({
created_at: false,
});
const tableData = ref([]);
const statusOptions = [
{
value: "0",
label: "准备参赛",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "正在参赛",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "已经结赛",
style:
"color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "3",
label: "已被封禁",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const loginStatusOptions = [
{
value: "0",
label: "未登录",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "已登录",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({
statusOptions,
});
const showAddForm = () => {
addAccountFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
accountMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
accountMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
accountMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const accountMsg = () => {
judgment(searchOptions, "uid", SearchUidKeyRef.value, "searchMsg");
judgment(searchOptions, "contest_uid", SearchContestUidKeyRef.value, "searchMsg");
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_status", SelectLoginStatusSearchRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showAccount, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.accountMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
accountMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
accountMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editAccountFormRef.value.accountForm({ ...singleMsg.data });
editAccountFormRef.value.operateDialogVisible = true;
editAccountFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const showResetDialog = (uid) => {
resetAccountUid.value = uid;
resetPasswordOauthRef.value.operateDialogVisible = true;
};
const resetAccount = () => {
const data = {
account_uid: encrypt(resetAccountUid.value),
password: encrypt(resetPasswordOauthRef.value.ruleForm.password),
};
$http.post($url.resetAccount, data).then((res) => {
resetAccountUid.value = "";
if (res.data.code === 200) {
ElMessage({
message: "重置账号密码成功!",
type: "success",
});
} else {
ElMessage.error("重置账号密码失败!");
}
});
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editAccount;
model = EditSelectRef.value.model;
password = editAccountFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.delAccount;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editAccountFormRef.value.ruleForm };
data.updateMsg.status = Number(data.updateMsg.status.value);
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
accountMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ accountMsg });
watch(searchOptions, (value) => {
accountMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
accountMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = accountMsgActive.pageCount;
dialogSearchVisible.value = accountMsgActive.dialogSearchVisible;
dialogSortVisible.value = accountMsgActive.dialogSortVisible;
dialogOperationVisible.value = accountMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.uid = accountMsgActive.searchOptions.uid;
searchOptions.contest_uid = accountMsgActive.searchOptions.contest_uid;
searchOptions.account_name = accountMsgActive.searchOptions.account_name;
searchOptions.status = accountMsgActive.searchOptions.status;
searchOptions.created_at = accountMsgActive.searchOptions.created_at;
searchOptions.login_status = accountMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
sortOptions.created_at = accountMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
accountMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchUidKeyRef.value.searchMsg = accountMsgActive.searchOptions.uid;
SearchContestUidKeyRef.value.searchMsg = accountMsgActive.searchOptions.contest_uid;
SearchAccountNameKeyRef.value.searchMsg =
accountMsgActive.searchOptions.account_name;
SelectStatusSearchRef.value.searchMsg = accountMsgActive.searchOptions.status;
createdDateTimePickerRef.value.created_at =
accountMsgActive.searchOptions.created_at;
SelectLoginStatusSearchRef.value.searchMsg =
accountMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = accountMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,538 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="choiceTopicMsgActive" />
<AddNewData newDataLabel="新增单选题" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
singleType="single"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="200" column-key="topic">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchTopicKeyRef"
holderText="输入题目以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 题目 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.topic }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="options_a">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOptionsAKeyRef"
holderText="输入选项A以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 选项A </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.options_a }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="options_b">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOptionsBKeyRef"
holderText="输入选项B以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 选项B </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.options_b }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="options_c">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOptionsCKeyRef"
holderText="输入选项C以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 选项C </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.options_c }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="options_d">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOptionsDKeyRef"
holderText="输入选项D以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 选项D </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.options_d }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="answer">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAnswerKeyRef"
holderText="输入答案以搜索相关数据"
@search="choiceTopicMsg"
/>
<div>
<el-text class="mx-1"> 答案 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.answer }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="choiceTopicMsgActive"
@sizeChangeBack="changePage"
@search="choiceTopicMsg"
/>
</div>
</el-card>
<AddChoiceTopicForm
ref="addChoiceTopicFormRef"
title="新增单选题"
@reloadData="choiceTopicMsg"
/>
<EditChoiceTopicForm
ref="editChoiceTopicFormRef"
operateLabel="编辑单选题"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除单选题"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../../operate/tabelTools.vue";
import AddNewData from "../../operate/addNewData.vue";
import TabelSelect from "../../operate/tabelSelect.vue";
import SearchKey from "../../search/searchKey.vue";
import Pagination from "../../search/pagination.vue";
import AddChoiceTopicForm from "../../addNewData/contest/choiceTopicForm/choiceTopicForm.vue";
import EditChoiceTopicForm from "../../editData/contest/choiceTopicForm.vue";
import PasswordOauth from "../../operate/passwordOauth.vue";
import choiceTopicActiveStore from "../../../stores/contest/choiceTopic";
import moment from "moment";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
import { judgment } from "../../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const choiceTopicMsgActive = choiceTopicActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑单选题",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除单选题",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchTopicKeyRef = ref(null);
const SearchOptionsAKeyRef = ref(null);
const SearchOptionsBKeyRef = ref(null);
const SearchOptionsCKeyRef = ref(null);
const SearchOptionsDKeyRef = ref(null);
const SearchAnswerKeyRef = ref(null);
const PaginationRef = ref(null);
const addChoiceTopicFormRef = ref(null);
const editChoiceTopicFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
topic: "",
options_a: "",
options_b: "",
options_c: "",
options_d: "",
answer: "",
});
const sortOptions = reactive({});
const tableData = ref([]);
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({});
const showAddForm = () => {
addChoiceTopicFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
choiceTopicMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
choiceTopicMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
choiceTopicMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const choiceTopicMsg = () => {
judgment(searchOptions, "topic", SearchTopicKeyRef.value, "searchMsg");
judgment(searchOptions, "options_a", SearchOptionsAKeyRef.value, "searchMsg");
judgment(searchOptions, "options_b", SearchOptionsBKeyRef.value, "searchMsg");
judgment(searchOptions, "options_c", SearchOptionsCKeyRef.value, "searchMsg");
judgment(searchOptions, "options_d", SearchOptionsDKeyRef.value, "searchMsg");
judgment(searchOptions, "answer", SearchAnswerKeyRef.value, "searchMsg");
resetOffset();
const data = {
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showChoiceTopic, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.choiceTopicMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
choiceTopicMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
choiceTopicMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editChoiceTopicFormRef.value.choiceTopicForm({ ...singleMsg.data });
editChoiceTopicFormRef.value.operateDialogVisible = true;
editChoiceTopicFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editChoiceTopic;
model = EditSelectRef.value.model;
password = editChoiceTopicFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.delChoiceTopic;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editChoiceTopicFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
choiceTopicMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ choiceTopicMsg });
watch(searchOptions, (value) => {
choiceTopicMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
choiceTopicMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = choiceTopicMsgActive.pageCount;
dialogSearchVisible.value = choiceTopicMsgActive.dialogSearchVisible;
dialogSortVisible.value = choiceTopicMsgActive.dialogSortVisible;
dialogOperationVisible.value = choiceTopicMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.topic = choiceTopicMsgActive.searchOptions.topic;
searchOptions.options_a = choiceTopicMsgActive.searchOptions.options_a;
searchOptions.options_b = choiceTopicMsgActive.searchOptions.options_b;
searchOptions.options_c = choiceTopicMsgActive.searchOptions.options_c;
searchOptions.options_d = choiceTopicMsgActive.searchOptions.options_d;
searchOptions.answer = choiceTopicMsgActive.searchOptions.answer;
}
if (dialogSortVisible.value) {
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
choiceTopicMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchTopicKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.topic;
SearchOptionsAKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.options_a;
SearchOptionsBKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.options_b;
SearchOptionsCKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.options_c;
SearchOptionsDKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.options_d;
SearchAnswerKeyRef.value.searchMsg = choiceTopicMsgActive.searchOptions.answer;
}
if (dialogSortVisible.value) {
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,928 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="contestMsgActive" />
<AddNewData newDataLabel="新增竞赛" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
singleType="single"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUidKeyRef"
holderText="输入竞赛uid以搜索相关数据"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="contest_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchContestNameKeyRef"
holderText="输入竞赛名称以搜索相关数据"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="contest_organizers">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearcContestOrganizersKeyRef"
holderText="输入竞赛主办方以搜索相关数据"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛主办方 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_organizers }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="contest_term">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchContestTermKeyRef"
holderText="输入竞赛届数以搜索相关数据"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛届数 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_term }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择竞赛类型以搜索相关数据"
:options="typeOptions"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择举办状态以搜索相关数据"
:options="statusOptions"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 举办状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="online_start">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="onlineStartDateTimePickerRef"
DateTimePicker="onlineStartMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 线上赛开始时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="onlineStartSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.online_start }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="online_end">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="onlineEndDateTimePickerRef"
DateTimePicker="onlineEndMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 线上赛结束时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="onlineEndSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.online_end }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="offline_start">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="offlineStartDateTimePickerRef"
DateTimePicker="offlineStartMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 线下赛开始时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="offlineStartSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.offline_start }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="offline_end">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="offlineEndDateTimePickerRef"
DateTimePicker="offlineEndMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 线下赛结束时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="offlineEndSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.offline_end }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="contest_start">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="contestStartDateTimePickerRef"
DateTimePicker="contestStartMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛开始时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="contestStartSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_start }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="contest_end">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="contestEndDateTimePickerRef"
DateTimePicker="contestEndMsgDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 竞赛结束时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="contestEndSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_end }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="contestMsg"
/>
<div>
<el-text class="mx-1"> 创建时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="contestMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="contestMsgActive"
@sizeChangeBack="changePage"
@search="contestMsg"
/>
</div>
</el-card>
<AddContestForm
ref="addContestFormRef"
title="新增竞赛"
:addData="addData"
@reloadData="contestMsg"
/>
<EditContestForm
ref="editContestFormRef"
operateLabel="编辑竞赛"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除竞赛"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../../operate/tabelTools.vue";
import AddNewData from "../../operate/addNewData.vue";
import TabelSelect from "../../operate/tabelSelect.vue";
import SearchKey from "../../search/searchKey.vue";
import SortSearch from "../../search/sortSearch.vue";
import SelectSearch from "../../search/selectSearch.vue";
import DateTimePicker from "../../search/dateTimePicker.vue";
import Pagination from "../../search/pagination.vue";
import AddContestForm from "../../addNewData/contest/contestForm/contestForm.vue";
import EditContestForm from "../../editData/contest/contestForm.vue";
import PasswordOauth from "../../operate/passwordOauth.vue";
import contestActiveStore from "../../../stores/contest/contest";
import moment from "moment";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
import { judgment } from "../../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const contestMsgActive = contestActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑竞赛",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除竞赛",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchUidKeyRef = ref(null);
const SearchContestNameKeyRef = ref(null);
const SearchContestOrganizersKeyRef = ref(null);
const SearchContestTermKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const SelectStatusSearchRef = ref(null);
const onlineStartDateTimePickerRef = ref(null);
const onlineEndDateTimePickerRef = ref(null);
const offlineStartDateTimePickerRef = ref(null);
const offlineEndDateTimePickerRef = ref(null);
const contestStartDateTimePickerRef = ref(null);
const contestEndDateTimePickerRef = ref(null);
const createdDateTimePickerRef = ref(null);
const onlineStartSortDateTimeRef = ref(null);
const onlineEndSortDateTimeRef = ref(null);
const offlineStartSortDateTimeRef = ref(null);
const offlineEndSortDateTimeRef = ref(null);
const contestStartSortDateTimeRef = ref(null);
const contestEndSortDateTimeRef = ref(null);
const createdSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addContestFormRef = ref(null);
const editContestFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
uid: "",
contest_name: "",
contest_organizers: "",
contest_term: "",
type: "",
status: "",
online_start: "",
online_end: "",
offline_start: "",
offline_end: "",
contest_start: "",
contest_end: "",
created_at: "",
});
const sortOptions = reactive({
online_start: false,
online_end: false,
offline_start: false,
offline_end: false,
contest_start: false,
contest_end: false,
created_at: false,
});
const tableData = ref([]);
const typeOptions = [
{
value: "0",
label: "线上赛",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "线下赛",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
const statusOptions = [
{
value: "0",
label: "准备开赛",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "正在进行",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "已经结赛",
style:
"color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "3",
label: "停止举办",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const addData = reactive({
typeOptions,
});
const editData = reactive({
typeOptions,
statusOptions,
});
const showAddForm = () => {
addContestFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
contestMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
contestMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
contestMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const contestMsg = () => {
judgment(searchOptions, "uid", SearchUidKeyRef.value, "searchMsg");
judgment(searchOptions, "contest_name", SearchContestNameKeyRef.value, "searchMsg");
judgment(
searchOptions,
"contest_organizers",
SearchContestOrganizersKeyRef.value,
"searchMsg"
);
judgment(searchOptions, "contest_term", SearchContestTermKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(
searchOptions,
"online_start",
onlineStartDateTimePickerRef.value,
"searchMsg"
);
judgment(searchOptions, "online_end", onlineEndDateTimePickerRef.value, "searchMsg");
judgment(
searchOptions,
"offline_start",
offlineStartDateTimePickerRef.value,
"searchMsg"
);
judgment(searchOptions, "offline_end", offlineEndDateTimePickerRef.value, "searchMsg");
judgment(
searchOptions,
"contest_start",
contestStartDateTimePickerRef.value,
"searchMsg"
);
judgment(searchOptions, "contest_end", contestEndDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "online_start", onlineStartSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "online_end", onlineEndSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "offline_start", offlineStartSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "offline_end", offlineEndSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "contest_start", contestStartSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "contest_end", contestEndSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showContest, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.contestMsg;
tableData.value.forEach((item) => {
item.origin_onlineStart = item.online_start;
item.online_start = moment
.utc(item.online_start)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_onlineEnd = item.online_end;
item.online_end = moment
.utc(item.online_end)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_offlineStart = item.offline_start;
item.offline_start = moment
.utc(item.offline_start)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_offlineEnd = item.offline_end;
item.offline_end = moment
.utc(item.offline_end)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_contestStart = item.contest_start;
item.contest_start = moment
.utc(item.contest_start)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_contestEnd = item.contest_end;
item.contest_end = moment
.utc(item.contest_end)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
contestMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
contestMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_onlineStart) {
item.online_start = item.origin_onlineStart;
}
if (item.origin_onlineEnd) {
item.online_end = item.origin_onlineEnd;
}
if (item.origin_offlineStart) {
item.offline_start = item.origin_offlineStart;
}
if (item.origin_offlineEnd) {
item.offline_end = item.origin_offlineEnd;
}
if (item.origin_contestStart) {
item.contest_start = item.origin_contestStart;
}
if (item.origin_contestEnd) {
item.contest_end = item.origin_contestEnd;
}
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
delete item.origin_onlineStart;
delete item.origin_onlineEnd;
delete item.origin_offlineStart;
delete item.origin_offlineEnd;
delete item.origin_contestStart;
delete item.origin_contestEnd;
delete item.origin_createdAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.online_start = singleData.origin_onlineStart;
singleData.online_end = singleData.origin_onlineEnd;
singleData.offline_start = singleData.origin_offlineStart;
singleData.offline_end = singleData.origin_offlineEnd;
singleData.contest_start = singleData.origin_contestStart;
singleData.contest_end = singleData.origin_contestEnd;
singleData.created_at = singleData.origin_createdAt;
if (singleMsg.operateType == "edit") {
editContestFormRef.value.contestForm({ ...singleMsg.data });
editContestFormRef.value.operateDialogVisible = true;
editContestFormRef.value.model = EditSelectRef.value.model;
}
delete singleData.origin_onlineStart;
delete singleData.origin_onlineEnd;
delete singleData.origin_offlineStart;
delete singleData.origin_offlineEnd;
delete singleData.origin_contestStart;
delete singleData.origin_contestEnd;
delete singleData.origin_createdAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editContest;
model = EditSelectRef.value.model;
password = editContestFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.delContest;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editContestFormRef.value.ruleForm };
data.updateMsg.type = Number(data.updateMsg.type.value);
data.updateMsg.status = Number(data.updateMsg.status.value);
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
contestMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ contestMsg });
watch(searchOptions, (value) => {
contestMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
contestMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = contestMsgActive.pageCount;
dialogSearchVisible.value = contestMsgActive.dialogSearchVisible;
dialogSortVisible.value = contestMsgActive.dialogSortVisible;
dialogOperationVisible.value = contestMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.uid = contestMsgActive.searchOptions.uid;
searchOptions.contest_name = contestMsgActive.searchOptions.contest_name;
searchOptions.contest_organizers = contestMsgActive.searchOptions.contest_organizers;
searchOptions.contest_term = contestMsgActive.searchOptions.contest_term;
searchOptions.type = contestMsgActive.searchOptions.type;
searchOptions.status = contestMsgActive.searchOptions.status;
searchOptions.online_start = contestMsgActive.searchOptions.online_start;
searchOptions.online_end = contestMsgActive.searchOptions.online_end;
searchOptions.offline_start = contestMsgActive.searchOptions.offline_start;
searchOptions.offline_end = contestMsgActive.searchOptions.offline_end;
searchOptions.contest_start = contestMsgActive.searchOptions.contest_start;
searchOptions.contest_end = contestMsgActive.searchOptions.contest_end;
searchOptions.created_at = contestMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
sortOptions.online_start = contestMsgActive.sortOptions.online_start;
sortOptions.online_end = contestMsgActive.sortOptions.online_end;
sortOptions.offline_start = contestMsgActive.sortOptions.offline_start;
sortOptions.offline_end = contestMsgActive.sortOptions.offline_end;
sortOptions.contest_start = contestMsgActive.sortOptions.contest_start;
sortOptions.contest_end = contestMsgActive.sortOptions.contest_end;
sortOptions.created_at = contestMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
contestMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchUidKeyRef.value.searchMsg = contestMsgActive.searchOptions.uid;
SearchContestNameKeyRef.value.searchMsg =
contestMsgActive.searchOptions.contest_name;
SearchContestOrganizersKeyRef.value.searchMsg =
contestMsgActive.searchOptions.contest_organizers;
SearchContestTermKeyRef.value.searchMsg =
contestMsgActive.searchOptions.contest_term;
SelectTypeSearchRef.value.searchMsg = contestMsgActive.searchOptions.type;
SelectStatusSearchRef.value.searchMsg = contestMsgActive.searchOptions.status;
onlineStartDateTimePickerRef.value.online_start =
contestMsgActive.searchOptions.online_start;
onlineEndDateTimePickerRef.value.online_end =
contestMsgActive.searchOptions.online_end;
offlineStartDateTimePickerRef.value.offline_start =
contestMsgActive.searchOptions.offline_start;
offlineEndDateTimePickerRef.value.offline_end =
contestMsgActive.searchOptions.offline_end;
contestStartDateTimePickerRef.value.contest_start =
contestMsgActive.searchOptions.contest_start;
contestEndDateTimePickerRef.value.contest_end =
contestMsgActive.searchOptions.contest_end;
createdDateTimePickerRef.value.created_at =
contestMsgActive.searchOptions.created_at;
}
if (dialogSortVisible.value) {
onlineStartSortDateTimeRef.value.searchMsg =
contestMsgActive.sortOptions.online_start;
onlineEndSortDateTimeRef.value.searchMsg = contestMsgActive.sortOptions.online_end;
offlineStartSortDateTimeRef.value.searchMsg =
contestMsgActive.sortOptions.offline_start;
offlineEndSortDateTimeRef.value.searchMsg =
contestMsgActive.sortOptions.offline_end;
contestStartSortDateTimeRef.value.searchMsg =
contestMsgActive.sortOptions.contest_start;
contestEndSortDateTimeRef.value.searchMsg =
contestMsgActive.sortOptions.contest_end;
createdSortDateTimeRef.value.searchMsg = contestMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,643 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="examinationMsgActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="user_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserUidKeyRef"
holderText="输入账号uid以搜索相关数据"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 账号uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="contest_uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchContestUidKeyRef"
holderText="输入竞赛uid以搜索相关数据"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 竞赛uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.contest_uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="exam_type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectExamTypeSearchRef"
holderText="选择竞赛类型以搜索相关数据"
:options="examTypeOptions"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 竞赛类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(examTypeOptions, scope.row.exam_type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(examTypeOptions, scope.row.exam_type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="topic_type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTopicTypeSearchRef"
holderText="选择题目类型以搜索相关数据"
:options="topicTypeOptions"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 题目类型 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(topicTypeOptions, scope.row.topic_type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(topicTypeOptions, scope.row.topic_type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="score">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchScoreKeyRef"
holderText="输入得分以搜索相关数据"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 得分 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="SortScoreRef"
activeText="顺序"
inactiveText="倒序"
@search="examinationMsg"
/>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.score }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 开始答题时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="examinationMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="examinationMsg"
/>
<div>
<el-text class="mx-1"> 结束答题时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="examinationMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="examinationMsgActive"
@sizeChangeBack="changePage"
@search="examinationMsg"
/>
</div>
</el-card>
<EditExaminationForm
ref="editExaminationFormRef"
operateLabel="编辑答题信息"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除答题信息"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../../operate/tabelTools.vue";
import AddNewData from "../../operate/addNewData.vue";
import TabelSelect from "../../operate/tabelSelect.vue";
import SearchKey from "../../search/searchKey.vue";
import SortSearch from "../../search/sortSearch.vue";
import SelectSearch from "../../search/selectSearch.vue";
import DateTimePicker from "../../search/dateTimePicker.vue";
import Pagination from "../../search/pagination.vue";
import EditExaminationForm from "../../editData/contest/examinationForm.vue";
import PasswordOauth from "../../operate/passwordOauth.vue";
import examinationActiveStore from "../../../stores/contest/examination";
import moment from "moment";
import $http from "../../../api/index";
import $url from "../../../api/url";
import { encrypt } from "../../../utils/aes";
import { judgment } from "../../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const examinationMsgActive = examinationActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑答题信息",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除答题信息",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchUserUidKeyRef = ref(null);
const SearchContestUidKeyRef = ref(null);
const SelectExamTypeSearchRef = ref(null);
const SelectTopicTypeSearchRef = ref(null);
const SearchScoreKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const SortScoreRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const editExaminationFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
user_uid: "",
contest_uid: "",
exam_type: "",
topic_type: "",
score: "",
created_at: "",
updated_at: "",
});
const sortOptions = reactive({
score: false,
created_at: false,
updated_at: false,
});
const tableData = ref([]);
const examTypeOptions = [
{
value: "0",
label: "线上赛",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "线下赛",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
const topicTypeOptions = [
{
value: "1",
label: "题目一",
style:
"color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "题目二",
style:
"color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "3",
label: "题目三",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
{
value: "4",
label: "题目四",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "5",
label: "题目五",
style:
"color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({
examTypeOptions,
topicTypeOptions,
});
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
examinationMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
examinationMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
examinationMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const examinationMsg = () => {
judgment(searchOptions, "user_uid", SearchUserUidKeyRef.value, "searchMsg");
judgment(searchOptions, "contest_uid", SearchContestUidKeyRef.value, "searchMsg");
judgment(searchOptions, "exam_type", SelectExamTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "topic_type", SelectTopicTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "score", SearchScoreKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "score", SortScoreRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showExamination, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.examinationMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
examinationMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
examinationMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editExaminationFormRef.value.examinationForm({ ...singleMsg.data });
editExaminationFormRef.value.operateDialogVisible = true;
editExaminationFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editExamination;
model = EditSelectRef.value.model;
password = editExaminationFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.delExamination;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editExaminationFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
examinationMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ examinationMsg });
watch(searchOptions, (value) => {
examinationMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
examinationMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = examinationMsgActive.pageCount;
dialogSearchVisible.value = examinationMsgActive.dialogSearchVisible;
dialogSortVisible.value = examinationMsgActive.dialogSortVisible;
dialogOperationVisible.value = examinationMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.user_uid = examinationMsgActive.searchOptions.user_uid;
searchOptions.contest_uid = examinationMsgActive.searchOptions.contest_uid;
searchOptions.exam_type = examinationMsgActive.searchOptions.exam_type;
searchOptions.topic_type = examinationMsgActive.searchOptions.topic_type;
searchOptions.score = examinationMsgActive.searchOptions.score;
searchOptions.created_at = examinationMsgActive.searchOptions.created_at;
searchOptions.updated_at = examinationMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
sortOptions.score = examinationMsgActive.sortOptions.score;
sortOptions.created_at = examinationMsgActive.sortOptions.created_at;
sortOptions.updated_at = examinationMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
examinationMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchUserUidKeyRef.value.searchMsg = examinationMsgActive.searchOptions.user_uid;
SearchContestUidKeyRef.value.searchMsg =
examinationMsgActive.searchOptions.contest_uid;
SelectExamTypeSearchRef.value.searchMsg =
examinationMsgActive.searchOptions.exam_type;
SelectTopicTypeSearchRef.value.searchMsg =
examinationMsgActive.searchOptions.topic_type;
SearchScoreKeyRef.value.searchMsg = examinationMsgActive.searchOptions.score;
createdDateTimePickerRef.value.created_at =
examinationMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
examinationMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
SortScoreRef.value.searchMsg = examinationMsgActive.sortOptions.score;
createdSortDateTimeRef.value.searchMsg =
examinationMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg =
examinationMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,850 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="csideMsgActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="100" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择账号状态以搜索相关数据"
:options="statusOptions"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 账号状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="role">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectRoleSearchRef"
holderText="选择账号角色以搜索相关数据"
:options="roleOptions"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 账号角色 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(roleOptions, scope.row.role)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(roleOptions, scope.row.role) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="account_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAccountNameKeyRef"
holderText="输入账号名称以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 账号名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.account_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="user_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserNameKeyRef"
holderText="输入用户姓名以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 用户姓名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="phone">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchPhoneKeyRef"
holderText="输入手机号码以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 手机号码 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.phone }}
</div>
</template>
</el-table-column>
<el-table-column min-width="60" column-key="gender">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectGenderSearchRef"
holderText="选择性别以搜索相关数据"
:options="genderOptions"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 性别 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(genderOptions, scope.row.gender)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(genderOptions, scope.row.gender) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="60" column-key="age">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAgeKeyRef"
holderText="输入年龄以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 年龄 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="SortAgeRef"
activeText="顺序"
inactiveText="倒序"
@search="csideMsg"
/>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.age }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="email">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchEmailKeyRef"
holderText="输入电子邮箱以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 电子邮箱 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.email }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="address">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAddressKeyRef"
holderText="输入通信地址以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 通信地址 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.address }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="post_code">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchPostCodeKeyRef"
holderText="输入邮政编码以搜索相关数据"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 邮政编码 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.post_code }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="csideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 账号信息变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="csideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="login_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="loginDateTimePickerRef"
DateTimePicker="loginMsgDateTimePicker"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 上次登录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="loginSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="csideMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.login_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="login_status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectLoginStatusSearchRef"
holderText="选择登录状态以搜索相关数据"
:options="loginStatusOptions"
@search="csideMsg"
/>
<div>
<el-text class="mx-1"> 登录状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(loginStatusOptions, scope.row.login_status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(loginStatusOptions, scope.row.login_status) }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="csideMsgActive"
@sizeChangeBack="changePage"
@search="csideMsg"
/>
</div>
</el-card>
<EditCsideForm
ref="editCsideFormRef"
operateLabel="编辑C端用户"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除C端用户"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import EditCsideForm from "../editData/csideForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import csideActiveStore from "../../stores/cside";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const csideMsgActive = csideActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑C端用户",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除C端用户",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SelectStatusSearchRef = ref(null);
const SelectRoleSearchRef = ref(null);
const SearchAccountNameKeyRef = ref(null);
const SearchUserNameKeyRef = ref(null);
const SearchPhoneKeyRef = ref(null);
const SelectGenderSearchRef = ref(null);
const SearchAgeKeyRef = ref(null);
const SearchEmailKeyRef = ref(null);
const SearchAddressKeyRef = ref(null);
const SearchPostCodeKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const loginDateTimePickerRef = ref(null);
const SelectLoginStatusSearchRef = ref(null);
const SortAgeRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const loginSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const editCsideFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
status: "",
role: "",
account_name: "",
user_name: "",
phone: "",
gender: "",
age: "",
email: "",
address: "",
post_code: "",
created_at: "",
updated_at: "",
login_at: "",
login_status: "",
});
const sortOptions = reactive({
age: false,
created_at: false,
updated_at: false,
login_at: false,
});
const tableData = ref([]);
const statusOptions = [
{
value: "0",
label: "默认",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "正在使用",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "封禁",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const roleOptions = [
{
value: "0",
label: "普通用户",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "特殊用户",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
];
const genderOptions = [
{
value: "0",
label: "女",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "1",
label: "男",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
];
const loginStatusOptions = [
{
value: "0",
label: "未登录",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "已登录",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const editData = reactive({
statusOptions,
roleOptions,
});
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
csideMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
csideMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
csideMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const csideMsg = () => {
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "role", SelectRoleSearchRef.value, "searchMsg");
judgment(searchOptions, "account_name", SearchAccountNameKeyRef.value, "searchMsg");
judgment(searchOptions, "user_name", SearchUserNameKeyRef.value, "searchMsg");
judgment(searchOptions, "phone", SearchPhoneKeyRef.value, "searchMsg");
judgment(searchOptions, "gender", SelectGenderSearchRef.value, "searchMsg");
judgment(searchOptions, "age", SearchAgeKeyRef.value, "searchMsg");
judgment(searchOptions, "email", SearchEmailKeyRef.value, "searchMsg");
judgment(searchOptions, "address", SearchAddressKeyRef.value, "searchMsg");
judgment(searchOptions, "post_code", SearchPostCodeKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_at", loginDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_status", SelectLoginStatusSearchRef.value, "searchMsg");
judgment(sortOptions, "age", SortAgeRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "login_at", loginSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showCSide, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.CSideMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_loginAt = item.login_at;
item.login_at = moment
.utc(item.login_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
csideMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
csideMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
if (item.origin_loginAt) {
item.created_at = item.origin_loginAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.origin_loginAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
singleData.login_at = singleData.origin_loginAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
delete singleData.origin_loginAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editCsideFormRef.value.operateDialogVisible = true;
editCsideFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editCSide;
model = EditSelectRef.value.model;
password = editCsideFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteCSide;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editCsideFormRef.value.ruleForm };
for (const element in data.updateMsg) {
if (data.updateMsg[element] == "") {
delete data.updateMsg[element];
}
}
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
csideMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ csideMsg });
watch(searchOptions, (value) => {
csideMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
csideMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = csideMsgActive.pageCount;
dialogSearchVisible.value = csideMsgActive.dialogSearchVisible;
dialogSortVisible.value = csideMsgActive.dialogSortVisible;
dialogOperationVisible.value = csideMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.status = csideMsgActive.searchOptions.status;
searchOptions.role = csideMsgActive.searchOptions.role;
searchOptions.account_name = csideMsgActive.searchOptions.account_name;
searchOptions.user_name = csideMsgActive.searchOptions.user_name;
searchOptions.phone = csideMsgActive.searchOptions.phone;
searchOptions.gender = csideMsgActive.searchOptions.gender;
searchOptions.age = csideMsgActive.searchOptions.age;
searchOptions.email = csideMsgActive.searchOptions.email;
searchOptions.address = csideMsgActive.searchOptions.address;
searchOptions.post_code = csideMsgActive.searchOptions.post_code;
searchOptions.created_at = csideMsgActive.searchOptions.created_at;
searchOptions.updated_at = csideMsgActive.searchOptions.updated_at;
searchOptions.login_at = csideMsgActive.searchOptions.login_at;
searchOptions.login_status = csideMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
sortOptions.age = csideMsgActive.sortOptions.age;
sortOptions.created_at = csideMsgActive.sortOptions.created_at;
sortOptions.updated_at = csideMsgActive.sortOptions.updated_at;
sortOptions.login_at = csideMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
csideMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SelectStatusSearchRef.value.searchMsg = csideMsgActive.searchOptions.status;
SelectStatusSearchRef.value.searchMsg = csideMsgActive.searchOptions.role;
SearchAccountNameKeyRef.value.searchMsg = csideMsgActive.searchOptions.account_name;
SearchUserNameKeyRef.value.searchMsg = csideMsgActive.searchOptions.user_name;
SearchPhoneKeyRef.value.searchMsg = csideMsgActive.searchOptions.phone;
SelectStatusSearchRef.value.searchMsg = csideMsgActive.searchOptions.gender;
SearchAgeKeyRef.value.searchMsg = csideMsgActive.searchOptions.age;
SearchEmailKeyRef.value.searchMsg = csideMsgActive.searchOptions.email;
SearchAddressKeyRef.value.searchMsg = csideMsgActive.searchOptions.address;
SearchPostCodeKeyRef.value.searchMsg = csideMsgActive.searchOptions.post_code;
createdDateTimePickerRef.value.created_at = csideMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at = csideMsgActive.searchOptions.updated_at;
loginDateTimePickerRef.value.login_at = csideMsgActive.searchOptions.login_at;
SelectStatusSearchRef.value.searchMsg = csideMsgActive.searchOptions.login_status;
}
if (dialogSortVisible.value) {
SortAgeRef.value.searchMsg = csideMsgActive.sortOptions.age;
createdSortDateTimeRef.value.searchMsg = csideMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = csideMsgActive.sortOptions.updated_at;
loginSortDateTimeRef.value.searchMsg = csideMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,750 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="insidersMsgActive" />
<AddNewData newDataLabel="新增公司员工" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="140" column-key="uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUidKeyRef"
holderText="输入员工uid以搜索相关数据"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 员工uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择账号状态以搜索相关数据"
:options="statusOptions"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 账号状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="role">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectRoleSearchRef"
holderText="选择账号角色以搜索相关数据"
:options="roleOptions"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 账号角色 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(roleOptions, scope.row.role)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(roleOptions, scope.row.role) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchNameKeyRef"
holderText="输入员工姓名以搜索相关数据"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 员工姓名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="department">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchDepartmentKeyRef"
holderText="输入所属部门以搜索相关数据"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 所属部门 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.department }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="change">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchChangeKeyRef"
holderText="输入信息变更描述以搜索相关数据"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 信息变更描述 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.change }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 注册时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="insidersMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 信息变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="insidersMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="login_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="loginDateTimePickerRef"
DateTimePicker="loginMsgDateTimePicker"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 上次登录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="loginSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="insidersMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.login_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="login_status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectLoginStatusSearchRef"
holderText="选择登录状态以搜索相关数据"
:options="loginStatusOptions"
@search="insidersMsg"
/>
<div>
<el-text class="mx-1"> 登录状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(loginStatusOptions, scope.row.login_status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(loginStatusOptions, scope.row.login_status) }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="insidersMsgActive"
@sizeChangeBack="changePage"
@search="insidersMsg"
/>
</div>
</el-card>
<AddInsidersForm
ref="addInsidersFormRef"
title="新增公司员工"
:addData="addData"
@reloadData="insidersMsg"
/>
<EditInsidersForm
ref="editInsidersFormRef"
operateLabel="编辑公司员工"
:editData="editData"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除公司员工"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddInsidersForm from "../addNewData/insidersForm/insidersForm.vue";
import EditInsidersForm from "../editData/insidersForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import insidersActiveStore from "../../stores/insiders";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const insidersMsgActive = insidersActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑公司员工",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除公司员工",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchUidKeyRef = ref(null);
const SelectStatusSearchRef = ref(null);
const SelectRoleSearchRef = ref(null);
const SearchNameKeyRef = ref(null);
const SearchDepartmentKeyRef = ref(null);
const SearchChangeKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const loginDateTimePickerRef = ref(null);
const SelectLoginStatusSearchRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const loginSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addInsidersFormRef = ref(null);
const editInsidersFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
uid: "",
status: "",
role: "",
name: "",
department: "",
change: "",
created_at: "",
updated_at: "",
login_at: "",
login_status: "",
});
const sortOptions = reactive({
created_at: false,
updated_at: false,
login_at: false,
});
const tableData = ref([]);
const statusOptions = [
{
value: "0",
label: "默认",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "正在使用",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "2",
label: "已弃用",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const roleOptions = [
{
value: "0",
label: "临时员工",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "3",
label: "普通员工",
style: "color: rgb(255, 120, 20);background-color: rgba(255, 120, 20, 0.1);padding: 0;",
},
{
value: "6",
label: "普通管理员",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "9",
label: "高级管理员",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const loginStatusOptions = [
{
value: "0",
label: "未登录",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "1",
label: "已登录",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const addData = reactive({
roleOptions,
});
const editData = reactive({
statusOptions,
roleOptions,
});
const showAddForm = () => {
addInsidersFormRef.value.dialogVisible = true;
};
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
insidersMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
insidersMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
insidersMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const insidersMsg = () => {
judgment(searchOptions, "uid", SearchUidKeyRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "role", SelectRoleSearchRef.value, "searchMsg");
judgment(searchOptions, "name", SearchNameKeyRef.value, "searchMsg");
judgment(searchOptions, "department", SearchDepartmentKeyRef.value, "searchMsg");
judgment(searchOptions, "change", SearchChangeKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "login_at", loginDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "login_at", loginSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showInsiders, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.InsidersMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_loginAt = item.login_at;
item.login_at = moment
.utc(item.login_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
insidersMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
insidersMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
if (item.origin_loginAt) {
item.created_at = item.origin_loginAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.origin_loginAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
singleData.login_at = singleData.origin_loginAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
delete singleData.origin_loginAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editInsidersFormRef.value.operateDialogVisible = true;
editInsidersFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editInsiders;
model = EditSelectRef.value.model;
password = editInsidersFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteInsiders;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editInsidersFormRef.value.ruleForm };
for (const element in data.updateMsg) {
if (data.updateMsg[element] == "") {
delete data.updateMsg[element];
}
}
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
insidersMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ insidersMsg });
watch(searchOptions, (value) => {
insidersMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
insidersMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = insidersMsgActive.pageCount;
dialogSearchVisible.value = insidersMsgActive.dialogSearchVisible;
dialogSortVisible.value = insidersMsgActive.dialogSortVisible;
dialogOperationVisible.value = insidersMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.uid = insidersMsgActive.searchOptions.uid;
searchOptions.status = insidersMsgActive.searchOptions.status;
searchOptions.role = insidersMsgActive.searchOptions.role;
searchOptions.name = insidersMsgActive.searchOptions.name;
searchOptions.department = insidersMsgActive.searchOptions.department;
searchOptions.change = insidersMsgActive.searchOptions.change;
searchOptions.created_at = insidersMsgActive.searchOptions.created_at;
searchOptions.updated_at = insidersMsgActive.searchOptions.updated_at;
searchOptions.login_at = insidersMsgActive.searchOptions.login_at;
}
if (dialogSortVisible.value) {
sortOptions.created_at = insidersMsgActive.sortOptions.created_at;
sortOptions.updated_at = insidersMsgActive.sortOptions.updated_at;
sortOptions.login_at = insidersMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
insidersMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchUidKeyRef.value.searchMsg = insidersMsgActive.searchOptions.uid;
SelectStatusSearchRef.value.searchMsg = insidersMsgActive.searchOptions.status;
SelectRoleSearchRef.value.searchMsg = insidersMsgActive.searchOptions.role;
SearchNameKeyRef.value.searchMsg = insidersMsgActive.searchOptions.name;
SearchDepartmentKeyRef.value.searchMsg = insidersMsgActive.searchOptions.department;
SearchChangeKeyRef.value.searchMsg = insidersMsgActive.searchOptions.change;
createdDateTimePickerRef.value.created_at =
insidersMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
insidersMsgActive.searchOptions.updated_at;
loginDateTimePickerRef.value.login_at = insidersMsgActive.searchOptions.login_at;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = insidersMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg = insidersMsgActive.sortOptions.updated_at;
loginSortDateTimeRef.value.searchMsg = insidersMsgActive.sortOptions.login_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,594 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="monitoringMsgActive" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="dialogOperationVisible"
fixed="left"
type="selection"
width="40"
column-key="selection"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="100" column-key="operate">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectOperateSearchRef"
holderText="选择操作名称以搜索相关数据"
:options="operateOptions"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 操作名称 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(operateOptions, scope.row.operate)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(operateOptions, scope.row.operate) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="operate_msg">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOperateMsgKeyRef"
holderText="输入操作描述以搜索相关数据"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 操作描述 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.operate_msg }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="type">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectTypeSearchRef"
holderText="选择危险等级以搜索相关数据"
:options="typeOptions"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 危险等级 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(typeOptions, scope.row.type)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(typeOptions, scope.row.type) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="150" column-key="status">
<template #header>
<SelectSearch
v-if="dialogSearchVisible"
ref="SelectStatusSearchRef"
holderText="选择执行状态以搜索相关数据"
:options="statusOptions"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 执行状态 </el-text>
</div>
</template>
<template #default="scope">
<div
:style="styleShunt(statusOptions, scope.row.status)"
class="flex justify-start items-center text-base"
>
{{ labelShunt(statusOptions, scope.row.status) }}
</div>
</template>
</el-table-column>
<el-table-column min-width="80" column-key="affect_entries">
<template #header>
<div>
<div>
<el-text class="mx-1"> 影响到的数据数目 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.affect_entries }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="user">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUserKeyRef"
holderText="输入操作者uid以搜索相关数据"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 操作者uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.user }}
</div>
</template>
</el-table-column>
<el-table-column min-width="140" column-key="name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchNameKeyRef"
holderText="输入操作者姓名以搜索相关数据"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 操作者姓名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="monitoringMsg"
/>
<div>
<el-text class="mx-1"> 行为记录时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="monitoringMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="monitoringMsgActive"
@sizeChangeBack="changePage"
@search="monitoringMsg"
/>
</div>
</el-card>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除系统记录"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import SelectSearch from "../search/selectSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import monitoringActiveStore from "../../stores/monitoring";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const monitoringMsgActive = monitoringActiveStore();
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除系统记录",
};
const DelSelectRef = ref(null);
const SelectOperateSearchRef = ref(null);
const SearchOperateMsgKeyRef = ref(null);
const SelectTypeSearchRef = ref(null);
const SelectStatusSearchRef = ref(null);
const SearchUserKeyRef = ref(null);
const SearchNameKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const createdSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("del");
const searchOptions = reactive({
operate: "",
operate_msg: "",
type: "",
status: "",
affect_entries: "",
user: "",
created_at: "",
});
const sortOptions = reactive({
created_at: false,
});
const tableData = ref([]);
const operateOptions = [
{
value: "0",
label: "新增数据",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "1",
label: "编辑数据",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "2",
label: "删除数据",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const typeOptions = [
{
value: "0",
label: "普通",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "1",
label: "重要",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "2",
label: "危险",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
const statusOptions = [
{
value: "0",
label: "操作执行失败,原因:无用户身份",
style: "color: rgb(120, 140, 180);background-color: rgba(120, 140, 180, 0.1);padding: 0;",
},
{
value: "1",
label: "操作执行失败,原因:密码错误",
style: "color: rgb(255, 100, 180);background-color: rgba(255, 100, 180, 0.1);padding: 0;",
},
{
value: "2",
label: "操作执行失败,原因:权限不足",
style: "color: rgb(56, 188, 248);background-color: rgba(56, 188, 248, 0.1);padding: 0;",
},
{
value: "3",
label: "操作执行失败,原因:查询条件错误",
style: "color: rgb(255, 200, 0);background-color: rgba(255, 200, 0, 0.1);padding: 0;",
},
{
value: "4",
label: "操作执行成功",
style: "color: rgb(16, 184, 130);background-color: rgba(16, 184, 130, 0.1);padding: 0;",
},
{
value: "5",
label: "操作执行失败,原因:程序错误",
style: "color: rgb(240, 70, 70);background-color: rgba(240, 70, 70, 0.1);padding: 0;",
},
];
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const styleShunt = (options, data) => {
let nowStyle;
options.forEach((item) => {
if (data == item.value) {
nowStyle = item.style;
}
});
return nowStyle;
};
const labelShunt = (options, data) => {
let nowLabel;
options.forEach((item) => {
if (data == item.value) {
nowLabel = item.label;
}
});
return nowLabel;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
monitoringMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
monitoringMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
monitoringMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const monitoringMsg = () => {
judgment(searchOptions, "operate", SelectOperateSearchRef.value, "searchMsg");
judgment(searchOptions, "operate_msg", SearchOperateMsgKeyRef.value, "searchMsg");
judgment(searchOptions, "type", SelectTypeSearchRef.value, "searchMsg");
judgment(searchOptions, "status", SelectStatusSearchRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "user", SearchUserKeyRef.value, "searchMsg");
judgment(searchOptions, "name", SearchNameKeyRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showMonitoring, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.MonitoringMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(0, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
monitoringMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
monitoringMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
delete item.origin_createdAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
delete singleData.origin_createdAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "del") {
operateType = "删除";
url = $url.deleteMonitoring;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
monitoringMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ monitoringMsg });
watch(searchOptions, (value) => {
monitoringMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
monitoringMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = monitoringMsgActive.pageCount;
dialogSearchVisible.value = monitoringMsgActive.dialogSearchVisible;
dialogSortVisible.value = monitoringMsgActive.dialogSortVisible;
dialogOperationVisible.value = monitoringMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.operate = monitoringMsgActive.searchOptions.operate;
searchOptions.operate_msg = monitoringMsgActive.searchOptions.operate_msg;
searchOptions.type = monitoringMsgActive.searchOptions.type;
searchOptions.status = monitoringMsgActive.searchOptions.status;
searchOptions.created_at = monitoringMsgActive.searchOptions.created_at;
searchOptions.user = monitoringMsgActive.searchOptions.user;
}
if (dialogSortVisible.value) {
sortOptions.created_at = monitoringMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
monitoringMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SelectOperateSearchRef.value.searchMsg = monitoringMsgActive.searchOptions.operate;
SearchOperateMsgKeyRef.value.searchMsg =
monitoringMsgActive.searchOptions.operate_msg;
SelectTypeSearchRef.value.searchMsg = monitoringMsgActive.searchOptions.type;
SelectStatusSearchRef.value.searchMsg = monitoringMsgActive.searchOptions.status;
createdDateTimePickerRef.value.created_at =
monitoringMsgActive.searchOptions.created_at;
SearchUserKeyRef.value.searchMsg = monitoringMsgActive.searchOptions.user;
SearchNameKeyRef.value.searchMsg = monitoringMsgActive.searchOptions.name;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg = monitoringMsgActive.sortOptions.created_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,655 @@
<template>
<div>
<!-- 表格 -->
<el-card>
<div class="flex justify-center flex-wrap">
<TabelTools @showTools="showTools" :dialogObj="organizationMsgActive" />
<AddNewData newDataLabel="新增用户单位" @showAddForm="showAddForm" />
<el-table
ref="tableRef"
:data="tableData"
style="width: 100%"
max-height="50rem"
table-layout="auto"
scrollbar-always-on
@selection-change="handleSelectionChange"
>
<TabelSelect
v-if="dialogOperationVisible"
ref="EditSelectRef"
:holderText="editSelectHold"
singleColor="primary"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="edit"
singleType="single"
@showComfirmDialog="showComfirmDialog"
/>
<TabelSelect
v-if="dialogOperationVisible"
ref="DelSelectRef"
:holderText="delSelectHold"
singleColor="danger"
multipleColor="warning"
allColor="danger"
singleSize="small"
multipleSize="small"
allSize="small"
:singlePlain="true"
:multiplePlain="false"
:allPlain="false"
operateType="del"
@showComfirmDialog="showComfirmDialog"
/>
<el-table-column min-width="150" column-key="uid">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchUidKeyRef"
holderText="输入单位uid以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 单位uid </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.uid }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="organization_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOrganizationNameKeyRef"
holderText="输入单位名称以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 单位名称 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.organization_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="address">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchAddressKeyRef"
holderText="输入通信地址以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 通信地址 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.address }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="liaison_name">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchLiaisonNameKeyRef"
holderText="输入联系人姓名以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 联系人姓名 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.liaison_name }}
</div>
</template>
</el-table-column>
<el-table-column min-width="120" column-key="phone">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchPhoneKeyRef"
holderText="输入联系人电话以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 联系人电话 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.phone }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="email">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchEmailKeyRef"
holderText="输入单位邮箱以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 单位邮箱 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.email }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="other_information">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchOtherInformationKeyRef"
holderText="输入信息关键字以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 其他信息 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.other_information }}
</div>
</template>
</el-table-column>
<el-table-column min-width="100" column-key="post_code">
<template #header>
<div>
<SearchKey
v-if="dialogSearchVisible"
ref="SearchPostCodeKeyRef"
holderText="输入邮政编码以搜索相关数据"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 邮政编码 </el-text>
</div>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.post_code }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="created_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="createdDateTimePickerRef"
DateTimePicker="createdDateTimePicker"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 添加时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="createdSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="organizationMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.created_at }}
</div>
</template>
</el-table-column>
<el-table-column min-width="200" column-key="updated_at">
<template #header>
<DateTimePicker
v-if="dialogSearchVisible"
ref="updatedDateTimePickerRef"
DateTimePicker="updatedMsgDateTimePicker"
@search="organizationMsg"
/>
<div>
<el-text class="mx-1"> 上次信息变更时间 </el-text>
<SortSearch
v-if="dialogSortVisible"
ref="updatedSortDateTimeRef"
activeText="顺序"
inactiveText="倒序"
@search="organizationMsg"
/>
</div>
</template>
<template #default="scope">
<div class="flex justify-start items-center text-base">
{{ scope.row.updated_at }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 表格 -->
<Pagination
ref="PaginationRef"
:active="organizationMsgActive"
@sizeChangeBack="changePage"
@search="organizationMsg"
/>
</div>
</el-card>
<AddOrganizationForm
ref="addOrganizationFormRef"
title="新增用户单位"
@reloadData="organizationMsg"
/>
<EditOrganizationForm
ref="editOrganizationFormRef"
operateLabel="编辑用户单位"
@requestOperate="requestOperate"
/>
<PasswordOauth
ref="delPasswordOauthRef"
operateLabel="删除用户单位"
@requestOperate="requestOperate"
/>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import TabelTools from "../operate/tabelTools.vue";
import AddNewData from "../operate/addNewData.vue";
import TabelSelect from "../operate/tabelSelect.vue";
import SearchKey from "../search/searchKey.vue";
import SortSearch from "../search/sortSearch.vue";
import DateTimePicker from "../search/dateTimePicker.vue";
import Pagination from "../search/pagination.vue";
import AddOrganizationForm from "../addNewData/organizationForm/organizationForm.vue";
import EditOrganizationForm from "../editData/organizationForm.vue";
import PasswordOauth from "../operate/passwordOauth.vue";
import organizationActiveStore from "../../stores/organization";
import moment from "moment";
import $http from "../../api/index";
import $url from "../../api/url";
import { encrypt } from "../../utils/aes";
import { judgment } from "../../utils/judgment.js";
import { hasNullOrEmptyPropertyWithTypeof } from "../../utils/hasNullOrEmptyPropertyWithTypeof.js";
const organizationMsgActive = organizationActiveStore();
const editSelectHold = {
single: "编辑",
multiple: "编辑选中",
all: "编辑所有",
label: "编辑用户单位",
};
const delSelectHold = {
single: "删除",
multiple: "删除选中",
all: "删除所有",
label: "删除用户单位",
};
const EditSelectRef = ref(null);
const DelSelectRef = ref(null);
const SearchUidKeyRef = ref(null);
const SearchOrganizationNameKeyRef = ref(null);
const SearchAddressKeyRef = ref(null);
const SearchLiaisonNameKeyRef = ref(null);
const SearchPhoneKeyRef = ref(null);
const SearchEmailKeyRef = ref(null);
const SearchOtherInformationKeyRef = ref(null);
const SearchPostCodeKeyRef = ref(null);
const createdDateTimePickerRef = ref(null);
const updatedDateTimePickerRef = ref(null);
const createdSortDateTimeRef = ref(null);
const updatedSortDateTimeRef = ref(null);
const PaginationRef = ref(null);
const addOrganizationFormRef = ref(null);
const editOrganizationFormRef = ref(null);
const delPasswordOauthRef = ref(null);
const dialogSearchVisible = ref(false);
const dialogSortVisible = ref(false);
const dialogOperationVisible = ref(false);
const tableRef = ref();
const offsetOff = ref(true);
const pageCount = ref(0);
const operate = ref("edit");
const searchOptions = reactive({
uid: "",
organization_name: "",
address: "",
liaison_name: "",
phone: "",
email: "",
other_information: "",
post_code: "",
created_at: "",
updated_at: "",
});
const sortOptions = reactive({
created_at: false,
updated_at: false,
});
const tableData = ref([]);
let singleData = reactive({});
let operateData = reactive({});
let operateDataClone = reactive({});
const showAddForm = () => {
addOrganizationFormRef.value.dialogVisible = true;
};
const showTools = (operateType) => {
switch (operateType) {
case "search":
dialogSearchVisible.value = !dialogSearchVisible.value;
organizationMsgActive.dialogSearchVisible = dialogSearchVisible.value;
break;
case "sort":
dialogSortVisible.value = !dialogSortVisible.value;
organizationMsgActive.dialogSortVisible = dialogSortVisible.value;
break;
case "operation":
dialogOperationVisible.value = !dialogOperationVisible.value;
organizationMsgActive.dialogOperationVisible = dialogOperationVisible.value;
break;
default:
break;
}
};
const resetOffset = () => {
if (hasNullOrEmptyPropertyWithTypeof(searchOptions)) {
if (PaginationRef.value.offset !== 1 && offsetOff.value) {
PaginationRef.value.handleCurrentChange(1);
offsetOff.value = false;
}
} else {
offsetOff.value = true;
}
};
const organizationMsg = () => {
judgment(searchOptions, "uid", SearchUidKeyRef.value, "searchMsg");
judgment(
searchOptions,
"organization_name",
SearchOrganizationNameKeyRef.value,
"searchMsg"
);
judgment(searchOptions, "address", SearchAddressKeyRef.value, "searchMsg");
judgment(searchOptions, "liaison_name", SearchLiaisonNameKeyRef.value, "searchMsg");
judgment(searchOptions, "phone", SearchPhoneKeyRef.value, "searchMsg");
judgment(searchOptions, "email", SearchEmailKeyRef.value, "searchMsg");
judgment(
searchOptions,
"other_information",
SearchOtherInformationKeyRef.value,
"searchMsg"
);
judgment(searchOptions, "post_code", SearchPostCodeKeyRef.value, "searchMsg");
judgment(searchOptions, "created_at", createdDateTimePickerRef.value, "searchMsg");
judgment(searchOptions, "updated_at", updatedDateTimePickerRef.value, "searchMsg");
judgment(sortOptions, "created_at", createdSortDateTimeRef.value, "searchMsg");
judgment(sortOptions, "updated_at", updatedSortDateTimeRef.value, "searchMsg");
resetOffset();
const data = {
uid: localStorage.data,
offset: PaginationRef.value == null ? 1 : PaginationRef.value.offset,
limit: PaginationRef.value == null ? 10 : PaginationRef.value.limit,
searchOptions: searchOptions,
sortOptions: sortOptions,
};
$http.post($url.showOrganization, data).then((res) => {
if (res.data.code === 200) {
tableData.value = res.data.OrganizationMsg;
tableData.value.forEach((item) => {
item.origin_createdAt = item.created_at;
item.created_at = moment
.utc(item.created_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
item.origin_updatedAt = item.updated_at;
item.updated_at = moment
.utc(item.updated_at)
.add(8, "hours")
.format("YYYY-MM-DD-HH:mm:ss");
});
PaginationRef.value.dataCount = res.data.count;
organizationMsgActive.dataCount = PaginationRef.value.dataCount;
pageCount.value = Math.ceil(
PaginationRef.value.dataCount / PaginationRef.value.limit
);
organizationMsgActive.pageCount = pageCount.value;
if (!operateData[PaginationRef.value.offset]) return;
operateData[PaginationRef.value.offset].forEach((element) => {
tableData.value.forEach((item) => {
if (item.created_at == element.created_at) {
nextTick(() => {
tableRef.value.toggleRowSelection(item, true);
});
}
});
});
} else {
tableData.value = [];
ElMessage.error("未查找到相关数据!");
}
});
};
const changePage = (val) => {
pageCount.value = Math.ceil(PaginationRef.value.dataCount / val);
operateData = {};
for (let i = 0; i < pageCount.value; i++) {
operateData[i + 1] = [];
for (const key in operateDataClone) {
operateDataClone[key].forEach((element) => {
// 判断数据在第几页
if (Math.ceil(element.location / PaginationRef.value.limit) == i + 1) {
operateData[i + 1].push(element);
}
});
}
}
};
const handleSelectionChange = (val) => {
operateData[PaginationRef.value.offset] = val;
tableData.value.forEach((item, index) => {
operateData[PaginationRef.value.offset].forEach((element) => {
if (item.created_at == element.created_at) {
// 数据在表格中的位置
element.location =
(PaginationRef.value.offset - 1) * PaginationRef.value.limit + (index + 1);
}
});
});
operateDataClone = JSON.parse(JSON.stringify(operateData));
for (const key in operateDataClone) {
operateDataClone[key].forEach((item) => {
if (item.origin_createdAt) {
item.created_at = item.origin_createdAt;
}
if (item.origin_updatedAt) {
item.created_at = item.origin_updatedAt;
}
delete item.origin_createdAt;
delete item.origin_updatedAt;
delete item.location;
});
}
};
const showComfirmDialog = (singleMsg) => {
singleData = { ...singleMsg.data };
singleData.created_at = singleData.origin_createdAt;
singleData.updated_at = singleData.origin_updatedAt;
delete singleData.origin_createdAt;
delete singleData.origin_updatedAt;
operate.value = singleMsg.operateType;
if (singleMsg.operateType == "edit") {
editOrganizationFormRef.value.originForm({ ...singleMsg.data });
editOrganizationFormRef.value.operateDialogVisible = true;
editOrganizationFormRef.value.model = EditSelectRef.value.model;
}
if (singleMsg.operateType == "del") {
delPasswordOauthRef.value.operateDialogVisible = true;
}
};
const requestOperate = () => {
let operateType, url, model, password;
if (operate.value == "edit") {
operateType = "编辑";
url = $url.editOrganization;
model = EditSelectRef.value.model;
password = editOrganizationFormRef.value.password;
} else if (operate.value == "del") {
operateType = "删除";
url = $url.deleteOrganization;
model = DelSelectRef.value.model;
password = delPasswordOauthRef.value.ruleForm.password;
}
const data = {
uid: localStorage.data,
model: encrypt(model),
password: encrypt(password),
requestMsg:
model == "single" ? singleData : model == "multiple" ? operateDataClone : "",
};
if (operate.value == "edit") {
data.updateMsg = { ...editOrganizationFormRef.value.ruleForm };
}
$http.post(url, data).then((res) => {
if (res.data.code === 200) {
tableRef.value.clearSelection();
operateData = {};
operateDataClone = {};
ElMessage({
message: `${operateType}成功!`,
type: "success",
});
organizationMsg();
} else {
ElMessage.error(`${operateType}失败!`);
}
});
};
defineExpose({ organizationMsg });
watch(searchOptions, (value) => {
organizationMsgActive.searchOptions = value;
});
watch(sortOptions, (value) => {
organizationMsgActive.sortOptions = value;
});
onMounted(() => {
pageCount.value = organizationMsgActive.pageCount;
dialogSearchVisible.value = organizationMsgActive.dialogSearchVisible;
dialogSortVisible.value = organizationMsgActive.dialogSortVisible;
dialogOperationVisible.value = organizationMsgActive.dialogOperationVisible;
if (dialogSearchVisible.value) {
searchOptions.uid = organizationMsgActive.searchOptions.uid;
searchOptions.organization_name =
organizationMsgActive.searchOptions.organization_name;
searchOptions.address = organizationMsgActive.searchOptions.address;
searchOptions.liaison_name = organizationMsgActive.searchOptions.liaison_name;
searchOptions.phone = organizationMsgActive.searchOptions.phone;
searchOptions.email = organizationMsgActive.searchOptions.email;
searchOptions.other_information =
organizationMsgActive.searchOptions.other_information;
searchOptions.post_code = organizationMsgActive.searchOptions.post_code;
searchOptions.type = organizationMsgActive.searchOptions.type;
searchOptions.status = organizationMsgActive.searchOptions.status;
searchOptions.created_at = organizationMsgActive.searchOptions.created_at;
searchOptions.updated_at = organizationMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
sortOptions.created_at = organizationMsgActive.sortOptions.created_at;
sortOptions.updated_at = organizationMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
setTimeout(() => {
organizationMsg();
}, 200);
setTimeout(() => {
if (dialogSearchVisible.value) {
SearchUidKeyRef.value.searchMsg = organizationMsgActive.searchOptions.uid;
SearchOrganizationNameKeyRef.value.searchMsg =
organizationMsgActive.searchOptions.organization_name;
SearchAddressKeyRef.value.searchMsg = organizationMsgActive.searchOptions.address;
SearchLiaisonNameKeyRef.value.searchMsg =
organizationMsgActive.searchOptions.liaison_name;
SearchPhoneKeyRef.value.searchMsg = organizationMsgActive.searchOptions.phone;
SearchEmailKeyRef.value.searchMsg = organizationMsgActive.searchOptions.email;
SearchOtherInformationKeyRef.value.searchMsg =
organizationMsgActive.searchOptions.other_information;
SearchPostCodeKeyRef.value.searchMsg =
organizationMsgActive.searchOptions.post_code;
createdDateTimePickerRef.value.created_at =
organizationMsgActive.searchOptions.created_at;
updatedDateTimePickerRef.value.updated_at =
organizationMsgActive.searchOptions.updated_at;
}
if (dialogSortVisible.value) {
createdSortDateTimeRef.value.searchMsg =
organizationMsgActive.sortOptions.created_at;
updatedSortDateTimeRef.value.searchMsg =
organizationMsgActive.sortOptions.updated_at;
}
if (dialogOperationVisible.value) {
}
}, 0);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,220 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ close, titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
密码管理
</div>
<div
@click="close"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer"
>
<el-icon class="el-icon--left">
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="原密码" prop="oldPassword">
<el-input
clearable
placeholder="请输入原密码"
type="password"
show-password
maxlength="16"
autocomplete="off"
v-model="ruleForm.oldPassword"
@input="filter(ruleForm.oldPassword, 'oldPassword')"
oncut="return false"
onpaste="return false"
oncopy="return false"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="新密码" prop="newPassword">
<el-text
style="color: rgb(240 70 70)"
class="mx-1 font-bold"
size="small"
type="info"
>
密码必须包含数字、大小写字母以及特殊字符(!@#$%^&*),且长度在8-16位之间
</el-text>
<el-input
clearable
placeholder="请输入新密码"
type="password"
show-password
maxlength="16"
autocomplete="off"
v-model="ruleForm.newPassword"
@input="filter(ruleForm.newPassword, 'newPassword')"
oncut="return false"
onpaste="return false"
oncopy="return false"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="确认新密码" prop="checkPass">
<el-input
clearable
placeholder="请再次输入新密码"
type="checkPass"
show-password
maxlength="16"
autocomplete="off"
v-model="ruleForm.checkPass"
@input="filter(ruleForm.checkPass, 'checkPass')"
oncut="return false"
onpaste="return false"
oncopy="return false"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="changePassword(ruleFormRef)"
>
提交修改
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { encrypt } from "../../utils/aes";
import $http from "../../api/index";
import $url from "../../api/url";
const dialogVisible = ref(false);
const ruleFormRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
oldPassword: "",
newPassword: "",
checkPass: "",
});
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
}
};
const passwordRegex = /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*]).{8,16}$/;
const validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
} else if (!passwordRegex.test(value)) {
callback(
new Error(
"密码必须包含数字、大小写字母以及特殊字符(!@#$%^&*),且长度在8-16位之间"
)
);
} else {
if (ruleForm.checkPass !== "") {
if (!ruleFormRef.value) return;
ruleFormRef.value.validateField("checkPass");
}
callback();
}
};
const validateCheck = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== ruleForm.newPassword) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
const rules = reactive({
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
newPassword: [{ required: true, validator: validatePass, trigger: "blur" }],
checkPass: [{ required: true, validator: validateCheck, trigger: "blur" }],
});
const handleClose = () => {
dialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetForm = (formEl) => {
dialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
const changePassword = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
dialogVisible.value = false;
let encryptForm = {
oldPassword: encrypt(ruleForm.oldPassword),
newPassword: encrypt(ruleForm.newPassword),
};
formEl.resetFields();
const data = {
passwordForm: encryptForm,
uid: localStorage.data,
};
$http.post($url.changePassword, data).then((res) => {
if (res.data.code === 200) {
ElMessage({
message: "密码修改成功!",
type: "success",
});
localStorage.clear();
window.location.reload();
} else {
ElMessage.error("密码修改失败!");
}
});
} else {
ElMessage.error("提交失败!");
}
});
};
defineExpose({ dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,190 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
:before-close="handleClose"
>
<template #header="{ close, titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
账户管理
</div>
<div
@click="close"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer"
>
<el-icon class="el-icon--left">
<CloseBold />
</el-icon>
</div>
</template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
size="default"
status-icon
class="mx-auto"
>
<el-form-item class="mx-1 font-bold" label="姓名" prop="name">
<el-input
:disabled="acabled"
minlength="1"
maxlength="20"
clearable
placeholder="请输入姓名"
v-model="ruleForm.name"
@input="filter(ruleForm.name, 'name')"
/>
</el-form-item>
<el-form-item class="mx-1 font-bold" label="所属部门" prop="department">
<el-input
maxlength="20"
clearable
placeholder="请输入所属部门"
v-model="ruleForm.department"
@input="filter(ruleForm.department, 'department')"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" @click="resetForm(ruleFormRef)">
取消
</el-button>
<el-button
style="font-weight: bold"
type="primary"
@click="editUser(ruleFormRef)"
>
提交修改
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import userManagerActiveStore from "../../stores/userManager";
import { encrypt, decrypt } from "../../utils/aes";
import $http from "../../api/index";
import $url from "../../api/url";
const userManagerActive = userManagerActiveStore();
const dialogVisible = ref(false);
const acabled = ref(true);
const ruleFormRef = ref(null);
const formElClone = ref(null);
const ruleForm = reactive({
name: "",
department: "",
});
const props = defineProps({
msg: Object,
});
const filter = (value, label) => {
if (/[=\s"'+-]/.test(value)) {
if (ruleForm[label]) {
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
}
} else {
ruleForm[label] = value;
}
};
const rules = reactive({
name: [{ required: false, message: "请输入姓名", trigger: "blur" }],
department: [],
});
const handleClose = () => {
dialogVisible.value = false;
if (!ruleFormRef) return;
formElClone.value = ruleFormRef.value;
formElClone.value.resetFields();
};
const resetForm = (formEl) => {
dialogVisible.value = false;
if (!formEl) return;
formEl.resetFields();
};
const emit = defineEmits(["resetData"]);
const reset = () => {
ruleForm.name = props.msg.name;
ruleForm.department = props.msg.department;
};
const editUser = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (valid) {
dialogVisible.value = false;
const data = {
userMsg: ruleForm,
uid: localStorage.data,
};
$http.post($url.editUser, data).then((res) => {
if (res.data.code === 200) {
ElMessage({
message: "用户信息修改成功!",
type: "success",
});
emit("resetData");
} else {
ElMessage.error("用户信息修改失败!");
}
});
} else {
ElMessage.error("提交失败!");
}
});
};
defineExpose({ dialogVisible, reset });
watch(ruleForm, (value) => {
if (dialogVisible.value) {
userManagerActive.dialogVisible = dialogVisible.value;
userManagerActive.ruleForm.name = encrypt(value.name);
userManagerActive.ruleForm.department = encrypt(value.department);
}
});
watch(dialogVisible, (value) => {
if (!value) {
userManagerActive.dialogVisible = value;
userManagerActive.ruleForm = {};
}
});
onMounted(() => {
dialogVisible.value = userManagerActive.dialogVisible;
if (userManagerActive.dialogVisible) {
ruleForm.name = decrypt(userManagerActive.ruleForm.name);
ruleForm.department = decrypt(userManagerActive.ruleForm.department);
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,29 @@
<template>
<div class="relative top-0 right-0">
<div class="absolute top-0 right-0" style="font-size: 1rem">
<el-button
style="font-weight: bold"
type="primary"
size="small"
plain
@click="showAddForm"
>
{{ newDataLabel }}
</el-button>
</div>
</div>
</template>
<script setup>
const props = defineProps({
newDataLabel: String
});
const emit = defineEmits(["showAddForm"]);
const showAddForm = () => {
emit("showAddForm");
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,62 @@
<template>
<el-dialog
v-model="dialogVisible"
:show-close="false"
style="width: 80%"
center
align-center
>
<template #header="{ close, titleId, titleClass }">
<div
style="font-size: 2rem"
class="w-full font-bold"
:id="titleId"
:class="titleClass"
>
数据展示
</div>
<div
@click="close"
class="bg-gray-400 hover:bg-red-600 text-3xl absolute top-0 right-0 cursor-pointer flex justify-center items-center"
>
<el-icon>
<CloseBold />
</el-icon>
</div>
</template>
<div class="text-center">
<el-tag
v-for="sn in dialogMsg.split(',')"
:key="sn"
type="info"
class="m-2"
effect="dark"
>
{{ sn }}
</el-tag>
</div>
<template #footer>
<div class="dialog-footer">
<el-button style="font-weight: bold" type="primary" @click="resetForm">
返回
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from "vue";
import { CloseBold } from "@element-plus/icons-vue";
const dialogMsg = ref();
const dialogVisible = ref(false);
const resetForm = () => {
dialogVisible.value = false;
};
defineExpose({ dialogMsg, dialogVisible });
</script>
<style scoped></style>

View File

@@ -0,0 +1,119 @@
<template>
<div
class="w-full h-8 flex flex-col justify-center items-center relative top-0 right-0"
>
<div class="absolute top-0 left-0" style="font-size: 1rem">
<el-dropdown>
<el-button style="font-weight: bold" type="warning" size="small" plain>
表单工具
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :style="singleBgColor" @click="showTools('single')">
<el-link style="font-weight: bold" :underline="false" type="success">
单独导入
<el-icon v-show="showSingle" class="el-icon--right">
<View />
</el-icon>
</el-link>
</el-dropdown-item>
<el-dropdown-item :style="multipleBgColor" @click="showTools('multiple')">
<el-link style="font-weight: bold" :underline="false" type="success">
批量导入
<el-icon v-show="showMultiple" class="el-icon--right">
<View />
</el-icon>
</el-link>
</el-dropdown-item>
<el-dropdown-item :style="excleBgColor" @click="showTools('excle')">
<el-link style="font-weight: bold" :underline="false" type="success">
excel表格导入
<el-icon v-show="showExcle" class="el-icon--right">
<View />
</el-icon>
</el-link>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from "vue";
import { ArrowDown, View } from "@element-plus/icons-vue";
const showSingle = ref(false);
const singleBgColor = ref("background-color: rgba(16, 184, 130, 0.1);");
const showMultiple = ref(false);
const multipleBgColor = ref("background-color: rgba(16, 184, 130, 0.1);");
const showExcle = ref(false);
const excleBgColor = ref("background-color: rgba(16, 184, 130, 0.1);");
const props = defineProps({
dialogObj: Object,
});
const emit = defineEmits(["showTools"]);
const showTools = (operateType) => {
switch (operateType) {
case "single":
emit("showTools", "single");
showSingle.value = true;
showMultiple.value = false;
showExcle.value = false;
break;
case "multiple":
emit("showTools", "multiple");
showSingle.value = false;
showMultiple.value = true;
showExcle.value = false;
break;
case "excle":
emit("showTools", "excle");
showSingle.value = false;
showMultiple.value = false;
showExcle.value = true;
break;
default:
break;
}
};
watch(showSingle, (value) => {
if (value) {
singleBgColor.value = "background-color: rgba(16, 184, 130, 0.2);";
} else {
singleBgColor.value = "background-color: rgba(16, 184, 130, 0.1);";
}
});
watch(showMultiple, (value) => {
if (value) {
multipleBgColor.value = "background-color: rgba(16, 184, 130, 0.2);";
} else {
multipleBgColor.value = "background-color: rgba(16, 184, 130, 0.1);";
}
});
watch(showExcle, (value) => {
if (value) {
excleBgColor.value = "background-color: rgba(16, 184, 130, 0.2);";
} else {
excleBgColor.value = "background-color: rgba(16, 184, 130, 0.1);";
}
});
onMounted(() => {
showSingle.value = props.dialogObj.dialogSingleVisible;
showMultiple.value = props.dialogObj.dialogMultipleVisible;
showExcle.value = props.dialogObj.dialogExcleVisible;
});
</script>
<style scoped></style>

Some files were not shown because too many files have changed in this diff Show More