提交 ac5e09be authored 作者: lhh's avatar lhh

11.27需求修改

上级 5cd99fb3
......@@ -21,7 +21,7 @@ watchEffect(() => {
...item,
old_score: parseFloat(item.old_score),
ratio: parseFloat(item.ratio),
score: isNaN(parseFloat(item.score)) ? null : parseFloat(item.score)
score: isNaN(parseFloat(item.score)) ? 'null' : parseFloat(item.score)
}
})
})
......@@ -43,7 +43,9 @@ const score = $computed(() => {
// 提交
function handleSubmit() {
const scores = tableList.map((item: any) => {
if (item.type === '2') { item.score = 0 }
if (item.type === '2') {
item.score = 0
}
return { id: item.id, score: item.score }
})
const params = { id: detail.id, scores: JSON.stringify(scores) }
......@@ -75,7 +77,7 @@ const handleScoreRule = function () {
<el-form-item label="选手姓名">{{ detail.student_name }}</el-form-item>
<el-form-item label="选手ID">{{ detail.login_id }}</el-form-item>
<div style="display: flex; justify-content: space-between">
<el-form-item label="报告">
<el-form-item label="报告" v-if="reportList.length">
<el-dropdown>
<el-button text>
查看报告<el-icon class="el-icon--right"><arrow-down /></el-icon>
......@@ -89,7 +91,7 @@ const handleScoreRule = function () {
</template>
</el-dropdown>
</el-form-item>
<el-button type="primary" @click="handleScoreRule">查看评分规则</el-button>
<el-button type="primary" style="margin-bottom: 20px" @click="handleScoreRule">查看评分规则</el-button>
</div>
</el-form>
<el-table :data="tableList" :header-cell-style="{ background: '#ededed' }">
......@@ -100,6 +102,7 @@ const handleScoreRule = function () {
<el-table-column label="评分" prop="score" align="center">
<template #default="{ row }">
<el-input-number
:disabled="row.type === '2'"
:controls="false"
v-model="row.score"
step-strictly
......@@ -107,10 +110,11 @@ const handleScoreRule = function () {
:min="0"
:max="row.old_score"
style="width: 100%"
placeholder="--"
/>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<el-table-column label="操作" align="center" v-if="false">
<template #default="{ row }">
<el-button text type="primary" v-if="row.type === '2'">
<a :href="`${qaURL}/exam/markingPaper?exam_id=${row.exam_id}&id_number=${detail.id_number}`" target="_blank"
......
......@@ -29,7 +29,7 @@ function scoreMethodText(value: string) {
</script>
<template>
<el-dialog title="同步1+X考试成绩" :close-on-click-modal="false">
<el-dialog title="同步1+同步线上考试成绩" :close-on-click-modal="false">
<el-form>
<el-form-item label="赛项名称">
<el-select v-model="form.competition" value-key="id">
......
......@@ -29,10 +29,10 @@ onMounted(() => {
fetchCompetition()
})
const platformKey = ref('career_data_analysis')
const platformKey = ref('data_marketing')
const platformKeys = ref([
{ platform_key: 'career_data_analysis', name: '商业数据分析实验' },
{ platform_key: 'data_marketing', name: '数据营销实操' },
{ platform_key: 'data_marketing', name: '数据营销实操' }
])
// async function fetchPlatformKeys(competition_id: string) {
// const res = await getPlatformKeys({ competition_id })
......@@ -62,7 +62,7 @@ onUnmounted(() => {
const statistics = reactive({
competitor_count: 0,
complete_answer_competitor_count: 0,
starting_answer_competitor_count: 0,
starting_answer_competitor_count: 0
})
async function fetchStatistics(competition_id: string, platform_key = 'career_data_analysis') {
const res = await getCompetitionStatistics({ competition_id, platform_key })
......@@ -97,8 +97,8 @@ const submittedListOptions = {
{ label: '所在专业', prop: 'student.specialty_name' },
{ label: '所在班级', prop: 'student.class_name' },
{ label: '提交时间', prop: 'commit_time' },
{ label: '作答用时', prop: 'answer_time' },
],
{ label: '作答用时', prop: 'answer_time' }
]
}
const submittedLis = computed(() => {
return competitorsTableData.value.filter((item: any) => item.commit_status == 3)
......@@ -114,9 +114,9 @@ const answeringListOptions = {
{ label: '所在班级', prop: 'student.class_name' },
{
label: '作答用时',
prop: 'answer_time',
},
],
prop: 'answer_time'
}
]
}
const answeringList = computed(() => {
return competitorsTableData.value.filter((item: any) => item.commit_status == 2 || item.commit_status == 4)
......@@ -137,44 +137,44 @@ const listOptions = {
prop: 'module_1',
computed({ row }: { row: any }) {
return getModuleStatus(row, 0)
},
}
},
{
label: '模块二',
prop: 'module_2',
computed({ row }: { row: any }) {
return getModuleStatus(row, 1)
},
}
},
{
label: '模块三',
prop: 'module_3',
computed({ row }: { row: any }) {
return getModuleStatus(row, 2)
},
}
},
{
label: '模块四',
prop: 'module_4',
computed({ row }: { row: any }) {
return getModuleStatus(row, 3)
},
}
},
{
label: '模块五',
prop: 'module_5',
computed({ row }: { row: any }) {
return getModuleStatus(row, 4)
},
}
},
{
label: '模块六',
prop: 'module_6',
computed({ row }: { row: any }) {
return getModuleStatus(row, 5)
},
},
],
}
}
]
}
function getModuleStatus(row: any, index: number) {
try {
......@@ -201,12 +201,13 @@ function getModuleStatus(row: any, index: number) {
<el-select v-model="currentCompetition" value-key="id" size="large" style="margin-right: 20px">
<el-option v-for="item in competitionList" :key="item.id" :value="item" :label="item.name"></el-option>
</el-select>
<el-select v-model="platformKey" size="large">
<el-select v-model="platformKey" size="large" v-if="false">
<el-option
v-for="item in platformKeys"
:key="item.platform_key"
:value="item.platform_key"
:label="item.name"></el-option>
:label="item.name"
></el-option>
</el-select>
</el-row>
<ul class="statistics">
......
......@@ -37,6 +37,7 @@ const listOptions = $computed(() => {
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '专家姓名', prop: 'name' },
{ label: '电话', prop: 'mobile' },
{ label: '所在单位', prop: 'company' },
{
label: '性别',
......
......@@ -20,6 +20,7 @@ const listOptions = {
{ label: '序号', type: 'index', width: 60 },
{ label: '选手姓名', prop: 'student.name' },
{ label: '参赛ID', prop: 'login_id' },
{ label: '电话', prop: 'mobile' },
{
label: '性别',
prop: 'student.gender',
......
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import type { ContestItem, ContestCreateParams, ContestUpdateParams } from '../types'
import { ElMessage } from 'element-plus'
import { pick } from 'lodash-es'
import dayjs from 'dayjs'
import isBetween from 'dayjs/plugin/isBetween'
import { createContest, updateContest, getExamList } from '../api'
import { useMapStore } from '@/stores/map'
import { useGetTeacherList } from '../composables/useGetTeacherList'
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
interface Props {
data?: ContestItem | null
}
const props = defineProps<Props>()
const emit = defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
dayjs.extend(isBetween)
// 赛项类型
const types = useMapStore().getMapValuesByKey('competition_type')
// 主办单位
const hostUnitList = useMapStore().getMapValuesByKey('host_unit')
// 承办单位
const organizerList = useMapStore().getMapValuesByKey('organizer')
// 技术支持单位
const technicalSupportUnitList = useMapStore().getMapValuesByKey('technical_support_unit')
// 数据状态
const status = useMapStore().getMapValuesByKey('system_status')
// 指导老师
const { teachers } = useGetTeacherList()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
client_id: '',
host_unit_id: '',
organizer_ids: [],
technical_support_unit_id: '',
type: '1',
teacher_ids: [],
apply_expiration_date: '',
status: '1',
logo: '',
cover: '',
train_platform_uri: '',
competition_uri: '',
dateRange: undefined,
date: undefined,
datetimeRange: undefined,
datetimeRange2: undefined,
is_switchable_theory_practice: 0,
train_platform_configs: [
{ name: appConfig.xTrainLabel || '1+X理论考试', is_show: '1', type: '1', url: '', platform_key: 'x_exam' },
{
name: appConfig.labTrainLabel || '商业数据分析实验',
is_show: '0',
type: '2',
url: '',
platform_key: 'career_data_analysis'
},
{ name: '数据营销实操', is_show: '0', type: '2', url: '', platform_key: 'data_marketing' }
],
competition_platform_configs: [
{
name: appConfig.xExamLabel || '1+X理论考试',
is_show: '1',
type: '1',
url: '',
exam_id: '',
platform_key: 'x_exam'
},
// {
// name: appConfig.labExamLabel || '商业数据分析实验',
// is_show: '0',
// type: '2',
// url: '',
// platform_key: 'career_data_analysis'
// },
{ name: '数据营销实操', is_show: '0', type: '2', url: '', platform_key: 'data_marketing' }
]
})
watchEffect(() => {
if (!props.data) return
const host_unit_id = props.data.host_unit.id
const organizer_ids = props.data.organizers.map(item => item.id)
const technical_support_unit_id = props.data.technical_support_unit.id
const teacher_ids = props.data.teachers.map(item => item.id)
const dateRange = [new Date(props.data.start_range * 1000), new Date(props.data.end_range * 1000)]
const date = new Date(props.data.start_at * 1000)
const datetimeRange = [new Date(props.data.start_at * 1000), new Date(props.data.end_at * 1000)]
const datetimeRange2 = [
new Date(props.data.operational_start_time * 1000),
new Date(props.data.operational_end_time * 1000)
]
const is_switchable_theory_practice = parseInt(props.data.is_switchable_theory_practice)
const apply_expiration_date = props.data.apply_expiration_date * 1000
Object.assign(form, props.data, {
host_unit_id,
organizer_ids,
technical_support_unit_id,
teacher_ids,
dateRange,
date,
datetimeRange,
datetimeRange2,
apply_expiration_date,
is_switchable_theory_practice
})
})
const checkApplyExpirationDate = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error('请选择报名截止日期'))
} else {
const [firstDate, secondDate] = form.dateRange || []
if (
!dayjs(value).isBetween(firstDate, secondDate, 'date', '[]') ||
!dayjs(value).isBefore(dayjs(form.date), 'date')
) {
callback(new Error('请选择赛项周期内的日期,且必须早于正式比赛日期'))
}
callback()
}
}
const checkTrainPlatformConfigs = (rule: any, value: any, callback: any) => {
const findItem = function (a: any, b: any) {
return form.train_platform_configs.find((item: any) => item[a] === b)
}
// 判断最少选择一项目
if (!findItem('is_show', '1')) {
callback(new Error('最少选择一项'))
} else {
form.train_platform_configs.forEach((item: any) => {
if (item.is_show === '1') {
if (item.type === '1') {
if (item.exam_id === '') {
callback(new Error(`请选择${item.name}`))
} else {
callback()
}
} else {
if (item.url === '') {
callback(new Error(`请填写${item.name}的链接`))
} else {
callback()
}
}
}
})
}
}
const checkCompetitionPlatformConfigs = (rule: any, value: any, callback: any) => {
const findItem = function (a: any, b: any) {
return form.competition_platform_configs.find((item: any) => item[a] === b)
}
// 判断最少选择一项目
if (!findItem('is_show', '1')) {
callback(new Error('最少选择一项'))
} else {
form.competition_platform_configs.forEach((item: any) => {
if (item.is_show === '1') {
if (item.type === '1') {
if (item.exam_id === '') {
callback(new Error(`请选择${item.name}`))
} else {
callback()
}
} else {
if (item.url === '') {
callback(new Error(`请填写${item.name}的链接`))
} else {
callback()
}
}
}
})
}
}
const rules = ref<FormRules>({
name: [{ required: true, message: '请输入赛项名称' }],
host_unit_id: [{ required: true, message: '请选择主办单位' }],
organizer_ids: [{ type: 'array', required: true, message: '请选择承办单位' }],
technical_support_unit_id: [{ required: true, message: '请选择技术支持单位' }],
type: [{ required: true, message: '请选择赛项类型' }],
teacher_ids: [{ type: 'array', required: true, message: '请选择指导教师', trigger: 'change' }],
dateRange: [{ type: 'array', required: true, message: '请选择赛项周期', trigger: 'change' }],
date: [{ required: true, message: '请选择正式比赛日期', trigger: 'change' }],
datetimeRange: [{ type: 'array', required: true, message: '正式比赛理论答题时间', trigger: 'change' }],
datetimeRange2: [{ type: 'array', required: true, message: '正式比赛实操答题时间', trigger: 'change' }],
apply_expiration_date: [
{ required: true, message: '请选择报名截止日期' },
{
validator: checkApplyExpirationDate,
message: '请选择赛项周期内的日期,且必须早于正式比赛日期'
}
],
// train_platform_uri: [{ required: true, message: '请输入训练平台地址' }],
// competition_uri: [{ required: true, message: '请输入正式比赛地址' }],
status: [{ required: true, message: '请选择有效状态' }],
is_switchable_theory_practice: [{ required: true, message: '请选择' }],
logo: [{ required: true, message: '请上传赛项LOGO' }],
cover: [{ required: true, message: '请上传赛项封面' }],
train_platform_configs: [{ required: true, message: '' }, { validator: checkTrainPlatformConfigs }],
competition_platform_configs: [{ required: true, message: '' }, { validator: checkCompetitionPlatformConfigs }]
})
const isUpdate = $computed(() => {
return !!form.id
})
const title = $computed(() => {
return isUpdate ? '编辑赛项' : '新增赛项'
})
// 是否禁用赛项周期
// const disabledRange = $computed(() => {
// const [firstDate, secondDate] = form.dateRange || []
// return isUpdate && dayjs().isBetween(firstDate, secondDate, 'date', '[]')
// })
// 提交
function handleSubmit() {
function containsNumber(A: number, B: number): boolean {
// 将数字A和B转换成字符串,并检查A的字符串是否包含B的字符串
return A.toString().includes(B.toString())
}
formRef?.validate().then(() => {
const [firstDate, secondDate] = form.dateRange || []
const [firstDatetime, secondDatetime] = form.datetimeRange || []
const [firstDatetime2, secondDatetime2] = form.datetimeRange2 || []
const year = dayjs(form.date).year()
const month = dayjs(form.date).month()
const date = dayjs(form.date).date()
const mergedForm = {
...form,
organizer_ids: JSON.stringify(form.organizer_ids),
// teacher_ids: form.teacher_ids.join(','),
start_range: dayjs(firstDate).unix(),
end_range: dayjs(secondDate).endOf('date').unix(),
start_at: dayjs(firstDatetime).year(year).month(month).date(date).unix(),
end_at: dayjs(secondDatetime).year(year).month(month).date(date).unix(),
operational_start_time: dayjs(firstDatetime2).year(year).month(month).date(date).unix(),
operational_end_time: dayjs(secondDatetime2).year(year).month(month).date(date).unix(),
apply_expiration_date: dayjs(form.apply_expiration_date).endOf('date').unix()
}
// 判断正式比赛理论答题时间和选择的考试
const findExam = examList.find(item => item.exam_id === form.competition_platform_configs[0].exam_id)
const examStartTime = new Date(findExam?.start_time || '').getTime()
const examEndTime = new Date(findExam?.end_time || '').getTime()
// console.log(containsNumber(examStartTime, mergedForm.start_at), containsNumber(examEndTime, mergedForm.end_at))
const findXItem = form.competition_platform_configs.find(item => item.type === '1')
console.log(findXItem, 'findXItem', form.competition_platform_configs)
if (findXItem?.is_show === '1') {
if (
containsNumber(examStartTime, mergedForm.start_at) !== true ||
containsNumber(examEndTime, mergedForm.end_at) !== true
) {
ElMessage({ message: `正式比赛理论答题时间与${findExam?.name}的考试时间不符`, type: 'warning' })
return false
}
}
const params: ContestUpdateParams = pick(mergedForm, [
'operational_start_time',
'operational_end_time',
'id',
'name',
'client_id',
'host_unit_id',
'organizer_ids',
'technical_support_unit_id',
'type',
'start_range',
'end_range',
'start_at',
'end_at',
'apply_expiration_date',
'status',
'logo',
'cover',
// 'train_platform_uri',
// 'competition_uri',
'teacher_ids',
'train_platform_configs',
'competition_platform_configs',
'is_switchable_theory_practice'
])
console.log(isUpdate, 'isUpdate')
isUpdate ? handleUpdate(params) : handleCreate(params)
})
}
// 新增
function handleCreate(params: ContestCreateParams) {
// console.log(params, 'aaa')
createContest(params).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate(params: ContestUpdateParams) {
updateContest(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 赛项周期改变
function handleDateRangeChange(value: any) {
if (value) {
const [, secondDate] = form.dateRange || []
form.date = secondDate
}
}
const clientList = [
{ label: '商务数据分析师赛项', value: 'business_data_analyst' },
{ label: '全媒体运营师赛项', value: 'all_media_operator' },
{ label: '网络主播赛项', value: 'network_anchor_competition' }
]
let examList = $ref<Record<string, any>[]>([])
// 获取关联考试列表
function fetchExamList() {
getExamList({ project: 'x1', 'per-page': 1000 }).then(res => {
examList = res.data.list || []
})
}
onMounted(() => {
fetchExamList()
})
</script>
<template>
<el-dialog
:title="title"
:close-on-click-modal="false"
align-center
width="600px"
@update:modelValue="value => $emit('update:modelValue', value)"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="165px">
<el-form-item label="客户端标识" prop="client_id">
<el-select v-model="form.client_id" style="width: 100%" clearable>
<el-option v-for="item in clientList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="赛项名称" prop="name">
<el-input v-model="form.name" :disabled="isUpdate" />
</el-form-item>
<el-form-item label="主办单位" prop="host_unit_id">
<el-select v-model="form.host_unit_id" style="width: 100%">
<el-option v-for="item in hostUnitList" :key="item.id" :label="item.label" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="承办单位" prop="organizer_ids">
<el-select v-model="form.organizer_ids" multiple style="width: 100%">
<el-option v-for="item in organizerList" :key="item.id" :label="item.label" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="技术支持单位" prop="technical_support_unit_id">
<el-select v-model="form.technical_support_unit_id" style="width: 100%">
<el-option
v-for="item in technicalSupportUnitList"
:key="item.id"
:label="item.label"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="赛项类型" prop="type">
<el-radio-group v-model="form.type">
<el-radio v-for="item in types" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="指导教师" prop="teacher_ids">
<el-select v-model="form.teacher_ids" multiple style="width: 100%">
<el-option v-for="item in teachers" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="赛项周期" prop="dateRange">
<el-date-picker
type="daterange"
range-separator="至"
v-model="form.dateRange"
style="width: 100%"
@change="handleDateRangeChange"
/>
</el-form-item>
<el-form-item label="正式比赛日期" prop="date">
<el-date-picker type="date" v-model="form.date" style="width: 100%" />
</el-form-item>
<el-form-item label="正式比赛理论答题时间" prop="datetimeRange">
<el-time-picker
is-range
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="form.datetimeRange"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="正式比赛实操答题时间" prop="datetimeRange2">
<el-time-picker
is-range
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="form.datetimeRange2"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="报名截止日期" prop="apply_expiration_date">
<el-date-picker type="date" v-model="form.apply_expiration_date" style="width: 100%" />
</el-form-item>
<el-form-item label="训练平台地址" prop="train_platform_configs">
<el-checkbox
true-label="1"
false-label="0"
style="margin-bottom: 10px"
v-model="item.is_show"
v-for="item in form.train_platform_configs"
:key="item.platform_key"
>
<div style="display: flex; align-items: center">
<!-- <span style="margin-right: 10px; width: 180px">{{ item.name }}</span> -->
<el-input v-model="item.name" style="margin-right: 10px; max-width: 130px" />
<el-input v-model="item.url" style="width: 200px" />
</div>
</el-checkbox>
</el-form-item>
<el-form-item label="正式比赛地址" prop="competition_platform_configs">
<el-checkbox
true-label="1"
false-label="0"
style="margin-bottom: 10px"
v-model="item.is_show"
v-for="item in form.competition_platform_configs"
:key="item.platform_key"
>
<div style="display: flex; align-items: center">
<!-- <span style="margin-right: 10px; width: 180px">{{ item.name }}</span> -->
<el-input v-model="item.name" style="margin-right: 10px; max-width: 130px" />
<el-input v-model="item.url" v-if="item.type === '2'" style="width: 200px" />
<el-select v-model="item.exam_id" filterable style="width: 200px" v-if="item.type === '1'">
<el-option
v-for="item in examList"
:key="item.exam_id"
:label="item.name"
:value="item.exam_id"
></el-option>
</el-select>
</div>
</el-checkbox>
</el-form-item>
<el-form-item label="是否允许客户端切换" prop="is_switchable_theory_practice">
<el-radio-group v-model="form.is_switchable_theory_practice">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="有效状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="item in status" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="赛项LOGO" prop="logo">
<AppUpload v-model="form.logo" accept="image/*"></AppUpload>
</el-form-item>
<el-form-item label="赛项封面" prop="cover">
<AppUpload v-model="form.cover" accept="image/*"></AppUpload>
</el-form-item>
<el-row justify="center">
<el-button type="primary" round auto-insert-space @click="handleSubmit">保存</el-button>
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
</el-row>
</el-form>
</el-dialog>
</template>
......@@ -60,6 +60,7 @@ const form = reactive({
datetimeRange: undefined,
datetimeRange2: undefined,
is_switchable_theory_practice: 0,
is_customer_anti_cheat: 0,
train_platform_configs: [
{ name: appConfig.xTrainLabel || '1+X理论考试', is_show: '1', type: '1', url: '', platform_key: 'x_exam' },
{
......@@ -104,6 +105,9 @@ watchEffect(() => {
new Date(props.data.operational_end_time * 1000)
]
const is_switchable_theory_practice = parseInt(props.data.is_switchable_theory_practice)
const is_customer_anti_cheat = parseInt(props.data?.is_customer_anti_cheat) || 0
const type = props.data?.type + ''
const status = props.data?.status + ''
const apply_expiration_date = props.data.apply_expiration_date * 1000
Object.assign(form, props.data, {
host_unit_id,
......@@ -115,7 +119,10 @@ watchEffect(() => {
datetimeRange,
datetimeRange2,
apply_expiration_date,
is_switchable_theory_practice
is_switchable_theory_practice,
is_customer_anti_cheat,
type,
status
})
})
const checkApplyExpirationDate = (rule: any, value: any, callback: any) => {
......@@ -210,6 +217,7 @@ const rules = ref<FormRules>({
// competition_uri: [{ required: true, message: '请输入正式比赛地址' }],
status: [{ required: true, message: '请选择有效状态' }],
is_switchable_theory_practice: [{ required: true, message: '请选择' }],
is_customer_anti_cheat: [{ required: true, message: '请选择' }],
logo: [{ required: true, message: '请上传赛项LOGO' }],
cover: [{ required: true, message: '请上传赛项封面' }],
train_platform_configs: [{ required: true, message: '' }, { validator: checkTrainPlatformConfigs }],
......@@ -218,9 +226,6 @@ const rules = ref<FormRules>({
const isUpdate = $computed(() => {
return !!form.id
})
const title = $computed(() => {
return isUpdate ? '编辑赛项' : '新增赛项'
})
// 是否禁用赛项周期
// const disabledRange = $computed(() => {
// const [firstDate, secondDate] = form.dateRange || []
......@@ -292,7 +297,8 @@ function handleSubmit() {
'teacher_ids',
'train_platform_configs',
'competition_platform_configs',
'is_switchable_theory_practice'
'is_switchable_theory_practice',
'is_customer_anti_cheat'
])
console.log(isUpdate, 'isUpdate')
isUpdate ? handleUpdate(params) : handleCreate(params)
......@@ -343,52 +349,22 @@ onMounted(() => {
</script>
<template>
<el-dialog
:title="title"
:close-on-click-modal="false"
align-center
width="600px"
@update:modelValue="value => $emit('update:modelValue', value)"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="165px">
<el-form-item label="客户端标识" prop="client_id">
<el-select v-model="form.client_id" style="width: 100%" clearable>
<el-option v-for="item in clientList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<div style="display: flex">
<div style="flex: 1; margin-right: 10px">
<el-form-item label="赛项名称" prop="name">
<el-input v-model="form.name" :disabled="isUpdate" />
</el-form-item>
<el-form-item label="主办单位" prop="host_unit_id">
<el-select v-model="form.host_unit_id" style="width: 100%">
<el-option v-for="item in hostUnitList" :key="item.id" :label="item.label" :value="item.id"></el-option>
</el-select>
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="承办单位" prop="organizer_ids">
<el-select v-model="form.organizer_ids" multiple style="width: 100%">
<el-option v-for="item in organizerList" :key="item.id" :label="item.label" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="技术支持单位" prop="technical_support_unit_id">
<el-select v-model="form.technical_support_unit_id" style="width: 100%">
<el-option
v-for="item in technicalSupportUnitList"
:key="item.id"
:label="item.label"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="赛项类型" prop="type">
<el-radio-group v-model="form.type">
<el-radio v-for="item in types" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="指导教师" prop="teacher_ids">
<el-select v-model="form.teacher_ids" multiple style="width: 100%">
<el-option v-for="item in teachers" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="赛项周期" prop="dateRange">
<el-date-picker
type="daterange"
......@@ -411,19 +387,6 @@ onMounted(() => {
style="width: 100%"
/>
</el-form-item>
<el-form-item label="正式比赛实操答题时间" prop="datetimeRange2">
<el-time-picker
is-range
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="form.datetimeRange2"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="报名截止日期" prop="apply_expiration_date">
<el-date-picker type="date" v-model="form.apply_expiration_date" style="width: 100%" />
</el-form-item>
<el-form-item label="训练平台地址" prop="train_platform_configs">
<el-checkbox
true-label="1"
......@@ -440,6 +403,69 @@ onMounted(() => {
</div>
</el-checkbox>
</el-form-item>
<el-form-item label="指导教师" prop="teacher_ids">
<el-select v-model="form.teacher_ids" multiple style="width: 100%">
<el-option v-for="item in teachers" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="实操赛题标签名称" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="实操环境标签名称" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="实操报告标签名称" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="实操答题标签名称" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="有效状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="item in status" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div style="flex: 1; margin-left: 10px">
<el-form-item label="主办单位" prop="host_unit_id">
<el-select v-model="form.host_unit_id" style="width: 100%">
<el-option v-for="item in hostUnitList" :key="item.id" :label="item.label" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="技术支持单位" prop="technical_support_unit_id">
<el-select v-model="form.technical_support_unit_id" style="width: 100%">
<el-option
v-for="item in technicalSupportUnitList"
:key="item.id"
:label="item.label"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="客户端" prop="type">
<el-radio-group v-model="form.type">
<el-radio v-for="item in types" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item label="客户端标识" prop="client_id">
<el-select v-model="form.client_id" style="width: 100%" clearable>
<el-option v-for="item in clientList" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="报名截止日期" prop="apply_expiration_date">
<el-date-picker type="date" v-model="form.apply_expiration_date" style="width: 100%" />
</el-form-item>
<el-form-item label="正式比赛实操答题时间" prop="datetimeRange2">
<el-time-picker
is-range
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="form.datetimeRange2"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="正式比赛地址" prop="competition_platform_configs">
<el-checkbox
true-label="1"
......@@ -470,21 +496,31 @@ onMounted(() => {
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="有效状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="item in status" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
<el-form-item label="客户端防作弊" prop="is_customer_anti_cheat">
<el-radio-group v-model="form.is_customer_anti_cheat">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="客户端切换理论与实操" prop="is_switchable_theory_practice">
<el-radio-group v-model="form.is_switchable_theory_practice">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="赛项LOGO" prop="logo">
<AppUpload v-model="form.logo" accept="image/*"></AppUpload>
</el-form-item>
<el-form-item label="赛项封面" prop="cover">
<AppUpload v-model="form.cover" accept="image/*"></AppUpload>
</el-form-item>
</div>
</div>
<el-row justify="center">
<el-button type="primary" round auto-insert-space @click="handleSubmit">保存</el-button>
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
</el-row>
</el-form>
</el-dialog>
</template>
......@@ -43,6 +43,7 @@ const listOptions = $computed(() => {
{ type: 'expand', slots: 'class' },
{ label: '序号', type: 'index', width: 60 },
{ label: '专家姓名', prop: 'name' },
{ label: '电话', prop: 'mobile' },
{ label: '所在单位', prop: 'company' },
{
label: '性别',
......
......@@ -11,7 +11,8 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: ':id', component: () => import('./views/View.vue'), props: true }
{ path: ':id', component: () => import('./views/View.vue'), props: true },
{ path: 'edit/:id', component: () => import('./views/Edit.vue'), props: true }
]
}
]
......@@ -34,7 +34,8 @@ export interface ContestItem {
expert_count: number
train_platform_configs: any[]
competition_platform_configs: any[]
is_switchable_theory_practice: string
is_switchable_theory_practice: string,
is_customer_anti_cheat: string
}
export interface ContestCreateParams {
......
<script setup lang="ts">
import type { ContestItem } from '../types'
// import { ElMessage } from 'element-plus'
import { getContest } from '../api'
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
interface Props {
id: string
}
const props = defineProps<Props>()
let detail = $ref<ContestItem | null>(null)
provide('detail', $$(detail))
// 获取赛项信息
function fetchInfo() {
getContest({ id: props.id }).then(res => {
detail = res.data.detail
})
}
onMounted(() => {
if (props.id === '1') return
fetchInfo()
})
</script>
<template>
<AppCard title="编辑赛项">
<FormDialog :data="detail"></FormDialog>
</AppCard>
</template>
<style lang="scss">
.top {
display: flex;
.el-descriptions {
flex: 1;
margin-top: 30px;
}
}
.top-cover {
width: 300px;
margin-right: 20px;
p {
font-weight: normal;
line-height: 30px;
font-size: 14px;
}
img {
width: 100%;
}
}
</style>
......@@ -8,7 +8,7 @@ import { useMapStore } from '@/stores/map'
// 赛项类型
const types = useMapStore().getMapValuesByKey('competition_type')
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
// const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null)
......@@ -50,31 +50,34 @@ const listOptions = {
]
}
let dialogVisible = $ref(false)
const rowData = ref<ContestItem | undefined | null>(null)
// let dialogVisible = $ref(false)
// const rowData = ref<ContestItem | undefined | null>(null)
// 新增
function handleAdd() {
rowData.value = null
dialogVisible = true
}
// 编辑
function handleUpdate(row: ContestItem) {
rowData.value = row
dialogVisible = true
}
// function handleAdd() {
// rowData.value = null
// dialogVisible = true
// }
// // 编辑
// function handleUpdate(row: ContestItem) {
// rowData.value = row
// dialogVisible = true
// }
function onUpdateSuccess() {
appList?.refetch()
}
// function onUpdateSuccess() {
// appList?.refetch()
// }
</script>
<template>
<AppCard title="赛项管理">
<AppList v-bind="listOptions" ref="appList">
<template #header-buttons>
<el-button type="primary" :icon="CirclePlus" v-permission="'competition-create'" @click="handleAdd">
<!-- <el-button type="primary" :icon="CirclePlus" v-permission="'competition-create'" @click="handleAdd">
新增赛项
</el-button> -->
<el-button type="primary" :icon="CirclePlus" round v-permission="'competition-create'">
<router-link :to="`/admin/contest/items/edit/1`" target="_blank">新增赛项</router-link>
</el-button>
</template>
......@@ -82,9 +85,14 @@ function onUpdateSuccess() {
<el-button type="primary" round v-permission="'competition-detail'">
<router-link :to="`/admin/contest/items/${row.id}`" target="_blank">查看</router-link>
</el-button>
<el-button type="primary" round @click="handleUpdate(row)" v-permission="'competition-edit'">编辑</el-button>
<el-button type="primary" round v-permission="'competition-detail'">
<router-link :to="`/admin/contest/items/edit/${row.id}`" target="_blank" v-permission="'competition-edit'"
>编辑</router-link
>
</el-button>
<!-- <el-button type="primary" round @click="handleUpdate(row)" v-permission="'competition-edit'">编辑</el-button> -->
</template>
</AppList>
</AppCard>
<FormDialog v-model="dialogVisible" :data="rowData" @update="onUpdateSuccess" v-if="dialogVisible"></FormDialog>
<!-- <FormDialog v-model="dialogVisible" :data="rowData" @update="onUpdateSuccess" v-if="dialogVisible"></FormDialog> -->
</template>
......@@ -161,16 +161,16 @@ function handleExperts() {
<AppCard title="训练指导书">
<ViewBook :id="id"></ViewBook>
</AppCard>
<AppCard title="操作视频">
<AppCard title="训练操作视频">
<ViewVideo :id="id"></ViewVideo>
</AppCard>
<AppCard title="大赛试题">
<AppCard title="比赛实操赛题">
<ViewQuestion :id="id"></ViewQuestion>
</AppCard>
<AppCard title="大赛试卷">
<AppCard title="比赛实操试卷">
<ViewExam :id="id"></ViewExam>
</AppCard>
<AppCard title="关联实验">
<AppCard title="关联营销实验">
<ViewExperiment :id="detail?.id || ''" :pid="id"></ViewExperiment>
</AppCard>
<AppCard title="抽签加密">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论