260720
This commit is contained in:
@@ -0,0 +1,930 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
placement="right"
|
||||
width="80%"
|
||||
:visible="visible"
|
||||
:title="isUpdate ? '编辑' : '新增'"
|
||||
:body-style="{ paddingBottom: '88px' }"
|
||||
@update:visible="updateVisible"
|
||||
>
|
||||
<a-form ref="formRef" :model="form">
|
||||
<a-form-item
|
||||
label="年份"
|
||||
name="year"
|
||||
:rules="[{ required: true, message: '请选择年份' }]"
|
||||
>
|
||||
<a-date-picker
|
||||
v-model:value="form.year"
|
||||
picker="year"
|
||||
value-format="YYYY"
|
||||
style="width: 240px"
|
||||
:disabled="!!props.fixedYear"
|
||||
placeholder="请选择年份"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-tabs v-model:activeKey="activeTab" type="card" class="gxmu-tag-tabs">
|
||||
<a-tab-pane key="base" tab="项目申报表">
|
||||
<div class="sheet-wrap">
|
||||
<div class="sheet-header">
|
||||
<div class="sheet-tag">附件 1</div>
|
||||
<div class="sheet-main-title"
|
||||
>{{ title || '' }}参赛项目申报表</div
|
||||
>
|
||||
</div>
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 32%" />
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 32%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label">所在省<br />(区、市)</td>
|
||||
<td class="sheet-value">
|
||||
<a-input
|
||||
v-model:value="form.provinceCity"
|
||||
placeholder="请输入所在省/市"
|
||||
/>
|
||||
</td>
|
||||
<td class="sheet-label">学校名称<br />(全称)</td>
|
||||
<td class="sheet-value">
|
||||
<a-input
|
||||
v-model:value="form.schoolName"
|
||||
placeholder="请输入学校名称"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">项目名称</td>
|
||||
<td class="sheet-value left" colspan="3">
|
||||
<a-input
|
||||
v-model:value="form.projectName"
|
||||
placeholder="请输入项目名称"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">项目类型</td>
|
||||
<td class="sheet-value left" colspan="3">
|
||||
<a-radio-group
|
||||
v-model:value="form.projectType"
|
||||
class="inline-radio"
|
||||
>
|
||||
<a-radio
|
||||
v-for="item in formProjectTypeOptions"
|
||||
:key="`base-type-${item.value}`"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">
|
||||
项目分组
|
||||
<div class="sheet-note"
|
||||
>(仅可选择1个组别,须在此栏中删除其他组别内容)</div
|
||||
>
|
||||
</td>
|
||||
<td class="sheet-value left" colspan="3">
|
||||
<a-radio-group
|
||||
v-model:value="form.projectGroup"
|
||||
class="group-radio"
|
||||
>
|
||||
<a-radio
|
||||
v-for="item in formProjectGroupOptions"
|
||||
:key="`base-group-${item.value}`"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 14%" />
|
||||
<col style="width: 12%" />
|
||||
<col style="width: 10%" />
|
||||
<col style="width: 16%" />
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 12%" />
|
||||
<col style="width: 18%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label" :rowspan="teamMembersCount + 1"
|
||||
>团队成员<br />(最多15人)</td
|
||||
>
|
||||
<td class="sheet-label">姓名</td>
|
||||
<td class="sheet-label">性别</td>
|
||||
<td class="sheet-label">学院</td>
|
||||
<td class="sheet-label">年级、专业</td>
|
||||
<td class="sheet-label">手机</td>
|
||||
<td class="sheet-label"
|
||||
>备注(负责人及各成员学历-本/硕/博)</td
|
||||
>
|
||||
</tr>
|
||||
<tr
|
||||
v-for="(item, index) in form.teamMembers"
|
||||
:key="`member-${index}`"
|
||||
>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.name"
|
||||
/></td>
|
||||
<td class="sheet-value">
|
||||
<a-select style="width: 120px"
|
||||
v-model:value="item.gender"
|
||||
:options="genderOptions"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</td>
|
||||
<td class="sheet-value">
|
||||
<a-select style="width: 120px"
|
||||
allow-clear
|
||||
show-search
|
||||
v-model:value="item.college"
|
||||
:options="collegeOptions"
|
||||
:filter-option="filterSelectOption"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.gradeMajor"
|
||||
/></td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.phone"
|
||||
/></td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.remark"
|
||||
/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 14%" />
|
||||
<col style="width: 12%" />
|
||||
<col style="width: 10%" />
|
||||
<col style="width: 16%" />
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 16%" />
|
||||
<col style="width: 14%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label" :rowspan="advisorCount + 1"
|
||||
>指导教师<br />(最多5人)</td
|
||||
>
|
||||
<td class="sheet-label">姓名</td>
|
||||
<td class="sheet-label">性别</td>
|
||||
<td class="sheet-label">学院</td>
|
||||
<td class="sheet-label">职称</td>
|
||||
<td class="sheet-label">职务</td>
|
||||
<td class="sheet-label">手机</td>
|
||||
</tr>
|
||||
<tr
|
||||
v-for="(item, index) in form.advisors"
|
||||
:key="`advisor-${index}`"
|
||||
>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.name"
|
||||
/></td>
|
||||
<td class="sheet-value">
|
||||
<a-select style="width: 120px"
|
||||
v-model:value="item.gender"
|
||||
:options="genderOptions"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</td>
|
||||
<td class="sheet-value">
|
||||
<a-select style="width: 120px"
|
||||
allow-clear
|
||||
show-search
|
||||
v-model:value="item.college"
|
||||
:options="collegeOptions"
|
||||
:filter-option="filterSelectOption"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.title"
|
||||
/></td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.duty"
|
||||
/></td>
|
||||
<td class="sheet-value"
|
||||
><a-input v-model:value="item.phone"
|
||||
/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 82%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label">项目简介<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.projectBrief"
|
||||
:rows="4"
|
||||
placeholder="请输入项目简介"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="detail" tab="项目说明">
|
||||
<div class="sheet-wrap">
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 82%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label">社会价值<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.socialValue"
|
||||
:rows="4"
|
||||
placeholder="请输入社会价值"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">实践过程<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.practiceProcess"
|
||||
:rows="4"
|
||||
placeholder="请输入实践过程"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">创新意义<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.innovationMeaning"
|
||||
:rows="4"
|
||||
placeholder="请输入创新意义"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">发展前景<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.developmentProspect"
|
||||
:rows="4"
|
||||
placeholder="请输入发展前景"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">团队协作<br />(500字以内)</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.teamCooperation"
|
||||
:rows="4"
|
||||
placeholder="请输入团队协作"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">项目介绍材料</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.projectMaterials"
|
||||
:rows="3"
|
||||
placeholder="请输入项目介绍材料"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">其他相关证明材料</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.otherProofs"
|
||||
:rows="3"
|
||||
placeholder="选报,所有其他相关证明材料需扫描在同一 PDF 文档中"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="public" tab="公开展示信息表">
|
||||
<div class="sheet-wrap">
|
||||
<div class="public-title">
|
||||
<div class="public-tag">附件 2</div>
|
||||
<div class="public-main-title"
|
||||
>{{ title || '' }}参赛项目公开展示信息表</div
|
||||
>
|
||||
</div>
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 82%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="sheet-label">项目名称</td>
|
||||
<td class="sheet-value left">
|
||||
<a-input
|
||||
v-model:value="form.projectName"
|
||||
placeholder="请输入项目名称"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">参赛学校</td>
|
||||
<td class="sheet-value left">
|
||||
<a-input
|
||||
v-model:value="form.schoolName"
|
||||
placeholder="请输入参赛学校"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">项目类型</td>
|
||||
<td class="sheet-value left">
|
||||
<a-radio-group
|
||||
v-model:value="form.publicProjectType"
|
||||
class="inline-radio"
|
||||
>
|
||||
<a-radio
|
||||
v-for="item in publicProjectTypeOptions"
|
||||
:key="`public-type-${item.value}`"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">项目分组</td>
|
||||
<td class="sheet-value left">
|
||||
<a-radio-group
|
||||
v-model:value="form.publicProjectGroup"
|
||||
class="group-radio"
|
||||
>
|
||||
<a-radio
|
||||
v-for="item in publicProjectGroupOptions"
|
||||
:key="`public-group-${item.value}`"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">我们的项目</td>
|
||||
<td class="sheet-value left">
|
||||
<a-textarea
|
||||
v-model:value="form.projectSummary"
|
||||
:rows="3"
|
||||
placeholder="150字以内,阐述项目的实践来源、社会背景、基本情况等"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">我们的团队</td>
|
||||
<td class="sheet-value left">
|
||||
<div class="media-upload-block">
|
||||
<div v-if="form.teamIntro" class="media-preview-wrap">
|
||||
<img
|
||||
class="media-image"
|
||||
:src="form.teamIntro"
|
||||
alt="团队图片"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="media-empty">请上传团队图片</div>
|
||||
<div class="media-actions">
|
||||
<a-upload
|
||||
:show-upload-list="false"
|
||||
accept="image/*"
|
||||
:customRequest="uploadTeamImage"
|
||||
>
|
||||
<a-button type="primary">上传图片</a-button>
|
||||
</a-upload>
|
||||
<a-button v-if="form.teamIntro" @click="form.teamIntro = ''">
|
||||
移除
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">我们的口号</td>
|
||||
<td class="sheet-value left">
|
||||
<a-input
|
||||
v-model:value="form.teamSlogan"
|
||||
placeholder="20字以内"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="sheet-label">我们的实践日志(选填)</td>
|
||||
<td class="sheet-value left">
|
||||
<div class="media-upload-block">
|
||||
<div v-if="form.practiceLog" class="media-preview-wrap media-preview-wrap--video">
|
||||
<video class="media-video" :src="form.practiceLog" controls></video>
|
||||
</div>
|
||||
<div v-else class="media-empty">请上传实践日志视频</div>
|
||||
<div class="media-actions">
|
||||
<a-upload
|
||||
:show-upload-list="false"
|
||||
accept="video/*"
|
||||
:customRequest="uploadPracticeVideo"
|
||||
>
|
||||
<a-button type="primary">上传视频</a-button>
|
||||
</a-upload>
|
||||
<a-button v-if="form.practiceLog" @click="form.practiceLog = ''">
|
||||
移除
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
<div class="drawer-footer">
|
||||
<a-space>
|
||||
<a-button @click="updateVisible(false)">取消</a-button>
|
||||
<a-button type="primary" :loading="loading" @click="save"
|
||||
>保存</a-button
|
||||
>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { addTzbcyForm, updateTzbcyForm } from '@/api/gxmu/tzbcy-form';
|
||||
import { uploadFile } from '@/api/system/file';
|
||||
import type {
|
||||
TzbcyAdvisor,
|
||||
TzbcyForm,
|
||||
TzbcyTeamMember
|
||||
} from '@/api/gxmu/tzbcy-form/model';
|
||||
import {
|
||||
filterSelectOption,
|
||||
useGxmuFormSelectOptions
|
||||
} from '@/views/gxmu/useFormSelectOptions';
|
||||
import {
|
||||
TZBCY_PROJECT_GROUP_OPTIONS,
|
||||
TZBCY_PROJECT_TYPE_OPTIONS
|
||||
} from '../options';
|
||||
|
||||
interface ChoiceOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
data?: TzbcyForm | null;
|
||||
title?: string;
|
||||
fixedYear?: string | number;
|
||||
declareFormProjectTypes?: string[];
|
||||
declareFormProjectGroups?: string[];
|
||||
declarePublicProjectTypes?: string[];
|
||||
declarePublicProjectGroups?: string[];
|
||||
}>();
|
||||
|
||||
const formRef = ref();
|
||||
const loading = ref(false);
|
||||
const isUpdate = ref(false);
|
||||
const activeTab = ref('base');
|
||||
const { genderOptions, collegeOptions, loadCollegeOptions } =
|
||||
useGxmuFormSelectOptions();
|
||||
|
||||
const createTeamMember = (): TzbcyTeamMember => ({
|
||||
name: '',
|
||||
gender: '',
|
||||
college: '',
|
||||
gradeMajor: '',
|
||||
phone: '',
|
||||
remark: ''
|
||||
});
|
||||
|
||||
const createAdvisor = (): TzbcyAdvisor => ({
|
||||
name: '',
|
||||
gender: '',
|
||||
college: '',
|
||||
title: '',
|
||||
duty: '',
|
||||
phone: ''
|
||||
});
|
||||
|
||||
const createDefaultForm = (): TzbcyForm => ({
|
||||
id: undefined,
|
||||
year: '',
|
||||
provinceCity: '',
|
||||
schoolName: '广西医科大学',
|
||||
projectName: '',
|
||||
projectType: '',
|
||||
projectGroup: '',
|
||||
publicProjectType: '',
|
||||
publicProjectGroup: '',
|
||||
leader: '',
|
||||
phone: '',
|
||||
teamMembers: Array.from({ length: 15 }).map(() => createTeamMember()),
|
||||
advisors: Array.from({ length: 5 }).map(() => createAdvisor()),
|
||||
projectBrief: '',
|
||||
socialValue: '',
|
||||
practiceProcess: '',
|
||||
innovationMeaning: '',
|
||||
developmentProspect: '',
|
||||
teamCooperation: '',
|
||||
projectMaterials: '',
|
||||
otherProofs: '',
|
||||
projectSummary: '',
|
||||
teamIntro: '',
|
||||
teamSlogan: '',
|
||||
practiceLog: ''
|
||||
});
|
||||
|
||||
const fillList = <T extends Record<string, unknown>>(
|
||||
list: T[] | undefined,
|
||||
count: number,
|
||||
createItem: () => T
|
||||
) => {
|
||||
const source = list?.map((item) => ({ ...createItem(), ...item })) ?? [];
|
||||
return Array.from({ length: count }).map(
|
||||
(_, index) => source[index] ?? createItem()
|
||||
);
|
||||
};
|
||||
|
||||
const normalizeForm = (record?: TzbcyForm | null): TzbcyForm => {
|
||||
const defaults = createDefaultForm();
|
||||
if (!record) {
|
||||
return defaults;
|
||||
}
|
||||
const normalizedProjectType = record.projectType || '';
|
||||
const normalizedProjectGroup = record.projectGroup || '';
|
||||
return {
|
||||
...defaults,
|
||||
...record,
|
||||
projectType: normalizedProjectType,
|
||||
projectGroup: normalizedProjectGroup,
|
||||
publicProjectType: record.publicProjectType || normalizedProjectType,
|
||||
publicProjectGroup: record.publicProjectGroup || normalizedProjectGroup,
|
||||
teamMembers: fillList(record.teamMembers, 15, createTeamMember),
|
||||
advisors: fillList(record.advisors, 5, createAdvisor)
|
||||
};
|
||||
};
|
||||
|
||||
const form = reactive<TzbcyForm>(createDefaultForm());
|
||||
|
||||
const teamMembersCount = computed(() => form.teamMembers?.length || 0);
|
||||
const advisorCount = computed(() => form.advisors?.length || 0);
|
||||
|
||||
const buildChoiceOptions = (
|
||||
customValues: string[] | undefined,
|
||||
fallback: readonly ChoiceOption[],
|
||||
currentValue?: string
|
||||
): ChoiceOption[] => {
|
||||
const values = (customValues?.length
|
||||
? customValues
|
||||
: fallback.map((item) => item.value)
|
||||
)
|
||||
.map((item) => item.trim())
|
||||
.filter((item, index, arr) => !!item && arr.indexOf(item) === index);
|
||||
|
||||
if (currentValue?.trim() && !values.includes(currentValue.trim())) {
|
||||
values.push(currentValue.trim());
|
||||
}
|
||||
|
||||
return values.map((value) => {
|
||||
const matched = fallback.find((item) => item.value === value);
|
||||
return {
|
||||
label: matched?.label ?? value,
|
||||
value
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const formProjectTypeOptions = computed(() =>
|
||||
buildChoiceOptions(
|
||||
props.declareFormProjectTypes,
|
||||
TZBCY_PROJECT_TYPE_OPTIONS,
|
||||
form.projectType
|
||||
)
|
||||
);
|
||||
const formProjectGroupOptions = computed(() =>
|
||||
buildChoiceOptions(
|
||||
props.declareFormProjectGroups,
|
||||
TZBCY_PROJECT_GROUP_OPTIONS,
|
||||
form.projectGroup
|
||||
)
|
||||
);
|
||||
const publicProjectTypeOptions = computed(() =>
|
||||
buildChoiceOptions(
|
||||
props.declarePublicProjectTypes,
|
||||
TZBCY_PROJECT_TYPE_OPTIONS,
|
||||
form.publicProjectType
|
||||
)
|
||||
);
|
||||
const publicProjectGroupOptions = computed(() =>
|
||||
buildChoiceOptions(
|
||||
props.declarePublicProjectGroups,
|
||||
TZBCY_PROJECT_GROUP_OPTIONS,
|
||||
form.publicProjectGroup
|
||||
)
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
async (visible) => {
|
||||
if (visible) {
|
||||
try {
|
||||
await loadCollegeOptions();
|
||||
} catch (e: any) {
|
||||
message.error(e.message || '下拉选项加载失败');
|
||||
}
|
||||
isUpdate.value = !!props.data?.id;
|
||||
Object.assign(form, normalizeForm(props.data));
|
||||
if (props.fixedYear) {
|
||||
form.year = String(props.fixedYear);
|
||||
}
|
||||
} else {
|
||||
formRef.value?.resetFields?.();
|
||||
Object.assign(form, createDefaultForm());
|
||||
}
|
||||
activeTab.value = 'base';
|
||||
}
|
||||
);
|
||||
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
const syncLeaderInfo = () => {
|
||||
const firstMember = form.teamMembers?.find(
|
||||
(item) => item.name?.trim() || item.phone?.trim()
|
||||
);
|
||||
form.leader = firstMember?.name?.trim() || '';
|
||||
form.phone = firstMember?.phone?.trim() || '';
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
syncLeaderInfo();
|
||||
loading.value = true;
|
||||
const saveOrUpdate = isUpdate.value ? updateTzbcyForm : addTzbcyForm;
|
||||
saveOrUpdate({
|
||||
...form,
|
||||
year: props.fixedYear ? String(props.fixedYear) : form.year
|
||||
})
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
const uploadTeamImage = (item) => {
|
||||
const file = item.file as File;
|
||||
if (!file.type.startsWith('image/')) {
|
||||
message.error('请上传图片文件');
|
||||
return;
|
||||
}
|
||||
uploadFile(file)
|
||||
.then((data) => {
|
||||
form.teamIntro = String(data.url || '');
|
||||
message.success('图片上传成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
const uploadPracticeVideo = (item) => {
|
||||
const file = item.file as File;
|
||||
if (!file.type.startsWith('video/')) {
|
||||
message.error('请上传视频文件');
|
||||
return;
|
||||
}
|
||||
uploadFile(file)
|
||||
.then((data) => {
|
||||
form.practiceLog = String(data.url || '');
|
||||
message.success('视频上传成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '../../form-theme.less';
|
||||
@import '../../tag-tabs.less';
|
||||
|
||||
.gxmu-field-theme();
|
||||
.gxmu-tag-tabs();
|
||||
|
||||
.sheet-wrap {
|
||||
border: 1px solid #d9d9d9;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.sheet-header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.sheet-tag {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.sheet-main-title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.sheet-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.sheet-table td {
|
||||
border: 1px solid #3b3b3b;
|
||||
padding: 8px 6px;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.sheet-label {
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sheet-note {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #444;
|
||||
margin-top: 6px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.sheet-value {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sheet-value.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sheet-table .sheet-value :deep(.ant-input),
|
||||
.sheet-table .sheet-value :deep(.ant-select-selector),
|
||||
.sheet-table .sheet-value :deep(.ant-radio-group),
|
||||
.sheet-table .sheet-value :deep(.ant-input-textarea),
|
||||
.sheet-table .sheet-value :deep(.ant-input-affix-wrapper) {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sheet-table .sheet-value :deep(.ant-input) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sheet-table .sheet-value.left :deep(.ant-input),
|
||||
.sheet-table .sheet-value.left :deep(.ant-input-textarea) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sheet-table .sheet-value :deep(textarea.ant-input) {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.inline-radio :deep(.ant-radio) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.group-radio {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.media-upload-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.media-preview-wrap {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.media-preview-wrap--video {
|
||||
background: #111827;
|
||||
}
|
||||
|
||||
.media-image {
|
||||
width: 100%;
|
||||
max-height: 220px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.media-video {
|
||||
width: 100%;
|
||||
max-height: 260px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.media-empty {
|
||||
padding: 24px 12px;
|
||||
border-radius: 8px;
|
||||
background: #f5f7fa;
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.public-title {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.public-tag {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.public-main-title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.drawer-footer {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sheet-main-title,
|
||||
.public-main-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user