Browse Source

订单支付等功能完成

chenlei 5 months ago
parent
commit
d484947ebe

+ 2 - 2
src/api/index.js

@@ -20,7 +20,7 @@ const _axios = axios.create(config);
 _axios.interceptors.request.use(
 _axios.interceptors.request.use(
   function (config) {
   function (config) {
     // 检查请求路径并设置responseType
     // 检查请求路径并设置responseType
-    if (config.url.endsWith('/user/temporary/export') || config.url.endsWith('/user/official/export')) {
+    if (config.url.endsWith('/export')) {
       config.responseType = 'blob'; // 如果是导出excel的请求,则设置responseType为blob
       config.responseType = 'blob'; // 如果是导出excel的请求,则设置responseType为blob
     }
     }
     // Do something before request is sent
     // Do something before request is sent
@@ -42,7 +42,7 @@ _axios.interceptors.response.use(
   function (response) {
   function (response) {
     // Do something with response data
     // Do something with response data
     let data
     let data
-    let isExportRequest = response.config.url.endsWith('/user/temporary/export') || response.config.url.endsWith('/user/official/export');
+    let isExportRequest = response.config.url.endsWith('/export');
     if (import.meta.env.MODE === 'production' && !isExportRequest) {
     if (import.meta.env.MODE === 'production' && !isExportRequest) {
       data = JSON.parse(CryptoJS.Des3Decrypt(response.data, import.meta.env.VITE_APP_RESPONSE_DES_KEY)); // 解密
       data = JSON.parse(CryptoJS.Des3Decrypt(response.data, import.meta.env.VITE_APP_RESPONSE_DES_KEY)); // 解密
     } else {
     } else {

+ 6 - 0
src/api/order/index.js

@@ -0,0 +1,6 @@
+import apiOrderConfig from './order'
+
+export {
+  apiOrderConfig,
+}
+

+ 66 - 0
src/api/order/order.js

@@ -0,0 +1,66 @@
+import { get, post } from "@/api/index";
+
+export default {
+    /**
+     * 商品订单列表 
+     * @param {String} params.PageSize
+     * @param {String} params.CurrentIndex
+     * @param {String} params.SortType
+     * @param {String} params.KeyWord
+     * @param {String} params.PaymentDate
+     * @param {String} params.PaymentWay
+     * @param {String} params.CreatedDate
+     * @param {String} params.ProductType
+     * @param {String} params.RefundStatus
+     * @param {String} params.OrderStatus
+     * @returns 
+     */
+    getProductOrderList:params=>{
+        return get('/order/productOrderList',params)
+    },
+    /**
+     * 支付明细列表 
+     * @param {String} params.PageSize
+     * @param {String} params.CurrentIndex
+     * @param {String} params.SortType
+     * @param {String} params.KeyWord
+     * @param {String} params.PaymentDate
+     * @param {String} params.PaymentWay
+     * @param {String} params.CreatedDate
+     * @param {String} params.OrderStatus
+     * @param {String} params.IsRefund
+     * @returns 
+     */
+    getTradeOrderList:params=>{
+        return get('/order/tradeOrderList',params)
+    },
+    /**
+     * 导出商品订单列表 
+     * @param {String} params.SortType
+     * @param {String} params.KeyWord
+     * @param {String} params.PaymentDate
+     * @param {String} params.PaymentWay
+     * @param {String} params.CreatedDate
+     * @param {String} params.ProductType
+     * @param {String} params.RefundStatus
+     * @param {String} params.OrderStatus
+     * @returns 
+     */
+    getExportProductOrder:params=>{
+        return get('/order/productOrder/export',params)
+    },
+    /**
+     * 导出支付明细列表 
+     * @param {String} params.SortType
+     * @param {String} params.KeyWord
+     * @param {String} params.PaymentDate
+     * @param {String} params.PaymentWay
+     * @param {String} params.CreatedDate
+     * @param {String} params.OrderStatus
+     * @param {String} params.IsRefund
+     * @returns 
+     */
+    getExportTradeOrder:params=>{
+        return get('/order/tradeOrder/export',params)
+    },
+};

+ 38 - 0
src/router/modules/order.js

@@ -0,0 +1,38 @@
+import LayoutIndex from '@/layout/Index.vue'
+
+export default[
+  {
+    path:'/order',
+    component:LayoutIndex,
+    name:'OrderIndex',
+    meta:{
+      title:'统计报表'
+    },
+    children:[
+      {
+        path:'orderList',
+        component:()=>import('@/views/order/OrderList.vue'),
+        name:'OrderList',
+        meta:{
+            title:'商品订单'
+        }
+      },
+      {
+        path:'paymentList',
+        component:()=>import('@/views/order/PaymentList.vue'),
+        name:'PaymentList',
+        meta:{
+            title:'支付明细'
+        }
+      },
+      {
+        path:'refundList',
+        component:()=>import('@/views/order/RefundList.vue'),
+        name:'RefundList',
+        meta:{
+            title:'退款明细'
+        }
+      }
+    ]
+  }
+]

+ 340 - 0
src/views/order/OrderList.vue

@@ -0,0 +1,340 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import {apiOrderConfig} from '@/api/order'
+import { apiMediaCommon } from '@/api/media'
+import UserDialog from './components/UserDialog.vue'
+
+const tableColumns = [
+    {
+        label:'订单编号',
+        key:'OrderID',
+        sortable:false
+    },
+    {
+        label:'姓名',
+        key:'RealName',
+        sortable:false
+    },
+    {
+        label:'手机号',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'商品名称',
+        key:'ProductName',
+        sortable:false
+    },{
+        label:'商品类型',
+        key:'ProductType',
+        sortable:false,
+    },{
+        label:'商品价格',
+        key:'TotalAmount',
+        sortable:false
+    },{
+        label:'有效期',
+        key:'ReadCount',
+        sortable:false
+    },{
+        label:'订单状态',
+        key:'Status',
+        sortable:false
+    },{
+        label:'支付渠道',
+        key:'PaymentWay',
+        sortable:false
+    },{
+        label:'支付金额',
+        key:'ReadCount',
+        sortable:false
+    },{
+        label:'售后状态',
+        key:'RefundStatus',
+        sortable:false
+    },{
+        label:'付款时间',
+        key:'PaymentTime',
+        sortable:false
+    },{
+        label:'下单时间',
+        key:'RefundFinishTime',
+        sortable:false
+    },
+    {
+        label:'操作',
+        key:'handle',
+        align: 'center'
+    }
+]
+const productTypeList = ref([
+    {
+        value: 'report',
+        label: '报告'
+    }, {
+        value: 'audio',
+        label: '音频'
+    }, {
+        value: 'video',
+        label: '视频'
+    }, {
+        value: 'package',
+        label: '套餐'
+    }
+])
+const orderStatusList = ref([
+    {
+        value: 'pending',
+        label: '待支付'
+    }, {
+        value: 'paid',
+        label: '已支付'
+    }, {
+        value: 'closed',
+        label: '已关闭'
+    }, {
+        value: 'refund',
+        label: '售后'
+    }
+])
+const refundListStatusList = ref([
+    {
+        value: 'processing',
+        label: '退款中'
+    }, {
+        value: 'failure',
+        label: '退款失败'
+    }, {
+        value: 'success',
+        label: '退款成功'
+    }
+])
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    sortType:'',
+    paymentDate:'',
+    paymentWay:'',
+    createdDate:'',
+    productType:'',
+    refundStatus:'',
+    orderStatus:''
+})
+
+const tableData = ref([])
+const show = ref(false)
+const showUserDialog = ref(false)
+function getTableData(){
+    apiOrderConfig.getProductOrderList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        SortType:tableQuery.sortType,
+        PaymentDate:tableQuery.paymentDate,
+        PaymentWay:tableQuery.paymentWay,
+        CreatedDate:tableQuery.createdDate,
+        ProductType:tableQuery.productType,
+        RefundStatus:tableQuery.refundStatus,
+        OrderStatus:tableQuery.orderStatus
+    }).then(res=>{
+        if(res.Ret!==200) return 
+
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+getTableData()
+getLableList()
+const labelOptions = ref([])
+const userId = ref('')
+const value1 = ref(['',''])
+function getLableList(){
+    apiMediaCommon.getPermissionList().then(res=>{
+        if(res.Ret!==200) return
+        labelOptions.value = res.Data.List||[]
+    })
+}
+
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    // ascending 
+    const propMap = {
+        0:'CreatedTime',
+        1:'ReadCount',
+        2:'LastReadTime',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+
+// 查看用户详情
+function Details(row) {
+    if (row.ReadCount <= 0) return;
+    show.value = true;
+    userId.value = row.TemplateUserId + '';
+}
+function handleSelectChange() {
+    getTableData();
+}
+function userDetails(row) {
+    showUserDialog.value = true;
+}
+
+/* 下载数据 */
+async function downloadExcel() {
+    const res = await apiOrderConfig.getExportProductOrder(
+        {
+            Keyword:tableQuery.keyWord,
+            SortType:tableQuery.sortType,
+            PaymentDate:tableQuery.paymentDate,
+            PaymentWay:tableQuery.paymentWay,
+            CreatedDate:tableQuery.createdDate,
+            ProductType:tableQuery.productType,
+            RefundStatus:tableQuery.refundStatus,
+            OrderStatus:tableQuery.orderStatus
+        }
+    )
+    const blob = new Blob([res], {
+        type: "application/vnd.ms-excel;charset=utf-8",
+    });
+    let fileName = res.fileName;
+    const elink = document.createElement("a");
+    elink.download = fileName; //命名下载名称
+    elink.style.display = "none";
+    elink.href = URL.createObjectURL(blob);
+    document.body.appendChild(elink);
+    elink.click(); // 点击下载
+    URL.revokeObjectURL(elink.href); // 释放URL 对象
+    document.body.removeChild(elink); // 释放标
+}
+</script>
+
+<template>
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap">
+            <div class="top-box">
+                <div class="search-box">
+                    <el-select clearable v-model="tableQuery.productType" @change="handleSelectChange()" placeholder="产品类型" style="width: 150px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in productTypeList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-select clearable v-model="tableQuery.orderStatus" @change="handleSelectChange()" placeholder="订单状态" style="width: 150px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in orderStatusList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-select v-model="tableQuery.FollowingGzh" clearable @change="handleSelectChange()" placeholder="支付渠道" style="width: 150px; margin-right: 20px;">
+                        <el-option label="是" :value="true"></el-option>
+                        <el-option label="否" :value="false"></el-option>
+                    </el-select>
+                    <el-select v-model="tableQuery.refundStatus" clearable @change="handleSelectChange()" placeholder="售后状态" style="width: 150px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in refundListStatusList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-date-picker
+                        v-model="tableQuery.createdDate"
+                        type="date"
+                        placeholder="付款时间"
+                        format="YYYY-MM-DD"
+                        style="margin-right: 20px;width: 150px;"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                    <el-date-picker
+                        v-model="tableQuery.paymentDate"
+                        type="date"
+                        placeholder="下单时间"
+                        style="margin-right: 20px;width: 150px;"
+                        format="YYYY-MM-DD"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                </div>
+                <div class="search-box">
+                    <el-button type="primary" style="margin-right: 20px;" @click="downloadExcel">导出表格</el-button>
+                    <el-input 
+                        v-model="tableQuery.keyWord"
+                        :prefix-icon="Search" clearable
+                        style="width:400px"
+                        placeholder="订单编号/姓名/手机号/商品名称" 
+                        @input="handlePageChange(1)"
+                        />
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table stripe border :data="tableData" @sort-change="handleSortChange">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else-if="column.key === 'handle'">
+                            <span v-if="scope.row.Status !== '已支付'" @click="operation('stock', scope.row)">-</span>
+                            <span class="edit" v-if="scope.row.Status === '已支付' && scope.row.RefundStatus === '退款成功'"  @click="operation('delist', scope.row)" >退款详情</span>
+                            <span class="edit" v-if="scope.row.Status === '已支付'" @click="operation('edit', scope.row)">退款</span>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key] || '-'}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end;margin-top: 20px;"
+                />
+            </div>
+        </div>
+        <UserDialog v-model:show="showUserDialog" :userId="userId"></UserDialog>
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+.temp-user-list-wrap{
+    // height: calc(100vh); //layout padding 30*2 headHeight 48
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .search-box{
+            text-align: right;
+            margin: 10px 0 20px 0;
+        }
+    }
+    .table-box{
+    //    .ReadCount {
+    //     color: rgba(8, 108, 224, 1);
+    //     cursor: pointer;
+    //    }
+       .edit {
+            cursor:pointer;
+            color: rgba(8, 108, 224, 1);
+            margin-right: 10px;
+       }
+    }
+}
+</style>

+ 278 - 0
src/views/order/PaymentList.vue

@@ -0,0 +1,278 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import {apiOrderConfig} from '@/api/order'
+import { apiMediaCommon } from '@/api/media'
+
+const tableColumns = [
+    {
+        label:'支付单号',
+        key:'transaction_id',
+        sortable:false
+    },
+    {
+        label:'订单编号',
+        key:'product_order_id',
+        sortable:false
+    },
+    {
+        label:'姓名',
+        key:'RealName',
+        sortable:false
+    },
+    {
+        label:'手机号',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'商品名称',
+        key:'ProductName',
+        sortable:false
+    },{
+        label:'支付金额',
+        key:'payment_account',
+        sortable:false
+    },{
+        label:'支付状态',
+        key:'payment_status',
+        sortable:false
+    },{
+        label:'支付渠道',
+        key:'payment_way',
+        sortable:false
+    },{
+        label:'支付账号',
+        key:'ReadCount',
+        sortable:false
+    },{
+        label:'收款方',
+        key:'merchant_id',
+        sortable:false
+    },{
+        label:'完成支付时间',
+        key:'DealTime',
+        sortable:false
+    },{
+        label:'创建时间',
+        key:'CreatedTime',
+        sortable:false
+    }
+]
+const orderStatusList = ref([
+    {
+        value: 'pending',
+        label: '待支付'
+    }, {
+        value: 'paid',
+        label: '已支付'
+    }, {
+        value: 'closed',
+        label: '已关闭'
+    }, {
+        value: 'refund',
+        label: '售后'
+    }
+])
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    sortType:'',
+    paymentDate:'',
+    paymentWay:'',
+    createdDate:'',
+    orderStatus:''
+})
+
+const tableData = ref([])
+const show = ref(false)
+const showUserDialog = ref(false)
+function getTableData(){
+    apiOrderConfig.getTradeOrderList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        SortType:tableQuery.sortType,
+        PaymentDate:tableQuery.paymentDate,
+        PaymentWay:tableQuery.paymentWay,
+        CreatedDate:tableQuery.createdDate,
+        OrderStatus:tableQuery.orderStatus,
+        IsRefund:false,
+    }).then(res=>{
+        if(res.Ret!==200) return 
+
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+getTableData()
+getLableList()
+const labelOptions = ref([])
+const userId = ref('')
+const value1 = ref(['',''])
+function getLableList(){
+    apiMediaCommon.getPermissionList().then(res=>{
+        if(res.Ret!==200) return
+        labelOptions.value = res.Data.List||[]
+    })
+}
+
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    // ascending 
+    const propMap = {
+        0:'CreatedTime',
+        1:'ReadCount',
+        2:'LastReadTime',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+
+// 查看用户详情
+function Details(row) {
+    if (row.ReadCount <= 0) return;
+    show.value = true;
+    userId.value = row.TemplateUserId + '';
+}
+function handleSelectChange() {
+    getTableData();
+}
+function userDetails(row) {
+    showUserDialog.value = true;
+}
+
+/* 下载数据 */
+async function downloadExcel() {
+    const res = await apiOrderConfig.getExportTradeOrder(
+        {
+            Keyword:tableQuery.keyWord,
+            SortType:tableQuery.sortType,
+            PaymentDate:tableQuery.paymentDate,
+            PaymentWay:tableQuery.paymentWay,
+            CreatedDate:tableQuery.createdDate,
+            OrderStatus:tableQuery.orderStatus,
+            IsRefund:false,
+        }
+    )
+    const blob = new Blob([res], {
+        type: "application/vnd.ms-excel;charset=utf-8",
+    });
+    let fileName = res.fileName;
+    const elink = document.createElement("a");
+    elink.download = fileName; //命名下载名称
+    elink.style.display = "none";
+    elink.href = URL.createObjectURL(blob);
+    document.body.appendChild(elink);
+    elink.click(); // 点击下载
+    URL.revokeObjectURL(elink.href); // 释放URL 对象
+    document.body.removeChild(elink); // 释放标
+}
+</script>
+
+<template>
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap">
+            <div class="top-box">
+                <div class="search-box">
+                    <el-select clearable v-model="tableQuery.orderStatus" @change="handleSelectChange()" placeholder="支付状态" style="width: 150px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in orderStatusList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-select v-model="tableQuery.FollowingGzh" clearable @change="handleSelectChange()" placeholder="支付渠道" style="width: 150px; margin-right: 20px;">
+                        <el-option label="微信" :value="true"></el-option>
+                        <el-option label="支付宝" :value="false"></el-option>
+                    </el-select>
+                    <el-date-picker
+                        v-model="tableQuery.createdDate"
+                        type="date"
+                        placeholder="付款时间"
+                        format="YYYY-MM-DD"
+                        style="margin-right: 20px;width: 150px;"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                    <el-date-picker
+                        v-model="tableQuery.paymentDate"
+                        type="date"
+                        placeholder="下单时间"
+                        style="margin-right: 20px;width: 150px;"
+                        format="YYYY-MM-DD"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                </div>
+                <div class="search-box">
+                    <el-button type="primary" style="margin-right: 20px;" @click="downloadExcel">导出表格</el-button>
+                    <el-input 
+                        v-model="tableQuery.keyWord"
+                        :prefix-icon="Search" clearable
+                        style="width:400px"
+                        placeholder="订单编号/姓名/手机号/商品名称" 
+                        @input="handlePageChange(1)"
+                        />
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table stripe border :data="tableData" @sort-change="handleSortChange">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else-if="column.key === 'ReadCount'">
+                            <span class="ReadCount" @click="Details(scope.row)">
+                                {{ scope.row[column.key] }}
+                            </span>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key]}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end;margin-top: 20px;"
+                />
+            </div>
+        </div>
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+.temp-user-list-wrap{
+    // height: calc(100vh); //layout padding 30*2 headHeight 48
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .search-box{
+            text-align: right;
+            margin: 10px 0 20px 0;
+        }
+    }
+    .table-box{
+       .ReadCount {
+        color: rgba(8, 108, 224, 1);
+        cursor: pointer;
+       }
+    }
+}
+</style>

+ 232 - 0
src/views/order/RefundList.vue

@@ -0,0 +1,232 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import {apiOrderConfig} from '@/api/order'
+import { apiMediaCommon } from '@/api/media'
+
+const tableColumns = [
+    {
+        label:'支付单号',
+        key:'transaction_id',
+        sortable:false
+    },
+    {
+        label:'订单编号',
+        key:'product_order_id',
+        sortable:false
+    },
+    {
+        label:'姓名',
+        key:'RealName',
+        sortable:false
+    },
+    {
+        label:'手机号',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'商品名称',
+        key:'ProductName',
+        sortable:false
+    },{
+        label:'支付金额',
+        key:'payment_account',
+        sortable:false
+    },{
+        label:'支付状态',
+        key:'payment_status',
+        sortable:false
+    },{
+        label:'支付渠道',
+        key:'payment_way',
+        sortable:false
+    },{
+        label:'支付账号',
+        key:'ReadCount',
+        sortable:false
+    },{
+        label:'收款方',
+        key:'merchant_id',
+        sortable:false
+    },{
+        label:'完成支付时间',
+        key:'DealTime',
+        sortable:false
+    },{
+        label:'创建时间',
+        key:'CreatedTime',
+        sortable:false
+    }
+]
+const orderStatusList = ref([
+    {
+        value: 'pending',
+        label: '退款中'
+    }, {
+        value: 'failed',
+        label: '退款失败'
+    }, {
+        value: 'done',
+        label: '退款成功'
+    }
+])
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    sortType:'',
+    paymentDate:'',
+    paymentWay:'',
+    createdDate:'',
+    orderStatus:''
+})
+
+const tableData = ref([])
+function getTableData(){
+    apiOrderConfig.getTradeOrderList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        SortType:tableQuery.sortType,
+        PaymentDate:tableQuery.paymentDate,
+        PaymentWay:tableQuery.paymentWay,
+        CreatedDate:tableQuery.createdDate,
+        OrderStatus:tableQuery.orderStatus,
+        IsRefund:true,
+    }).then(res=>{
+        if(res.Ret!==200) return 
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+getTableData()
+
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSelectChange() {
+    getTableData();
+}
+
+/* 下载数据 */
+async function downloadExcel() {
+    const res = await apiOrderConfig.getExportTradeOrder(
+        {
+            Keyword:tableQuery.keyWord,
+            SortType:tableQuery.sortType,
+            PaymentDate:tableQuery.paymentDate,
+            PaymentWay:tableQuery.paymentWay,
+            CreatedDate:tableQuery.createdDate,
+            OrderStatus:tableQuery.orderStatus,
+            IsRefund:true,
+        }
+    )
+    const blob = new Blob([res], {
+        type: "application/vnd.ms-excel;charset=utf-8",
+    });
+    let fileName = res.fileName;
+    const elink = document.createElement("a");
+    elink.download = fileName; //命名下载名称
+    elink.style.display = "none";
+    elink.href = URL.createObjectURL(blob);
+    document.body.appendChild(elink);
+    elink.click(); // 点击下载
+    URL.revokeObjectURL(elink.href); // 释放URL 对象
+    document.body.removeChild(elink); // 释放标
+}
+</script>
+
+<template>
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap">
+            <div class="top-box">
+                <div class="search-box">
+                    <el-select clearable v-model="tableQuery.orderStatus" @change="handleSelectChange()" placeholder="退款状态" style="width: 150px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in orderStatusList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-date-picker
+                        v-model="tableQuery.createdDate"
+                        type="date"
+                        placeholder="完成退款时间"
+                        format="YYYY-MM-DD"
+                        style="margin-right: 20px;width: 200px;"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                    <el-date-picker
+                        v-model="tableQuery.paymentDate"
+                        type="date"
+                        placeholder="下单时间"
+                        style="margin-right: 20px;width: 200px;"
+                        format="YYYY-MM-DD"
+                        value-format="YYYY-MM-DD"
+                        @change="handlePageChange(1)"
+                    />
+                </div>
+                <div class="search-box">
+                    <el-button type="primary" style="margin-right: 20px;" @click="downloadExcel">导出表格</el-button>
+                    <el-input 
+                        v-model="tableQuery.keyWord"
+                        :prefix-icon="Search" clearable
+                        style="width:400px"
+                        placeholder="订单编号/姓名/手机号/商品名称" 
+                        @input="handlePageChange(1)"
+                        />
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table stripe border :data="tableData">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key]}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end;margin-top: 20px;"
+                />
+            </div>
+        </div>
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+.temp-user-list-wrap{
+    // height: calc(100vh); //layout padding 30*2 headHeight 48
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .search-box{
+            text-align: right;
+            margin: 10px 0 20px 0;
+        }
+    }
+    .table-box{
+       .ReadCount {
+        color: rgba(8, 108, 224, 1);
+        cursor: pointer;
+       }
+    }
+}
+</style>

