【修改】前端提交代码

This commit is contained in:
huababa1
2025-11-08 18:16:41 +08:00
parent e225586dbc
commit 47ca453401
59 changed files with 1724 additions and 221 deletions

View 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 })
}

View File

@@ -87,6 +87,11 @@ export const importUserTemplate = () => {
export const importUserTemplateStu = () => { export const importUserTemplateStu = () => {
return request.download({ url: '/system/user/get-import-template-stu' }) 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 = () => { export const importUserTemplateTeacher = () => {
return request.download({ url: '/system/user/get-import-template-teacher' }) return request.download({ url: '/system/user/get-import-template-teacher' })

View File

@@ -1,6 +1,7 @@
import { service } from './service' import { service } from './service'
import { config } from './config' import { config } from './config'
import { TranParam } from '@/api/tranparam'
const { default_headers } = config const { default_headers } = config
@@ -31,7 +32,7 @@ export default {
const res = await request({ method: 'DELETE', ...option }) const res = await request({ method: 'DELETE', ...option })
return res.data as unknown as T 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 }) const res = await request({ method: 'PUT', ...option })
return res.data as unknown as T return res.data as unknown as T
}, },

View File

@@ -114,7 +114,7 @@ export default {
small: '小' small: '小'
}, },
login: { login: {
welcome: '湖北省技能高考万维考试平台', welcome: '万维智能实训平台',
message: '', message: '',
tenantname: '租户名称', tenantname: '租户名称',
username: '用户名', username: '用户名',
@@ -128,7 +128,7 @@ export default {
remember: '记住我', remember: '记住我',
hasUser: '已有账号?去登录', hasUser: '已有账号?去登录',
forgetPassword: '忘记密码?', forgetPassword: '忘记密码?',
tenantNamePlaceholder: '请输入租户名称', tenantNamePlaceholder: '请输入学校名称',
usernamePlaceholder: '请输入用户名', usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码', passwordPlaceholder: '请输入密码',
codePlaceholder: '请输入验证码', codePlaceholder: '请输入验证码',

View File

@@ -110,6 +110,7 @@ export const getDictLabel = (dictType: string, value: any): string => {
export enum DICT_TYPE { export enum DICT_TYPE {
USER_TYPE = 'user_type', USER_TYPE = 'user_type',
COMMON_STATUS = 'common_status', COMMON_STATUS = 'common_status',
C = 'c',
TERMINAL = 'terminal', // 终端 TERMINAL = 'terminal', // 终端
DATE_INTERVAL = 'date_interval', // 数据间隔 DATE_INTERVAL = 'date_interval', // 数据间隔

View File

@@ -56,7 +56,7 @@
v-if="refreshTable" v-if="refreshTable"
> >
<el-table-column prop="name" label="专业名称" /> <el-table-column prop="name" label="专业名称" />
<el-table-column prop="roles" label="软件环境" /> <!-- <el-table-column prop="roles" label="软件环境" /> -->
<el-table-column prop="status" label="状态"> <el-table-column prop="status" label="状态">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
@@ -75,7 +75,7 @@
修改 修改
</el-button> </el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button> <el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button>
<!-- 第三级才显示规则按钮 --> <!-- 第三级才显示规则按钮
<el-button <el-button
v-if="scope.row.level === 3" v-if="scope.row.level === 3"
link link
@@ -83,7 +83,7 @@
@click="handleRule(scope.row)" @click="handleRule(scope.row)"
> >
软件环境 软件环境
</el-button> </el-button>-->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

View File

@@ -119,7 +119,15 @@
/> />
</el-select> </el-select>
</el-form-item> </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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
@@ -171,6 +179,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="试卷任务" align="center" prop="taskName" /> <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="机器ip" align="center" prop="ip" width="180px"/>
<el-table-column <el-table-column
label="更新时间" label="更新时间"
@@ -361,7 +370,8 @@ const queryParams = reactive({
ip: undefined, ip: undefined,
remainingTime: [], remainingTime: [],
startTime: undefined, startTime: undefined,
endTime: undefined endTime: undefined,
batch: undefined
}) })
const queryFormRef = ref() // 搜索的表单 const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中 const exportLoading = ref(false) // 导出的加载中

View File

@@ -96,8 +96,12 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
</el-row> <el-form-item label="标题" prop="contentText">
<el-input v-model="formData.contentText" placeholder="请输入标题" />
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -446,6 +450,7 @@ const formData = ref({
pointNamesVo:'', pointNamesVo:'',
chapteridDictTextVo:'', chapteridDictTextVo:'',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -106,13 +106,11 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<!-- <el-row> <el-col :span="12">
<el-col :span="12"> <el-form-item label="标题" prop="contentText">
<el-form-item label="来源" prop="resourceValue"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-input v-model="formData.resourceValue" placeholder="请输入来源" /> </el-form-item>
</el-form-item> </el-col>
</el-col>
</el-row> -->
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
<div class="edit-left bottom-common"> <div class="edit-left bottom-common">
@@ -326,6 +324,7 @@ const formData = ref({
pointNamesVo:'', pointNamesVo:'',
chapteridDictTextVo:'', chapteridDictTextVo:'',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -84,18 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12"> <el-col :span="12">
<el-form-item label="审核状态" prop="audit"> <el-form-item label="标题" prop="contentText">
<el-select v-model="formData.audit" placeholder="请选择审核状态"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -381,6 +374,7 @@ const formData = ref<any>({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -96,7 +96,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </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-row>
</el-form> </el-form>
@@ -506,6 +510,7 @@ const formData = ref({
pointNamesVo:'', pointNamesVo:'',
chapteridDictTextVo:'', chapteridDictTextVo:'',
content: '<p>---------------------------------------------------------------------</p><p> 请在打开的窗口中,进行下列操作,完成所有操作后,请关闭窗口。</p><p>---------------------------------------------------------------------</p><p>', content: '<p>---------------------------------------------------------------------</p><p> 请在打开的窗口中,进行下列操作,完成所有操作后,请关闭窗口。</p><p>---------------------------------------------------------------------</p><p>',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

File diff suppressed because one or more lines are too long

View File

@@ -96,9 +96,12 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </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-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
<div class="edit-left bottom-common"> <div class="edit-left bottom-common">
@@ -487,6 +490,7 @@ const formData = ref({
pointNamesVo:'', pointNamesVo:'',
chapteridDictTextVo:'', chapteridDictTextVo:'',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',
@@ -671,7 +675,7 @@ function flattenPsVoList(list, parentPath = '') {
if (item.children && item.children.length > 0) { if (item.children && item.children.length > 0) {
result.push(...flattenPsVoList(item.children, currentPath)); result.push(...flattenPsVoList(item.children, currentPath));
} else { } else {
const symbol = item.value === 'true' ? '✅' : item.value === 'false' ? '❌' : item.value; const symbol = item.value ;
result.push({ result.push({
key: item.key, // 一定要有 key key: item.key, // 一定要有 key
label: `${currentPath}: ${symbol}`, label: `${currentPath}: ${symbol}`,
@@ -697,11 +701,7 @@ function flattenPsVoListOther(list, parentPath = '') {
: item.key; : item.key;
// 处理值显示类似原函数的symbol逻辑 // 处理值显示类似原函数的symbol逻辑
const valueDisplay = item.value === 'true' const valueDisplay = item.value ;
? '✅'
: item.value === 'false'
? '❌'
: item.value ;
// 只有叶子节点没有children属性才添加到结果 // 只有叶子节点没有children属性才添加到结果
// 根据您的数据结构type=1可能是叶子节点的标识 // 根据您的数据结构type=1可能是叶子节点的标识
@@ -765,7 +765,7 @@ console.log(formData.value.fileUploads+"formData.value.fileUploads")
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
// specialtyName: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }] status: [{ required: true, message: '启用状态必填', trigger: 'blur' }]
}) })
const formRef = ref() // 表单 Ref const formRef = ref() // 表单 Ref
// 左侧试题描述 // 左侧试题描述
@@ -1113,7 +1113,7 @@ const handleNodeClick = (data, node) => {
} }
// 构造一个 label用 key 和 value 显示 // 构造一个 label用 key 和 value 显示
const symbol = data.value === true ? '✅' : data.value === false ? '❌' : data.value; const symbol = data.value ;
const label = `${data.key}: ${symbol}`; const label = `${data.key}: ${symbol}`;
// 判断是否已存在,避免重复添加 // 判断是否已存在,避免重复添加
@@ -1154,8 +1154,12 @@ const updateSort = () => {
item.sort = index + 1 item.sort = index + 1
}) })
} }
const removePoint = (index: number) => { const removePoint = (row) => {
flatPointList.value.splice(index, 1); for (let i = 0; i < flatPointList.value.length; i++) {
if (row.label == flatPointList.value[i].label) {
flatPointList.value.splice(i, 1)
}
}
}; };

View File

@@ -84,18 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12"> <el-col :span="12">
<el-form-item label="审核状态" prop="audit"> <el-form-item label="标题" prop="contentText">
<el-select v-model="formData.audit" placeholder="请选择审核状态"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -313,6 +306,7 @@ const formData = ref({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -84,6 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </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-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -252,6 +257,7 @@ const formData = ref({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -84,18 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12"> <el-col :span="12">
<el-form-item label="审核状态" prop="audit"> <el-form-item label="标题" prop="contentText">
<el-select v-model="formData.audit" placeholder="请选择审核状态"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -394,6 +387,7 @@ const formData = ref({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -84,18 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12"> <el-col :span="12">
<el-form-item label="审核状态" prop="audit"> <el-form-item label="标题" prop="contentText">
<el-select v-model="formData.audit" placeholder="请选择审核状态"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -406,6 +399,7 @@ const formData = ref({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText: '',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -84,18 +84,11 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="12"> <el-col :span="12">
<el-form-item label="审核状态" prop="audit"> <el-form-item label="标题" prop="contentText">
<el-select v-model="formData.audit" placeholder="请选择审核状态"> <el-input v-model="formData.contentText" placeholder="请输入标题" />
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<div class="edit-bottom"> <div class="edit-bottom">
@@ -487,6 +480,7 @@ const formData = ref({
pointNamesVo: '', pointNamesVo: '',
chapteridDictTextVo: '', chapteridDictTextVo: '',
content: '', content: '',
contentText:'',
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
quBankName: '', quBankName: '',

View File

@@ -50,15 +50,15 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- <el-form-item label="手机号码" prop="mobile">--> <el-form-item label="标题" prop="contentText">
<!-- <el-input--> <el-input
<!-- v-model="queryParams.mobile"--> v-model="queryParams.contentText"
<!-- placeholder="请输入手机号码"--> placeholder="请输入标题"
<!-- clearable--> clearable
<!-- @keyup.enter="handleQuery"--> @keyup.enter="handleQuery"
<!-- class="!w-240px"--> class="!w-240px"
<!-- />--> />
<!-- </el-form-item>--> </el-form-item>
<!-- <el-form-item label="审核状态" prop="audit"> <!-- <el-form-item label="审核状态" prop="audit">
<el-select <el-select
v-model="queryParams.audit" v-model="queryParams.audit"
@@ -179,6 +179,11 @@
prop="quNum" prop="quNum"
:show-overflow-tooltip="true" :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"> <el-table-column label="题干" align="center" prop="content" width="120">
<template #default="{ row }"> <template #default="{ row }">
{{ getFirstNChineseChars(row.content, 5) }} {{ getFirstNChineseChars(row.content, 5) }}
@@ -428,6 +433,7 @@ const queryParams = reactive({
specialtyName: '', specialtyName: '',
courseName: '', courseName: '',
subjectName: '', subjectName: '',
contentText:'',
pointNames: '', pointNames: '',
chapteridDictText: '', chapteridDictText: '',
pageNo: 1, pageNo: 1,
@@ -829,20 +835,19 @@ const importFormRef = ref()
/** 修改用户状态 */ /** 修改用户状态 */
const handleStatusChange = async (row: any) => { const handleStatusChange = async (row: any) => {
const oldStatus = row.status
console.log(oldStatus)
try { try {
// 修改状态的二次确认 await message.confirm(`确认要修改「${row.quNum}」的试题状态吗?`)
await message.confirm('确认要修改' + row.quNum + '"试题状态吗?') await QuestionApi.updateQuStatus(row.quId, row.status)
// 发起修改状态
QuestionApi.updateQuStatus(row.quId, row.status)
// 刷新列表
await getList() await getList()
} catch { } catch {
// 取消后,进行恢复按钮 row.status = oldStatus
row.status = await getList()
row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
} }
} }
/** 导出按钮操作 */ /** 导出按钮操作 */
const exportLoading = ref(false) const exportLoading = ref(false)
@@ -931,23 +936,37 @@ const handleRole = (row: UserApi.UserVO) => {
} }
function getFirstNChineseChars(htmlStr) { function getFirstNChineseChars(htmlStr,limit ) {
if (!htmlStr) return '' if (!htmlStr) return ''
// 将 HTML 转为纯文本 // 尝试反转义(处理 &lt; &gt; 等)
const tempDiv = document.createElement('div') const txt = document.createElement('textarea')
tempDiv.innerHTML = htmlStr txt.innerHTML = htmlStr
let text = tempDiv.textContent || tempDiv.innerText || '' 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, '') 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 '' if (!match) return ''
return match.slice(0, 6).join('') return match.slice(0, limit).join('')+ '...';
} }
/** 初始化 */ /** 初始化 */
onMounted(() => { onMounted(() => {
getList() getList()

View 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>

View 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>

View 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>

View File

@@ -33,32 +33,34 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<Pagination <Pagination
:total="total" :total="total"
v-model:page="queryParams.pageNo" v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize" v-model:limit="queryParams.pageSize"
@pagination="getList" @pagination="getList"
/> />
<!-- 新增/修改弹窗 --> <!-- 新增/修改弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px"> <el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
<el-form ref="formRef" :model="form" label-width="80px"> <el-form ref="formRef" :model="form" label-width="80px">
<el-form-item label="名称" prop="name" required> <el-form-item label="名称" prop="name" required>
<el-input v-model="form.name" placeholder="请输入名称" /> <el-input v-model="form.name" placeholder="请输入名称" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button @click="dialogVisible = false">取消</el-button> <el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button> <el-button type="primary" @click="submitForm">确定</el-button>
</template> </template>
</el-dialog> </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 { ElMessage, ElMessageBox } from 'element-plus'
import * as WhiteApi from '@/api/system/whiteList' import * as WhiteApi from '@/api/system/whiteList'
// API //
const loading = ref(false) const loading = ref(false)
const list = ref([]) const list = ref([])
const total = ref(0) const total = ref(0)
const queryParams = reactive({ pageNo: 1, pageSize: 10, name: '' }) const queryParams = reactive({ pageNo: 1, pageSize: 10, name: '' })
@@ -68,35 +70,36 @@ const dialogTitle = ref('')
const formRef = ref() const formRef = ref()
const form = reactive({ id: '', name: '', path: '', remark: '' }) const form = reactive({ id: '', name: '', path: '', remark: '' })
// //
const getList = async () => { loading.value = true const getList = async () => { loading.value = true
const params = { const params = {
...queryParams, ...queryParams,
} }
try { const res = await WhiteApi.getAppWhiteListCenter(params) try { const res = await WhiteApi.getAppWhiteListCenter(params)
list.value = res.list list.value = res.list
total.value = res.total total.value = res.total
} finally } finally
{ {
loading.value = false loading.value = false
} } } }
// //
const resetQuery = () => { const resetQuery = () => {
queryParams.name = '' queryParams.name = ''
getList() getList()
} }
// //
const openForm = async (type: string, id?: string) => { const openForm = async (type: string, id?: string) => {
dialogVisible.value = true dialogVisible.value = true
if (type === 'create') { if (type === 'create') {
dialogTitle.value = '新增白名单' dialogTitle.value = '新增白名单'
Object.assign(form, { id: '', name: '', path: '', remark: '' }) Object.assign(form, { id: '', name: '', path: '', remark: '' })
} else { } else {
dialogTitle.value = '修改白名单' dialogTitle.value = '修改白名单'
const data = await WhiteApi.getWhite(id) const data = await WhiteApi.getWhite(id)
Object.assign(form, data) } Object.assign(form, data) }
} // }
//
const submitForm = async () => { const submitForm = async () => {
if (!form.name) { if (!form.name) {
ElMessage.warning('请输入名称') ElMessage.warning('请输入名称')
@@ -105,21 +108,26 @@ const form = reactive({ id: '', name: '', path: '', remark: '' })
if (form.id) { if (form.id) {
await WhiteApi.updateAppWhite(form) await WhiteApi.updateAppWhite(form)
ElMessage.success('修改成功') ElMessage.success('修改成功')
} else { }
await WhiteApi.addAppWhite(form) else {
ElMessage.success('新增成功') await WhiteApi.addAppWhite(form)
} ElMessage.success('新增成功')
dialogVisible.value = false }
getList() dialogVisible.value = false
} getList()
}
// //
const handleDelete = async (id: string) => { const handleDelete = async (id: string) => {
ElMessageBox.confirm('确认删除该白名单?', '提示', { ElMessageBox.confirm('确认删除该白名单?', '提示', {
type: 'warning' type: 'warning'
}).then(async () => { })
.then(async () => {
await WhiteApi.delWhite(id) await WhiteApi.delWhite(id)
ElMessage.success('删除成功') ElMessage.success('删除成功')
getList() }) } getList()
// }
getList() )
}
//
getList()
</script> </script>

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,13 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功')
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,25 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +98,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 * as SmsPersonlApi from '@/api/system/person';
import PersonEdit from './components/person-edit.vue'; import PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import StudentImportForm from './components/StudentImportForm.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined, status: undefined,
createTime: [], createTime: [],
taskId: props.taskId taskId: props.taskId
@@ -220,6 +237,10 @@ if(res =='删除成功'){
await getList() await getList()
} catch {} } catch {}
} }
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
const openEdit = (type: string, row?: object) => { const openEdit = (type: string, row?: object) => {

View File

@@ -79,7 +79,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -149,7 +149,7 @@
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res.data || {}; const { educationPaperSchemeList, examQuestionList } = res.data || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -79,7 +79,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -149,7 +149,7 @@
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res.data || {}; const { educationPaperSchemeList, examQuestionList } = res.data || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,13 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功');
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,25 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +98,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import StudentImportForm from './components/StudentImportForm.vue'
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
defineOptions({ name: 'SystemSmsChannel' }) defineOptions({ name: 'SystemSmsChannel' })
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined, status: undefined,
createTime: [], createTime: [],
taskId: props.taskId taskId: props.taskId
@@ -221,6 +238,10 @@ if(res =='删除成功'){
} catch {} } catch {}
} }
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
const openEdit = (type: string, row?: object) => { const openEdit = (type: string, row?: object) => {
showEdit.value = true showEdit.value = true

View File

@@ -79,7 +79,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -149,7 +149,7 @@
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res.data || {}; const { educationPaperSchemeList, examQuestionList } = res.data || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,13 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功');
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,25 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +98,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 * as SmsPersonlApi from '@/api/system/person';
import PersonEdit from './components/person-edit.vue'; import PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import StudentImportForm from './components/StudentImportForm.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined, status: undefined,
createTime: [], createTime: [],
taskId: props.taskId taskId: props.taskId
@@ -220,6 +237,10 @@ if(res =='删除成功'){
await getList() await getList()
} catch {} } catch {}
} }
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
const openEdit = (type: string, row?: object) => { const openEdit = (type: string, row?: object) => {

View File

@@ -79,7 +79,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -149,7 +149,7 @@
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res.data || {}; const { educationPaperSchemeList, examQuestionList } = res.data || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,12 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功');
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,25 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +98,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 * as SmsPersonlApi from '@/api/system/person';
import PersonEdit from './components/person-edit.vue'; import PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import StudentImportForm from './components/StudentImportForm.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined, status: undefined,
createTime: [], createTime: [],
taskId: props.taskId taskId: props.taskId
@@ -220,7 +237,10 @@ if(res =='删除成功'){
await getList() await getList()
} catch {} } catch {}
} }
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
const openEdit = (type: string, row?: object) => { const openEdit = (type: string, row?: object) => {
showEdit.value = true showEdit.value = true

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,13 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功');
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,25 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +98,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 * as SmsPersonlApi from '@/api/system/person';
import PersonEdit from './components/person-edit.vue'; import PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import StudentImportForm from './components/StudentImportForm.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
@@ -133,7 +150,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined, status: undefined,
createTime: [], createTime: [],
taskId: props.taskId taskId: props.taskId
@@ -237,6 +254,10 @@ const openSearch = (type: string, row?: object) => {
}) })
} }
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
/** 删除按钮操作 */ /** 删除按钮操作 */

View File

@@ -81,7 +81,7 @@
<script setup> <script setup>
import { ref, reactive, nextTick, computed } from 'vue'; import { ref, reactive, nextTick, computed } from 'vue';
import { useFormData } from '@/utils/use-form-data'; import { useFormData } from '@/utils/use-form-data';
import { getPaperDetailByTaskId } from '@/api/system/paper'; import { getPaperDetailCenterByTaskId } from '@/api/system/paper';
const message = useMessage(); // 消息弹窗 const message = useMessage(); // 消息弹窗
const props = defineProps({ const props = defineProps({
@@ -150,7 +150,7 @@ const handleOpen = (type, paperId) => {
console.log(paperId+"paperIdpaperId") console.log(paperId+"paperIdpaperId")
if (props.paperId) { if (props.paperId) {
loading.value = true; loading.value = true;
getPaperDetailByTaskId(props.paperId) getPaperDetailCenterByTaskId(props.paperId)
.then((res) => { .then((res) => {
const { educationPaperSchemeList, examQuestionList } = res || {}; const { educationPaperSchemeList, examQuestionList } = res || {};
if (Array.isArray(examQuestionList)) { if (Array.isArray(examQuestionList)) {

View File

@@ -306,6 +306,7 @@ const fetchpaperOptions = async () => {
const handleOpen = () => { const handleOpen = () => {
resetFields(); resetFields();
form.taskId = props.taskId; form.taskId = props.taskId;
fetchpaperOptions();
nextTick(() => { nextTick(() => {
formRef.value?.clearValidate?.(); formRef.value?.clearValidate?.();
}); });

View File

@@ -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>仅允许导入 xlsxlsx 格式文件</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>

View File

@@ -205,14 +205,12 @@ const removeBatch = async () => {
const res=await PersonApi.removeSessionStu(data); const res=await PersonApi.removeSessionStu(data);
if(res =='删除成功'){ if(res =='删除成功'){
message.success(t('common.delSuccess')) message.success('删除成功');
}else{ }else{
message.error(res) message.error(res)
} }
await getPersonList(); // 删除后刷新右侧列表 await getPersonList(); // 删除后刷新右侧列表
emit('done'); emit('done');
ElMessage.success('删除成功');
}; };
const exportData = () => { const exportData = () => {

View File

@@ -8,10 +8,26 @@
:inline="true" :inline="true"
label-width="68px" 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-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <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 @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 <el-button
type="primary" type="primary"
@@ -83,6 +99,7 @@
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" /> <person-edit v-model="showEdit" :task-Id="props.taskId" @done="reload" />
<PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" /> <PersonSearch :task-id="props.taskId" v-model="showPersonEdit" ref="stuAddRef" @done="reload" />
<StudentImportForm ref="importFormRef" @success="getList" :task-id="props.taskId"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 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 * as SmsPersonlApi from '@/api/system/person';
import PersonEdit from './components/person-edit.vue'; import PersonEdit from './components/person-edit.vue';
import PersonSearch from './components/person-serach.vue' import PersonSearch from './components/person-serach.vue'
import StudentImportForm from './components/StudentImportForm.vue'
import * as SmsChannelApi from '@/api/system/session'; import * as SmsChannelApi from '@/api/system/session';
import { fa } from 'element-plus/es/locale'; import { fa } from 'element-plus/es/locale';
@@ -133,8 +151,7 @@ const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
signature: undefined, batch: undefined,
status: undefined,
createTime: [], createTime: [],
taskId: props.taskId 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) => { const handleDelete = async (id: number) => {