소스 검색

feat: 功能修改

zhangjie 1 년 전
부모
커밋
1caa3a6e8b

+ 20 - 4
src/api/order.ts

@@ -10,6 +10,8 @@ import type {
   OrderRecordListPageRes,
   OrderRecordListPageParam,
   StudentExportListPageRes,
+  OrderRecordPrintTimeItem,
+  OrderRecordPrintParam,
 } from './types/order';
 import { AbleParams } from './types/common';
 
@@ -64,6 +66,14 @@ export function updateTaskNotice(
 export function ableTask(params: AbleParams): Promise<boolean> {
   return axios.post('/api/admin/apply/task/enable', {}, { params });
 }
+// 预约任务管理-删除时段
+export function deleteTaskTime(timeId: number): Promise<boolean> {
+  return axios.post(
+    '/api/admin/apply/task/rule/delete',
+    {},
+    { params: { timeId } }
+  );
+}
 
 // 考生信息导入
 // 考生信息导入分页
@@ -104,11 +114,17 @@ export function orderRecordTemplate(): Promise<AxiosResponse<Blob>> {
     }
   );
 }
+
+// 预约名单详情分页
+export function orderRecordPrintTimeListPage(): Promise<
+  OrderRecordPrintTimeItem[]
+> {
+  return axios.post('/api/apply/sign/in/date', {});
+}
 // 预约名单详情-打印签到表
