Bladeren bron

完成卡管理功能以及开卡申请功能

month-red-love 1 maand geleden
bovenliggende
commit
53d3f6700c

+ 47 - 0
back-ui/src/api/dz/cards.js

@@ -138,3 +138,50 @@ export function reopenCard(cardIds) {
     },
   });
 }
+
+// 退费
+export function refundCard(cardIds) {
+  return request({
+    url: "/dz/cards/changeCard",
+    method: "post",
+    params: {
+      action: "Refund",
+      cardIds: Array.isArray(cardIds) ? cardIds.join(",") : cardIds,
+    },
+  });
+}
+
+// 获取校区列表
+export function getCampusList(query) {
+  return request({
+    url: "/dz/school/getSchoolList",
+    method: "get",
+    params: query,
+  });
+}
+
+// 关联校区
+export function associateCampus(beginCardNo, endCardNo, campusId) {
+  return request({
+    url: "/dz/cards/changeCampus",
+    method: "post",
+    params: {
+      campusId,
+      begin: beginCardNo,
+      end: endCardNo,
+    },
+  });
+}
+
+// 申请开卡
+export function requestOpenCard(schoolId, beginCardNo, endCardNo) {
+  return request({
+    url: "/dz/cards/requestOpenCard",
+    method: "post",
+    params: {
+      schoolId,
+      begin: beginCardNo,
+      end: endCardNo,
+    },
+  });
+}

+ 87 - 11
back-ui/src/views/dz/cards/components/ApplyCardDialog.vue

@@ -57,7 +57,7 @@
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="handleCancel">取消</el-button>
-        <el-button type="primary" @click="handleSubmit">
+        <el-button type="primary" @click="handleSubmit" :loading="loading">
           <svg-icon
             icon-class="lightning"
             class="mr-1"
@@ -72,19 +72,21 @@
 
 <script setup>
 import { ref, computed, watch } from "vue";