+ 143 - 0
src/views/order/components/UserDialog.vue

@@ -0,0 +1,143 @@
+<script setup>
+const show = defineModel('show', { type: Boolean, default: false })
+const props=defineProps({
+    userId:{
+        type:String,
+        default:''
+    },
+})
+const emits = defineEmits(["success"])
+emits("success")
+
+watch(() => props.show, (newval) => {
+  if (newval) {
+    getTableData()
+  }
+})
+const options = ref([
+    {
+        value: 'report',
+        label: '报告'
+    }, {
+        value: 'audio',
+        label: '音频'
+    }, {
+        value: 'video',
+        label: '视频'
+    }
+])
+
+import { ref, reactive } from 'vue'
+import {apiOrderConfig} from '@/api/order'
+
+const tableColumns = [
+    {
+        label:'标题',
+        key:'SourceName',
+        sortable:false
+    },{
+        label:'产品类型',
+        key:'SourceId',
+        sortable:false
+    },{
+        label:'品种',
+        key:'PermissionNames',
+        sortable:false,
+    },{
+        label:'最近一次点击时间',
+        key:'ClickTime',
+        sortable:true
+    },{
+        label:'停留时长',
+        key:'ReadDurationMinutes',
+        sortable:true
+    }
+]
+
+const tableQuery = reactive({
+    sortParam:'',
+    sortType:'',
+})
+const tableData = ref([])
+function getTableData(){
+    apiOrderConfig.getUserDetail({
+        UserId:props.userId,
+    }).then(res=>{
+        if(res.Ret!==200) return
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging && res.Data.Paging.Totals||0
+    })
+}
+// function handlePageChange(page){
+//     tableQuery.currentPage = page
+//     getTableData()
+// }
+function handleSortChange({order,prop}){
+    const propMap = {
+        0:'ClickTime',
+        1:'ReadDurationMinutes',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+
+function handleSelectChange(){
+    getTableData()
+}
+
+</script>
+
+<template>
+  <el-dialog
+    v-model="show"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    width="60%"
+    draggable
+    title="阅读详情"
+  >
+    <div class="dialog-content">
+        <div class="dialog-content-top">
+        </div>
+        <div class="table">
+            <el-table :data="tableData" @sort-change="handleSortChange">
+                <el-table-column 
+                    v-for="column in tableColumns" :key="column.key"
+                    :prop="column.key" :label="column.label" :sortable="column.sortable">
+                    <template #default="scope">
+                        {{scope.row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+            <!-- <el-pagination
+                background
+                layout="total,prev,pager,next,jumper"
+                :current-page="tableQuery.currentPage"
+                :page-size="tableQuery.pageSize"
+                :total="tableQuery.totals"
+                @current-change="handlePageChange"
+                style=" justify-content: flex-end; margin-top: 10px;"
+            /> -->
+        </div>
+    </div>
+  </el-dialog>
+</template>
+
+<style scoped lang="scss">
+.dialog-content {
+    // padding: 10px 50px 50px 50px;
+    .dialog-content-top {
+        display: flex;
+        justify-content: flex-start;
+        padding-bottom: 30px;
+        :deep(.el-cascader-node__label) {
+            max-width: 111px;
+        }
+    }
+    .table {
+        padding-bottom: 30px;
+    }
+}
+
+</style>