123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- <template>
- <div class="p-base full">
- <el-card shadow="never">
- <base-form
- ref="formRef"
- :label-width="'150px'"
- size="small"
- :groups="groups"
- :model="model"
- :items="items"
- :rules="rules"
- :disabled="adding || editing"
- >
- <template #form-item-setLevelRange>
- <div class="flex items-center">
- <el-input :model-value="levelRangeView" :disabled="true"></el-input>
- <el-button class="m-l-base" type="primary" @click="setLevelRangeVisible = true">设置</el-button>
- </div>
- </template>
- <template #form-item-expand>
- <el-button type="primary" link @click="expand = !expand">高级设置</el-button>
- </template>
- <template #form-item-operation>
- <confirm-button
- :loading="adding || editing"
- ok-text="保存"
- @confirm="onSubmit"
- @cancel="onCancel"
- ></confirm-button>
- </template>
- <template #form-item-compare>
- <el-select v-model="compare" :disabled="isEdit" @change="compareChange">
- <el-option value="1" label="启用"></el-option>
- <el-option value="0" label="不启用"></el-option>
- </el-select>
- </template>
- </base-form>
- </el-card>
- </div>
- <base-dialog v-model="setLevelRangeVisible" title="档次设置" destroy-on-close :width="340">
- <div class="level-list">
- <div v-for="([start, end], index) in levelRanges" :key="index" class="flex items-center level-row">
- <div class="m-r-large level-label flex items-center justify-between">
- <span class="s1">档次{{ (start + end) / 2 }}</span>
- <span class="s2">-</span>
- <span class="s3">({{ start }}~{{ end }})</span>
- </div>
- <div class="flex items-center level-input">
- <el-input-number
- v-model="levelRangValues[index]"
- class="m-r-mini"
- size="small"
- :min="0"
- :max="100"
- :controls="false"
- style="width: 100px"
- @keyup="levelItemChange(index, $event)"
- ></el-input-number>
- %
- </div>
- </div>
- </div>
- <template #footer>
- <div class="flex justify-center">
- <confirm-button @confirm="onSetLevelRangeSubmit" @cancel="setLevelRangeVisible = false"></confirm-button>
- </div>
- </template>
- </base-dialog>
- </template>
- <script setup lang="ts" name="SubjectAddQuestion">
- /** 添加大题 */
- import { computed, reactive, ref } from 'vue'
- import { useRouter } from 'vue-router'
- import { ElCard, ElButton, ElMessage, ElInput, ElInputNumber, ElSelect, ElOption } from 'element-plus'
- import { omit } from 'lodash-es'
- import ConfirmButton from '@/components/common/ConfirmButton.vue'
- import BaseDialog from '@/components/element/BaseDialog.vue'
- import BaseForm from '@/components/element/BaseForm.vue'
- import useFetch from '@/hooks/useFetch'
- import useForm from '@/hooks/useForm'
- import useVW from '@/hooks/useVW'
- import { TrueOrFalse } from '@/constants/dicts'
- import type { ExtractApiParams } from '@/api/api'
- import type { EpFormItem, EpFormRules, FormGroup } from 'global-type'
- const { fetch: getMainQuestionList, result: mainQuestionListResult } = useFetch('getMainQuestionList')
- const { back } = useRouter()
- const props = defineProps<{ subjectCode: string; mainNumber?: number | string }>()
- getMainQuestionList({ subjectCode: props.subjectCode, excludeNumber: props.mainNumber || undefined })
- const mainQuestionOptions = computed(() => {
- return (
- mainQuestionListResult.value?.map((v: any) => {
- return {
- ...v,
- label: `${v.mainNumber}-${v.title}`,
- value: v.mainNumber,
- }
- }) || []
- )
- })
- const isEdit = !!props.mainNumber
- // const levelRanges = [
- // [0, 2],
- // [3, 5],
- // [6, 8],
- // [9, 11],
- // [12, 14],
- // ]
- const levelRanges = [
- [0, 0],
- [1, 3],
- [4, 6],
- [7, 9],
- [10, 12],
- [13, 15],
- ]
- const levelItemChange = (index: number, e: any) => {
- if (Number(e.target.value) > 100) {
- levelRangValues.value[index] = 100
- e.target.value = 100
- }
- }
- const setLevelRangeVisible = ref<boolean>(false)
- const levelRangValues = ref<number[]>(Array.from<number>({ length: 6 }).fill(0))
- const { fetch: getMainQuestionInfo } = useFetch('getMainQuestionInfo')
- const { fetch: addMainQuestion, loading: adding } = useFetch('addMainQuestion')
- const { fetch: editMainQuestion, loading: editing } = useFetch('editMainQuestion')
- const model = reactive<ExtractApiParams<'addMainQuestion'>>({
- subjectCode: props.subjectCode,
- groupNumber: void 0,
- category: void 0,
- intervalScore: 1,
- mainNumber: void 0,
- mainTitle: '',
- minMarkTime: void 0,
- questionCount: void 0,
- questionScore: void 0,
- remarkNumber: void 0,
- remarkType: 'QUANTITY',
- levelRange: Array.from<number>({ length: 6 }).fill(0),
- standardRate: void 0,
- selfRate: void 0,
- systemRate: void 0,
- startNumber: 1,
- relationMainNumber: void 0,
- markSpeedLimit: false,
- })
- const compareChange = (val: string) => {
- if (val == '0') {
- model.relationMainNumber = void 0
- }
- }
- const levelRangeView = computed(() => {
- return model.levelRange.map((n) => `${n * 100 || 0}%`).join(',')
- })
- const { formRef, elFormRef, defineColumn, _ } = useForm()
- const validateSmallQuestion = (rule: any, value: any, callback: any) => {
- if (
- Number(model.questionCount) &&
- Number(model.questionScore) &&
- (model.questionCount as number) * (model.questionScore as number) > 15
- ) {
- callback(new Error('小题总分(小题数量乘以小题满分)不能大于15'))
- } else {
- callback()
- }
- }
- const rules = computed<EpFormRules>(() => {
- return {
- groupNumber: [{ required: true, message: '请输入小组数量' }],
- category: [{ required: false, message: '请选择成绩表对应字段' }],
- intervalScore: [{ required: true, message: '请输入小题间隔分' }],
- mainNumber: [{ required: true, message: '请输入大题号' }],
- mainTitle: [
- { required: true, message: '请输入大题名称' },
- { type: 'string', message: '大题名称限制50字以内' },
- ],
- minMarkTime: [{ required: true, message: '请输入最小阅卷时长' }],
- questionCount: [
- { required: true, message: '请输入小题数量' },
- { validator: validateSmallQuestion, trigger: 'change' },
- ],
- questionScore: [
- { required: true, message: '请输入小题满分' },
- { validator: validateSmallQuestion, trigger: 'change' },
- ],
- remarkType: [{ required: true, message: '请选择回评设置' }],
- remarkNumber: [{ required: true, message: '请输入回评设置' }],
- startNumber: [{ required: true, message: '请输入小题起始号' }],
- systemRate: [{ required: !!model.levelRange?.filter(Boolean)?.length, message: '请设置系统抽查比例' }],
- relationMainNumber: [{ required: true, message: '请选择关联大题' }],
- }
- })
- const expand = ref<boolean>(false)
- const compare = ref('0')
- const groups = computed<FormGroup[]>(() => {
- return [
- {
- rowKeys: Array.from({ length: 11 }).map((_, i) => `row-${i + 1}`),
- },
- {
- rowKeys: ['row-12', 'row-13', 'row-14'],
- groupTitle: '高级设置',
- hidden: !expand.value,
- },
- {
- rowKeys: ['expand'],
- hidden: expand.value,
- },
- ]
- })
- const Span8 = defineColumn(_, _, { span: 8 })
- const items = computed<any>(() =>
- [
- Span8(
- {
- label: '大题号',
- slotType: 'inputNumber',
- prop: 'mainNumber',
- slot: {
- placeholder: '大题号',
- disabled: isEdit,
- },
- },
- 'row-1'
- ),
- Span8({ label: '大题名称', slotType: 'input', prop: 'mainTitle', slot: { placeholder: '大题名称' } }, 'row-2'),
- Span8(
- {
- label: '成绩表对应字段',
- slotType: 'select',
- prop: 'category',
- slot: {
- placeholder: '成绩表对应字段',
- clearable: true,
- options: [
- { label: '作文分', value: 'WRITING' },
- { label: '翻译分', value: 'TRANSLATION' },
- ],
- },
- },
- 'row-2'
- ),
- Span8(
- {
- label: '小题起始号',
- slotType: 'inputNumber',
- prop: 'startNumber',
- slot: { placeholder: '小题起始号', disabled: isEdit, stepStrictly: true, step: 1, min: 0, max: 999999 },
- },
- 'row-3'
- ),
- Span8(
- {
- label: '小题数量',
- slotType: 'inputNumber',
- prop: 'questionCount',
- slot: { placeholder: '小题数量', stepStrictly: true, step: 1, min: 0, max: 999999 },
- },
- 'row-4'
- ),
- Span8(
- {
- label: '小题满分',
- slotType: 'inputNumber',
- prop: 'questionScore',
- slot: { placeholder: '小题满分', stepStrictly: true, step: 1, min: 0, max: 999999 },
- },
- 'row-5'
- ),
- Span8(
- {
- label: '间隔分',
- slotType: 'inputNumber',
- prop: 'intervalScore',
- slot: { placeholder: '间隔分', stepStrictly: true, step: 1, min: 0, max: 999999 },
- },
- 'row-6'
- ),
- Span8(
- {
- label: '最小阅卷时长(秒)',
- slotType: 'inputNumber',
- prop: 'minMarkTime',
- slot: { placeholder: '最小阅卷时长(秒)', stepStrictly: true, step: 1, min: 0, max: 9999999 },
- },
- 'row-7'
- ),
- Span8(
- {
- label: '评卷小组数量',
- slotType: 'inputNumber',
- prop: 'groupNumber',
- slot: { placeholder: '评卷小组数量', stepStrictly: true, step: 1, min: 0, max: 999999 },
- },
- 'row-8'
- ),
- Span8(
- {
- label: '回评设置',
- slotType: 'select',
- prop: 'remarkType',
- slot: {
- placeholder: '回评设置',
- disabled: isEdit,
- options: [
- { value: 'QUANTITY', label: '按数量' },
- { value: 'TIME', label: '按时间' },
- ],
- },
- },
- 'row-9'
- ),
- Span8(
- {
- label: model.remarkType === 'QUANTITY' ? '数量' : '时间:(近N分钟)',
- prop: 'remarkNumber',
- slotType: 'inputNumber',
- slot: {
- stepStrictly: true,
- step: 1,
- min: 0,
- max: 120,
- },
- },
- 'row-10'
- ),
- Span8(
- {
- label: '是否进行限速提醒',
- slotType: 'select',
- prop: 'markSpeedLimit',
- slot: {
- placeholder: '是否进行限速提醒',
- options: TrueOrFalse,
- },
- },
- 'row-11'
- ),
- Span8(
- {
- label: '标准卷分发频度',
- slotType: 'inputNumber',
- prop: 'standardRate',
- slot: { placeholder: '标准卷分发频度', stepStrictly: true, step: 1 },
- },
- 'row-12'
- ),
- Span8(
- {
- label: '自查卷分发频度',
- slotType: 'inputNumber',
- prop: 'selfRate',
- slot: { placeholder: '自查卷分发频度', stepStrictly: true, step: 1 },
- },
- 'row-12'
- ),
- Span8(
- {
- label: '系统抽查卷比例',
- slotType: 'inputNumber',
- prop: 'systemRate',
- slot: { placeholder: '系统抽查卷比例', stepStrictly: true, step: 1 },
- },
- 'row-13'
- ),
- Span8(
- {
- label: '档次抽查比例',
- slotName: 'setLevelRange',
- },
- 'row-13'
- ),
- Span8(
- {
- label: '人机抽查比对',
- slotName: 'compare',
- },
- 'row-14'
- ),
- compare.value == '1'
- ? Span8(
- {
- label: '关联大题',
- slotType: 'select',
- prop: 'relationMainNumber',
- slot: {
- clearable: true,
- options: mainQuestionOptions.value,
- disabled: isEdit,
- },
- },
- 'row-14'
- )
- : null,
- Span8({ slotName: 'expand' }, 'expand'),
- Span8({ slotName: 'operation' }, 'operation'),
- ].filter((v) => !!v)
- )
- if (isEdit) {
- getMainQuestionInfo({ subjectCode: props.subjectCode, mainNumber: +props.mainNumber }).then((result) => {
- if (!!result.relationMainNumber) {
- compare.value = '1'
- }
- if (result.remarkType === 'TIME') {
- result.remarkNumber = (result.remarkNumber || 0) / 60
- }
- Object.assign(model, omit(result, 'examId'))
- // levelRangValues.value = result.levelRange.slice(0)
- levelRangValues.value = result.levelRange.slice(0).map((item) => {
- return item * 100
- })
- })
- }
- const onSetLevelRangeSubmit = () => {
- // model.levelRange = levelRangValues.value
- model.levelRange = levelRangValues.value.map((item) => {
- return !!item ? item / 100 : 0
- })
- setLevelRangeVisible.value = false
- }
- const onSubmit = async () => {
- try {
- const valid = await elFormRef?.value?.validate().catch((error: object) => {
- if (
- !expand.value &&
- Object.keys(error).some((k) => ['standardRate', 'selfRate', 'systemRate', 'levelRange'].includes(k))
- ) {
- expand.value = true
- }
- })
- if (valid) {
- const data = Object.assign(
- { ...model, levelRange: model.levelRange || [], category: model.category || void 0 },
- { remarkNumber: model.remarkType === 'TIME' ? (model.remarkNumber || 0) * 60 : model.remarkNumber }
- )
- await (isEdit ? editMainQuestion(data) : addMainQuestion(data))
- ElMessage.success('保存成功')
- back()
- }
- } catch (error) {
- console.error(error)
- }
- }
- const onCancel = () => {
- back()
- }
- </script>
- <style scoped lang="scss">
- .level-list {
- .level-row {
- margin-bottom: 8px;
- .level-label {
- width: 125px;
- text-align: right;
- .s1 {
- width: 41px;
- text-align: left;
- }
- .s2 {
- width: 7px;
- }
- .s3 {
- width: 49px;
- text-align: right;
- }
- }
- }
- }
- </style>
|