浏览代码

Merge remote-tracking branch 'origin/development' into development

spy 3 周之前
父节点
当前提交
a63c809a63

+ 4 - 0
src/api/modules/homeEntry.ts

@@ -58,6 +58,10 @@ export const getAccountBalance = params => {
 export const getPaymentCycle = params => {
   return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/incomeManage/getPaymentCycle`, params);
 };
+//今日可收益
+export const getGroupIncome = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/incomeManage/getGroupIncome`, params);
+};
 //是否有支付密码
 export const checkPayPassword = params => {
   return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/merchantUser/checkPayPassword`, params);

+ 37 - 26
src/views/financialManagement/realName.vue

@@ -189,26 +189,36 @@
     <!--收款账户-->
     <div class="content-section" v-if="activeTab === 'receivingAccount'">
       <div class="content-wrapper">
-        <el-button type="primary" class="auth-button" @click="handleGoZFB" v-if="userInfo.alipayAccount == null">
+        <el-button type="primary" class="auth-button" @click="handleGoZFB" v-if="!userInfo.alipayAccount">
           添加支付宝账号
         </el-button>
-
-        <div class="zfb-wrapper" v-else>
-          <div class="zfb-left">
-            <el-image :src="zfbIcon" class="zfbIcon" />
-            <div>
-              <div>支付宝</div>
-              <div>{{ userInfo.phone }}</div>
+        <div class="zfb-wrapper" v-if="userInfo.alipayAccount">
+          <div style="width: 100%">
+            <div style="display: flex; align-items: center; justify-content: space-between; width: 100%; margin-top: 10px">
+              <div class="zfb-left">
+                <el-image :src="zfbIcon" class="zfbIcon" />
+                <div>
+                  <div>支付宝</div>
+                  <div>{{ userInfo.alipayAccount }}</div>
+                </div>
+              </div>
+              <div class="operate">
+                <div @click="getEditZfb">编辑</div>
+                <div @click="getDelZfb">删除</div>
+              </div>
             </div>
-          </div>
-          <div class="operate">
-            <div @click="getEditZfb">编辑</div>
-            <div @click="getDelZfb">删除</div>
+            <el-button
+              type="primary"
+              @click="goToCashApply"
+              class="submit-button"
+              style=" position: relative; left: -10%; width: 20%;margin-top: 90px; margin-left: 50%"
+            >
+              去提现
+            </el-button>
           </div>
         </div>
       </div>
     </div>
-    <el-button type="primary" @click="goToCashApply"> 去提现 </el-button>
     <!--添加支付宝账号--->
     <el-dialog v-model="dialogVisibleZFB" :title="zfbTitle" width="500px" :close-on-click-modal="false">
       <el-form ref="authFormRef1" :model="authForm1" :rules="authRules1" label-width="100px" label-position="left">
@@ -284,13 +294,13 @@ import homeIcon from "../../assets/images/home-icon.png";
 import zfbIcon from "../../assets/financial/zfb-icon.png";
 import { lo } from "element-plus/es/locale";
 import { getPhoneCode } from "@/api/modules/newLoginApi";
-const userInfo = localGet("geeker-user").userInfo;
+const userInfo = ref(localGet("geeker-user")?.userInfo || {});
 const router = useRouter();
 const activeTab = ref("realName");
 const dialogVisible = ref(false);
 const loading = ref(false);
 //实名认证
-const goAuth = ref(!userInfo.idCard);
+const goAuth = ref(!userInfo.value.idCard);
 const authFormRef = ref<FormInstance>();
 const authForm = reactive({
   name: "",
@@ -338,7 +348,7 @@ const handleConfirm = async () => {
         if (res && res.code == 200) {
           ElMessage.success(res.msg || "实名认证提交成功");
           let param = {
-            phone: userInfo.phone
+            phone: userInfo.value.phone
           };
           const res1: any = await getMerchantByPhone(param);
           if (res1.code == 200) {
@@ -429,7 +439,7 @@ const handlePasswordOneSubmit = async () => {
       try {
         const res: any = await setPayPassword({
           payPassword: passwordForm.password,
-          id: userInfo.id
+          id: userInfo.value.id
         });
         if (res.code == 200) {
           ElMessage.success(res.msg || "提现密码设置成功");
@@ -497,7 +507,7 @@ const getForgetPassword = async () => {
 };
 // 发送短信验证码
 const sendForgotCode = async () => {
-  let phoneCode: any = await getPhoneCode({ phone: userInfo.phone, appType: "2", businessType: "6" });
+  let phoneCode: any = await getPhoneCode({ phone: userInfo.value.phone, appType: "2", businessType: "6" });
   if (phoneCode.code === 200) {
     ElMessage.success("验证码已发送");
     // 开始倒计时
@@ -525,7 +535,7 @@ const oldTwoPasswordForm = reactive({
 });
 
 const nextStept = async () => {
-  if (oldPasswordForm.password === userInfo.payPassword) {
+  if (oldPasswordForm.password === userInfo.value.payPassword) {
     currentStep.value = 2;
   } else {
     ElMessage.error("原密码错误");
@@ -542,7 +552,7 @@ const handlePasswordTwoSubmit = async () => {
       try {
         const res: any = await setPayPassword({
           payPassword: oldTwoPasswordForm.password,
-          id: userInfo.id
+          id: userInfo.value.id
         });
         if (res.code == 200) {
           ElMessage.success(res.msg || "提现密码修改成功");
@@ -605,13 +615,14 @@ const handleConfirmZFB = async () => {
         const res: any = await addAlipayAccount(params);
         if (res && res.code == 200) {
           ElMessage.success(res.msg || "添加支付宝账号成功");
-
           // 更新本地存储中的支付宝账号
           try {
             const geekerUser = localGet("geeker-user");
             if (geekerUser && geekerUser.userInfo) {
               geekerUser.userInfo.aliPayAccount = authForm1.zfbName;
               localSet("geeker-user", geekerUser);
+              // 更新响应式的 userInfo
+              userInfo.value.alipayAccount = authForm1.zfbName;
             }
           } catch (error) {
             console.error("更新本地存储失败:", error);
@@ -636,7 +647,7 @@ const handleConfirmZFB = async () => {
 const getEditZfb = async () => {
   zfbTitle.value = "编辑支付宝账号";
   dialogVisibleZFB.value = true;
-  authForm1.zfbName = userInfo.phone;
+  authForm1.zfbName = userInfo.value.alipayAccount || userInfo.value.phone;
 };
 const getDelZfb = async () => {
   ElMessageBox.confirm("确定要删除该账号,删除后无法进行提现操作", "删除账号", {
@@ -660,9 +671,9 @@ const forgotPasswordRules: FormRules = {
 // 检查提现密码状态
 const checkPasswordStatus = async () => {
   try {
-    if (userInfo.idCard && userInfo.id) {
+    if (userInfo.value.idCard && userInfo.value.id) {
       const param = {
-        storeUserId: userInfo.id
+        storeUserId: userInfo.value.id
       };
       const res: any = await checkPayPassword(param as any);
       if (res.code == 200) {
@@ -687,9 +698,9 @@ const checkPasswordStatus = async () => {
 const checkWithdrawPassword = async () => {
   try {
     // 如果已实名认证,检查是否设置了提现密码
-    if (userInfo.idCard) {
+    if (userInfo.value.idCard) {
       const param = {
-        storeUserId: userInfo.id
+        storeUserId: userInfo.value.id
       };
       const res: any = await checkPayPassword(param as any);
       if (res.code == 200) {

+ 62 - 29
src/views/financialManagement/reconciled.vue

@@ -2,7 +2,7 @@
   <!-- 头部 -->
   <div class="header">
     <el-button class="back-btn" @click="goBack"> 返回 </el-button>
-    <h2 class="title">到账期金额</h2>
+    <h2 class="title">到账期金额</h2>
   </div>
   <div class="table-box">
     <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :init-param="initParam" :data-callback="dataCallback">
@@ -12,20 +12,25 @@
       </template>
     </ProTable>
     <el-dialog v-model="dialogVisible" title="详情" width="500px">
-      <h3>火锅一人惨</h3>
-      <el-row>
-        <el-col :span="12"> 实际收益:+138.32 </el-col>
-        <el-col :span="12"> 技术服务费(3%):-138.32 </el-col>
+      <h3 class="orderInfo">
+        {{ reconciled.couponName }}
+      </h3>
+      <el-row class="couponRow">
+        <el-col :span="12"> 实际收益: +{{ ((reconciled.money || 0) / 100).toFixed(2) }} </el-col>
+        <el-col :span="12">
+          {{ `技术服务费(${reconciled.commissionRate || 3}%)` }}:{{
+            reconciled.commissionStr != null ? reconciled.commissionStr : "--"
+          }}
+        </el-col>
       </el-row>
-      <el-row>
-        <el-col :span="12"> 售价:+138.32 </el-col>
+      <el-row class="couponRow">
+        <el-col :span="12"> 售价: {{ reconciled.price != null ? reconciled.price : "--" }} </el-col>
       </el-row>
-      <h3>订单信息</h3>
+      <h3 class="orderInfo">订单信息</h3>
       <div>
-        <div>券码:</div>
-        <div>下单时间:</div>
-        <div>验券时间:</div>
-        <div>入账时间:</div>
+        <div class="couponRow">下单时间: {{ reconciled.orderTime != null ? reconciled.orderTime : "--" }}</div>
+        <div class="couponRow">验券时间: {{ reconciled.checkTime != null ? reconciled.checkTime : "--" }}</div>
+        <div class="couponRow">入账时间: {{ reconciled.createdTime != null ? reconciled.createdTime : "--" }}</div>
       </div>
     </el-dialog>
   </div>
@@ -39,13 +44,15 @@ import { getPaymentCycle } from "@/api/modules/homeEntry";
 import { localGet } from "@/utils";
 import { useRouter } from "vue-router";
 const router = useRouter();
-const dialogVisible = ref(true);
+const dialogVisible = ref(false);
+const reconciled = ref<any>({});
 // 返回
 const goBack = () => {
   router.back();
 };
 const toDetail = (row: any) => {
   dialogVisible.value = true;
+  reconciled.value = row;
 };
 // ProTable 实例(需要在使用它的地方之前定义)
 const proTable = ref<ProTableInstance>();
@@ -53,24 +60,20 @@ const proTable = ref<ProTableInstance>();
 // 表格配置项
 const columns = reactive<ColumnProps<any>[]>([
   {
-    prop: "name",
-    label: "商品名称",
-    search: {
-      el: "input"
-    }
+    prop: "couponName",
+    label: "商品名称"
   },
   {
-    prop: "price",
-    label: "券码",
-    render: (scope: any) => {
-      return scope.row.price ? `¥${scope.row.price}` : "--";
-    }
-  },
-  {
-    prop: "saleNum",
+    prop: "createdTime",
     label: "入账时间",
-    render: scope => {
-      return scope.row.saleNum === null || !scope.row.saleNum ? "--" : scope.row.saleNum;
+    search: {
+      el: "date-picker",
+      props: {
+        type: "daterange",
+        "range-separator": " - ",
+        "start-placeholder": "开始日期",
+        "end-placeholder": "结束日期"
+      }
     }
   },
   { prop: "operation", label: "操作", fixed: "right", width: 330 }
@@ -98,15 +101,34 @@ onActivated(() => {
 // 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
 const dataCallback = (data: any) => {
   return {
-    list: data.records,
+    list: data.data.records,
     total: data.total
   };
 };
 
+// 格式化日期为 yyyy-mm-dd
+const formatDate = (date: string | Date) => {
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, "0");
+  const day = String(d.getDate()).padStart(2, "0");
+  return `${year}-${month}-${day}`;
+};
+
 // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
 // 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
 const getTableList = (params: any) => {
   let newParams = JSON.parse(JSON.stringify(params));
+  // 处理 createdTime 参数,转换为 startTime 和 endTime
+  if (newParams.createdTime && Array.isArray(newParams.createdTime) && newParams.createdTime.length === 2) {
+    newParams.startTime = formatDate(newParams.createdTime[0]);
+    newParams.endTime = formatDate(newParams.createdTime[1]);
+    delete newParams.createdTime;
+  } else {
+    // 如果没有选择日期范围,清空 startTime 和 endTime
+    newParams.startTime = null;
+    newParams.endTime = null;
+  }
   return getPaymentCycle(newParams);
 };
 </script>
@@ -142,6 +164,17 @@ const getTableList = (params: any) => {
     transform: translateX(-50%);
   }
 }
+.orderInfo {
+  padding-bottom: 20px;
+  font-size: 18px;
+  font-weight: bold;
+}
+.couponRow {
+  padding-bottom: 20px;
+}
+.couponRow:last-child {
+  padding-bottom: 0;
+}
 
 // 在组件样式中添加
 .date-range {

+ 38 - 29
src/views/financialManagement/todayIncomeList.vue

@@ -20,19 +20,24 @@
         </template>
       </ProTable>
       <el-dialog v-model="dialogVisible" title="详情" width="500px">
-        <h2>{{ unposted.couponName }}</h2>
+        <h2 class="orderInfo">
+          {{ unposted.storeName }}
+        </h2>
         <el-row class="couponRow">
-          <el-col :span="12"> 实际收益:+138.32 </el-col>
-          <el-col :span="12"> {{ `技术服务费(${unposted.commissionRate || 3}%)` }}:{{ unposted.commissionStr }} </el-col>
+          <el-col :span="12"> 实际收益: {{ ((unposted.money || 0) / 100).toFixed(2) }} </el-col>
+          <el-col :span="12">
+            {{ `技术服务费(${unposted.commissionRate || 3}%)` }}:
+            {{ unposted.commissionStr != null ? unposted.commissionStr : "--" }}
+          </el-col>
         </el-row>
         <el-row class="couponRow">
-          <el-col :span="12"> 售价:{{ unposted.incomeMoney || ((unposted?.money || 0) / 100).toFixed(2) || "0.00" }} </el-col>
+          <el-col :span="12"> 售价: {{ unposted.price != null ? unposted.price : "--" }} </el-col>
         </el-row>
         <h3 class="orderInfo">订单信息</h3>
         <div>
-          <div class="couponRow">下单时间:{{ unposted.orderTime }}</div>
-          <div class="couponRow">验券时间:{{ unposted.checkTime }}</div>
-          <div class="couponRow">入账时间:</div>
+          <div class="couponRow">下单时间: {{ unposted.orderTime != null ? unposted.orderTime : "--" }}</div>
+          <div class="couponRow">验券时间: {{ unposted.checkTime != null ? unposted.checkTime : "--" }}</div>
+          <div class="couponRow">入账时间: {{ unposted.incomeTime != null ? unposted.incomeTime : "--" }}</div>
         </div>
       </el-dialog>
     </div>
@@ -46,11 +51,11 @@ import type { FormInstance, FormRules } from "element-plus";
 import { ElMessage } from "element-plus";
 import ProTable from "@/components/ProTable/index.vue";
 import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
-import { getPaymentCycle } from "@/api/modules/homeEntry";
+import { getGroupIncome } from "@/api/modules/homeEntry";
 import { ElMessageBox } from "element-plus/es";
 import { localGet } from "@/utils";
 const router = useRouter();
-const dialogVisible = ref(true);
+const dialogVisible = ref(false);
 const unposted = ref<any>({});
 const toDetail = (row: any) => {
   dialogVisible.value = true;
@@ -66,35 +71,25 @@ const proTable = ref<ProTableInstance>();
 // 表格配置项
 const columns = reactive<ColumnProps<any>[]>([
   {
-    prop: "couponName",
+    prop: "storeName",
     label: "商品名称"
   },
   {
-    prop: "price",
-    label: "券码",
-    render: (scope: any) => {
-      return scope.row.price ? `¥${scope.row.price}` : "--";
-    }
-  },
-  {
-    prop: "createdTime",
+    prop: "money",
     label: "实际收益",
     render: scope => {
-      return scope.row.saleNum === null || !scope.row.saleNum ? "--" : scope.row.saleNum;
+      return ((scope.row.money || 0) / 100).toFixed(2) || "0.00";
     }
   },
   {
-    prop: "createdTime",
-    label: "售价",
-    render: scope => {
-      return scope.row.saleNum === null || !scope.row.saleNum ? "--" : scope.row.saleNum;
-    }
+    prop: "price",
+    label: "售价"
   },
   {
     prop: "createdTime",
     label: "技术服务费",
     render: scope => {
-      return scope.row.saleNum === null || !scope.row.saleNum ? "--" : scope.row.saleNum;
+      return scope.row.commissionRate === null || !scope.row.commissionRate ? "--" : scope.row.commissionRate;
     }
   },
   { prop: "operation", label: "操作", fixed: "right", width: 330 }
@@ -104,7 +99,6 @@ const columns = reactive<ColumnProps<any>[]>([
 const initParam = reactive({
   storeId: localGet("createdId"),
   incomeType: 0,
-  paymentType: 0,
   startTime: null,
   endTime: null
 });
@@ -121,8 +115,9 @@ onActivated(() => {
 // dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
 // 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
 const dataCallback = (data: any) => {
+  console.log(data);
   return {
-    list: data.data?.records || data.records || [],
+    list: data.incomeDetailsRecordVoList,
     total: data.data?.total || data.total || 0
   };
 };
@@ -130,15 +125,29 @@ const dataCallback = (data: any) => {
 // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
 // 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
 const getTableList = (params: any) => {
+  console.log(params);
+  // 获取当前日期,格式为 YYYY-MM-DD
+  const today = new Date();
+  const year = today.getFullYear();
+  const month = String(today.getMonth() + 1).padStart(2, "0");
+  const day = String(today.getDate()).padStart(2, "0");
+  const currentDate = `${year}-${month}-${day}`;
+
   let newParams = JSON.parse(JSON.stringify(params));
-  return getPaymentCycle(newParams);
+  // 设置固定参数
+  newParams.date = currentDate;
+  newParams.incomeType = 1;
+  // 确保分页参数存在
+  newParams.page = params.page || params.pageNum || 1;
+  newParams.size = params.size || params.pageSize || 10;
+
+  return getGroupIncome(newParams);
 };
 </script>
 
 <style lang="scss" scoped>
 .todayIncomeList {
   height: 100%;
-  border: 1px solid red;
 }
 .header {
   position: relative;

+ 35 - 11
src/views/financialManagement/unposted.vue

@@ -22,16 +22,20 @@
       <h2>{{ unposted.couponName }}</h2>
       <el-row class="couponRow">
         <el-col :span="12"> 实际收益:+138.32 </el-col>
-        <el-col :span="12"> {{ `技术服务费(${unposted.commissionRate || 3}%)` }}:{{ unposted.commissionStr }} </el-col>
+        <el-col :span="12">
+          {{ `技术服务费(${unposted.commissionRate || 3}%)` }}:{{
+            unposted.commissionStr != null ? unposted.commissionStr : "--"
+          }}
+        </el-col>
       </el-row>
       <el-row class="couponRow">
         <el-col :span="12"> 售价:{{ unposted.incomeMoney || ((unposted?.money || 0) / 100).toFixed(2) || "0.00" }} </el-col>
       </el-row>
       <h3>订单信息</h3>
       <div>
-        <div class="couponRow">下单时间:{{ unposted.orderTime }}</div>
-        <div class="couponRow">验券时间:{{ unposted.checkTime }}</div>
-        <div class="couponRow">入账时间:</div>
+        <div class="couponRow">下单时间:{{ unposted.orderTime != null ? unposted.orderTime : "--" }}</div>
+        <div class="couponRow">验券时间:{{ unposted.checkTime != null ? unposted.checkTime : "--" }}</div>
+        <div class="couponRow">入账时间:{{ unposted.createdTime != null ? unposted.createdTime : "--" }}</div>
       </div>
     </el-dialog>
   </div>
@@ -65,10 +69,7 @@ const goBack = () => {
 const columns = reactive<ColumnProps<any>[]>([
   {
     prop: "couponName",
-    label: "商品名称",
-    search: {
-      el: "input"
-    }
+    label: "商品名称"
   },
   // {
   //   prop: "price",
@@ -80,8 +81,14 @@ const columns = reactive<ColumnProps<any>[]>([
   {
     prop: "createdTime",
     label: "入账时间",
-    render: scope => {
-      return scope.row.saleNum === null || !scope.row.saleNum ? "--" : scope.row.saleNum;
+    search: {
+      el: "date-picker",
+      props: {
+        type: "daterange",
+        "range-separator": " - ",
+        "start-placeholder": "开始日期",
+        "end-placeholder": "结束日期"
+      }
     }
   },
   { prop: "operation", label: "操作", fixed: "right", width: 330 }
@@ -113,11 +120,28 @@ const dataCallback = (data: any) => {
     total: data.data?.total || data.total || 0
   };
 };
-
+// 格式化日期为 yyyy-mm-dd
+const formatDate = (date: string | Date) => {
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, "0");
+  const day = String(d.getDate()).padStart(2, "0");
+  return `${year}-${month}-${day}`;
+};
 // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
 // 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
 const getTableList = (params: any) => {
   let newParams = JSON.parse(JSON.stringify(params));
+  // 处理 createdTime 参数,转换为 startTime 和 endTime
+  if (newParams.createdTime && Array.isArray(newParams.createdTime) && newParams.createdTime.length === 2) {
+    newParams.startTime = formatDate(newParams.createdTime[0]);
+    newParams.endTime = formatDate(newParams.createdTime[1]);
+    delete newParams.createdTime;
+  } else {
+    // 如果没有选择日期范围,清空 startTime 和 endTime
+    newParams.startTime = null;
+    newParams.endTime = null;
+  }
   return getPaymentCycle(newParams);
 };
 </script>

+ 33 - 1
src/views/financialManagement/withdrawaRecord.vue

@@ -67,6 +67,10 @@
               <span class="detail-label">提现状态</span>
               <span class="detail-value status">{{ paymentName(withdrawalDetail.paymentStatus) }}</span>
             </div>
+            <div class="detail-item" v-if="withdrawalDetail.approveFailReason">
+              <span class="detail-label">拒绝原因</span>
+              <span class="detail-value">{{ withdrawalDetail.approveFailReason }}</span>
+            </div>
           </div>
         </div>
       </div>
@@ -124,7 +128,16 @@ const columns = reactive<ColumnProps<any>[]>([
   },
   {
     prop: "createdTime",
-    label: "发起提现时间"
+    label: "发起提现时间",
+    search: {
+      el: "date-picker",
+      props: {
+        type: "daterange",
+        "range-separator": " - ",
+        "start-placeholder": "开始日期",
+        "end-placeholder": "结束日期"
+      }
+    }
   },
   {
     prop: "paymentStatus",
@@ -177,10 +190,29 @@ const dataCallback = (data: any) => {
   };
 };
 
+// 格式化日期为 yyyy-mm-dd
+const formatDate = (date: string | Date) => {
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, "0");
+  const day = String(d.getDate()).padStart(2, "0");
+  return `${year}-${month}-${day}`;
+};
+
 // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
 // 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
 const getTableList = (params: any) => {
   let newParams = JSON.parse(JSON.stringify(params));
+  // 处理 createdTime 参数,转换为 cashOutStartTime 和 cashOutEndTime
+  if (newParams.createdTime && Array.isArray(newParams.createdTime) && newParams.createdTime.length === 2) {
+    newParams.cashOutStartTime = formatDate(newParams.createdTime[0]);
+    newParams.cashOutEndTime = formatDate(newParams.createdTime[1]);
+    delete newParams.createdTime;
+  } else {
+    // 如果没有选择日期范围,清空 cashOutStartTime 和 cashOutEndTime
+    newParams.cashOutStartTime = null;
+    newParams.cashOutEndTime = null;
+  }
   return getCashOutRecordList(newParams);
 };
 

+ 9 - 3
src/views/home/components/go-examine.vue

@@ -54,6 +54,7 @@ import homeOrder from "../../../assets/images/home-order.png";
 import homeIncome from "../../../assets/images/home-income.png";
 import { verifyOrder, verifyCoupon, getTodayOrderCount, getTodayIncome } from "@/api/modules/homeEntry.ts";
 import { localGet } from "@/utils/index";
+const userInfo = localGet("geeker-user").userInfo;
 // 数据(可根据实际接口替换)
 const storeName = ref("时间图书馆");
 const expireDate = ref("2027/10/29");
@@ -85,12 +86,17 @@ const handleVerify = async () => {
   if (res.code == 200) {
     let i = {
       quanCode: voucherCode.value,
-      storeId: 120
+      storeId: userInfo.storeId
     };
-    const res1 = await verifyCoupon(i);
-    if (res && res.data.code === "true") {
+    const res1: any = await verifyCoupon(i);
+    if (res && res1.data.code === 200) {
+      ElMessage.success(res.msg);
+      voucherCode.value = "";
+    } else {
       ElMessage.success(res.msg);
     }
+  } else {
+    ElMessage.success(res.msg);
   }
   console.log("verify voucher:", voucherCode.value);
 };

+ 133 - 114
src/views/licenseManagement/contractManagement.vue

@@ -32,7 +32,14 @@
     </div>
 
     <!-- 更换合同弹窗 -->
-    <el-dialog v-model="replaceDialogVisible" title="更换合同" width="860px" :before-close="handleReplaceDialogClose">
+    <el-dialog
+      v-model="replaceDialogVisible"
+      title="更换合同"
+      width="860px"
+      :before-close="handleReplaceDialogClose"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+    >
       <el-scrollbar height="400px" class="replace-upload-scrollbar">
         <div class="replace-upload-area" :class="{ 'upload-full': uploadedImageCount >= uploadMaxCount }">
           <el-upload
@@ -79,32 +86,39 @@
 
     <!-- 变更记录弹窗 -->
     <el-dialog v-model="changeRecordDialogVisible" title="变更记录" width="900px" :close-on-click-modal="false">
-      <div class="change-record-content">
-        <div class="record-date">
-          {{ currentRecordDate }}
-        </div>
-        <div class="record-items">
-          <div v-for="(item, index) in changeRecordList" :key="index" class="record-item">
-            <div class="record-status-badge" :class="getStatusClass(item.status)">
-              {{ getStatusName(item.status) }}
+      <el-scrollbar height="400px" class="change-record-scrollbar">
+        <div v-if="changeRecordList && changeRecordList.length > 0" class="change-record-content">
+          <div v-for="(item, index) in changeRecordList" :key="index" class="record-group">
+            <div class="record-date" v-if="item.date">
+              {{ item.date }}
             </div>
-            <el-image
-              :src="item.imgUrl"
-              fit="cover"
-              class="record-image"
-              :preview-src-list="changeRecordList.map(record => record.imgUrl)"
-              :initial-index="index"
-            >
-              <template #error>
-                <div class="image-slot">
-                  <el-icon><Picture /></el-icon>
+            <div class="record-items">
+              <div class="record-item">
+                <div class="record-status-badge" :class="getStatusClass(item.licenseExecuteStatus)">
+                  {{ item.licenseExecuteName }}
                 </div>
-              </template>
-            </el-image>
+                <el-image
+                  :src="item.imgUrl"
+                  fit="cover"
+                  class="record-image"
+                  :preview-src-list="changeRecordList.map(record => record.imgUrl)"
+                  :initial-index="index"
+                >
+                  <template #error>
+                    <div class="image-slot">
+                      <el-icon><Picture /></el-icon>
+                    </div>
+                  </template>
+                </el-image>
+              </div>
+            </div>
+            <div v-if="item.rejectionReason" class="rejection-reason">拒绝原因: {{ item.rejectionReason }}</div>
           </div>
         </div>
-        <div v-if="rejectionReason" class="rejection-reason">拒绝原因: {{ rejectionReason }}</div>
-      </div>
+        <div v-else class="empty-record">
+          <el-empty description="暂无变更记录" :image-size="100" />
+        </div>
+      </el-scrollbar>
       <template #footer>
         <div class="dialog-footer">
           <el-button type="primary" @click="changeRecordDialogVisible = false"> 关闭 </el-button>
@@ -120,29 +134,20 @@ import { ElMessage, ElMessageBox } from "element-plus";
 import { Plus, Picture } from "@element-plus/icons-vue";
 import type { UploadProps, UploadFile } from "element-plus";
 import { localGet } from "@/utils";
-import { getContractImages, uploadContractImage, submitContractReview } from "@/api/modules/licenseManagement";
-
-interface ChangeRecordItem {
-  id: string;
-  status: number; // 状态:0-审核中,1-审核通过,2-审核拒绝
-  imgUrl: string; // 图片URL
-  rejectionReason?: string;
-}
+import { getContractImages, uploadContractImage, submitContractReview, getChangeRecords } from "@/api/modules/licenseManagement";
 
 // 状态映射对象
 const statusMap: Record<number, { name: string; class: string }> = {
-  0: { name: "审核中", class: "status-pending" },
   1: { name: "审核通过", class: "status-success" },
-  2: { name: "审核拒绝", class: "status-failed" }
+  2: { name: "审核中", class: "status-pending" },
+  3: { name: "审核拒绝", class: "status-failed" }
 };
 
 const contractList = ref<any>([]);
 const replaceDialogVisible = ref(false);
 const changeRecordDialogVisible = ref(false);
 const fileList = ref<UploadFile[]>([]);
-const currentRecordDate = ref("2025.08.01 10:29");
-const changeRecordList = ref<ChangeRecordItem[]>([]);
-const rejectionReason = ref("");
+const changeRecordList = ref<any>([]);
 
 const id = localGet("createdId");
 
@@ -201,25 +206,22 @@ const handleReplace = () => {
 
 const handleViewChangeRecord = async () => {
   try {
-    // TODO: 调用API获取变更记录
-    // const response = await getChangeRecords();
-    // if (response.code === 200) {
-    //   changeRecordList.value = response.data.records;
-    //   currentRecordDate.value = response.data.date;
-    //   rejectionReason.value = response.data.rejectionReason || "";
-    // }
-    // 模拟数据(假数据)
-    changeRecordList.value = [
-      { id: "1", status: 0, imgUrl: "https://picsum.photos/150/150?random=1" },
-      { id: "2", status: 1, imgUrl: "https://picsum.photos/150/150?random=2" },
-      { id: "3", status: 0, imgUrl: "https://picsum.photos/150/150?random=3" },
-      { id: "4", status: 2, imgUrl: "https://picsum.photos/150/150?random=4" },
-      { id: "5", status: 1, imgUrl: "https://picsum.photos/150/150?random=5" }
-    ];
-    rejectionReason.value = "";
+    const params = {
+      storeId: localGet("createdId")
+    };
+    const res: any = await getChangeRecords(params);
+    if (res.code === 200) {
+      changeRecordList.value = res.data;
+    } else {
+      // 请求失败时清空数据
+      changeRecordList.value = [];
+    }
     changeRecordDialogVisible.value = true;
   } catch (error) {
     ElMessage.error("获取变更记录失败");
+    // 发生错误时清空数据并显示空状态
+    changeRecordList.value = [];
+    changeRecordDialogVisible.value = true;
   }
 };
 
@@ -697,75 +699,92 @@ const getStatusName = (status: number) => {
     color: #8c939d;
   }
 }
-.change-record-content {
-  padding: 20px 0;
-  .record-date {
-    margin-bottom: 20px;
-    font-size: 16px;
-    font-weight: 500;
-    color: var(--el-text-color-primary);
-  }
-  .record-items {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 15px;
-    margin-bottom: 20px;
+.change-record-scrollbar {
+  :deep(.el-scrollbar__wrap) {
+    overflow-x: hidden;
   }
-  .record-item {
-    position: relative;
-    width: 150px;
-    height: 150px;
-    overflow: hidden;
-    border-radius: 8px;
-    .record-status-badge {
-      position: absolute;
-      right: 0;
-      bottom: 0;
-      left: 0;
-      z-index: 1;
-      padding: 4px 8px;
-      font-size: 12px;
+}
+.change-record-content {
+  .record-group {
+    padding: 20px;
+    margin-bottom: 30px;
+    background-color: var(--el-fill-color-lighter);
+    &:last-child {
+      margin-bottom: 0;
+    }
+    .record-date {
+      margin-bottom: 15px;
+      font-size: 16px;
       font-weight: 500;
-      text-align: center;
-      border-radius: 0 0 8px 8px;
-      &.status-pending {
-        color: #e6a23c;
-        background-color: rgb(253 246 236 / 95%);
-        border-top: 1px solid #e6a23c;
-      }
-      &.status-success {
-        color: #67c23a;
-        background-color: rgb(240 249 255 / 95%);
-        border-top: 1px solid #67c23a;
-      }
-      &.status-failed {
-        color: #f56c6c;
-        background-color: rgb(254 240 240 / 95%);
-        border-top: 1px solid #f56c6c;
-      }
+      color: var(--el-text-color-primary);
     }
-    .record-image {
-      width: 100%;
-      height: 100%;
-      .image-slot {
-        display: flex;
-        align-items: center;
-        justify-content: center;
+    .record-items {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 15px;
+    }
+    .record-item {
+      position: relative;
+      width: 150px;
+      height: 150px;
+      overflow: hidden;
+      border-radius: 8px;
+      .record-status-badge {
+        position: absolute;
+        right: 0;
+        bottom: 0;
+        left: 0;
+        z-index: 1;
+        padding: 4px 8px;
+        font-size: 12px;
+        font-weight: 500;
+        text-align: center;
+        border-radius: 0 0 8px 8px;
+        &.status-pending {
+          color: #e6a23c;
+          background-color: rgb(253 246 236 / 90%);
+          border-top: 1px solid #e6a23c;
+        }
+        &.status-success {
+          color: #67c23a;
+          background-color: rgb(240 249 255 / 90%);
+          border-top: 1px solid #67c23a;
+        }
+        &.status-failed {
+          color: #f56c6c;
+          background-color: rgb(254 240 240 / 90%);
+          border-top: 1px solid #f56c6c;
+        }
+      }
+      .record-image {
         width: 100%;
         height: 100%;
-        font-size: 30px;
-        color: var(--el-text-color-placeholder);
-        background: var(--el-fill-color-light);
+        .image-slot {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 100%;
+          height: 100%;
+          font-size: 30px;
+          color: var(--el-text-color-placeholder);
+          background: var(--el-fill-color-light);
+        }
       }
     }
+    .rejection-reason {
+      margin-top: 15px;
+      font-size: 14px;
+      font-weight: 500;
+      color: var(--el-text-color-regular);
+      border-radius: 8px;
+    }
   }
-  .rejection-reason {
-    padding: 15px;
-    margin-top: 20px;
-    font-size: 14px;
-    color: var(--el-text-color-regular);
-    background-color: var(--el-fill-color-lighter);
-    border-radius: 8px;
-  }
+}
+.empty-record {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 300px;
+  padding: 40px 20px;
 }
 </style>