Bläddra i källkod

退款功能、路由跳转

zuy 2 år sedan
förälder
incheckning
ec236e6a75

+ 4 - 7
admin-web/src/components/form/ExtDLabel.vue

@@ -166,17 +166,14 @@ const setupLabel = ()=>{
         return "-";
       }
     }
-    if(props.modelValue){
-      let dict = (<Dicts>dicts).find(k => k.value == props.modelValue);
+    let dict = (<Dicts>dicts).find(k => k.value == props.modelValue);
 
-      if (dict) {
-        state.text = dict.name||dict.label;
-        state.style = setupColorStyle(state.colorList[dict.value%8]);
-      }
+    if (dict) {
+      state.text = dict.name||dict.label;
+      state.style = setupColorStyle(state.colorList[dict.value%8]);
     }else{
       return "-"
     }
-
   }
 }
 </script>

+ 15 - 0
admin-web/src/router/route.ts

@@ -225,6 +225,21 @@ export const adminRoutes: Array<RouteRecordRaw> = [
                     perm:"recharge.list",
                 },
             },
+            {
+                path: '/refund',
+                name: 'adminRefund',
+                component: () => import('/@/views/admin/refund/index.vue'),
+                meta: {
+                    title: '退款记录',
+                    isLink: '',
+                    isHide: false,
+                    isKeepAlive: true,
+                    isAffix: false,
+                    isIframe: false,
+                    icon: 'ele-Cloudy',
+                    perm:"refund.list",
+                },
+            },
             {
                 path: '/org',
                 name: 'adminOrg',

+ 7 - 0
admin-web/src/theme/app.scss

@@ -236,6 +236,13 @@ body,
 .flex-justify-center{
 	justify-content: center;
 }
+
+.flex-justify-around{
+	justify-content: space-around;
+}
+.flex-justify-between{
+	justify-content: space-between;
+}
 .flex-align-items-center{
 	align-items: center;
 	align-content: center;

+ 12 - 1
admin-web/src/views/admin/account/index.vue

@@ -95,7 +95,14 @@
              <ext-d-label type="User.status" v-model="row[field.prop]"/>
             </template>
             <template v-else-if="'rechargeTimes'===field.prop">
-              <el-button link type="primary" @click="handleGotoRecharge(row)">{{row[field.prop]}} </el-button>
+              <div class="flex w100 flex-justify-around hp">
+                <span>  <el-button link type="primary" @click="handleGotoRecharge(row)">{{row[field.prop]}} <SvgIcon name="ele-Link" class="hc"></SvgIcon></el-button></span>
+              </div>
+            </template>
+            <template v-else-if="'chargeTimes'===field.prop">
+              <div class="flex w100 flex-justify-around hp">
+                <span>  <el-button link type="primary" @click="handleGotoCharge(row)">{{row[field.prop]}} <SvgIcon name="ele-Link" class="hc"></SvgIcon></el-button></span>
+              </div>
             </template>
             <template v-else>
               <div>{{ row[field.prop] }}</div>
@@ -215,6 +222,10 @@ const handleGotoRecharge=(row:any)=>{
   router.push(`/finance?mobilePhone=${row.mobilePhone}`)
 }
 
+const handleGotoCharge=(row:any)=>{
+  router.push(`/ordering?mobilePhone=${row.mobilePhone}`)
+}
+
 // 打开修改用户弹窗
 const onRowClick = (type: string, row: any) => {
   adminUserDialogRef.value.open(type, row);

+ 7 - 1
admin-web/src/views/admin/ordering/index.vue

@@ -239,8 +239,10 @@ const state = reactive({
     data: [] as Array < any >,
     loading: false,
     columns: [
-      {label: '站点ID',  prop: 'stationId',width:100, resizable: true, fixed: 'left'},
+      // {label: '站点ID',  prop: 'stationId',width:100, resizable: true, fixed: 'left'},
+      {label: '站点',  prop: 'stationName',width:150, resizable: true, fixed: 'left'},
       {label: '充电订单号', prop: 'startChargeSeq', width:170, resizable: true, fixed: 'left'},
+      {label: '用户手机号', prop: 'mobilePhone', width:140, resizable: true, fixed: 'left'},
       {label: '充电设备接口编码', prop: 'connectorId', width:160, resizable: true},
       {label: '充电开始时间', prop: 'startTime', sortable: 'custom', width:160, resizable: true},
       {label: '充电结束时间', prop: 'endTime', sortable: 'custom',width:160,  resizable: true},
@@ -291,6 +293,10 @@ onMounted(() => {
     state.formQuery.connectorId = query.connectorId;
   }
 
+  if (query.mobilePhone) {
+    state.formQuery.mobilePhone = query.mobilePhone;
+  }
+
   loadData();
 
   nextTick(() => {

+ 283 - 0
admin-web/src/views/admin/refund/index.vue

@@ -0,0 +1,283 @@
+<style scoped lang="scss">
+.system-container {
+
+  :deep(.el-card__body) {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    flex: 1;
+    overflow: auto;
+
+    .el-table {
+      flex: 1;
+    }
+
+  }
+}
+
+.page-content {
+  margin-bottom: 20px;
+}
+
+.page-pager {
+  background-color: #fff;
+  height: 24px;
+}
+</style>
+<template>
+  <div class="system-container layout-padding">
+    <el-card shadow="hover" class="layout-padding-auto">
+
+
+      <el-form
+          :model="state.formQuery"
+          ref="queryRef"
+          size="default" label-width="0px" class="mt5 mb5">
+        <ext-d-select
+            v-model="state.formQuery.status"
+            placeholder="退款状态"
+            clearable
+            type="Refund.status"
+            @on-change="loadData(true)"
+            class="wd150 mr10">
+        </ext-d-select>
+<!--       <ext-d-select
+            v-model="state.formQuery.fundsAccount"
+            placeholder="资金账户"
+            clearable
+            type="Refund.account"
+            @on-change="loadData(true)"
+            class="wd150 mr10">
+        </ext-d-select>-->
+        <el-input
+            v-model="state.formQuery.mobilePhone"
+            placeholder="手机号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.outRefundNo"
+            placeholder="商户退款单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.outTradeNo"
+            placeholder="商户订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.refundId"
+            placeholder="微信支付退款单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.transactionId"
+            placeholder="微信支付订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+
+        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
+          <SvgIcon name="ele-Search"/>
+          查询
+        </el-button>
+      </el-form>
+
+      <el-table
+          border
+          stripe="stripe"
+          :height="state.tableData.height"
+          highlight-current-row
+          current-row-key="id"
+          row-key="id"
+          :data="state.tableData.data"
+          v-loading="state.tableData.loading"
+          @selection-change="handleTableSelectionChange"
+          @sort-change="handleTableSortChange">
+        <template #empty>
+          <el-empty></el-empty>
+        </template>
+        <el-table-column
+            v-for="field in state.tableData.columns"
+            :key="field.prop"
+            :label="field.label"
+            :column-key="field.prop"
+            :width="field.width"
+            :min-width="field.minWidth"
+            :fixed="field.fixed"
+            :sortable="field.sortable"
+            :show-overflow-tooltip="!field.fixed&&field.width>150"
+        >
+          <template #default="{row}">
+            <template v-if="field.prop==='expand'">
+              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>
+            </template>
+            <template v-else-if="'total'===field.prop">
+              {{u.fmt.fmtMoney(row[field.prop])}}
+            </template>
+            <template v-else-if="'refund'===field.prop">
+              {{u.fmt.fmtMoney(row[field.prop])}}
+            </template>
+            <template v-else-if="'status'===field.prop">
+              <ext-d-label type="Refund.status" v-model="row[field.prop]"/>
+            </template>
+            <template v-else-if="'action'===field.prop">
+              <el-button  v-if="!row.status"  size="small" plain  type="warning" @click="onRefundClick(row)">退款</el-button>
+            </template>
+            <template v-else>
+              <div>{{ row[field.prop] }}</div>
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts" name="RefundLogList">
+import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
+import {$body, $get} from "/@/utils/request";
+import {Msg} from "/@/utils/message";
+import u from "/@/utils/u"
+
+
+import ExtPage from '/@/components/form/ExtPage.vue'
+
+import mittBus from '/@/utils/mitt';
+import ExtDSelect from "/@/components/form/ExtDSelect.vue";
+import ExtDLabel from "/@/components/form/ExtDLabel.vue";
+
+
+//定义引用
+const queryRef = ref();
+
+//定义变量
+const state = reactive({
+  formQuery: {},
+  pageQuery: {
+    pageNum: 1,
+    pageSize: 10,
+    total: 0
+  },
+  tableData: {
+    height: 500,
+    data: [] as Array<any>,
+    loading: false,
+    columns: [
+      {label: '商户退款单号', prop: 'outRefundNo', width: 150, resizable: true,fixed:'left'},
+      {label: '商户订单号', prop: 'outTradeNo', width: 150, resizable: true,fixed:'left'},
+      {label: '手机号', prop: 'mobilePhone', width: 150, resizable: true,fixed:'left'},
+      {label: '退款渠道', prop: 'channel', width: 150,resizable: true},
+      {label: '退款创建(受理)时间', prop: 'createTime', sortable: 'custom', resizable: true, width: 180},
+      {label: '退款状态', prop: 'status', resizable: true, width: 120},
+      {label: '退款成功时间', prop: 'successTime', sortable: 'custom', resizable: true, width: 160},
+      {label: '订单金额', prop: 'total', resizable: true, width: 130},
+      {label: '退款金额', prop: 'refund', resizable: true, width: 130},
+      {label: '用户支付币种', prop: 'currency', resizable: true, width: 120},
+      {label: '资金账户', prop: 'fundsAccount', resizable: true, width: 120},
+      {label: '退款原因', prop: 'reason', resizable: true, width: 120},
+      {label: '微信支付退款单号', prop: 'refundId', resizable: true, width: 150},
+      {label: '微信支付订单号', prop: 'transactionId', resizable: true, width: 150},
+      {label: '退款入账账户', prop: 'userReceivedAccount', resizable: true, width: 120},
+      {
+        label: '操作', prop: 'action', width: 110, align: 'center', fixed: 'right',
+      }
+    ],
+  },
+})
+
+
+// 监听双向绑定 modelValue 的变化
+// watch(
+//         () => state.pageIndex,
+//         () => {
+//
+//         }
+// );
+
+//生命周期钩子
+onBeforeMount(() => {
+})
+
+onMounted(() => {
+  loadData();
+
+  nextTick(() => {
+    let bodyHeight = document.body.clientHeight;
+    let queryHeight = queryRef.value.$el.clientHeight;
+    state.tableData.height = bodyHeight - queryHeight - 320
+  })
+
+  mittBus.on("refundLog.refresh", () => {
+    loadData();
+  })
+});
+
+onBeforeUnmount(() => {
+  mittBus.off("refundLog.refresh")
+})
+
+
+//region 方法区
+// 初始化表格数据
+const loadData = (refresh: boolean = false) => {
+  if (refresh) {
+    state.pageQuery.pageNum = 1;
+  }
+  state.tableData.loading = true;
+  $get(`/finance/listRefundLog`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
+    let {list, total} = res;
+    state.tableData.data = list;
+    state.pageQuery.total = total;
+    state.tableData.loading = false;
+  }).catch(e => {
+    console.error(e)
+    state.tableData.loading = false;
+  })
+};
+
+// 打开修改用户弹窗
+const onRefundClick = ( row: any) => {
+  // if(row.status){
+  //   return;
+  // }
+  Msg.confirm("请确认是否执行退款操作?").then(()=>{
+    $get(`/finance/customWxRefund/${row.refundLogId}`).then((res: any) => {
+      Msg.message(`操作已提交`)
+      loadData(true)
+    }).catch(e => {
+      console.error(e)
+    })
+  })
+};
+
+
+const handleTableSelectionChange = (selection: any) => {
+  console.log("handleTableSelectionChange>>", selection)
+  // emit("on-check-change", selection)
+}
+
+const handleTableSortChange = (column, prop, order) => {
+  console.log("handleTableSortChange>>", column, prop, order)
+  // emit("on-sort-change", column)
+}
+
+
+//endregion
+
+
+// 暴露变量
+// defineExpose({
+//     loadData,
+// });
+</script>

+ 9 - 0
entity/src/main/java/com/kym/entity/admin/queryParams/CustomChargeOrdersQueryParam.java

@@ -70,5 +70,14 @@ public class CustomChargeOrdersQueryParam extends PageParams {
      */
     private LocalDateTime endDate;
 
+    /**
+     * 发票状态
+     */
+    private Integer invoiceStatus;
+
+    /**
+     * 停止原因
+     */
+    private Integer stopReason;
 
 }

+ 2 - 0
entity/src/main/java/com/kym/entity/admin/vo/CustomOrderVo.java

@@ -31,4 +31,6 @@ public class CustomOrderVo {
     private Integer serviceMoney;
     private Integer orderStatus;
     private Integer chargeStatus;
+    private Integer stopReason;
+    private Integer invoiceStatus;
 }

+ 1 - 1
entity/src/main/java/com/kym/entity/miniapp/DataDict.java

@@ -35,7 +35,7 @@ public class DataDict extends BaseEntity implements Serializable {
     /**
      * 定义值
      */
-    private Integer value;
+    private String value;
 
     /**
      * 备注

+ 11 - 1
mapper/src/main/resources/mappers/miniapp/ChargeOrderMapper.xml

@@ -41,6 +41,8 @@
         <result column="service_money" property="serviceMoney"/>
         <result column="order_status" property="orderStatus"/>
         <result column="charge_status" property="chargeStatus"/>
+        <result column="stop_reason" property="stopReason"/>
+        <result column="invoice_status" property="invoiceStatus"/>
     </resultMap>
 
     <resultMap id="StationStatMap" type="com.kym.entity.admin.vo.StationStatVo">
@@ -113,7 +115,9 @@
         t1.elec_money,
         t1.service_money,
         t1.order_status,
-        t1.charge_status
+        t1.charge_status,
+        t1.invoice_status,
+        t1.stop_reason
         FROM
         t_charge_order t1
         LEFT JOIN t_user t2
@@ -146,6 +150,12 @@
             <if test="params.endDate != null">
                 and t1.start_time &lt;= #{params.endDate}
             </if>
+            <if test="params.invoiceStatus != null">
+                and t1.invoice_status = #{params.invoiceStatus}
+            </if>
+            <if test="params.stopReason != null">
+                and t1.stop_reason = #{params.stopReason}
+            </if>
         </where>
         order by t1.start_time desc
     </select>