|
| 1 | +<template> |
| 2 | + <a-modal |
| 3 | + v-model:visible="visible" |
| 4 | + :title="$t('common.operation.updateRecruitment')" |
| 5 | + :on-before-ok="sendForm" |
| 6 | + draggable |
| 7 | + > |
| 8 | + <a-space direction="vertical" size="mini"> |
| 9 | + <a-form ref="recruitmentForm" :model="formData" layout="vertical"> |
| 10 | + <a-form-item field="select_recruitment" label="选择招新"> |
| 11 | + <a-select |
| 12 | + v-model="selectedRid" |
| 13 | + placeholder="请选择要修改的招新" |
| 14 | + @change="onRecruitmentChange" |
| 15 | + > |
| 16 | + <a-option |
| 17 | + v-for="rec in recruitmentStore.data" |
| 18 | + :key="rec.uid" |
| 19 | + :value="rec.uid" |
| 20 | + :label="rec.name" |
| 21 | + > |
| 22 | + {{ rec.name }} |
| 23 | + </a-option> |
| 24 | + </a-select> |
| 25 | + </a-form-item> |
| 26 | + |
| 27 | + <a-form-item field="rec_name" :label="$t('common.createRec.recName')"> |
| 28 | + <a-input |
| 29 | + v-model="formData.name" |
| 30 | + :placeholder="$t('common.createRec.inputRecName')" |
| 31 | + /> |
| 32 | + </a-form-item> |
| 33 | + |
| 34 | + <a-form-item |
| 35 | + field="rec_time_range" |
| 36 | + :label="$t('common.createRec.recTimeRange')" |
| 37 | + > |
| 38 | + <a-range-picker |
| 39 | + v-model="timeRange1" |
| 40 | + show-time |
| 41 | + :time-picker-props="{ defaultValue: ['00:00:00', '00:00:00'] }" |
| 42 | + format="YYYY-MM-DD HH:mm" |
| 43 | + @ok="onOk1" |
| 44 | + /> |
| 45 | + </a-form-item> |
| 46 | + |
| 47 | + <a-form-item field="deadline" label="报名结束时间"> |
| 48 | + <a-date-picker |
| 49 | + v-model="deadline" |
| 50 | + show-time |
| 51 | + :time-picker-props="{ defaultValue: '00:00:00' }" |
| 52 | + format="YYYY-MM-DD HH:mm" |
| 53 | + @ok="onDeadlineChange" |
| 54 | + /> |
| 55 | + </a-form-item> |
| 56 | + </a-form> |
| 57 | + </a-space> |
| 58 | + </a-modal> |
| 59 | +</template> |
| 60 | + |
| 61 | +<script setup lang="ts"> |
| 62 | +import { ref, watch } from 'vue'; |
| 63 | +import { Message } from '@arco-design/web-vue'; |
| 64 | +import { useI18n } from 'vue-i18n'; |
| 65 | +import useRecruitmentStore from '@/store/modules/recruitment'; |
| 66 | +import type { UpdateParams } from '@/store/modules/recruitment/types'; |
| 67 | +
|
| 68 | +const { t } = useI18n(); |
| 69 | +const recruitmentStore = useRecruitmentStore(); |
| 70 | +
|
| 71 | +const visible = defineModel<boolean>('visible', { |
| 72 | + type: Boolean, |
| 73 | + default: false, |
| 74 | + required: true, |
| 75 | +}); |
| 76 | +
|
| 77 | +const selectedRid = ref<string>(''); |
| 78 | +
|
| 79 | +const formData = ref<{ |
| 80 | + name?: string; |
| 81 | + beginning?: string; |
| 82 | + deadline?: string; |
| 83 | + end?: string; |
| 84 | +}>({ |
| 85 | + name: '', |
| 86 | + beginning: '', |
| 87 | + deadline: '', |
| 88 | + end: '', |
| 89 | +}); |
| 90 | +
|
| 91 | +const emit = defineEmits<{ |
| 92 | + (e: 'recruitmentUpdated'): void; |
| 93 | +}>(); |
| 94 | +
|
| 95 | +const timeRange1 = ref<string[]>([]); |
| 96 | +const deadline = ref<string>(''); |
| 97 | +
|
| 98 | +// 当选择招新时,填充表单数据 |
| 99 | +const onRecruitmentChange = (rid: string) => { |
| 100 | + const recruitment = recruitmentStore.data.find((rec) => rec.uid === rid); |
| 101 | + if (recruitment) { |
| 102 | + formData.value = { |
| 103 | + name: recruitment.name || '', |
| 104 | + beginning: recruitment.beginning || '', |
| 105 | + deadline: recruitment.deadline || '', |
| 106 | + end: recruitment.end || '', |
| 107 | + }; |
| 108 | +
|
| 109 | + // 填充时间选择器(转换为本地时间) |
| 110 | + if (recruitment.beginning && recruitment.end) { |
| 111 | + timeRange1.value = [ |
| 112 | + new Date(recruitment.beginning).toLocaleString().replace(' ', ' '), |
| 113 | + new Date(recruitment.end).toLocaleString().replace(' ', ' '), |
| 114 | + ]; |
| 115 | + } else { |
| 116 | + timeRange1.value = []; |
| 117 | + } |
| 118 | +
|
| 119 | + // 填充报名结束时间(转换为本地时间) |
| 120 | + if (recruitment.deadline) { |
| 121 | + deadline.value = new Date(recruitment.deadline) |
| 122 | + .toLocaleString() |
| 123 | + .replace(' ', ' '); |
| 124 | + } else { |
| 125 | + deadline.value = ''; |
| 126 | + } |
| 127 | +
|
| 128 | + console.log('timeRange1.value:', timeRange1.value); |
| 129 | + console.log('deadline.value:', deadline.value); |
| 130 | + } |
| 131 | +}; |
| 132 | +
|
| 133 | +// 当 modal 打开时,清空表单 |
| 134 | +watch( |
| 135 | + () => visible.value, |
| 136 | + (newValue) => { |
| 137 | + if (!newValue) { |
| 138 | + // modal 关闭时,清空表单 |
| 139 | + selectedRid.value = ''; |
| 140 | + formData.value = { |
| 141 | + name: '', |
| 142 | + beginning: '', |
| 143 | + deadline: '', |
| 144 | + end: '', |
| 145 | + }; |
| 146 | + timeRange1.value = []; |
| 147 | + deadline.value = ''; |
| 148 | + } |
| 149 | + }, |
| 150 | +); |
| 151 | +
|
| 152 | +const formatName = (name: string) => { |
| 153 | + let normalizedName = name.trim(); |
| 154 | + if (normalizedName.includes('春')) { |
| 155 | + normalizedName = normalizedName.replace(/春.*/, 'S'); |
| 156 | + } else if (normalizedName.includes('夏')) { |
| 157 | + normalizedName = normalizedName.replace(/夏.*/, 'C'); |
| 158 | + } else if (normalizedName.includes('秋')) { |
| 159 | + normalizedName = normalizedName.replace(/秋.*/, 'A'); |
| 160 | + } |
| 161 | + return normalizedName; |
| 162 | +}; |
| 163 | +
|
| 164 | +const formValidate = () => { |
| 165 | + const errors: { [key: string]: string } = {}; |
| 166 | + const originalName = formData.value.name; |
| 167 | +
|
| 168 | + // 名称验证(如果提供了名称) |
| 169 | + if (originalName) { |
| 170 | + const formattedName = formatName(originalName); |
| 171 | + const nameRegex = /^\d{4}[SAC]$/; |
| 172 | + if (!nameRegex.test(formattedName)) { |
| 173 | + errors.name = t('common.createRec.nameFormat'); |
| 174 | + } else { |
| 175 | + formData.value.name = formattedName; |
| 176 | + } |
| 177 | + } |
| 178 | +
|
| 179 | + // 时间范围验证 |
| 180 | + if (formData.value.beginning && formData.value.end) { |
| 181 | + const beginningTime = new Date(formData.value.beginning).getTime(); |
| 182 | + const endTime = new Date(formData.value.end).getTime(); |
| 183 | +
|
| 184 | + if (beginningTime >= endTime) { |
| 185 | + errors.rec_time_range = '招新开始时间必须早于结束时间'; |
| 186 | + } |
| 187 | + } |
| 188 | +
|
| 189 | + if (formData.value.deadline && formData.value.end) { |
| 190 | + const endTime = new Date(formData.value.end).getTime(); |
| 191 | + const deadlineTime = new Date(formData.value.deadline).getTime(); |
| 192 | +
|
| 193 | + if (deadlineTime >= endTime) { |
| 194 | + errors.signup_time_range = t( |
| 195 | + 'common.createRec.signupEndTimeBeforeRecEndTime', |
| 196 | + ); |
| 197 | + } |
| 198 | + } |
| 199 | +
|
| 200 | + if (Object.keys(errors).length > 0) { |
| 201 | + Message.error(Object.values(errors).join('; ')); |
| 202 | + return false; |
| 203 | + } |
| 204 | +
|
| 205 | + return true; |
| 206 | +}; |
| 207 | +
|
| 208 | +const sendForm = async () => { |
| 209 | + try { |
| 210 | + // 检查是否选择了招新 |
| 211 | + if (!selectedRid.value) { |
| 212 | + Message.error('请先选择要修改的招新'); |
| 213 | + return false; |
| 214 | + } |
| 215 | +
|
| 216 | + const isValid = formValidate(); |
| 217 | + if (!isValid) { |
| 218 | + return false; |
| 219 | + } |
| 220 | +
|
| 221 | + // 只发送有值的字段 |
| 222 | + const updateData: UpdateParams = {}; |
| 223 | + if (formData.value.name) { |
| 224 | + updateData.name = formData.value.name; |
| 225 | + } |
| 226 | + if (formData.value.beginning) { |
| 227 | + updateData.beginning = formData.value.beginning; |
| 228 | + } |
| 229 | + if (formData.value.deadline) { |
| 230 | + updateData.deadline = formData.value.deadline; |
| 231 | + } |
| 232 | + if (formData.value.end) { |
| 233 | + updateData.end = formData.value.end; |
| 234 | + } |
| 235 | +
|
| 236 | + // 如果没有任何更新,提示用户 |
| 237 | + if (Object.keys(updateData).length === 0) { |
| 238 | + Message.warning('没有任何修改'); |
| 239 | + return false; |
| 240 | + } |
| 241 | +
|
| 242 | + await recruitmentStore.updateRecruitment(selectedRid.value, updateData); |
| 243 | + Message.success('招新更新成功'); |
| 244 | + emit('recruitmentUpdated'); |
| 245 | + return true; |
| 246 | + } catch (error) { |
| 247 | + Message.error((error as any).message || '更新失败'); |
| 248 | + return false; |
| 249 | + } |
| 250 | +}; |
| 251 | +
|
| 252 | +const onOk1 = (dateString: string[], _date: any) => { |
| 253 | + formData.value.beginning = new Date(dateString[0]).toISOString(); |
| 254 | + formData.value.end = new Date(dateString[1]).toISOString(); |
| 255 | +}; |
| 256 | +
|
| 257 | +const onDeadlineChange = (dateString: string, _date: any) => { |
| 258 | + formData.value.deadline = new Date(dateString).toISOString(); |
| 259 | +}; |
| 260 | +</script> |
0 commit comments