2626 </a-select >
2727 </div >
2828
29- <div class =" flex justify-between mb-2 sm:flex-row flex-col" >
30- <div class =" sm:w-1/2 w-4/5 sm:mb-0 mb-4" >
29+ <div class =" flex gap-4 mb-6" >
30+ <div class =" flex-1" >
31+ <div class =" font-semibold mb-2" >
32+ {{ $t('common.interview.duration') }}
33+ </div >
34+ <a-input-number v-model =" duration" :min =" 1" />
35+ </div >
36+ <div class =" flex-1" >
37+ <div class =" font-semibold mb-2" >
38+ {{ $t('common.interview.rest') }}
39+ </div >
40+ <a-input-number v-model =" rest" :min =" 0" />
41+ </div >
42+ </div >
43+
44+ <div class =" flex gap-4" >
45+ <div class =" w-5/12" >
3146 <div class =" font-semibold mb-2" >
3247 {{ $t('common.date') }}<span class =" text-blue-600" >*</span >
3348 </div >
34- <a-date-picker v-model =" interviewDate" class =" w-5/6 " />
49+ <a-date-picker v-model =" interviewDate" class =" w-full " />
3550 </div >
36- <div class =" sm:w-1/2 w-4/5 pr-2" >
51+
52+ <div class =" flex-1" >
3753 <div class =" font-semibold mb-2" >
3854 {{ $t('common.time') }}<span class =" text-blue-600" >*</span >
3955 </div >
40- <a-time-picker
41- v-model =" interviewTime"
42- type =" time-range"
43- class =" w-full"
44- />
56+ <div
57+ v-for =" (_, index) in interviewTimes"
58+ :key =" index"
59+ class =" flex items-center mb-2 gap-2"
60+ >
61+ <a-time-picker
62+ v-model =" interviewTimes[index]"
63+ type =" time-range"
64+ format =" HH:mm"
65+ class =" flex-1"
66+ />
67+ <a-button
68+ type =" text"
69+ status =" danger"
70+ class =" px-1"
71+ @click =" removeTimeRange(index)"
72+ >
73+ <template #icon ><icon-delete /></template >
74+ </a-button >
75+ <a-button
76+ v-if =" index === interviewTimes.length - 1"
77+ type =" text"
78+ class =" px-1"
79+ @click =" addTimeRange"
80+ >
81+ <template #icon ><icon-plus /></template >
82+ </a-button >
83+ <!-- 占位,保证对齐 -->
84+ <div v-else class =" w-8" ></div >
85+ </div >
4586 </div >
4687 </div >
4788 </div >
@@ -54,6 +95,7 @@ import { Group, Period, PeriodDefineHour } from '@/constants/team';
5495import useRecruitmentStore from ' @/store/modules/recruitment' ;
5596import { Message } from ' @arco-design/web-vue' ;
5697import { useI18n } from ' vue-i18n' ;
98+ import { IconPlus , IconDelete } from ' @arco-design/web-vue/es/icon' ;
5799
58100const { t } = useI18n ();
59101
@@ -72,9 +114,40 @@ const props = defineProps({
72114
73115const currentGroup = ref <Group >(props .currentGroupStart );
74116const interviewDate = ref <string >(' ' );
75- const interviewTime = ref <string []>([]);
117+ const interviewTimes = ref <string [][]>([[]]);
118+ const duration = ref (30 );
119+ const rest = ref (10 );
76120const recStore = useRecruitmentStore ();
77121
122+ const addTimeRange = () => {
123+ const lastRange = interviewTimes .value [interviewTimes .value .length - 1 ];
124+ if (lastRange && lastRange [1 ]) {
125+ const [h, m, s] = lastRange [1 ].split (' :' ).map (Number );
126+ const date = new Date ();
127+ date .setHours (h , m , s || 0 );
128+
129+ const nextStart = new Date (date .getTime () + rest .value * 60000 );
130+ const nextEnd = new Date (nextStart .getTime () + duration .value * 60000 );
131+
132+ const format = (d : Date ) =>
133+ ` ${String (d .getHours ()).padStart (2 , ' 0' )}:${String (
134+ d .getMinutes (),
135+ ).padStart (2 , ' 0' )} ` ;
136+
137+ interviewTimes .value .push ([format (nextStart ), format (nextEnd )]);
138+ } else {
139+ interviewTimes .value .push ([]);
140+ }
141+ };
142+
143+ const removeTimeRange = (index : number ) => {
144+ if (interviewTimes .value .length > 1 ) {
145+ interviewTimes .value .splice (index , 1 );
146+ } else {
147+ interviewTimes .value = [[]];
148+ }
149+ };
150+
78151const groupOptions = Object .entries (Group ).map (([label , value ]) => ({
79152 label ,
80153 value ,
@@ -93,22 +166,28 @@ const calcPeriod = (time: Date): Period => {
93166};
94167
95168const handleCreate = async () => {
96- const [startTime, endTime] = interviewTime .value ;
97-
98- // 创建日期和时间的ISO格式
99- const startDate = new Date (` ${interviewDate .value }T${startTime } ` );
100- const start = startDate .toISOString ();
101- const end = new Date (` ${interviewDate .value }T${endTime } ` ).toISOString ();
169+ if (
170+ ! interviewDate .value ||
171+ interviewTimes .value .some ((time ) => time .length < 2 )
172+ ) {
173+ Message .warning (t (' common.interview.error.incompleteInfo' ));
174+ return ;
175+ }
102176
103- visible .value = false ;
104- const res = await recStore .createInterview (currentGroup .value , [
105- {
177+ const interviews = interviewTimes .value .map (([startTime , endTime ]) => {
178+ const startDate = new Date (` ${interviewDate .value }T${startTime } ` );
179+ const start = startDate .toISOString ();
180+ const end = new Date (` ${interviewDate .value }T${endTime } ` ).toISOString ();
181+ return {
106182 date: new Date (interviewDate .value ).toISOString (),
107183 period: calcPeriod (startDate ),
108184 start ,
109185 end ,
110- },
111- ]);
186+ };
187+ });
188+
189+ visible .value = false ;
190+ const res = await recStore .createInterview (currentGroup .value , interviews );
112191 if (res ) {
113192 recStore .refresh ();
114193 Message .success (t (' common.result.addInterviewSuccess' ));
0 commit comments