-export function orderRecordPrint(params: {
-  teachingId: number;
-  agentId?: number;
-}): Promise<AxiosResponse<Blob>> {
+export function orderRecordPrint(
+  params: OrderRecordPrintParam
+): Promise<AxiosResponse<Blob>> {
   return axios.post(
     '/api/apply/std/auto/sign/in/print',
     {},

+ 12 - 1
src/api/types/order.ts

@@ -43,7 +43,6 @@ export interface TaskItemDetail {
 export interface TaskRuleUpdateParams {
   id: number | null;
   name: string;
-  allowApplyDays: number;
   allowApplyCancelDays: number;
   selfApplyStartTime: number | undefined;
   selfApplyEndTime: number | undefined;
@@ -85,6 +84,8 @@ export interface OrderRecordListFilter {
   name: string;
   identityNumber: string;
   studentCode: string;
+  startDate: number | undefined;
+  endDate: number | undefined;
 }
 export type OrderRecordListPageParam = PageParams<OrderRecordListFilter>;
 
@@ -98,3 +99,13 @@ export interface StudentExportItem {
 }
 
 export type StudentExportListPageRes = PageResult<StudentExportItem>;
+
+export interface OrderRecordPrintTimeItem {
+  examDate: number;
+}
+
+export interface OrderRecordPrintParam {
+  teachingId: number | null;
+  agentId: number | null;
+  examDate: number | undefined;
+}

+ 5 - 0
src/utils/day.ts

@@ -0,0 +1,5 @@
+import dayjs from 'dayjs';
+
+export function getBeforeWeek() {
+  return [dayjs().add(-1, 'week').valueOf(), dayjs().valueOf()];
+}

+ 28 - 29
src/views/order/order-record-manage/index.vue

@@ -20,6 +20,11 @@
         prefix
         :teaching-id="searchModel.teachingId"
       />
+      <select-range-datetime
+        v-model:startTime="searchModel.startDate"
+        v-model:endTime="searchModel.endDate"
+      >
+      </select-range-datetime>
       <a-input v-model.trim="searchModel.name" placeholder="请输入" allow-clear>
         <template #prefix>姓名</template>
       </a-input>
@@ -49,13 +54,18 @@
         </template>
         导入预考
       </a-button>
-      <a-button type="text" :loading="assginLoading" @click="toAssgin">
+      <a-button
+        v-if="isAdmin"
+        type="text"
+        :loading="assginLoading"
+        @click="toAssgin"
+      >
         <template #icon> <svg-icon name="icon-assign" /> </template>
         一键自动分配
       </a-button>
-      <a-button type="text" :loading="printLoading" @click="toPrint">
+      <a-button type="text" @click="toPrint">
         <template #icon> <svg-icon name="icon-print" /> </template>
-        打印签到表
+        导出签到表
       </a-button>
     </a-space>
     <a-table
@@ -97,17 +107,18 @@
       :auto-upload="false"
       @upload-success="getList"
     />
+    <!-- PrintDialog -->
+    <PrintDialog ref="printDialogRef" />
   </div>
 </template>
 
 <script setup lang="ts">
-  import { reactive, ref } from 'vue';
+  import { computed, reactive, ref } from 'vue';
   import { Message, TableColumnData } from '@arco-design/web-vue';
   import {
     orderRecordCancel,
     orderRecordAutoAssign,
     orderRecordListPage,
-    orderRecordPrint,
     orderRecordTemplate,
   } from '@/api/order';
   import { OrderRecordItem, OrderRecordListFilter } from '@/api/types/order';
@@ -116,11 +127,13 @@
   import useLoading from '@/hooks/loading';
   import { timestampFilter } from '@/utils/filter';
   import { modalConfirm } from '@/utils/arco';
-  import { downloadByApi } from '@/utils/download';
   import { parseTimeRangeDateAndTimeContent } from '@/utils/utils';
+  import { useAppStore, useUserStore } from '@/store';
+  import { downloadByApi } from '@/utils/download';
+  import { getBeforeWeek } from '@/utils/day';
 
   import ImportDialog from '@/components/import-dialog/index.vue';
-  import { useAppStore } from '@/store';
+  import PrintDialog from './printDialog.vue';
 
   defineOptions({
     name: 'OrderRecordManage',
@@ -128,9 +141,10 @@
 
   const appStore = useAppStore();
   appStore.setInfo({ breadcrumbs: ['考试预约管理', '预约明细'] });
+  const userStore = useUserStore();
+  const isAdmin = computed(() => userStore.role === 'ADMIN');
 
-  // const { getLabel: getAbleLabel } = useDictOption('ABLE_TYPE');
-
+  const preDate = getBeforeWeek();
   const searchModel = reactive<OrderRecordListFilter>({
     taskId: null,
     teachingId: null,
@@ -138,6 +152,8 @@
     name: '',
     identityNumber: '',
     studentCode: '',
+    startDate: preDate[0],
+    endDate: preDate[1],
   });
 
   const columns: TableColumnData[] = [
@@ -249,26 +265,9 @@
   }
 
   // 打印签到表
-  const { loading: printLoading, setLoading: setPrintLoading } = useLoading();
-  async function toPrint() {
-    if (printLoading.value) return;
-    if (!searchModel.teachingId) {
-      Message.error('请先选择教学点');
-      return;
-    }
-    setPrintLoading(true);
-
-    const res = await downloadByApi(() =>
-      orderRecordPrint({
-        teachingId: searchModel.teachingId as number,
-        agentId: searchModel.agentId || undefined,
-      })
-    ).catch((e) => {
-      Message.error(e || '下载失败,请重新尝试!');
-    });
-    setPrintLoading(false);
-    if (!res) return;
-    Message.success('下载成功!');
+  const printDialogRef = ref();
+  function toPrint() {
+    printDialogRef.value?.open();
   }
 
   // 取消

+ 130 - 0
src/views/order/order-record-manage/printDialog.vue

@@ -0,0 +1,130 @@
+<template>
+  <a-modal
+    v-model:visible="visible"
+    :width="500"
+    title-align="start"
+    top="10vh"
+    :align-center="false"
+    :mask-closable="false"
+    :esc-to-close="false"
+    @before-open="modalBeforeOpen"
+  >
+    <template #title> 导出签到表 </template>
+    <a-form ref="formRef" :model="formData" :rules="rules" auto-label-width>
+      <a-form-item field="teachingId" label="教学点">
+        <SelectTeaching
+          v-model="formData.teachingId"
+          placeholder="请选择"
+          allow-clear
+        />
+      </a-form-item>
+      <a-form-item label="考点">
+        <SelectAgent
+          v-model="formData.agentId"
+          placeholder="请选择"
+          allow-clear
+          :teaching-id="formData.teachingId"
+        />
+      </a-form-item>
+      <a-form-item field="examDate" label="考试日期">
+        <a-select
+          v-model="formData.examDate"
+          placeholder="请选择"
+          :allow-clear="false"
+          :options="optionList"
+          filter-option
+        >
+        </a-select>
+      </a-form-item>
+    </a-form>
+
+    <template #footer>
+      <a-button @click="close">取消</a-button>
+      <a-button type="primary" :disabled="loading" @click="confirm"
+        >确认</a-button
+      >
+    </template>
+  </a-modal>
+</template>
+
+<script setup lang="ts">
+  import { nextTick, reactive, ref } from 'vue';
+  import { Message } from '@arco-design/web-vue';
+  import type { FormInstance } from '@arco-design/web-vue/es/form';
+  import { orderRecordPrintTimeListPage, orderRecordPrint } from '@/api/order';
+  import useLoading from '@/hooks/loading';
+  import useModal from '@/hooks/modal';
+  import { formatDate, objAssign, objModifyAssign } from '@/utils/utils';
+  import { OrderRecordPrintParam } from '@/api/types/order';
+  import { FormRules, Options } from '@/types/global';
+  import { downloadByApi } from '@/utils/download';
+
+  defineOptions({
+    name: 'PrintDialog',
+  });
+
+  /* modal */
+  const { visible, open, close } = useModal();
+  defineExpose({ open, close });
+
+  const defaultFormData = {
+    examDate: undefined,
+    teachingId: null,
+    agentId: null,
+  };
+
+  const formRef = ref<FormInstance>();
+  const formData = reactive<OrderRecordPrintParam>({ ...defaultFormData });
+  const rules: FormRules<keyof OrderRecordPrintParam> = {
+    teachingId: [
+      {
+        required: true,
+        message: '请选择教学点',
+      },
+    ],
+    examDate: [
+      {
+        required: true,
+        message: '请选择打印日期',
+      },
+    ],
+  };
+
+  const optionList = ref<Options[]>([]);
+  async function getTimes() {
+    const res = await orderRecordPrintTimeListPage();
+    optionList.value = (res || []).map((item) => {
+      return {
+        value: item.examDate,
+        label: formatDate('YYYY-MM-DD', new Date(item.examDate)),
+      };
+    });
+  }
+  getTimes();
+
+  /* confirm */
+  const { loading, setLoading } = useLoading();
+  async function confirm() {
+    const err = await formRef.value?.validate();
+    if (err) return;
+
+    setLoading(true);
+    const datas = objAssign(formData, {});
+    const res = await downloadByApi(() => orderRecordPrint(datas)).catch(
+      (e) => {
+        Message.error(e || '下载失败,请重新尝试!');
+      }
+    );
+    setLoading(false);
+    if (!res) return;
+    Message.success('操作成功,开始下载!');
+    close();
+  }
+  /* init modal */
+  function modalBeforeOpen() {
+    objModifyAssign(formData, defaultFormData);
+    nextTick(() => {
+      formRef.value?.clearValidate();
+    });
+  }
+</script>

+ 2 - 23
src/views/order/task-manage/ruleForm.vue

@@ -8,21 +8,7 @@
           allow-clear
         ></a-input>
       </a-form-item>
-      <a-form-item field="allowApplyDays" label="开放预约限制">
-        <span>考前</span>
-        <a-input-number
-          v-model="formData.allowApplyDays"
-          :style="{ width: '120px', margin: '0 10px' }"
-          placeholder="请输入"
-          mode="button"
-          :min="1"
-          :max="999"
-          :step="1"
-          :formatter="intFormatter"
-        />
-        <span>天,禁止考生自主预约</span>
-      </a-form-item>
-      <a-form-item field="allowApplyCancelDays" label="取消预约限制">
+      <a-form-item field="allowApplyCancelDays" label="学生自主操作限制">
         <span>考前</span>
         <a-input-number
           v-model="formData.allowApplyCancelDays"
@@ -34,7 +20,7 @@
           :step="1"
           :formatter="intFormatter"
         />
-        <span>天,禁止考生自主取消预约</span>
+        <span>天,禁止考生自主取消预约</span>
       </a-form-item>
       <a-form-item field="selfApplyStartTime" label="第一阶段开启时间">
         <select-range-datetime
@@ -88,7 +74,6 @@
   const defaultFormData = {
     id: null,
     name: '',
-    allowApplyDays: 1,
     allowApplyCancelDays: 1,
     selfApplyStartTime: undefined,
     selfApplyEndTime: undefined,
@@ -109,12 +94,6 @@
         message: '名称不能超过50字符',
       },
     ],
-    allowApplyDays: [
-      {
-        required: true,
-        message: '请输入开放预约限制时间',
-      },
-    ],
     allowApplyCancelDays: [
       {
         required: true,

+ 38 - 22
src/views/order/task-manage/timeForm.vue

@@ -4,26 +4,33 @@
       <a-form-item label="可选考试时段">
         <a-button type="primary" @click="toAdd">添加</a-button>
       </a-form-item>
-      <div class="time-box">
-        <a-form-item
-          v-for="(time, index) in formData.times"
-          :key="index"
-          :field="`times[${index}].startTime`"
-          :rules="rules"
-          :label="index + 1 + ''"
-        >
-          <select-range-datetime
-            v-model:startTime="time.startTime"
-            v-model:endTime="time.endTime"
+      <a-list
+        class="time-box"
+        :virtual-list-props="{
+          height: 400,
+        }"
+        :data="formData.times"
+        :bordered="false"
+      >
+        <template #item="{ item, index }">
+          <a-form-item
+            :field="`times[${index}].startTime`"
+            :rules="rules"
+            :label="index + 1 + ''"
           >
-          </select-range-datetime>
-          <a-button class="ml-10" status="danger" @click="toDelete(index)">
-            <template #icon>
-              <svg-icon name="icon-delete"></svg-icon>
-            </template>
-          </a-button>
-        </a-form-item>
-      </div>
+            <select-range-datetime
+              v-model:startTime="item.startTime"
+              v-model:endTime="item.endTime"
+            >
+            </select-range-datetime>
+            <a-button class="ml-10" status="danger" @click="toDelete(index)">
+              <template #icon>
+                <svg-icon name="icon-delete"></svg-icon>
+              </template>
+            </a-button>
+          </a-form-item>
+        </template>
+      </a-list>
     </a-form>
   </div>
 
@@ -41,11 +48,13 @@
 <script setup lang="ts">
   import { onMounted, reactive, ref } from 'vue';
   import { Message } from '@arco-design/web-vue';
-  import { updateTaskTime } from '@/api/order';
+  import { updateTaskTime, deleteTaskTime } from '@/api/order';
   import useLoading from '@/hooks/loading';
   import type { FormInstance, FieldRule } from '@arco-design/web-vue/es/form';
   import { deepCopy } from '@/utils/utils';
   import { TaskItemDetail } from '@/api/types/order';
+  import { modalConfirm } from '@/utils/arco';
+
   import AddTimes from './addTimes.vue';
 
   defineOptions({
@@ -90,6 +99,15 @@
   }
 
   async function toDelete(index: number) {
+    const confirmRes = await modalConfirm(
+      '提示',
+      `确定要删除当前时间吗?`
+    ).catch(() => false);
+    if (confirmRes !== 'confirm') return;
+
+    if (formData.times[index].id) {
+      await deleteTaskTime(formData.times[index].id as number);
+    }
     formData.times.splice(index, 1);
     await formRef.value?.validate();
   }
@@ -126,8 +144,6 @@
 
 <style lang="less" scoped>
   .time-box {
-    height: 400px;
-    overflow: auto;
     padding: 10px 0;
     border-radius: var(--border-radius-small);
     border: 1px solid var(--color-border);