Sfoglia il codice sorgente

预约其他页面

zhangjie 1 anno fa
parent
commit
9ac25d6c73

+ 29 - 0
src/api/order.ts

@@ -4,8 +4,11 @@ import type {
   TaskListPageRes,
   TaskItemDetail,
   TaskRuleUpdateParams,
+  TaskTimeUpdateParams,
+  TaskNoticeUpdateParams,
   OrderRecordListPageRes,
   OrderRecordListPageParam,
+  StudentExportListPageRes,
 } from './types/order';
 import { AbleParams } from './types/common';
 
@@ -38,10 +41,36 @@ export function updateTaskRule(
 ): Promise<{ id: string }> {
   return axios.post('/api/admin/apply/task/rule/save', datas);
 }
+export function updateTaskTime(
+  datas: TaskTimeUpdateParams
+): Promise<{ id: string }> {
+  return axios.post('/api/admin/apply/task/time/save', datas);
+}
+export function updateTaskNotice(
+  datas: TaskNoticeUpdateParams
+): Promise<{ id: string }> {
+  return axios.post('/api/admin/apply/task/notice/save', datas);
+}
 export function ableTask(params: AbleParams): Promise<boolean> {
   return axios.post('/api/admin/apply/task/enable', params);
 }
 
+// 考生信息导入
+// 考生信息导入分页
+export function studentImportListPage(): Promise<StudentExportListPageRes> {
+  return axios.post('/api/admin/std/import/page', {});
+}
+// 考生信息导入-导入模板下载
+export function studentInfoTemplate(): Promise<Blob> {
+  return axios.post(
+    '/api/admin/std/import/template',
+    {},
+    {
+      responseType: 'blob',
+    }
+  );
+}
+
 // 预约名单
 // 预约名单详情分页
 export function orderRecordListPage(

+ 15 - 0
src/api/types/order.ts

@@ -48,6 +48,14 @@ export interface TaskRuleUpdateParams {
   openApplyEndTime: number;
 }
 
+export interface TaskTimeUpdateParams {
+  times: number[][];
+}
+
+export interface TaskNoticeUpdateParams {
+  content: string;
+}
+
 export interface OrderRecordItem {
   id: string;
   name: string;
@@ -73,3 +81,10 @@ export interface OrderRecordListFilter {
   studentCode: string;
 }
 export type OrderRecordListPageParam = PageParams<OrderRecordListFilter>;
+
+export interface StudentExportItem {
+  id: string;
+  name: string;
+}
+
+export type StudentExportListPageRes = PageResult<StudentExportItem>;

+ 1 - 0
src/assets/style/arco-custom.less

@@ -14,6 +14,7 @@
 // .arco-pagination
 .arco-table-pagination {
   display: block;
+  margin-top: 16px;
 }
 .arco-pagination {
   display: flex;

+ 1 - 4
src/assets/style/base.less

@@ -76,15 +76,12 @@
 
 // page-table
 .page-table {
-  .arco-table-container {
-    border: none;
-  }
   .arco-table-tr {
     .arco-table-th {
       color: var(--color-text-gray);
       font-weight: 400;
       background-color: #f7f7f7;
-      border-color: var(--color-border);
+      border-bottom: 1px solid var(--color-border);
     }
     .arco-table-td {
       border-color: var(--color-border);

+ 10 - 1
src/router/routes/modules/order.ts

@@ -18,12 +18,21 @@ const ORDER: AppRouteRecordRaw = {
         requiresAuth: true,
       },
     },
+    {
+      path: 'student-import',
+      name: 'StudentImport',
+      component: () => import('@/views/order/student-import/index.vue'),
+      meta: {
+        title: '考生信息导入',
+        requiresAuth: true,
+      },
+    },
     {
       path: 'student-manage',
       name: 'StudentManage',
       component: () => import('@/views/order/student-manage/index.vue'),
       meta: {
-        title: '考生信息导入',
+        title: '考生管理',
         requiresAuth: true,
       },
     },

+ 5 - 5
src/store/modules/app/menuData.ts

@@ -16,27 +16,27 @@ export const menus = [
     parentId: '1',
     sequence: 1,
     enable: true,
-    roles: [],
+    roles: ['ADMIN'],
   },
   {
     id: '3',
     name: '考生信息导入',
-    url: 'StudentManage',
+    url: 'StudentImport',
     type: 'MENU',
     parentId: '1',
     sequence: 2,
     enable: true,
-    roles: [],
+    roles: ['ADMIN'],
   },
   {
     id: '4',
     name: '考生管理',
-    url: 'ExamStudentManage',
+    url: 'StudentManage',
     type: 'MENU',
     parentId: '1',
     sequence: 3,
     enable: true,
-    roles: [],
+    roles: ['ADMIN'],
   },
   {
     id: '5',

+ 2 - 1
src/views/order/order-record-manage/index.vue

@@ -59,8 +59,9 @@
       class="page-table"
       :columns="columns"
       :data="dataList"
-      :scroll="{ x: 1200 }"
       :pagination="pagination"
+      :scroll="{ x: 1200 }"
+      :bordered="false"
     >
       <template #status="{ record }">
         {{ record.cancel ? '已取消' : '正常' }}

+ 140 - 0
src/views/order/student-import/index.vue

@@ -0,0 +1,140 @@
+<template>
+  <div class="part-box">
+    <a-space class="part-action" :size="6">
+      <a-button type="text" @click="toImport">
+        <template #icon>
+          <svg-icon name="icon-import" />
+        </template>
+        导入
+      </a-button>
+    </a-space>
+    <a-table
+      class="page-table"
+      :columns="columns"
+      :data="dataList"
+      :pagination="pagination"
+      :scroll="{ x: 1200 }"
+      :bordered="false"
+    >
+      <template #status="{ record }">
+        {{ record.cancel ? '已取消' : '正常' }}
+      </template>
+      <template #updateTime="{ record }">
+        {{ timestampFilter(record.updateTime) }}
+      </template>
+      <template #action="{ record }">
+        <a-button type="text" class="btn-danger" @click="toDownload(record)"
+          >下载文件</a-button
+        >
+        <a-button type="text" class="btn-danger" @click="toExportReport(record)"
+          >导出报告</a-button
+        >
+      </template>
+    </a-table>
+
+    <!-- ImportDialog -->
+    <ImportDialog
+      ref="importStudentDialogRef"
+      title="导入考生信息"
+      upload-url="/api/admin/std/upload"
+      :format="['xls', 'xlsx']"
+      :download-handle="downloadTemplate"
+      download-filename="考生信息导入模板.xlsx"
+      :auto-upload="false"
+      @upload-success="getList"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { reactive, ref } from 'vue';
+  import { Message, TableColumnData } from '@arco-design/web-vue';
+  import { studentImportListPage, studentInfoTemplate } from '@/api/order';
+  import { StudentExportItem } from '@/api/types/order';
+  import useTable from '@/hooks/table';
+  // import useLoading from '@/hooks/loading';
+  import { timestampFilter } from '@/utils/filter';
+  import { downloadByApi } from '@/utils/download';
+
+  import ImportDialog from '@/components/import-dialog/index.vue';
+  import { useAppStore } from '@/store';
+
+  defineOptions({
+    name: 'StudentImport',
+  });
+
+  const appStore = useAppStore();
+  appStore.setInfo({ breadcrumbs: ['考试预约管理', '考生信息导入'] });
+
+  const searchModel = reactive({
+    taskId: '',
+    teachingId: '',
+    agentId: '',
+    name: '',
+    identityNumber: '',
+    studentCode: '',
+  });
+
+  const columns: TableColumnData[] = [
+    {
+      title: '任务名称',
+      dataIndex: 'taskName',
+    },
+    {
+      title: '文件名',
+      dataIndex: 'identityNumber',
+    },
+    {
+      title: '状态',
+      dataIndex: 'studentCode',
+      width: 100,
+    },
+    {
+      title: '异常',
+      dataIndex: 'teachingName',
+      width: 100,
+    },
+    {
+      title: '上传时间',
+      slotName: 'updateTime',
+      width: 170,
+    },
+
+    {
+      title: '操作',
+      slotName: 'action',
+      width: 80,
+      fixed: 'right',
+      cellClass: 'action-column',
+    },
+  ];
+  const { dataList, pagination, getList } = useTable<StudentExportItem[]>(
+    studentImportListPage,
+    searchModel,
+    true
+  );
+
+  async function downloadTemplate() {
+    const res = await downloadByApi(() => studentInfoTemplate()).catch((e) => {
+      Message.error(e || '下载失败,请重新尝试!');
+    });
+    if (!res) return;
+    Message.success('下载成功!');
+  }
+
+  // table action
+  // 导入
+  const importStudentDialogRef = ref(null);
+  function toImport() {
+    importStudentDialogRef.value?.open();
+  }
+
+  // 下载文件
+  function toDownload(row: StudentExportItem) {
+    console.log(row);
+  }
+  // 导出报告
+  function toExportReport(row: StudentExportItem) {
+    console.log(row);
+  }
+</script>

+ 147 - 0
src/views/order/student-manage/index.vue

@@ -0,0 +1,147 @@
+<template>
+  <div class="part-box is-filter">
+    <a-space class="filter-line" :size="12" wrap>
+      <SelectTask
+        v-model="searchModel.taskId"
+        placeholder="请选择"
+        allow-clear
+      />
+      <SelectTeaching
+        v-model="searchModel.teachingId"
+        placeholder="请选择"
+        allow-clear
+      />
+      <SelectAgent
+        v-model="searchModel.agentId"
+        placeholder="请选择"
+        allow-clear
+        :teaching-id="searchModel.teachingId"
+      />
+      <a-input v-model.trim="searchModel.name" placeholder="请输入" allow-clear>
+        <template #prefix>姓名</template>
+      </a-input>
+      <a-input
+        v-model.trim="searchModel.identityNumber"
+        placeholder="请输入"
+        allow-clear
+      >
+        <template #prefix>证件号</template>
+      </a-input>
+      <a-input
+        v-model.trim="searchModel.studentCode"
+        placeholder="请输入"
+        allow-clear
+      >
+        <template #prefix>学号</template>
+      </a-input>
+
+      <a-button type="primary" @click="toPage(1)">查询</a-button>
+    </a-space>
+  </div>
+  <div class="part-box">
+    <a-table
+      class="page-table"
+      :columns="columns"
+      :data="dataList"
+      :pagination="pagination"
+      :scroll="{ x: 1200 }"
+      :bordered="false"
+    >
+      <template #status="{ record }">
+        {{ record.cancel ? '已取消' : '正常' }}
+      </template>
+      <template #action="{ record }">
+        <a-button
+          v-if="!record.cancel"
+          type="text"
+          class="btn-danger"
+          @click="toCancel(record)"
+          >取消</a-button
+        >
+      </template>
+    </a-table>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { reactive } from 'vue';
+  import { Message, TableColumnData } from '@arco-design/web-vue';
+  import { orderRecordCancel, orderRecordListPage } from '@/api/order';
+  import { OrderRecordItem } from '@/api/types/order';
+  import useTable from '@/hooks/table';
+  // import useLoading from '@/hooks/loading';
+  import { modalConfirm } from '@/utils/arco';
+  import { useAppStore } from '@/store';
+
+  defineOptions({
+    name: 'StudentManage',
+  });
+
+  const appStore = useAppStore();
+  appStore.setInfo({ breadcrumbs: ['考试预约管理', '考生管理'] });
+
+  // const { getLabel: getAbleLabel } = useDictOption('ABLE_TYPE');
+
+  const searchModel = reactive({
+    taskId: '',
+    teachingId: '',
+    agentId: '',
+    name: '',
+    identityNumber: '',
+    studentCode: '',
+  });
+
+  const columns: TableColumnData[] = [
+    {
+      title: '姓名',
+      dataIndex: 'name',
+      width: 120,
+    },
+    {
+      title: '证件号',
+      dataIndex: 'identityNumber',
+      width: 200,
+    },
+    {
+      title: '学号',
+      dataIndex: 'studentCode',
+      width: 160,
+    },
+    {
+      title: '教学点',
+      dataIndex: 'teachingName',
+      width: 160,
+    },
+    {
+      title: '可约次数',
+      dataIndex: 'agentName',
+      width: 160,
+    },
+    {
+      title: '操作',
+      slotName: 'action',
+      width: 80,
+      fixed: 'right',
+      cellClass: 'action-column',
+    },
+  ];
+  const { dataList, pagination, toPage, getList } = useTable<OrderRecordItem[]>(
+    orderRecordListPage,
+    searchModel,
+    true
+  );
+
+  // table action
+  // 取消
+  async function toCancel(row: OrderRecordItem) {
+    const confirmRes = await modalConfirm(
+      '提示',
+      `确定要取消【${row.name}】的预约吗?`
+    ).catch(() => false);
+    if (confirmRes !== 'confirm') return;
+
+    await orderRecordCancel(row.id);
+    Message.success('操作成功!');
+    getList();
+  }
+</script>

+ 10 - 5
src/views/order/task-manage/index.vue

@@ -22,7 +22,13 @@
     </div>
   </div>
   <div class="part-box">
-    <a-table :columns="columns" :data="dataList" :pagination="pagination">
+    <a-table
+      :columns="columns"
+      :data="dataList"
+      :pagination="pagination"
+      :scroll="{ x: 1200 }"
+      :bordered="false"
+    >
       <template #enable="{ record }">
         {{ getAbleLabel(record.enable) }}
       </template>
@@ -59,10 +65,13 @@
   import useDictOption from '@/hooks/dict-option';
   import { timestampFilter } from '@/utils/filter';
   import { modalConfirm } from '@/utils/arco';
+  import { useAppStore } from '@/store';
 
   defineOptions({
     name: 'TaskManage',
   });
+  const appStore = useAppStore();
+  appStore.setInfo({ breadcrumbs: ['考试预约管理', '预约任务列表'] });
 
   const { getLabel: getAbleLabel } = useDictOption('ABLE_TYPE');
 
@@ -81,25 +90,21 @@
     },
     {
       title: '开启预约时间',
-      dataIndex: 'selfApplyStartTime',
       slotName: 'selfApplyStartTime',
       width: 170,
     },
     {
       title: '自由预约时间',
-      dataIndex: 'openApplyStartTime',
       slotName: 'openApplyStartTime',
       width: 170,
     },
     {
       title: '任务状态',
-      dataIndex: 'enable',
       slotName: 'enable',
       width: 100,
     },
     {
       title: '更新时间',
-      dataIndex: 'updateTime',
       slotName: 'updateTime',
       width: 170,
     },