+import { requestOpenCard } from "@/api/dz/cards";
+import { listUniversity } from "@/api/dz/school";
 
 const props = defineProps({
   modelValue: {
     type: Boolean,
     default: false,
   },
-  schoolList: {
+  selectedCards: {
     type: Array,
     default: () => [],
   },
 });
 
-const emit = defineEmits(["update:modelValue", "confirm"]);
+const emit = defineEmits(["update:modelValue", "confirm", "success"]);
 
 const visible = computed({
   get: () => props.modelValue,
@@ -92,6 +94,8 @@ const visible = computed({
 });
 
 const applyCardFormRef = ref();
+const loading = ref(false);
+const schoolList = ref([]);
 
 const form = ref({
   beginCardNo: "",
@@ -104,8 +108,68 @@ const rules = {
     { required: true, message: "开始卡号不能为空", trigger: "blur" },
   ],
   endCardNo: [{ required: true, message: "结束卡号不能为空", trigger: "blur" }],
+  schoolId: [{ required: true, message: "学校不能为空", trigger: "change" }],
 };
 
+// 获取所有学校列表
+async function getAllSchools() {
+  try {
+    const response = await listUniversity({
+      pageNum: 1,
+      pageSize: 1000,
+    });
+    if (response.code === 200) {
+      // 处理API返回的数据结构
+      let schoolData = [];
+
+      // 检查是否有rows字段(直接在response中)
+      if (response.rows) {
+        schoolData = response.rows;
+      }
+      // 检查是否有data.rows字段
+      else if (response.data && response.data.rows) {
+        schoolData = response.data.rows;
+      }
+      // 检查是否有data数组
+      else if (response.data && Array.isArray(response.data)) {
+        schoolData = response.data;
+      }
+      // 检查是否有data对象
+      else if (response.data && response.data.id) {
+        schoolData = [response.data];
+      }
+
+      schoolList.value = schoolData;
+      console.log("所有学校数据:", schoolData);
+    }
+  } catch (error) {
+    console.error("获取所有学校列表失败:", error);
+    schoolList.value = [];
+  }
+}
+
+// 自动填充卡号段
+function autoFillCardRange() {
+  if (props.selectedCards && props.selectedCards.length > 0) {
+    const cardNos = props.selectedCards
+      .map((card) => card.cardNo || card.id)
+      .filter((cardNo) => cardNo && cardNo !== "未知")
+      .sort();
+
+    if (cardNos.length > 0) {
+      const minCardNo = cardNos[0];
+      const maxCardNo = cardNos[cardNos.length - 1];
+
+      // 开始卡号段是最小卡号段的整十数部分
+      const minCardNoNum = parseInt(minCardNo);
+      const beginCardNo = Math.floor(minCardNoNum / 10) * 10;
+
+      form.value.beginCardNo = beginCardNo.toString();
+      form.value.endCardNo = maxCardNo;
+    }
+  }
+}
+
 // 重置表单
 function resetForm() {
   form.value = {
@@ -126,18 +190,27 @@ async function handleSubmit() {
   applyCardFormRef.value.validate(async (valid) => {
     if (valid) {
       try {
-        const data = {
-          beginCardNo: form.value.beginCardNo,
-          endCardNo: form.value.endCardNo,
-          schoolId: form.value.schoolId,
-        };
-
-        emit("confirm", data);
+        loading.value = true;
+        const begin = form.value.beginCardNo;
+        const end = form.value.endCardNo;
+        const schoolId = form.value.schoolId;
+
+        if (!begin || !end) {
+          throw new Error("请填写完整的卡号段");
+        }
+        if (!schoolId) {
+          throw new Error("请选择学校");
+        }
+
+        await requestOpenCard(schoolId, begin, end);
+        emit("success", "申请开卡成功!");
         visible.value = false;
         resetForm();
       } catch (error) {
         console.error("申请开卡失败:", error);
-        throw error;
+        emit("confirm", { error: error.message });
+      } finally {
+        loading.value = false;
       }
     }
   });
@@ -147,6 +220,9 @@ async function handleSubmit() {
 watch(visible, (newVal) => {
   if (!newVal) {
     resetForm();
+  } else {
+    getAllSchools();
+    autoFillCardRange();
   }
 });
 </script>

+ 49 - 5
back-ui/src/views/dz/cards/components/AssignCardDialog.vue

@@ -121,8 +121,12 @@
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="handleCancel">取消</el-button>
-        <el-button type="primary" @click="handleSubmit">分配</el-button>
-        <el-button @click="handleReassign">重新分配</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="loading"
+          >分配</el-button
+        >
+        <el-button @click="handleReassign" :loading="reassignLoading"
+          >重新分配</el-button
+        >
       </div>
     </template>
   </el-dialog>
@@ -157,6 +161,8 @@ const visible = computed({
 });
 
 const assignCardFormRef = ref();
+const loading = ref(false);
+const reassignLoading = ref(false);
 const provinceList = ref([]); // 省份列表
 const schoolList = ref([]); // 学校列表
 const examTypeList = ref([]); // 考生类型列表
@@ -292,6 +298,7 @@ async function handleSubmit() {
   assignCardFormRef.value.validate(async (valid) => {
     if (valid) {
       try {
+        loading.value = true;
         // 获取开始号和结束号
         const begin = form.value.beginCardNo;
         const end = form.value.endCardNo;
@@ -317,15 +324,52 @@ async function handleSubmit() {
       } catch (error) {
         console.error("分配卡失败:", error);
         throw error;
+      } finally {
+        loading.value = false;
       }
     }
   });
 }
 
 // 重新分配
-function handleReassign() {
-  resetForm();
-  emit("success", "已重置分配表单,请重新填写");
+async function handleReassign() {
+  assignCardFormRef.value.validate(async (valid) => {
+    if (valid) {
+      try {
+        reassignLoading.value = true;
+        // 获取开始号和结束号
+        const begin = form.value.beginCardNo;
+        const end = form.value.endCardNo;
+
+        if (!begin || !end) {
+          throw new Error("请填写完整的卡号段");
+        }
+
+        // 再次调用分配卡API
+        await assignCard(
+          form.value.cardType,
+          form.value.agentId,
+          begin,
+          end,
+          form.value.province,
+          form.value.studentCategory,
+          form.value.school
+        );
+
+        emit("success", "重新分配卡成功!");
+        visible.value = false;
+        resetForm();
+      } catch (error) {
+        console.error("重新分配卡失败:", error);
+        throw error;
+      } finally {
+        reassignLoading.value = false;
+      }
+    } else {
+      // 如果表单验证失败,提示用户
+      console.warn("表单验证失败,请检查必填项");
+    }
+  });
 }
 
 // 监听弹窗关闭,重置表单

+ 60 - 11
back-ui/src/views/dz/cards/components/AssociateCampusDialog.vue

@@ -58,7 +58,7 @@
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="handleCancel">取消</el-button>
-        <el-button type="primary" @click="handleConfirm">
+        <el-button type="primary" @click="handleConfirm" :loading="loading">
           <svg-icon
             icon-class="lightning"
             class="mr-1"
@@ -73,19 +73,20 @@
 
 <script setup>
 import { ref, computed, watch } from "vue";
+import { associateCampus, getCampusList } from "@/api/dz/cards";
 
 const props = defineProps({
   modelValue: {
     type: Boolean,
     default: false,
   },
-  campusList: {
+  selectedCards: {
     type: Array,
     default: () => [],
   },
 });
 
-const emit = defineEmits(["update:modelValue", "confirm"]);
+const emit = defineEmits(["update:modelValue", "confirm", "success"]);
 
 const visible = computed({
   get: () => props.modelValue,
@@ -93,6 +94,8 @@ const visible = computed({
 });
 
 const associateCampusFormRef = ref();
+const loading = ref(false);
+const campusList = ref([]);
 
 const form = ref({
   beginCardNo: "",
@@ -108,6 +111,40 @@ const rules = {
   campusId: [{ required: true, message: "校区不能为空", trigger: "change" }],
 };
 
+// 获取校区列表
+async function getCampusListData() {
+  try {
+    const response = await getCampusList({ pageNum: 1, pageSize: 1000 });
+    if (response.code === 200) {
+      campusList.value = response.data || [];
+    }
+  } catch (error) {
+    console.error("获取校区列表失败:", error);
+  }
+}
+
+// 自动填充卡号段
+function autoFillCardRange() {
+  if (props.selectedCards && props.selectedCards.length > 0) {
+    const cardNos = props.selectedCards
+      .map((card) => card.cardNo || card.id)
+      .filter((cardNo) => cardNo && cardNo !== "未知")
+      .sort();
+
+    if (cardNos.length > 0) {
+      const minCardNo = cardNos[0];
+      const maxCardNo = cardNos[cardNos.length - 1];
+
+      // 开始卡号段是最小卡号段的整十数部分
+      const minCardNoNum = parseInt(minCardNo);
+      const beginCardNo = Math.floor(minCardNoNum / 10) * 10;
+
+      form.value.beginCardNo = beginCardNo.toString();
+      form.value.endCardNo = maxCardNo;
+    }
+  }
+}
+
 // 重置表单
 function resetForm() {
   form.value = {
@@ -128,18 +165,27 @@ async function handleConfirm() {
   associateCampusFormRef.value.validate(async (valid) => {
     if (valid) {
       try {
-        const data = {
-          beginCardNo: form.value.beginCardNo,
-          endCardNo: form.value.endCardNo,
-          campusId: form.value.campusId,
-        };
-
-        emit("confirm", data);
+        loading.value = true;
+        const begin = form.value.beginCardNo;
+        const end = form.value.endCardNo;
+        const campusId = form.value.campusId;
+
+        if (!begin || !end) {
+          throw new Error("请填写完整的卡号段");
+        }
+        if (!campusId || campusId === "all") {
+          throw new Error("请选择校区");
+        }
+
+        await associateCampus(begin, end, campusId);
+        emit("success", "关联校区成功!");
         visible.value = false;
         resetForm();
       } catch (error) {
         console.error("关联校区失败:", error);
-        throw error;
+        emit("confirm", { error: error.message });
+      } finally {
+        loading.value = false;
       }
     }
   });
@@ -149,6 +195,9 @@ async function handleConfirm() {
 watch(visible, (newVal) => {
   if (!newVal) {
     resetForm();
+  } else {
+    getCampusListData();
+    autoFillCardRange();
   }
 });
 </script>

+ 24 - 22
back-ui/src/views/dz/cards/index.vue

@@ -230,14 +230,14 @@
 
     <AssociateCampusDialog
       v-model="associateCampusOpen"
-      :campus-list="campusList"
-      @confirm="handleAssociateCampusConfirm"
+      :selected-cards="selectedRows"
+      @success="handleAssociateCampusSuccess"
     />
 
     <ApplyCardDialog
       v-model="applyCardOpen"
-      :school-list="schoolList"
-      @confirm="handleApplyCardConfirm"
+      :selected-cards="selectedRows"
+      @success="handleApplyCardSuccess"
     />
   </div>
 </template>
@@ -319,7 +319,6 @@ const currentCardNo = ref([]); // 当前缴费的卡号(支持数组)
 const currentCloseCardNo = ref([]); // 当前关卡的卡号(支持数组)
 const currentReopenCardNo = ref([]); // 当前重开的卡号(支持数组)
 const currentRefundCardNo = ref(""); // 当前退费的卡号
-const campusList = ref([]); // 校区列表
 const agentList = ref([]); // 代理商列表
 const institutionList = ref([]); // 机构列表
 const selectedRows = ref([]); // 选中的行
@@ -809,12 +808,15 @@ function handleAssociateCampus() {
     proxy.$modal.msgWarning("请选择要关联校区的卡片");
     return;
   }
-
-  // 获取校区列表
-  getCampusList();
   associateCampusOpen.value = true;
 }
 
+// 处理关联校区成功
+function handleAssociateCampusSuccess(message) {
+  proxy.$modal.msgSuccess(message);
+  getList();
+}
+
 // 处理关联校区确认
 function handleAssociateCampusConfirm(data) {
   proxy.$modal.msgSuccess(
@@ -823,21 +825,16 @@ function handleAssociateCampusConfirm(data) {
   getList(); // 刷新列表
 }
 
-// 获取校区列表
-async function getCampusList() {
+// 获取代理商列表
+async function getAgentListData() {
   try {
-    // 这里应该调用获取校区列表的API
-    // 暂时使用模拟数据
-    campusList.value = [
-      { id: 1, name: "主校区" },
-      { id: 2, name: "东校区" },
-      { id: 3, name: "西校区" },
-      { id: 4, name: "南校区" },
-      { id: 5, name: "北校区" },
-    ];
+    const response = await getAgentList({ pageNum: 1, pageSize: 1000 });
+    if (response.code === 200) {
+      agentList.value = response.data || [];
+    }
   } catch (error) {
-    console.error("获取校区列表失败:", error);
-    campusList.value = [];
+    console.error("获取代理商列表失败:", error);
+    agentList.value = [];
   }
 }
 
@@ -847,10 +844,15 @@ function handleApplyCard() {
     proxy.$modal.msgWarning("请选择要申请开卡的卡片");
     return;
   }
-
   applyCardOpen.value = true;
 }
 
+// 处理申请开卡成功
+function handleApplyCardSuccess(message) {
+  proxy.$modal.msgSuccess(message);
+  getList();
+}
+
 // 处理申请开卡确认
 function handleApplyCardConfirm(data) {
   proxy.$modal.msgSuccess(

+ 39 - 0
back-ui/src/views/dz/open/config/form.js

@@ -0,0 +1,39 @@
+const info = [
+  {
+    label: "申请人",
+    name: "applicant",
+    value: "",
+    type: "text",
+    search: true,
+    placeholder: "请输入申请人",
+  },
+  {
+    label: "卡号",
+    name: "cardNo",
+    value: "",
+    type: "text",
+    search: true,
+    placeholder: "请输入卡号",
+  },
+  {
+    label: "申请状态",
+    name: "status",
+    value: "",
+    type: "select",
+    search: true,
+    placeholder: "请选择申请状态",
+    option: [
+      { label: "待审核", value: "0" },
+      { label: "审核通过", value: "1" },
+      { label: "已拒绝", value: "2" },
+    ],
+    optionLabel: "label",
+    optionValue: "value",
+  },
+];
+
+const formInfo = {
+  info,
+};
+
+export default formInfo;

+ 89 - 0
back-ui/src/views/dz/open/config/table.js

@@ -0,0 +1,89 @@
+const tableConfig = {
+  // 表格列配置
+  columns: [
+    {
+      label: "编号",
+      prop: "id",
+      align: "center",
+      width: 80,
+    },
+    {
+      label: "卡号段",
+      prop: "cardRange",
+      align: "center",
+      minWidth: 180,
+      type: "slot",
+      slotName: "cardRange",
+    },
+    {
+      label: "申请数量",
+      prop: "quantity",
+      align: "center",
+      width: 100,
+      type: "slot",
+      slotName: "quantity",
+    },
+    {
+      label: "申请人",
+      prop: "applicant",
+      align: "center",
+      minWidth: 120,
+    },
+    {
+      label: "学校",
+      prop: "schoolName",
+      align: "center",
+      minWidth: 150,
+    },
+    {
+      label: "申请时间",
+      prop: "createTime",
+      align: "center",
+      width: 180,
+      type: "time",
+      format: "{y}-{m}-{d} {h}:{i}:{s}",
+    },
+    {
+      label: "申请状态",
+      prop: "status",
+      align: "center",
+      width: 100,
+      type: "slot",
+      slotName: "status",
+    },
+    {
+      label: "原因",
+      prop: "reason",
+      align: "center",
+      minWidth: 120,
+      type: "slot",
+      slotName: "reason",
+    },
+  ],
+
+  // 操作按钮配置
+  actions: [
+    {
+      key: "review",
+      label: "审核",
+      type: "primary",
+      link: true,
+      permission: ["dz:open:review"],
+      condition: (row) => row.status === 0, // 只有待审核状态才显示审核按钮
+    },
+  ],
+
+  // 表格属性配置
+  tableProps: {
+    stripe: true,
+    border: false,
+    showSelection: true,
+    showIndex: false,
+    showPagination: true,
+    actionWidth: 150,
+    selectionMode: "multiple",
+    rowKey: "id",
+  },
+};
+
+export default tableConfig;

+ 329 - 276
back-ui/src/views/dz/open/index.vue

@@ -1,90 +1,15 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="代理" prop="agentId">
-        <el-input
-          v-model="queryParams.agentId"
-          placeholder="请输入代理"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="起始卡号" prop="startNo">
-        <el-input
-          v-model="queryParams.startNo"
-          placeholder="请输入起始卡号"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="截至卡号" prop="endNo">
-        <el-input
-          v-model="queryParams.endNo"
-          placeholder="请输入截至卡号"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="结束日期" prop="endDate">
-        <el-date-picker clearable
-          v-model="queryParams.endDate"
-          type="date"
-          value-format="YYYY-MM-DD"
-          placeholder="请选择结束日期">
-        </el-date-picker>
-      </el-form-item>
-      <el-form-item label="校区" prop="schoolId">
-        <el-input
-          v-model="queryParams.schoolId"
-          placeholder="请输入校区"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="发件人" prop="sender">
-        <el-input
-          v-model="queryParams.sender"
-          placeholder="请输入发件人"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="重新开卡:0否,1是" prop="isReopen">
-        <el-select v-model="queryParams.isReopen" placeholder="请选择重新开卡:0否,1是" clearable>
-          <el-option
-            v-for="dict in sys_normal_disable"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="卡类型,对应card_type" prop="cardType">
-        <el-select v-model="queryParams.cardType" placeholder="请选择卡类型,对应card_type" clearable>
-          <el-option
-            v-for="dict in card_type"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="状态(0:无效,1:审核结束,2:审核中)" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择状态(0:无效,1:审核结束,2:审核中)" clearable>
-          <el-option
-            v-for="dict in sys_yes_no"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
+    <!-- 搜索表单 -->
+    <SearchForm
+      :config="searchConfig"
+      v-model="queryParams"
+      @search="handleQuery"
+      @reset="resetQuery"
+      :loading="loading"
+    />
 
+    <!-- 操作按钮 -->
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
         <el-button
@@ -93,27 +18,8 @@
           icon="Plus"
           @click="handleAdd"
           v-hasPermi="['dz:open:add']"
-        >新增</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="success"
-          plain
-          icon="Edit"
-          :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['dz:open:edit']"
-        >修改</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="danger"
-          plain
-          icon="Delete"
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['dz:open:remove']"
-        >删除</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -122,60 +28,57 @@
           icon="Download"
           @click="handleExport"
           v-hasPermi="['dz:open:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        v-model:showSearch="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="openList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="标识" align="center" prop="id" />
-      <el-table-column label="代理" align="center" prop="agentId" />
-      <el-table-column label="起始卡号" align="center" prop="startNo" />
-      <el-table-column label="截至卡号" align="center" prop="endNo" />
-      <el-table-column label="结束日期" align="center" prop="endDate" width="180">
-        <template #default="scope">
-          <span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="校区" align="center" prop="schoolId" />
-      <el-table-column label="发件人" align="center" prop="sender" />
-      <el-table-column label="重新开卡:0否,1是" align="center" prop="isReopen">
-        <template #default="scope">
-          <dict-tag :options="sys_normal_disable" :value="scope.row.isReopen"/>
-        </template>
-      </el-table-column>
-      <el-table-column label="卡类型,对应card_type" align="center" prop="cardType">
-        <template #default="scope">
-          <dict-tag :options="card_type" :value="scope.row.cardType"/>
-        </template>
-      </el-table-column>
-      <el-table-column label="状态(0:无效,1:审核结束,2:审核中)" align="center" prop="status">
-        <template #default="scope">
-          <dict-tag :options="sys_yes_no" :value="scope.row.status"/>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template #default="scope">
-          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dz:open:edit']">修改</el-button>
-          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:open:remove']">删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    
-    <pagination
-      v-show="total>0"
+    <!-- 数据表格 -->
+    <Table
+      :data="openList"
+      :columns="tableConfigData.columns"
+      :actions="tableConfigData.actions"
+      :loading="loading"
       :total="total"
-      v-model:page="queryParams.pageNum"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      :query-params="queryParams"
+      v-model:selected-rows="selectedRows"
+      @selection-change="handleSelectionChange"
+      @action="handleAction"
+      @get-list="getList"
+      v-bind="tableConfigData.tableProps"
+    >
+      <!-- 卡号段插槽 -->
+      <template #cardRange="{ row }">
+        <span>{{ row.startNo }}~{{ row.endNo }}</span>
+      </template>
+
+      <!-- 申请数量插槽 -->
+      <template #quantity="{ row }">
+        <span>{{ calculateQuantity(row.startNo, row.endNo) }}</span>
+      </template>
+
+      <!-- 申请状态插槽 -->
+      <template #status="{ row }">
+        <el-tag :type="getStatusType(row.status)">
+          {{ getStatusText(row.status) }}
+        </el-tag>
+      </template>
+
+      <!-- 原因插槽 -->
+      <template #reason="{ row }">
+        <span>{{ row.reason || "-" }}</span>
+      </template>
+    </Table>
 
     <!-- 添加或修改开卡申请对话框 -->
     <el-dialog :title="title" v-model="open" width="500px" append-to-body>
       <el-form ref="openRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="代理" prop="agentId">
-          <el-input v-model="form.agentId" placeholder="请输入代理" />
+        <el-form-item label="申请人" prop="applicant">
+          <el-input v-model="form.applicant" placeholder="请输入申请人" />
         </el-form-item>
         <el-form-item label="起始卡号" prop="startNo">
           <el-input v-model="form.startNo" placeholder="请输入起始卡号" />
@@ -183,47 +86,18 @@
         <el-form-item label="截至卡号" prop="endNo">
           <el-input v-model="form.endNo" placeholder="请输入截至卡号" />
         </el-form-item>
-        <el-form-item label="结束日期" prop="endDate">
-          <el-date-picker clearable
-            v-model="form.endDate"
-            type="date"
-            value-format="YYYY-MM-DD"
-            placeholder="请选择结束日期">
-          </el-date-picker>
+        <el-form-item label="学校" prop="schoolName">
+          <el-input v-model="form.schoolName" placeholder="请输入学校" />
         </el-form-item>
-        <el-form-item label="校区" prop="schoolId">
-          <el-input v-model="form.schoolId" placeholder="请输入校区" />
-        </el-form-item>
-        <el-form-item label="发件人" prop="sender">
-          <el-input v-model="form.sender" placeholder="请输入发件人" />
-        </el-form-item>
-        <el-form-item label="重新开卡:0否,1是" prop="isReopen">
-          <el-radio-group v-model="form.isReopen">
-            <el-radio
-              v-for="dict in sys_normal_disable"
-              :key="dict.value"
-              :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="卡类型,对应card_type" prop="cardType">
-          <el-select v-model="form.cardType" placeholder="请选择卡类型,对应card_type">
-            <el-option
-              v-for="dict in card_type"
-              :key="dict.value"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-            ></el-option>
+        <el-form-item label="申请状态" prop="status">
+          <el-select v-model="form.status" placeholder="请选择申请状态">
+            <el-option label="待审核" :value="0" />
+            <el-option label="审核通过" :value="1" />
+            <el-option label="已拒绝" :value="2" />
           </el-select>
         </el-form-item>
-        <el-form-item label="状态(0:无效,1:审核结束,2:审核中)" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio
-              v-for="dict in sys_yes_no"
-              :key="dict.value"
-              :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
-          </el-radio-group>
+        <el-form-item label="原因" prop="reason">
+          <el-input v-model="form.reason" placeholder="请输入原因" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -233,161 +107,340 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 审核对话框 -->
+    <el-dialog
+      title="审核开卡申请"
+      v-model="reviewOpen"
+      width="400px"
+      append-to-body
+    >
+      <div class="detail">
+        <div class="item">
+          <span class="label"> 卡号段: </span>
+          <span class="value">
+            {{ reviewForm.startNo }}~{{ reviewForm.endNo }}
+          </span>
+        </div>
+        <div class="item">
+          <span class="label"> 申请人: </span>
+          <span class="value">
+            {{ reviewForm.applicant }}
+          </span>
+        </div>
+        <div class="item">
+          <span class="label"> 申请时间: </span>
+          <span class="value">
+            {{ reviewForm.createTime }}
+          </span>
+        </div>
+        <div class="item">
+          <span class="label"> 学校: </span>
+          <span class="value">
+            {{ reviewForm.schoolName }}
+          </span>
+        </div>
+      </div>
+      <el-form
+        ref="reviewRef"
+        :model="reviewForm"
+        :rules="reviewRules"
+        label-width="80px"
+      >
+        <el-form-item label="审核结果" prop="status">
+          <el-radio-group v-model="reviewForm.status">
+            <el-radio :value="1">审核通过</el-radio>
+            <el-radio :value="2">已拒绝</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="原因" prop="reason">
+          <el-input
+            v-model="reviewForm.reason"
+            placeholder="请输入审核原因"
+            type="textarea"
+            :rows="3"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitReview">确 定</el-button>
+          <el-button @click="cancelReview">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Open">
-import { listOpen, getOpen, delOpen, addOpen, updateOpen } from "@/api/dz/open"
+import { listOpen, getOpen, addOpen, updateOpen } from "@/api/dz/open";
+import SearchForm from "@/components/SearchForm/index.vue";
+import Table from "@/components/Table/index.vue";
+import formConfig from "./config/form.js";
+import tableConfig from "./config/table.js";
 
-const { proxy } = getCurrentInstance()
-const { sys_yes_no, sys_normal_disable, card_type } = proxy.useDict('sys_yes_no', 'sys_normal_disable', 'card_type')
+const { proxy } = getCurrentInstance();
 
-const openList = ref([])
-const open = ref(false)
-const loading = ref(true)
-const showSearch = ref(true)
-const ids = ref([])
-const single = ref(true)
-const multiple = ref(true)
-const total = ref(0)
-const title = ref("")
+const openList = ref([]);
+const open = ref(false);
+const reviewOpen = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const total = ref(0);
+const title = ref("");
+const selectedRows = ref([]);
+
+// 搜索配置
+const searchConfig = computed(() => {
+  return formConfig.info.filter((item) => item.search);
+});
+
+// 表格配置
+const tableConfigData = computed(() => tableConfig);
 
 const data = reactive({
   form: {},
+  reviewForm: {
+    id: null,
+    status: null,
+    reason: null,
+    startNo: null,
+    endNo: null,
+    applicant: null,
+    createTime: null,
+    schoolName: null,
+  },
   queryParams: {
     pageNum: 1,
     pageSize: 10,
-    agentId: null,
-    startNo: null,
-    endNo: null,
-    endDate: null,
-    schoolId: null,
-    sender: null,
-    isReopen: null,
-    cardType: null,
-    status: null
+    applicant: null,
+    cardNo: null,
+    status: null,
   },
   rules: {
-    createTime: [
-      { required: true, message: "申请时间不能为空", trigger: "blur" }
+    applicant: [{ required: true, message: "申请人不能为空", trigger: "blur" }],
+    startNo: [{ required: true, message: "起始卡号不能为空", trigger: "blur" }],
+    endNo: [{ required: true, message: "截至卡号不能为空", trigger: "blur" }],
+    schoolName: [{ required: true, message: "学校不能为空", trigger: "blur" }],
+    status: [
+      { required: true, message: "申请状态不能为空", trigger: "change" },
     ],
+  },
+  reviewRules: {
     status: [
-      { required: true, message: "状态(0:无效,1:审核结束,2:审核中)不能为空", trigger: "change" }
-    ]
-  }
-})
+      { required: true, message: "审核结果不能为空", trigger: "change" },
+    ],
+    reason: [],
+  },
+});
 
-const { queryParams, form, rules } = toRefs(data)
+const { queryParams, form, rules, reviewForm, reviewRules } = toRefs(data);
 
 /** 查询开卡申请列表 */
 function getList() {
-  loading.value = true
-  listOpen(queryParams.value).then(response => {
-    openList.value = response.rows
-    total.value = response.total
-    loading.value = false
-  })
+  loading.value = true;
+  listOpen(queryParams.value).then((response) => {
+    openList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 计算申请数量
+function calculateQuantity(startNo, endNo) {
+  if (!startNo || !endNo) return 0;
+  const start = parseInt(startNo);
+  const end = parseInt(endNo);
+  return end - start + 1;
+}
+
+// 获取状态文本
+function getStatusText(status) {
+  const statusMap = {
+    0: "待审核",
+    1: "审核通过",
+    2: "已拒绝",
+  };
+  return statusMap[status] || "未知";
+}
+
+// 获取状态类型
+function getStatusType(status) {
+  const typeMap = {
+    0: "warning",
+    1: "success",
+    2: "danger",
+  };
+  return typeMap[status] || "info";
 }
 
 // 取消按钮
 function cancel() {
-  open.value = false
-  reset()
+  open.value = false;
+  reset();
+}
+
+// 取消审核
+function cancelReview() {
+  reviewOpen.value = false;
+  resetReview();
 }
 
 // 表单重置
 function reset() {
   form.value = {
     id: null,
-    agentId: null,
+    applicant: null,
     startNo: null,
     endNo: null,
-    endDate: null,
-    schoolId: null,
-    sender: null,
+    schoolName: null,
+    status: null,
+    reason: null,
     createTime: null,
-    isReopen: null,
-    cardType: null,
-    status: null
-  }
-  proxy.resetForm("openRef")
+  };
+  proxy.resetForm("openRef");
+}
+
+// 审核表单重置
+function resetReview() {
+  reviewForm.value = {
+    id: null,
+    status: null,
+    reason: null,
+    startNo: null,
+    endNo: null,
+    applicant: null,
+    createTime: null,
+    schoolName: null,
+  };
+  proxy.resetForm("reviewRef");
 }
 
 /** 搜索按钮操作 */
 function handleQuery() {
-  queryParams.value.pageNum = 1
-  getList()
+  queryParams.value.pageNum = 1;
+  getList();
 }
 
 /** 重置按钮操作 */
 function resetQuery() {
-  proxy.resetForm("queryRef")
-  handleQuery()
+  proxy.resetForm("queryRef");
+  handleQuery();
 }
 
 // 多选框选中数据
 function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.id)
-  single.value = selection.length != 1
-  multiple.value = !selection.length
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
 }
 
 /** 新增按钮操作 */
 function handleAdd() {
-  reset()
-  open.value = true
-  title.value = "添加开卡申请"
+  reset();
+  open.value = true;
+  title.value = "添加开卡申请";
 }
 
 /** 修改按钮操作 */
 function handleUpdate(row) {
-  reset()
-  const _id = row.id || ids.value
-  getOpen(_id).then(response => {
-    form.value = response.data
-    open.value = true
-    title.value = "修改开卡申请"
-  })
+  reset();
+  const _id = row.id || ids.value;
+  getOpen(_id).then((response) => {
+    form.value = response.data;
+    open.value = true;
+    title.value = "修改开卡申请";
+  });
+}
+
+/** 审核按钮操作 */
+function handleReview(row) {
+  resetReview();
+
+  // 从列表中获取对应的数据并填充到reviewForm中
+  reviewForm.value = {
+    id: row.id,
+    status: null,
+    reason: null,
+    startNo: row.startNo || "-",
+    endNo: row.endNo || "-",
+    applicant: row.applicant || "-",
+    createTime: row.createTime || "-",
+    schoolName: row.schoolName || "-",
+  };
+
+  reviewOpen.value = true;
+}
+
+/** 表格操作处理 */
+function handleAction(action, row) {
+  switch (action.key) {
+    case "review":
+      handleReview(row);
+      break;
+  }
 }
 
 /** 提交按钮 */
 function submitForm() {
-  proxy.$refs["openRef"].validate(valid => {
+  proxy.$refs["openRef"].validate((valid) => {
     if (valid) {
       if (form.value.id != null) {
-        updateOpen(form.value).then(response => {
-          proxy.$modal.msgSuccess("修改成功")
-          open.value = false
-          getList()
-        })
+        updateOpen(form.value).then((response) => {
+          proxy.$modal.msgSuccess("修改成功");
+          open.value = false;
+          getList();
+        });
       } else {
-        addOpen(form.value).then(response => {
-          proxy.$modal.msgSuccess("新增成功")
-          open.value = false
-          getList()
-        })
+        addOpen(form.value).then((response) => {
+          proxy.$modal.msgSuccess("新增成功");
+          open.value = false;
+          getList();
+        });
       }
     }
-  })
+  });
 }
 
-/** 删除按钮操作 */
-function handleDelete(row) {
-  const _ids = row.id || ids.value
-  proxy.$modal.confirm('是否确认删除开卡申请编号为"' + _ids + '"的数据项?').then(function() {
-    return delOpen(_ids)
-  }).then(() => {
-    getList()
-    proxy.$modal.msgSuccess("删除成功")
-  }).catch(() => {})
+/** 提交审核 */
+function submitReview() {
+  proxy.$refs["reviewRef"].validate((valid) => {
+    if (valid) {
+      // 这里应该调用审核API,暂时使用更新API
+      const updateData = {
+        id: reviewForm.value.id,
+        status: reviewForm.value.status,
+        reason: reviewForm.value.reason,
+      };
+      updateOpen(updateData).then((response) => {
+        proxy.$modal.msgSuccess("审核成功");
+        reviewOpen.value = false;
+        getList();
+      });
+    }
+  });
 }
 
 /** 导出按钮操作 */
 function handleExport() {
-  proxy.download('dz/open/export', {
-    ...queryParams.value
-  }, `open_${new Date().getTime()}.xlsx`)
+  proxy.download(
+    "dz/open/export",
+    {
+      ...queryParams.value,
+    },
+    `open_${new Date().getTime()}.xlsx`
+  );
 }
 
-getList()
+getList();
 </script>
+<style>
+.detail {
+  padding-left: 10px;
+  .item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 10px;
+  }
+}
+</style>