【修改】前端提交代码 #6
19
src/api/system/tranparam/index.ts
Normal file
19
src/api/system/tranparam/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import request from '@/config/axios'
|
||||
// 通用参数实体
|
||||
export interface TranParam {
|
||||
id?: number
|
||||
examSet: string // 0 是开启,1 否关闭
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取列表
|
||||
export const getSet = () => {
|
||||
return request.get({ url: '/exam/tranparam/getSetList' })
|
||||
}
|
||||
|
||||
|
||||
// 修改
|
||||
export const updateSet = (data) => {
|
||||
return request.put({ url: '/exam/tranparam/updateSet', data })
|
||||
}
|
||||
@@ -87,6 +87,11 @@ export const importUserTemplate = () => {
|
||||
export const importUserTemplateStu = () => {
|
||||
return request.download({ url: '/system/user/get-import-template-stu' })
|
||||
}
|
||||
// 下载学生试卷任务导入模板
|
||||
export const importUserTaskStu = () => {
|
||||
return request.download({ url: '/system/user/get-import-task-stu' })
|
||||
}
|
||||
|
||||
// 下载教师导入模板
|
||||
export const importUserTemplateTeacher = () => {
|
||||
return request.download({ url: '/system/user/get-import-template-teacher' })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { service } from './service'
|
||||
|
||||
import { config } from './config'
|
||||
import { TranParam } from '@/api/tranparam'
|
||||
|
||||
const { default_headers } = config
|
||||
|
||||
@@ -31,7 +32,7 @@ export default {
|
||||
const res = await request({ method: 'DELETE', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
put: async <T = any>(option: any) => {
|
||||
put: async <T = any>(option: any, data: TranParam) => {
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
return res.data as unknown as T
|
||||
},
|
||||
|
||||
@@ -114,7 +114,7 @@ export default {
|
||||
small: '小'
|
||||
},
|
||||
login: {
|
||||
welcome: '湖北省技能高考万维考试平台',
|
||||
welcome: '万维智能实训平台',
|
||||
message: '',
|
||||
tenantname: '租户名称',
|
||||
username: '用户名',
|
||||
@@ -128,7 +128,7 @@ export default {
|
||||
remember: '记住我',
|
||||
hasUser: '已有账号?去登录',
|
||||
forgetPassword: '忘记密码?',
|
||||
tenantNamePlaceholder: '请输入租户名称',
|
||||
tenantNamePlaceholder: '请输入学校名称',
|
||||
usernamePlaceholder: '请输入用户名',
|
||||
passwordPlaceholder: '请输入密码',
|
||||
codePlaceholder: '请输入验证码',
|
||||
|
||||
@@ -110,6 +110,7 @@ export const getDictLabel = (dictType: string, value: any): string => {
|
||||
export enum DICT_TYPE {
|
||||
USER_TYPE = 'user_type',
|
||||
COMMON_STATUS = 'common_status',
|
||||
C = 'c',
|
||||
TERMINAL = 'terminal', // 终端
|
||||
DATE_INTERVAL = 'date_interval', // 数据间隔
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
v-if="refreshTable"
|
||||
>
|
||||
<el-table-column prop="name" label="专业名称" />
|
||||
<el-table-column prop="roles" label="软件环境" />
|
||||
<!-- <el-table-column prop="roles" label="软件环境" /> -->
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
|
||||
@@ -75,7 +75,7 @@
|
||||
修改
|
||||
</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button>
|
||||
<!-- 第三级才显示规则按钮 -->
|
||||
<!-- 第三级才显示规则按钮
|
||||
<el-button
|
||||
v-if="scope.row.level === 3"
|
||||
link
|
||||
@@ -83,7 +83,7 @@
|
||||
@click="handleRule(scope.row)"
|
||||
>
|
||||
软件环境
|
||||
</el-button>
|
||||
</el-button>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -119,7 +119,15 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
@@ -171,6 +179,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="试卷任务" align="center" prop="taskName" />
|
||||
<el-table-column label="场次" align="center" prop="batch" />
|
||||
<el-table-column label="机器ip" align="center" prop="ip" width="180px"/>
|
||||
<el-table-column
|
||||
label="更新时间"
|
||||
@@ -361,7 +370,8 @@ const queryParams = reactive({
|
||||
ip: undefined,
|
||||
remainingTime: [],
|
||||
startTime: undefined,
|
||||
endTime: undefined
|
||||
endTime: undefined,
|
||||
batch: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
@@ -96,8 +96,12 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -446,6 +450,7 @@ const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -106,13 +106,11 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- <el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="来源" prop="resourceValue">
|
||||
<el-input v-model="formData.resourceValue" placeholder="请输入来源" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row> -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
<div class="edit-left bottom-common">
|
||||
@@ -326,6 +324,7 @@ const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -84,18 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -381,6 +374,7 @@ const formData = ref<any>({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -96,7 +96,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
@@ -506,6 +510,7 @@ const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '<p>---------------------------------------------------------------------</p><p> 请在打开的窗口中,进行下列操作,完成所有操作后,请关闭窗口。</p><p>---------------------------------------------------------------------</p><p>',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -96,9 +96,12 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
<div class="edit-left bottom-common">
|
||||
@@ -487,6 +490,7 @@ const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
@@ -671,7 +675,7 @@ function flattenPsVoList(list, parentPath = '') {
|
||||
if (item.children && item.children.length > 0) {
|
||||
result.push(...flattenPsVoList(item.children, currentPath));
|
||||
} else {
|
||||
const symbol = item.value === 'true' ? '✅' : item.value === 'false' ? '❌' : item.value;
|
||||
const symbol = item.value ;
|
||||
result.push({
|
||||
key: item.key, // 一定要有 key
|
||||
label: `${currentPath}: ${symbol}`,
|
||||
@@ -697,11 +701,7 @@ function flattenPsVoListOther(list, parentPath = '') {
|
||||
: item.key;
|
||||
|
||||
// 处理值显示(类似原函数的symbol逻辑)
|
||||
const valueDisplay = item.value === 'true'
|
||||
? '✅'
|
||||
: item.value === 'false'
|
||||
? '❌'
|
||||
: item.value ;
|
||||
const valueDisplay = item.value ;
|
||||
|
||||
// 只有叶子节点(没有children属性)才添加到结果
|
||||
// 根据您的数据结构,type=1可能是叶子节点的标识
|
||||
@@ -765,7 +765,7 @@ console.log(formData.value.fileUploads+"formData.value.fileUploads")
|
||||
|
||||
|
||||
const formRules = reactive<FormRules>({
|
||||
// specialtyName: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }]
|
||||
status: [{ required: true, message: '启用状态必填', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
// 左侧试题描述
|
||||
@@ -1113,7 +1113,7 @@ const handleNodeClick = (data, node) => {
|
||||
}
|
||||
|
||||
// 构造一个 label,用 key 和 value 显示
|
||||
const symbol = data.value === true ? '✅' : data.value === false ? '❌' : data.value;
|
||||
const symbol = data.value ;
|
||||
const label = `${data.key}: ${symbol}`;
|
||||
|
||||
// 判断是否已存在,避免重复添加
|
||||
@@ -1154,8 +1154,12 @@ const updateSort = () => {
|
||||
item.sort = index + 1
|
||||
})
|
||||
}
|
||||
const removePoint = (index: number) => {
|
||||
flatPointList.value.splice(index, 1);
|
||||
const removePoint = (row) => {
|
||||
for (let i = 0; i < flatPointList.value.length; i++) {
|
||||
if (row.label == flatPointList.value[i].label) {
|
||||
flatPointList.value.splice(i, 1)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -84,18 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -313,6 +306,7 @@ const formData = ref({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -84,6 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -252,6 +257,7 @@ const formData = ref({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -84,18 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -394,6 +387,7 @@ const formData = ref({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -84,18 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -406,6 +399,7 @@ const formData = ref({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText: '',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -84,18 +84,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input v-model="formData.contentText" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -487,6 +480,7 @@ const formData = ref({
|
||||
pointNamesVo: '',
|
||||
chapteridDictTextVo: '',
|
||||
content: '',
|
||||
contentText:'',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
|
||||
@@ -50,15 +50,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- <el-form-item label="手机号码" prop="mobile">-->
|
||||
<!-- <el-input-->
|
||||
<!-- v-model="queryParams.mobile"-->
|
||||
<!-- placeholder="请输入手机号码"-->
|
||||
<!-- clearable-->
|
||||
<!-- @keyup.enter="handleQuery"-->
|
||||
<!-- class="!w-240px"-->
|
||||
<!-- />-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="标题" prop="contentText">
|
||||
<el-input
|
||||
v-model="queryParams.contentText"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="审核状态" prop="audit">
|
||||
<el-select
|
||||
v-model="queryParams.audit"
|
||||
@@ -179,6 +179,11 @@
|
||||
prop="quNum"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column label="标题" align="center" prop="contentText">
|
||||
<template #default="{ row }">
|
||||
{{ getFirstNChineseChars(row.contentText, 10) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="题干" align="center" prop="content" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ getFirstNChineseChars(row.content, 5) }}
|
||||
@@ -428,6 +433,7 @@ const queryParams = reactive({
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
subjectName: '',
|
||||
contentText:'',
|
||||
pointNames: '',
|
||||
chapteridDictText: '',
|
||||
pageNo: 1,
|
||||
@@ -829,20 +835,19 @@ const importFormRef = ref()
|
||||
|
||||
/** 修改用户状态 */
|
||||
const handleStatusChange = async (row: any) => {
|
||||
const oldStatus = row.status
|
||||
console.log(oldStatus)
|
||||
try {
|
||||
// 修改状态的二次确认
|
||||
await message.confirm('确认要修改' + row.quNum + '"试题状态吗?')
|
||||
// 发起修改状态
|
||||
QuestionApi.updateQuStatus(row.quId, row.status)
|
||||
// 刷新列表
|
||||
await message.confirm(`确认要修改「${row.quNum}」的试题状态吗?`)
|
||||
await QuestionApi.updateQuStatus(row.quId, row.status)
|
||||
await getList()
|
||||
} catch {
|
||||
// 取消后,进行恢复按钮
|
||||
row.status =
|
||||
row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
|
||||
row.status = oldStatus
|
||||
await getList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const exportLoading = ref(false)
|
||||
|
||||
@@ -931,23 +936,37 @@ const handleRole = (row: UserApi.UserVO) => {
|
||||
}
|
||||
|
||||
|
||||
function getFirstNChineseChars(htmlStr) {
|
||||
function getFirstNChineseChars(htmlStr,limit ) {
|
||||
if (!htmlStr) return ''
|
||||
|
||||
// 将 HTML 转为纯文本
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = htmlStr
|
||||
let text = tempDiv.textContent || tempDiv.innerText || ''
|
||||
// 尝试反转义(处理 < > 等)
|
||||
const txt = document.createElement('textarea')
|
||||
txt.innerHTML = htmlStr
|
||||
htmlStr = txt.value // => <p>test</p>
|
||||
|
||||
// 去掉空格和换行
|
||||
// 判断是否包含 HTML 标签
|
||||
const hasHtmlTag = /<[^>]+>/.test(htmlStr)
|
||||
|
||||
// 提取纯文本
|
||||
let text = hasHtmlTag
|
||||
? (() => {
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = htmlStr
|
||||
return tempDiv.textContent || tempDiv.innerText || ''
|
||||
})()
|
||||
: htmlStr
|
||||
|
||||
// 去空格和换行
|
||||
text = text.replace(/\s+/g, '')
|
||||
|
||||
// 匹配汉字
|
||||
const match = text.match(/[\u4e00-\u9fa5]/g)
|
||||
// 这里改成提取“中英文混合”而非仅中文
|
||||
const match = text.match(/[\u4e00-\u9fa5a-zA-Z0-9]/g)
|
||||
if (!match) return ''
|
||||
|
||||
return match.slice(0, 6).join('')
|
||||
return match.slice(0, limit).join('')+ '...';
|
||||
}
|
||||
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getList()
|
||||
|
||||
58
src/views/system/set/examset/index.vue
Normal file
58
src/views/system/set/examset/index.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<ContentWrap title="考试模式设置">
|
||||
<el-card>
|
||||
<div class="flex items-center gap-4">
|
||||
<span>是否开启考试模式:</span>
|
||||
<el-switch
|
||||
v-model="examSet"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
@change="handleSwitchChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import * as TranParamApi from '@/api/system/tranparam'
|
||||
import type { TranParam } from '@/api/system/tranparam'
|
||||
|
||||
const examSet = ref<'0' | '1'>('1') // 默认关闭
|
||||
const examId = ref<number | null>(null) // 👈 存储ID
|
||||
// 页面加载时获取当前状态
|
||||
const getExamSet = async () => {
|
||||
const res = await TranParamApi.getSet()
|
||||
const record = res.list?.[0]
|
||||
examSet.value = record?.examSet ?? '1'
|
||||
examId.value = record?.id ?? null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getExamSet()
|
||||
})
|
||||
|
||||
// 修改考试模式
|
||||
const handleSwitchChange = async (val: string) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定要${val === '0' ? '开启' : '关闭'}考试模式吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
const data: TranParam = {
|
||||
id: examId.value!,
|
||||
examSet: val
|
||||
}
|
||||
await TranParamApi.updateSet(data)
|
||||
getExamSet();
|
||||
ElMessage.success('修改成功')
|
||||
} catch {
|
||||
|
||||
examSet.value = val === '0' ? '1' : '0'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
150
src/views/system/set/param/SpecialtyForm.vue
Normal file
150
src/views/system/set/param/SpecialtyForm.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="上级专业" prop="parentId">
|
||||
<el-tree-select
|
||||
v-model="formData.parentId"
|
||||
:data="specialtyTree"
|
||||
:props="defaultProps"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
placeholder="请选择上级专业"
|
||||
value-key="spId"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业名称" prop="spName">
|
||||
<el-input v-model="formData.spName" placeholder="请输入专业名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="formData.status" clearable placeholder="请选择状态">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import * as SpecialtyApi from '@/api/exam/specialty'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import { FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'SpecialtyForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
title: '',
|
||||
parentId: undefined,
|
||||
name: undefined,
|
||||
sort: undefined,
|
||||
leaderUserId: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
parentId: [{ required: true, message: '上级专业不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '专业名称不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const specialtyTree = ref() // 树形结构
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await SpecialtyApi.getSpecialty(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
// 获得用户列表
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
// 获得专业树
|
||||
await getTree()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value
|
||||
if (formType.value === 'create') {
|
||||
await SpecialtyApi.createSpecialty(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await SpecialtyApi.updateSpecialty(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
title: '',
|
||||
parentId: undefined,
|
||||
name: undefined,
|
||||
sort: undefined,
|
||||
leaderUserId: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
/** 获得专业-课程-题型树 */
|
||||
const getTree = async () => {
|
||||
specialtyTree.value = []
|
||||
const data = await SpecialtyApi.getSpecialtyPage()
|
||||
let dept: Tree = { id: 0, name: '专业-课程-题型', children: [] }
|
||||
dept.children = handleTree(data)
|
||||
specialtyTree.value.push(dept)
|
||||
}
|
||||
</script>
|
||||
260
src/views/system/set/param/index.vue
Normal file
260
src/views/system/set/param/index.vue
Normal file
@@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<!-- 搜索工作栏 -->
|
||||
|
||||
<ContentWrap>
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="专业名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入专业名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择专业状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<!-- <el-button type="primary" plain @click="openForm('create')">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button> -->
|
||||
<el-button type="danger" plain @click="toggleExpandAll">
|
||||
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
row-key="id"
|
||||
:default-expand-all="isExpandAll"
|
||||
v-if="refreshTable"
|
||||
>
|
||||
<el-table-column prop="name" label="专业名称" />
|
||||
<el-table-column prop="roles" label="软件环境" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" @click="openForm('update', scope.row.id)">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button> -->
|
||||
<!-- 第三级才显示规则按钮 -->
|
||||
<el-button
|
||||
v-if="scope.row.level === 3"
|
||||
link
|
||||
type="warning"
|
||||
@click="handleRule(scope.row)"
|
||||
>
|
||||
软件环境
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
<el-dialog v-model="ruleDialogVisible" title="软件环境" width="600px">
|
||||
<!-- 弹窗内容 -->
|
||||
<el-form :model="formData" label-width="100px">
|
||||
<el-form-item label="软件环境" prop="roles">
|
||||
<!-- 当专业名称为“编程题”时显示下拉框,否则显示输入框 -->
|
||||
<template v-if="formData.name === '编程题'">
|
||||
<el-select
|
||||
v-model="formData.roles"
|
||||
placeholder="请选择软件环境"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in softwareOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input
|
||||
v-model="formData.roles"
|
||||
style="width: 240px"
|
||||
placeholder="输入对应需要软件名称"
|
||||
/>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 弹窗底部按钮 -->
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="ruleDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleRuleSave">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<SpecialtyForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { handleTree } from '@/utils/tree'
|
||||
import * as SpecialtyApi from '@/api/exam/specialty'
|
||||
import SpecialtyForm from './SpecialtyForm.vue'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
|
||||
defineOptions({ name: 'SystemDept' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref() // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
name: undefined,
|
||||
status: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const isExpandAll = ref(true) // 是否展开,默认全部展开
|
||||
const refreshTable = ref(true) // 重新渲染表格状态
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
const ruleDialogVisible = ref(false) // 控制弹窗显示
|
||||
const currentRuleRow = ref<any>(null) // 当前点击的那一行数据
|
||||
const formData = ref({
|
||||
roles: '',
|
||||
id: '',
|
||||
name:''
|
||||
})
|
||||
const handleRule = async (row: any) => {
|
||||
currentRuleRow.value = row.id
|
||||
const res = await SpecialtyApi.getSpecialtyRole(currentRuleRow.value)
|
||||
console.log(res)
|
||||
formData.value.roles = res
|
||||
formData.value.name = row.name
|
||||
ruleDialogVisible.value = true
|
||||
}
|
||||
// 本地自定义下拉数据
|
||||
const softwareOptions = ref([
|
||||
{ label: 'Visual C++', value: 'Visual C++' },
|
||||
{ label: 'VC++ 2010 Express', value: 'VC++ 2010 Express' },
|
||||
{ label: 'CFree', value: 'CFree' },
|
||||
{ label: 'Dev-c', value: 'Dev-c' },
|
||||
{ label: 'Code::Blocks', value: 'Code::Blocks' },
|
||||
{ label: 'VS2008', value: 'VS2008' },
|
||||
{ label: 'VS2010', value: 'VS2010' },
|
||||
{ label: 'VS2019', value: 'VS2019' },
|
||||
])
|
||||
const handleRuleSave = async () => {
|
||||
formData.value.id = currentRuleRow.value
|
||||
const data = formData.value
|
||||
const res = await SpecialtyApi.setSpecialtyRole(data)
|
||||
message.success(t(res))
|
||||
handleQuery()
|
||||
ruleDialogVisible.value = false
|
||||
}
|
||||
/** 查询部门列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await SpecialtyApi.getSpecialtyPage(queryParams)
|
||||
console.log(data)
|
||||
const treeData = handleTree(data)
|
||||
list.value = addLevelToTree(treeData)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 展开/折叠操作 */
|
||||
const toggleExpandAll = () => {
|
||||
refreshTable.value = false
|
||||
isExpandAll.value = !isExpandAll.value
|
||||
nextTick(() => {
|
||||
refreshTable.value = true
|
||||
})
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await SpecialtyApi.deleteSpecialty(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
// 递归添加 level 字段
|
||||
const addLevelToTree = (nodes, level = 1) => {
|
||||
return nodes.map((node) => {
|
||||
const newNode = { ...node, level }
|
||||
if (newNode.children && newNode.children.length > 0) {
|
||||
newNode.children = addLevelToTree(newNode.children, level + 1)
|
||||
}
|
||||
return newNode
|
||||
})
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
// 获取用户列表
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
})
|
||||
</script>
|
||||
@@ -33,32 +33,34 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 新增/修改弹窗 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
|
||||
<el-form ref="formRef" :model="form" label-width="80px">
|
||||
<el-form-item label="名称" prop="name" required>
|
||||
<el-input v-model="form.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 新增/修改弹窗 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
|
||||
<el-form ref="formRef" :model="form" label-width="80px">
|
||||
<el-form-item label="名称" prop="name" required>
|
||||
<el-input v-model="form.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</ContentWrap> </template> <script lang="ts" setup> import { ref, reactive } from 'vue'
|
||||
</ContentWrap>
|
||||
</template>
|
||||
<script lang="ts" setup> import { ref, reactive } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import * as WhiteApi from '@/api/system/whiteList'
|
||||
// 你可以把 API 封装在这个文件里 // 数据
|
||||
const loading = ref(false)
|
||||
|
||||
const loading = ref(false)
|
||||
const list = ref([])
|
||||
const total = ref(0)
|
||||
const queryParams = reactive({ pageNo: 1, pageSize: 10, name: '' })
|
||||
@@ -68,35 +70,36 @@ const dialogTitle = ref('')
|
||||
const formRef = ref()
|
||||
const form = reactive({ id: '', name: '', path: '', remark: '' })
|
||||
// 获取列表
|
||||
const getList = async () => { loading.value = true
|
||||
const params = {
|
||||
...queryParams,
|
||||
|
||||
}
|
||||
try { const res = await WhiteApi.getAppWhiteListCenter(params)
|
||||
list.value = res.list
|
||||
total.value = res.total
|
||||
|
||||
} finally
|
||||
{
|
||||
loading.value = false
|
||||
const getList = async () => { loading.value = true
|
||||
const params = {
|
||||
...queryParams,
|
||||
|
||||
}
|
||||
try { const res = await WhiteApi.getAppWhiteListCenter(params)
|
||||
list.value = res.list
|
||||
total.value = res.total
|
||||
|
||||
} finally
|
||||
{
|
||||
loading.value = false
|
||||
} }
|
||||
// 重置
|
||||
const resetQuery = () => {
|
||||
queryParams.name = ''
|
||||
getList()
|
||||
}
|
||||
// 打开弹窗
|
||||
const openForm = async (type: string, id?: string) => {
|
||||
dialogVisible.value = true
|
||||
if (type === 'create') {
|
||||
dialogTitle.value = '新增白名单'
|
||||
Object.assign(form, { id: '', name: '', path: '', remark: '' })
|
||||
} else {
|
||||
dialogTitle.value = '修改白名单'
|
||||
const data = await WhiteApi.getWhite(id)
|
||||
Object.assign(form, data) }
|
||||
} // 提交
|
||||
// 打开弹窗
|
||||
const openForm = async (type: string, id?: string) => {
|
||||
dialogVisible.value = true
|
||||
if (type === 'create') {
|
||||
dialogTitle.value = '新增白名单'
|
||||
Object.assign(form, { id: '', name: '', path: '', remark: '' })
|
||||
} else {
|
||||
dialogTitle.value = '修改白名单'
|
||||
const data = await WhiteApi.getWhite(id)
|
||||
Object.assign(form, data) }
|
||||
}
|
||||
// 提交
|
||||
const submitForm = async () => {
|
||||
if (!form.name) {
|
||||
ElMessage.warning('请输入名称')
|
||||
@@ -105,21 +108,26 @@ const form = reactive({ id: '', name: '', path: '', remark: '' })
|
||||
if (form.id) {
|
||||
await WhiteApi.updateAppWhite(form)
|
||||
ElMessage.success('修改成功')
|
||||
} else {
|
||||
await WhiteApi.addAppWhite(form)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
}
|
||||
}
|
||||
else {
|
||||
await WhiteApi.addAppWhite(form)
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
getList()
|
||||
}
|
||||
// 删除
|
||||
const handleDelete = async (id: string) => {
|
||||
ElMessageBox.confirm('确认删除该白名单?', '提示', {
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
})
|
||||
.then(async () => {
|
||||
await WhiteApi.delWhite(id)
|
||||
ElMessage.success('删除成功')
|
||||
getList() }) }
|
||||
// 初始化
|
||||
getList()
|
||||
getList()
|
||||
}
|
||||
)
|
||||
}
|
||||
// 初始化
|
||||
getList()
|
||||
</script>
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,13 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
|
||||
message.success('删除成功')
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +98,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -90,6 +106,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
batch: undefined,
|
||||
status: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
@@ -220,6 +237,10 @@ if(res =='删除成功'){
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
|
||||
const openEdit = (type: string, row?: object) => {
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res.data || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res.data || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,13 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
message.success('删除成功');
|
||||
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +98,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -91,6 +107,7 @@ import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
defineOptions({ name: 'SystemSmsChannel' })
|
||||
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
batch: undefined,
|
||||
status: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
@@ -221,6 +238,10 @@ if(res =='删除成功'){
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
const openEdit = (type: string, row?: object) => {
|
||||
showEdit.value = true
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res.data || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,13 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
message.success('删除成功');
|
||||
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +98,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -90,6 +106,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
batch: undefined,
|
||||
status: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
@@ -220,6 +237,10 @@ if(res =='删除成功'){
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
|
||||
const openEdit = (type: string, row?: object) => {
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res.data || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,12 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
|
||||
message.success('删除成功');
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +98,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -90,6 +106,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
batch: undefined,
|
||||
status: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
@@ -220,7 +237,10 @@ if(res =='删除成功'){
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
const openEdit = (type: string, row?: object) => {
|
||||
showEdit.value = true
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,13 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
message.success('删除成功');
|
||||
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,25 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +98,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -90,6 +106,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
batch: undefined,
|
||||
status: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
@@ -237,6 +254,10 @@ const openSearch = (type: string, row?: object) => {
|
||||
})
|
||||
}
|
||||
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
|
||||
/** 删除按钮操作 */
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import { getPaperDetailByTaskId } from '@/api/system/paper';
|
||||
import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
|
||||
const message = useMessage(); // 消息弹窗
|
||||
|
||||
const props = defineProps({
|
||||
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
|
||||
console.log(paperId+"paperIdpaperId")
|
||||
if (props.paperId) {
|
||||
loading.value = true;
|
||||
getPaperDetailByTaskId(props.paperId)
|
||||
getPaperDetailCenterByTaskId(props.paperId)
|
||||
.then((res) => {
|
||||
const { educationPaperSchemeList, examQuestionList } = res || {};
|
||||
if (Array.isArray(examQuestionList)) {
|
||||
|
||||
@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
|
||||
const handleOpen = () => {
|
||||
resetFields();
|
||||
form.taskId = props.taskId;
|
||||
fetchpaperOptions();
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="学生导入" width="400">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="fileList"
|
||||
:action="importUrl + '?updateSupport=' + updateSupport + '&taskId=' + props.taskId"
|
||||
:auto-upload="false"
|
||||
:disabled="formLoading"
|
||||
:headers="uploadHeaders"
|
||||
:limit="1"
|
||||
:on-error="submitFormError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="submitFormSuccess"
|
||||
accept=".xlsx, .xls"
|
||||
drag
|
||||
>
|
||||
<Icon icon="ep:upload" />
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="updateSupport" />
|
||||
是否更新已经存在的学生数据
|
||||
</div>
|
||||
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
style="font-size: 12px; vertical-align: baseline"
|
||||
type="primary"
|
||||
@click="importTemplate"
|
||||
>
|
||||
下载模板
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import download from '@/utils/download'
|
||||
defineOptions({ name: 'SystemUserImportForm' })
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const uploadRef = ref()
|
||||
const importUrl =
|
||||
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/system/user/importTaskStu'
|
||||
const uploadHeaders = ref() // 上传 Header 头
|
||||
const fileList = ref([]) // 文件列表
|
||||
const updateSupport = ref(0) // 是否更新已经存在的用户数据
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
updateSupport.value = 0
|
||||
fileList.value = []
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (fileList.value.length == 0) {
|
||||
message.error('请上传文件')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
uploadHeaders.value = {
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
}
|
||||
formLoading.value = true
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
/** 文件上传成功 */
|
||||
const emits = defineEmits(['success'])
|
||||
const submitFormSuccess = (response: any) => {
|
||||
if (response.code !== 0) {
|
||||
message.error(response.msg)
|
||||
formLoading.value = false
|
||||
return
|
||||
}
|
||||
// 拼接提示语
|
||||
const data = response.data
|
||||
let text = '上传成功数量:' + data.createUsernames.length + ';'
|
||||
for (let username of data.createUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新成功数量:' + data.updateUsernames.length + ';'
|
||||
for (const username of data.updateUsernames) {
|
||||
text += '< ' + username + ' >'
|
||||
}
|
||||
text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
|
||||
for (const username in data.failureUsernames) {
|
||||
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
|
||||
}
|
||||
message.alert(text)
|
||||
formLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emits('success')
|
||||
}
|
||||
|
||||
/** 上传错误提示 */
|
||||
const submitFormError = (): void => {
|
||||
message.error('上传失败,请您重新上传!')
|
||||
formLoading.value = false
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = async (): Promise<void> => {
|
||||
// 重置上传状态和文件
|
||||
formLoading.value = false
|
||||
await nextTick()
|
||||
uploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
/** 文件数超出提示 */
|
||||
const handleExceed = (): void => {
|
||||
message.error('最多只能上传一个文件!')
|
||||
}
|
||||
|
||||
/** 下载模板操作 */
|
||||
const importTemplate = async () => {
|
||||
const res = await UserApi.importUserTaskStu()
|
||||
download.excel(res, '任务学生导入模版.xls')
|
||||
}
|
||||
</script>
|
||||
@@ -205,14 +205,12 @@ const removeBatch = async () => {
|
||||
|
||||
const res=await PersonApi.removeSessionStu(data);
|
||||
if(res =='删除成功'){
|
||||
message.success(t('common.delSuccess'))
|
||||
|
||||
message.success('删除成功');
|
||||
}else{
|
||||
message.error(res)
|
||||
}
|
||||
await getPersonList(); // 删除后刷新右侧列表
|
||||
emit('done');
|
||||
ElMessage.success('删除成功');
|
||||
};
|
||||
|
||||
const exportData = () => {
|
||||
|
||||
@@ -8,10 +8,26 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
|
||||
<el-form-item label="场次" prop="batch">
|
||||
<el-input
|
||||
v-model="queryParams.batch"
|
||||
placeholder="请输入场次"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
@click="handleImport"
|
||||
>
|
||||
<Icon icon="ep:upload" /> 导入
|
||||
</el-button>
|
||||
<el-button
|
||||
|
||||
type="primary"
|
||||
@@ -83,6 +99,7 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
|
||||
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
|
||||
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
@@ -90,6 +107,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import * as SmsPersonlApi from '@/api/system/person';
|
||||
import PersonEdit from './components/person-edit.vue';
|
||||
import PersonSearch from './components/person-serach.vue'
|
||||
import StudentImportForm from './components/StudentImportForm.vue'
|
||||
import * as SmsChannelApi from '@/api/system/session';
|
||||
import { fa } from 'element-plus/es/locale';
|
||||
|
||||
@@ -133,8 +151,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: undefined,
|
||||
status: undefined,
|
||||
batch: undefined,
|
||||
createTime: [],
|
||||
taskId: props.taskId
|
||||
})
|
||||
@@ -237,7 +254,10 @@ const openSearch = (type: string, row?: object) => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const importFormRef = ref()
|
||||
const handleImport = () => {
|
||||
importFormRef.value.open()
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
|
||||
Reference in New Issue
Block a user