|
@@ -1,480 +0,0 @@
|
|
|
-<template>
|
|
|
- <a-modal
|
|
|
- v-model:visible="visible"
|
|
|
- :width="700"
|
|
|
- top="10px"
|
|
|
- :align-center="false"
|
|
|
- @before-open="modalBeforeOpen"
|
|
|
- >
|
|
|
- <template #title> {{ title }} </template>
|
|
|
- <a-form ref="formRef" :model="formData" :rules="rules" auto-label-width>
|
|
|
- <a-form-item field="name" label="模板名称">
|
|
|
- <a-input
|
|
|
- v-model.trim="formData.name"
|
|
|
- placeholder="建议不超过30个字,规则名称不允许重复"
|
|
|
- allow-clear
|
|
|
- ></a-input>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item field="remark" label="备注">
|
|
|
- <a-textarea
|
|
|
- v-model.trim="formData.remark"
|
|
|
- placeholder="建议不超过50个字"
|
|
|
- allow-clear
|
|
|
- :max-length="50"
|
|
|
- show-word-limit
|
|
|
- ></a-textarea>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item field="classify" label="分类">
|
|
|
- <a-select
|
|
|
- v-model="formData.classify"
|
|
|
- placeholder="请选择分类"
|
|
|
- :options="templateClassifyOption"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- </a-select>
|
|
|
- </a-form-item>
|
|
|
- <!-- SIGN -->
|
|
|
- <template v-if="formData.classify === 'SIGN'">
|
|
|
- <a-form-item field="testDesc" label="文字说明">
|
|
|
- <a-textarea
|
|
|
- v-model.trim="formData.testDesc"
|
|
|
- placeholder="建议不超过500个字"
|
|
|
- allow-clear
|
|
|
- :max-length="500"
|
|
|
- show-word-limit
|
|
|
- ></a-textarea>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- field="fields"
|
|
|
- label="显示字段"
|
|
|
- :content-flex="false"
|
|
|
- :style="{ lineHeight: '32px' }"
|
|
|
- >
|
|
|
- <a-space :size="[20, 0]" wrap>
|
|
|
- <a-checkbox
|
|
|
- v-for="field in signDatas.basic"
|
|
|
- :key="field.code"
|
|
|
- v-model="field.enable"
|
|
|
- >{{ field.name }}</a-checkbox
|
|
|
- >
|
|
|
- </a-space>
|
|
|
- <a-divider></a-divider>
|
|
|
- <a-space :size="[20, 0]" wrap>
|
|
|
- <a-checkbox
|
|
|
- v-for="field in signDatas.table"
|
|
|
- :key="field.code"
|
|
|
- v-model="field.enable"
|
|
|
- >{{ field.name }}</a-checkbox
|
|
|
- >
|
|
|
- </a-space>
|
|
|
- </a-form-item>
|
|
|
- <a-divider orientation="left">签到表页面设置</a-divider>
|
|
|
- <a-form-item
|
|
|
- field="diallel"
|
|
|
- label="考生数据显示方式"
|
|
|
- :style="{ marginBottom: 0 }"
|
|
|
- >
|
|
|
- <a-radio-group v-model="formData.diallel">
|
|
|
- <a-radio :value="false">单列</a-radio>
|
|
|
- <a-radio :value="true">双列</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- field="addBlankPage"
|
|
|
- label="是否增加空白页"
|
|
|
- :style="{ marginBottom: 0 }"
|
|
|
- >
|
|
|
- <a-radio-group v-model="formData.addBlankPage">
|
|
|
- <a-radio :value="false">否</a-radio>
|
|
|
- <a-radio :value="true">是</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- field="lineHeightTimes"
|
|
|
- label="考生信息行间距"
|
|
|
- :style="{ marginBottom: 0 }"
|
|
|
- >
|
|
|
- <a-radio-group v-model="formData.lineHeightTimes">
|
|
|
- <a-radio :value="1">1倍</a-radio>
|
|
|
- <a-radio :value="1.5">1.5倍</a-radio>
|
|
|
- <a-radio :value="2">2倍</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- field="fontSize"
|
|
|
- label="考生信息字号"
|
|
|
- :style="{ marginBottom: 0 }"
|
|
|
- >
|
|
|
- <a-radio-group v-model="formData.fontSize">
|
|
|
- <a-radio value="SMALL">小</a-radio>
|
|
|
- <a-radio value="MEDIUM">中</a-radio>
|
|
|
- <a-radio value="LARGE">大</a-radio>
|
|
|
- </a-radio-group>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item field="fieldWidth" label="信息宽度设置">
|
|
|
- <a-table
|
|
|
- :columns="fieldColumns"
|
|
|
- :data="signTableDatas"
|
|
|
- :pagination="false"
|
|
|
- >
|
|
|
- <template #rate="{ record }">
|
|
|
- <a-input-number
|
|
|
- v-model="record.rate"
|
|
|
- placeholder="请输入"
|
|
|
- :min="1"
|
|
|
- :max="100"
|
|
|
- :step="1"
|
|
|
- hide-button
|
|
|
- >
|
|
|
- <template #suffix>%</template>
|
|
|
- </a-input-number>
|
|
|
- </template>
|
|
|
- </a-table>
|
|
|
- </a-form-item>
|
|
|
- </template>
|
|
|
- <!-- PACKAGE -->
|
|
|
- <template v-else-if="formData.classify === 'PACKAGE'">
|
|
|
- <a-form-item
|
|
|
- field="fields"
|
|
|
- label="显示字段"
|
|
|
- :content-flex="false"
|
|
|
- :style="{ lineHeight: '32px' }"
|
|
|
- >
|
|
|
- <a-space :size="[20, 0]" wrap>
|
|
|
- <a-checkbox
|
|
|
- v-for="field in packageDatas.title"
|
|
|
- :key="field.code"
|
|
|
- v-model="field.enable"
|
|
|
- >{{ field.name }}</a-checkbox
|
|
|
- >
|
|
|
- </a-space>
|
|
|
- <a-divider></a-divider>
|
|
|
- <a-space :size="[20, 0]" wrap>
|
|
|
- <a-checkbox
|
|
|
- v-for="field in packageDatas.basic"
|
|
|
- :key="field.code"
|
|
|
- v-model="field.enable"
|
|
|
- >{{ field.name }}</a-checkbox
|
|
|
- >
|
|
|
- </a-space>
|
|
|
- </a-form-item>
|
|
|
- </template>
|
|
|
- <!-- CHECKIN -->
|
|
|
- <template v-else>
|
|
|
- <a-form-item field="attachmentId" label="上传模板文件">
|
|
|
- <FileUpload
|
|
|
- ref="fileUploadRef"
|
|
|
- :upload-data="uploadData"
|
|
|
- :upload-url="uploadUrl"
|
|
|
- :format="format"
|
|
|
- @upload-success="uploadSuccess"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </template>
|
|
|
- </a-form>
|
|
|
-
|
|
|
- <template #footer>
|
|
|
- <a-button type="primary" :disabled="loading" @click="confirm"
|
|
|
- >确认</a-button
|
|
|
- >
|
|
|
- <a-button @click="close">取消</a-button>
|
|
|
- </template>
|
|
|
- </a-modal>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
- import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
|
|
- import { Message, TableColumnData } from '@arco-design/web-vue';
|
|
|
- import type { FormInstance, FieldRule } from '@arco-design/web-vue/es/form';
|
|
|
- import {
|
|
|
- attachmentDetail,
|
|
|
- examRuleDetail,
|
|
|
- templateDetail,
|
|
|
- updateTemplate,
|
|
|
- } from '@/api/base';
|
|
|
- import useLoading from '@/hooks/loading';
|
|
|
- import useModal from '@/hooks/modal';
|
|
|
- import useDictOption from '@/hooks/dict-option';
|
|
|
-
|
|
|
- import { calcSum, objAssign, objModifyAssign } from '@/utils/utils';
|
|
|
- import {
|
|
|
- AttachmentItem,
|
|
|
- PackageScope,
|
|
|
- PrintTemplateItem,
|
|
|
- SignScope,
|
|
|
- } from '@/api/types/base';
|
|
|
-
|
|
|
- import FileUpload from '@/components/file-upload/index.vue';
|
|
|
- import type { UploadSuccessData } from '@/components/file-upload/types';
|
|
|
-
|
|
|
- defineOptions({
|
|
|
- name: 'ModifyPrintTemplate',
|
|
|
- });
|
|
|
-
|
|
|
- /* modal */
|
|
|
- const { visible, open, close } = useModal();
|
|
|
- defineExpose({ open, close });
|
|
|
-
|
|
|
- const { optionList: templateClassifyOption } =
|
|
|
- useDictOption('TEMPLATE_CLASSIFY');
|
|
|
-
|
|
|
- const defaultFormData = {
|
|
|
- id: null,
|
|
|
- name: '',
|
|
|
- remark: '',
|
|
|
- classify: '',
|
|
|
- diallel: true,
|
|
|
- addBlankPage: false,
|
|
|
- lineHeightTimes: 1,
|
|
|
- fontSize: '',
|
|
|
- textDesc: '',
|
|
|
- attachmentId: '',
|
|
|
- };
|
|
|
- type FormDataType = Pick<PrintTemplateItem, keyof typeof defaultFormData>;
|
|
|
-
|
|
|
- const props = defineProps<{
|
|
|
- rowData: PrintTemplateItem;
|
|
|
- }>();
|
|
|
- const emit = defineEmits(['modified']);
|
|
|
-
|
|
|
- const isEdit = computed(() => !!props.rowData.id);
|
|
|
- const title = computed(() => `${isEdit.value ? '编辑' : '新增'}模板`);
|
|
|
-
|
|
|
- const packageDatas = ref<PackageScope>({ title: [], basic: [] });
|
|
|
- const signDatas = ref<SignScope>({ basic: [], table: [] });
|
|
|
- const PACKAGE_DATA = ref<PackageScope>({ title: [], basic: [] });
|
|
|
- const SIGN_DATA = ref<SignScope>({ basic: [], table: [] });
|
|
|
- const signTableDatas = computed(() => {
|
|
|
- return signDatas.value.table.filter((item) => item.enable);
|
|
|
- });
|
|
|
- const fileUploadRef = ref(null);
|
|
|
-
|
|
|
- /** formdata */
|
|
|
- const fieldColumns: TableColumnData[] = [
|
|
|
- {
|
|
|
- title: '列名',
|
|
|
- dataIndex: 'name',
|
|
|
- width: 120,
|
|
|
- },
|
|
|
- {
|
|
|
- title: '宽度',
|
|
|
- dataIndex: 'rate',
|
|
|
- slotName: 'rate',
|
|
|
- width: 100,
|
|
|
- },
|
|
|
- ];
|
|
|
-
|
|
|
- const attachment = ref<AttachmentItem>({});
|
|
|
-
|
|
|
- const formRef = ref<FormInstance>();
|
|
|
- const formData = reactive<FormDataType>({ ...defaultFormData });
|
|
|
- const rules: Record<keyof FormDataType, FieldRule[]> = {
|
|
|
- name: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入模板名称',
|
|
|
- },
|
|
|
- {
|
|
|
- max: 30,
|
|
|
- message: '模板名称不能超过30个字',
|
|
|
- },
|
|
|
- ],
|
|
|
- classify: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请选择分类',
|
|
|
- },
|
|
|
- ],
|
|
|
- attachmentId: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请上传模板文件',
|
|
|
- },
|
|
|
- ],
|
|
|
- fields: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- validator: (value, callback) => {
|
|
|
- if (formData.classify === 'PACKAGE') {
|
|
|
- if (!packageDatas.value.basic.some((item) => item.enable)) {
|
|
|
- return callback('请选择显示字段');
|
|
|
- }
|
|
|
- return callback();
|
|
|
- }
|
|
|
-
|
|
|
- if (
|
|
|
- !signDatas.value.basic.some((item) => item.enable) ||
|
|
|
- !signDatas.value.table.some((item) => item.enable)
|
|
|
- ) {
|
|
|
- return callback('请选择显示字段');
|
|
|
- }
|
|
|
- return callback();
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
- fieldWidth: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- validator: (value, callback) => {
|
|
|
- if (signTableDatas.value.some((item) => !item.rate)) {
|
|
|
- return callback('请完成设置');
|
|
|
- }
|
|
|
- const rateSum = calcSum(
|
|
|
- signTableDatas.value.map((item) => item.rate)
|
|
|
- );
|
|
|
- if (rateSum !== 100) {
|
|
|
- return callback(`宽度总和需要等于100,当前总和为 ${rateSum}`);
|
|
|
- }
|
|
|
- return callback();
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
- };
|
|
|
-
|
|
|
- async function getScopeField() {
|
|
|
- const examRule = await examRuleDetail();
|
|
|
- PACKAGE_DATA.value = examRule.packageScope
|
|
|
- ? JSON.parse(examRule.packageScope)
|
|
|
- : { title: [], basic: [] };
|
|
|
- SIGN_DATA.value = examRule.signScope
|
|
|
- ? JSON.parse(examRule.signScope)
|
|
|
- : { basic: [], table: [] };
|
|
|
- }
|
|
|
-
|
|
|
- function getDefaultFieldData() {
|
|
|
- packageDatas.value.title = PACKAGE_DATA.value.title.map((item) => {
|
|
|
- return { ...item, enable: false };
|
|
|
- });
|
|
|
- packageDatas.value.basic = PACKAGE_DATA.value.basic.map((item) => {
|
|
|
- return { ...item, enable: false };
|
|
|
- });
|
|
|
- packageDatas.value.basic.push(
|
|
|
- ...[
|
|
|
- {
|
|
|
- code: 'paperCount',
|
|
|
- name: '试卷数量',
|
|
|
- enable: false,
|
|
|
- },
|
|
|
- {
|
|
|
- code: 'examCount',
|
|
|
- name: '应考人数',
|
|
|
- enable: false,
|
|
|
- },
|
|
|
- {
|
|
|
- code: 'actualExamCount',
|
|
|
- name: '实考人数',
|
|
|
- enable: false,
|
|
|
- },
|
|
|
- ]
|
|
|
- );
|
|
|
- signDatas.value.basic = SIGN_DATA.value.basic.map((item) => {
|
|
|
- return { ...item, enable: false };
|
|
|
- });
|
|
|
- signDatas.value.basic.push(
|
|
|
- ...[
|
|
|
- {
|
|
|
- code: 'examCount',
|
|
|
- name: '应考人数',
|
|
|
- enable: false,
|
|
|
- },
|
|
|
- {
|
|
|
- code: 'actualExamCount',
|
|
|
- name: '实考人数',
|
|
|
- enable: false,
|
|
|
- },
|
|
|
- ]
|
|
|
- );
|
|
|
- signDatas.value.table = SIGN_DATA.value.table.map((item) => {
|
|
|
- return { ...item, rate: undefined, enable: false };
|
|
|
- });
|
|
|
- signDatas.value.table.push({
|
|
|
- code: 'studentSign',
|
|
|
- name: '签名',
|
|
|
- rate: undefined,
|
|
|
- enable: true,
|
|
|
- });
|
|
|
- }
|
|
|
- function initEditFieldData(data: PrintTemplateItem) {
|
|
|
- const displayRange = data.displayRange
|
|
|
- ? JSON.parse(data.displayRange)
|
|
|
- : null;
|
|
|
- if (!displayRange) {
|
|
|
- getDefaultFieldData();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (data.classify === 'PACKAGE') {
|
|
|
- packageDatas.value = displayRange;
|
|
|
- } else {
|
|
|
- signDatas.value = displayRange;
|
|
|
- }
|
|
|
- }
|
|
|
- async function getAttachment() {
|
|
|
- if (!props.rowData.attachmentId) return;
|
|
|
- const data = await attachmentDetail(props.rowData.attachmentId);
|
|
|
- attachment.value = data;
|
|
|
-
|
|
|
- nextTick(() => {
|
|
|
- fileUploadRef.value?.setAttachmentName(`${data.name}${data.type}`);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- /* upload */
|
|
|
- const uploadUrl = '/api/admin/common/file/upload';
|
|
|
- const format = ['ftl', 'html', 'pdf'];
|
|
|
- const uploadData = {
|
|
|
- type: 'UPLOAD',
|
|
|
- };
|
|
|
-
|
|
|
- function uploadSuccess(data: UploadSuccessData) {
|
|
|
- formData.attachmentId = data.response.id;
|
|
|
- formRef.value?.validateField('attachmentId');
|
|
|
- }
|
|
|
-
|
|
|
- /* confirm */
|
|
|
- const { loading, setLoading } = useLoading();
|
|
|
- async function confirm() {
|
|
|
- const err = await formRef.value?.validate();
|
|
|
- if (err) return;
|
|
|
-
|
|
|
- setLoading(true);
|
|
|
- const datas = objAssign(formData, {});
|
|
|
- if (formData.classify === 'PACKAGE') {
|
|
|
- datas.displayRange = packageDatas.value;
|
|
|
- } else if (formData.classify === 'SIGN') {
|
|
|
- const signTableRates = {};
|
|
|
- signTableDatas.value.forEach((item) => {
|
|
|
- signTableRates[item.code] = item.rate;
|
|
|
- });
|
|
|
- signDatas.value.table.forEach((item) => {
|
|
|
- item.rate = signTableRates[item.code] || 0;
|
|
|
- });
|
|
|
- datas.displayRange = signDatas.value;
|
|
|
- }
|
|
|
- const res = await updateTemplate(datas).catch(() => false);
|
|
|
- setLoading(false);
|
|
|
- if (!res) return;
|
|
|
- Message.success('修改成功!');
|
|
|
- emit('modified', datas);
|
|
|
- close();
|
|
|
- }
|
|
|
- /* init modal */
|
|
|
- async function modalBeforeOpen() {
|
|
|
- if (props.rowData.id) {
|
|
|
- const data = await templateDetail(props.rowData.id);
|
|
|
- objModifyAssign(formData, data);
|
|
|
- const unAttachmentTemps = ['SIGN', 'PACKAGE'];
|
|
|
- if (unAttachmentTemps.includes(formData.classify)) {
|
|
|
- initEditFieldData(data);
|
|
|
- } else {
|
|
|
- getAttachment();
|
|
|
- }
|
|
|
- } else {
|
|
|
- objModifyAssign(formData, defaultFormData);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- onMounted(() => {
|
|
|
- getScopeField();
|
|
|
- });
|
|
|
-</script>
|