瀏覽代碼

Merge branch 'refs/heads/master' into cg_dev

yuhongqi 1 月之前
父節點
當前提交
29427d0dd1

+ 16 - 0
src/api/hisStore/statistics.js

@@ -31,3 +31,19 @@ export function exportStorePayment(query) {
   })
 }
 
+export function storeProduct(query) {
+  return request({
+    url: '/store/store/statistics/storeProduct',
+    method: 'get',
+    params: query
+  })
+}
+
+ export function storeOrderStatistics(params) {
+    return request({
+      url: '/store/store/statistics/storeOrderStatistics',
+      method: 'get',
+      params
+    });
+  }
+

+ 9 - 0
src/api/hisStore/storeOrderAudit.js

@@ -17,3 +17,12 @@ export const audit = (data) => {
     data: data
   })
 }
+
+// 批量审核
+export const auditBatch = (data) => {
+  return request({
+    url: '/store/storeOrderAudit/auditBatch',
+    method: 'get',
+    params: data
+  })
+}

+ 6 - 6
src/api/hisStore/userOnlineState.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 查询用户上线情况列表
 export function listUserOnlineState(query) {
   return request({
-    url: '/store/store/userOnlineState/list',
+    url: '/store/userOnlineState/list',
     method: 'get',
     params: query
   })
@@ -12,7 +12,7 @@ export function listUserOnlineState(query) {
 // 查询用户上线情况详细
 export function getUserOnlineState(userId) {
   return request({
-    url: '/store/store/userOnlineState/' + userId,
+    url: '/store/userOnlineState/' + userId,
     method: 'get'
   })
 }
@@ -20,7 +20,7 @@ export function getUserOnlineState(userId) {
 // 新增用户上线情况
 export function addUserOnlineState(data) {
   return request({
-    url: '/store/store/userOnlineState',
+    url: '/store/userOnlineState',
     method: 'post',
     data: data
   })
@@ -29,7 +29,7 @@ export function addUserOnlineState(data) {
 // 修改用户上线情况
 export function updateUserOnlineState(data) {
   return request({
-    url: '/store/store/userOnlineState',
+    url: '/store/userOnlineState',
     method: 'put',
     data: data
   })
@@ -38,7 +38,7 @@ export function updateUserOnlineState(data) {
 // 删除用户上线情况
 export function delUserOnlineState(userId) {
   return request({
-    url: '/store/store/userOnlineState/' + userId,
+    url: '/store/userOnlineState/' + userId,
     method: 'delete'
   })
 }
@@ -46,7 +46,7 @@ export function delUserOnlineState(userId) {
 // 导出用户上线情况
 export function exportUserOnlineState(query) {
   return request({
-    url: '/store/store/userOnlineState/export',
+    url: '/store/userOnlineState/export',
     method: 'get',
     params: query
   })

+ 6 - 0
src/api/store/packageOrder.js

@@ -96,3 +96,9 @@ export function getUserPhone(orderId) {
     method: 'get'
   })
 }
+export function getWxaCodePackageOrderUnLimit(orderId) {
+  return request({
+    url: '/store/packageOrder/getWxaCodePackageOrderUnLimit/'+orderId,
+    method: 'get',
+  })
+}

+ 18 - 0
src/api/store/statistics.js

@@ -76,3 +76,21 @@ export function exportStorePayment(query) {
   })
 }
 
+export function storeProduct(query) {
+  return request({
+    url: '/store/store/statistics/storeProduct',
+    method: 'get',
+    params: query
+  })
+}
+
+export function storeOrderStatistics(query) {
+  return request({
+    url: '/store/store/statistics/storeOrder',
+    method: 'get',
+    params: query
+  })
+}
+
+
+

+ 56 - 11
src/layout/components/Navbar.vue

@@ -107,32 +107,77 @@ export default {
   data() {
     return {
       msgCount:0,
+      previousMsgCount: 0, // 保存上一次的消息计数
       msg:{
         open:false,
         title:'通知消息'
       },
+      msgPollingTimer: null, // 轮询定时器
     }
   },
   created() {
     this.getMsgCount();
+    // 启动消息轮询,每30秒检查一次新消息
+    this.startMsgPolling();
+  },
+  beforeDestroy() {
+    // 组件销毁前清除定时器
+    this.stopMsgPolling();
   },
   methods: {
+    startMsgPolling() {
+      // 清除已存在的定时器
+      if (this.msgPollingTimer) {
+        clearInterval(this.msgPollingTimer);
+      }
+
+      // 设置定时器,每30秒获取一次消息计数
+      this.msgPollingTimer = setInterval(() => {
+        this.getMsgCount();
+      }, 30000); // 30秒轮询一次
+    },
+    stopMsgPolling() {
+      if (this.msgPollingTimer) {
+        clearInterval(this.msgPollingTimer);
+        this.msgPollingTimer = null;
+      }
+    },
     getMsgCount(){
-      // getMsgCount().then(response => {
-      //     this.msgCount = response.counts;
-      //     if(this.msgCount>0){
-      //       this.$notify({
-      //         title: '提示',
-      //         message: '您有'+this.msgCount+"条消息通知",
-      //         position: 'top-right'
-      //       });
-      //     }
-
-      // });
+      getMsg().then(response => {
+        // 计算所有未读消息总数
+        let totalCount = 0;
+        response.counts.forEach(item => {
+          totalCount += item.total;
+        });
+
+        // 保存旧的消息计数
+        this.previousMsgCount = this.msgCount;
+        // 更新消息计数
+        this.msgCount = totalCount;
+
+        // 如果消息计数增加了,显示通知弹框
+        if (this.msgCount > this.previousMsgCount && this.msgCount > 0) {
+          this.$notify({
+            title: '提示',
+            message: '您有'+this.msgCount+"条消息通知",
+            position: 'top-right',
+            type: 'info'
+          });
+        }
+
+      }).catch(error => {
+        console.error("获取消息计数失败:", error);
+      });
     },
     openMsg(){
       console.log(11);
       this.msg.open=true;
+      // 每次打开消息界面时刷新数据
+      if (this.$refs.msg) {
+        this.$refs.msg.getMsg();
+      }
+      // 打开消息后重新获取消息计数来更新角标
+      this.getMsgCount();
     },
     toggleSideBar() {
       this.$store.dispatch('app/toggleSideBar')

+ 199 - 0
src/views/hisStore/components/OrderSummaryTable.vue

@@ -0,0 +1,199 @@
+<!-- src/components/OrderSummaryTable.vue -->
+<template>
+  <div class="table-container">
+    <h3 class="table-title">{{ title }}</h3>
+    <el-table
+      :data="tableData"
+      border
+      stripe
+      style="width: 100%; margin-top: 20px;"
+      :row-class-name="tableRowClassName"
+      :span-method="objectSpanMethod"
+      show-summary
+      :summary-method="getSummaries"
+      >
+      <el-table-column prop="name" :label="nameLable" width="150" class-name="sticky-column" align="center">
+        <template slot-scope="scope">
+          <span :class="{'group-name': scope.row.isGroup}">{{ scope.row.name }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="totalCalls" label="总单数" width="80" align="center"></el-table-column>
+      <el-table-column prop="totalAmount" label="总金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.totalAmount ? scope.row.totalAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="validAmount" label="成单金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.validAmount ? scope.row.validAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="waitingOrders" label="待审数" width="80" align="center"></el-table-column>
+      <el-table-column prop="waitingAmount" label="待审金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.waitingAmount ? scope.row.waitingAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="unPassedOrders" label="未过数" width="80" align="center"></el-table-column>
+      <el-table-column prop="unPassedAmount" label="未过金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.unpassedAmount ? scope.row.unpassedAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="cancelOrders" label="取消数" width="80" align="center"></el-table-column>
+      <el-table-column prop="cancelAmount" label="取消金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.cancelAmount ? scope.row.cancelAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="completeOrders" label="成交数" width="120" align="center"></el-table-column>
+      <el-table-column prop="completeAmount" label="成交金额" width="130" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.completeAmount ? scope.row.completeAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="unshippedOrders" label="成交未发货数" width="120" align="center"></el-table-column>
+      <el-table-column prop="unshippedAmount" label="成交未发货金额" width="130" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.unshippedAmount ? scope.row.unshippedAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="shippedOrders" label="发货数" width="80" align="center"></el-table-column>
+      <el-table-column prop="shippedAmount" label="发货金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.shippedAmount ? scope.row.shippedAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="transitOrders" label="在途数" width="80" align="center"></el-table-column>
+      <el-table-column prop="transitAmount" label="在途金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.transitAmount ? scope.row.transitAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="receivedOrders" label="签收数" width="80" align="center"></el-table-column>
+      <el-table-column prop="receivedAmount" label="签收金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.receivedAmount ? scope.row.receivedAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="returnOrders" label="退货数" width="80" align="center"></el-table-column>
+      <el-table-column prop="returnAmount" label="退货金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.returnAmount ? scope.row.returnAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="paybackOrders" label="回款数" width="80" align="center"></el-table-column>
+      <el-table-column prop="paybackAmount" label="回款金额" width="100" align="center">
+        <template slot-scope="scope">
+          {{ scope.row.paybackAmount ? scope.row.paybackAmount.toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'OrderSummaryTable',
+  props: {
+    title: {
+      type: String,
+      required: true
+    },
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    nameLable: {  // 新增 prop
+      type: String,
+      default: '姓名/工号'
+    }
+  },
+  watch: {
+    tableData: {
+      handler(newVal) {
+        console.log('接收到的tableData:', newVal);
+        console.log('tableData长度:', newVal ? newVal.length : 0);
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    console.log('组件挂载时的tableData:', this.tableData);
+    console.log('tableData长度:', this.tableData ? this.tableData.length : 0);
+  },
+  methods: {
+    // 表格行样式
+    tableRowClassName({ row, rowIndex }) {
+      if (row.isGroup) {
+        return 'group-row';
+      }
+      return '';
+    },
+    // 表格合并方法
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      return {
+        rowspan: 1,
+        colspan: 1
+      };
+    },
+    // 合计方法
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+      const sumFields = ['totalCalls', 'totalAmount', 'validAmount', 'waitingOrders', 'waitingAmount',
+        'unPassedOrders', 'unPassedAmount', 'cancelOrders', 'cancelAmount', 'completeOrders',
+        'completeAmount', 'unshippedOrders', 'unshippedAmount', 'shippedOrders', 'shippedAmount',
+        'transitOrders', 'transitAmount', 'receivedOrders', 'receivedAmount', 'returnOrders',
+        'returnAmount', 'paybackOrders', 'paybackAmount'];
+      
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = '合计';
+          return;
+        }
+        
+        if (sumFields.includes(column.property)) {
+          const values = data.map(item => Number(item[column.property]));
+          if (!values.every(value => Number.isNaN(value))) {
+            const sum = values.reduce((prev, curr) => {
+              const value = Number(curr);
+              if (!Number.isNaN(value)) {
+                return prev + value;
+              } else {
+                return prev;
+              }
+            }, 0);
+            
+            // 对于金额字段保留两位小数
+            if (column.property && column.property.includes('Amount')) {
+              sums[index] = sum.toFixed(2);
+            } else {
+              sums[index] = sum;
+            }
+          } else {
+            sums[index] = '0';
+          }
+        } else {
+          sums[index] = '';
+        }
+      });
+
+      return sums;
+    }
+  } 
+}
+</script>
+
+<style scoped>
+.table-container {
+  margin-top: 30px;
+}
+
+.table-title {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10px;
+}
+</style>

+ 561 - 0
src/views/hisStore/statistics/storeOrderStatistics.vue

@@ -0,0 +1,561 @@
+<template>
+  <div class="app-container">
+    <div class="app-content">
+      <div class="title">
+        商城订单统计
+      </div>
+      <el-form class="search-form" :inline="true" >
+
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <el-form-item label="时间:">
+              <el-select v-model="value" placeholder="请选择日期">
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+             <el-form-item label="公司名:" prop="companyId">
+              <el-select filterable v-model="companyId" @change="companyChange" placeholder="请选择公司名" clearable size="small">
+                <el-option
+                  v-for="item in companys"
+                  :key="item.companyId"
+                  :label="item.companyName"
+                  :value="item.companyId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="部门:">
+              <treeselect :clearable="true"  v-model="deptId"  :options="deptOptions" :show-count="true"  placeholder="请选择归属部门" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="员工:">
+              <el-select filterable v-model="userIds" placeholder="请选择员工" clearable size="small">
+                <el-option
+                  v-for="item in users"
+                  :key="item.userId"
+                  :label="item.nickName"
+                  :value="item.userId">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <el-form-item label="订单类型:">
+              <el-select v-model="orderType" placeholder="请选择订单类型" clearable size="small">
+                <el-option
+                  v-for="item in orderTypeOptions"
+                  :key="item.dictLabel"
+                  :label="item.dictLabel"
+                  :value="item.dictValue">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="媒体来源:">
+              <el-select v-model="orderMedium" placeholder="请选择媒体来源" clearable size="small">
+                <el-option
+                  v-for="item in orderMediumOptions"
+                  :key="item.dictLabel"
+                  :label="item.dictLabel"
+                  :value="item.dictValue">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+
+
+
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <!-- 查询方式 下单时间 发货时间 -->
+            <el-form-item label="下单时间:">
+              <el-select v-model="queryType" placeholder="查询方式" size="small">
+                <el-option
+                  v-for="item in queryTypes"
+                  :key="item.dictLabel"
+                  :label="item.dictLabel"
+                  :value="item.dictValue">
+                </el-option>
+              </el-select>
+            </el-form-item>
+
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="筛选日期" prop="createTime">
+              <el-date-picker clearable size="small" style="width: 220px"
+                v-model="dateRange"
+                type="daterange"
+                value-format="yyyy-MM-dd"
+                        start-placeholder="开始日期" end-placeholder="结束日期"
+                        >
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <!-- 实收金额 金额等于0 金额大于0 -->
+            <el-form-item label="实收金额:">
+              <el-select v-model="amountType" placeholder="请选择金额" clearable size="small">
+                <el-option
+                  v-for="item in amountTypes"
+                  :key="item.dictLabel"
+                  :label="item.dictLabel"
+                  :value="item.dictValue">
+                </el-option>
+              </el-select>
+            </el-form-item>
+
+          </el-col>
+          <el-col :span="6">
+
+          </el-col>
+        </el-row>
+
+
+        
+        <el-form-item>
+                    <el-button type="primary" icon="el-icon-search" plain   @click="storeOrderStatistics">搜索</el-button>
+        </el-form-item>
+      </el-form>
+      <div class="data-box">
+        <!-- <div class="echart-box">
+          <div id="echart-customer"></div>
+        </div> -->
+
+        <!-- 新增的数据表格 -->
+        <div class="table-container">
+          <!-- 使用组件替换原有表格 -->
+          <order-summary-table 
+            title="员工下单汇总" 
+            :table-data="tableData" 
+            nameLable="员工姓名" />
+            
+          <order-summary-table 
+            title="公司下单汇总" 
+            :table-data="companyTableData" 
+            nameLable="公司" />
+            
+          <order-summary-table 
+            title="部门下单汇总" 
+            :table-data="deptTableData" 
+            nameLable="部门"/>
+        </div>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import OrderSummaryTable from '../components/OrderSummaryTable';
+import { storeOrderStatistics } from "@/api/hisStore/statistics";
+import { getUserListByDeptId} from "@/api/company/companyUser";
+// import echarts from 'echarts'
+import resize from '../../dashboard/mixins/resize'
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyList } from "@/api/company/company";
+export default {
+  name: 'storeOrderStatatic',
+  mixins: [resize],
+  components: { Treeselect,OrderSummaryTable },
+  watch: {
+    // 监听deptId
+    'deptId': 'currDeptChange'
+  },
+  data() {
+    return {
+      queryTypes:[
+        { dictLabel: '下单时间', dictValue: 1 },
+        { dictLabel: '发货时间', dictValue: 2 }
+      ],
+      amountTypes:[
+        { dictLabel: '金额等于0', dictValue: 1 },
+        { dictLabel: '金额大于0', dictValue: 2 }
+      ],
+      queryType: 1,
+      amountType: null,
+      companys: [],
+      deptOptions: [],
+      companyId: undefined,
+      deptId: undefined,
+      userIds: undefined,
+      users: [],
+      dateRange: [],
+      chart: null,
+      orderTypeOptions:[],// 订单类型
+      orderType:'',
+      orderMediumOptions:[], // 媒体来源
+      orderMedium:'',
+      options: [{
+        value: '1',
+        label: '今天'
+      }, {
+        value: '2',
+        label: '昨天'
+      }, {
+        value: '3',
+        label: '本周'
+      }, {
+        value: '4',
+        label: '上周'
+      }, {
+        value: '5',
+        label: '本月'
+      }, {
+        value: '6',
+        label: '上月'
+      }, {
+        value: '7',
+        label: '本季度'
+      }, {
+        value: '8',
+        label: '上季度'
+      }, {
+        value: '9',
+        label: '本年'
+      }, {
+        value: '10',
+        label: '上年'
+      }],
+      value: '5',
+      list: [],
+      dates: [],
+      orderCount: [],
+      payPrice: [],
+      // 新增表格数据
+      tableData: [],        // 员工下单汇总
+      companyTableData: [], // 公司下单汇总
+      deptTableData: []     // 部门下单汇总
+    }
+  },
+  created() {
+    getCompanyList().then(response => {
+      this.companys = response.data;
+      // if (this.companys != null && this.companys.length > 0) {
+      //   this.companyId = this.companys[0].companyId;
+      //   this.getTreeselect();
+      // }
+    });
+    // 获取订单类型
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    // 媒体来源
+    this.getDicts("crm_customer_source").then((response) => {
+      this.orderMediumOptions = response.data;
+    });
+  },
+  methods: {
+    companyChange(val) {
+      console.log(val);
+      this.companyId = val;
+      this.getTreeselect();
+    },
+    currDeptChange(val) {
+      console.log(val)
+      this.deptId = val;
+      this.getUserListByDeptId();
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      var that = this;
+      var param = { companyId: this.companyId }
+      treeselect(param).then((response) => {
+        this.deptOptions = response.data;
+        console.log(this.deptOptions)
+        if (response.data != null && response.data.length > 0) {
+          // this.deptId = response.data[0].id;
+          that.storeOrderStatistics()
+        }
+      });
+    },
+    handleExport() {
+      var data;
+      if (this.userIds != undefined) {
+        data = { type: this.value, userIds: this.userIds + "", deptId: this.deptId }
+      }
+      else {
+        data = { type: this.value, deptId: this.deptId }
+      }
+      exportVoiceLogs(data).then((response) => {
+        console.log(response)
+        this.download(response.msg);
+      });
+    },
+    getUserListByDeptId() {
+      this.userIds = undefined;
+      var data = { deptId: this.deptId };
+      getUserListByDeptId(data).then(response => {
+        this.users = response.data;
+      });
+    },
+    storeOrderStatistics() {
+      var data={};
+      if(this.value){
+        data.type = this.value
+      }
+      if(this.userIds){
+        data.companyUserId = this.userIds
+      }
+
+      if(this.queryType){
+        data.queryType = this.queryType
+      }
+      if(this.amountType){
+        data.amountType = this.amountType
+      }
+
+      if(this.dateRange && this.dateRange.length>0){
+        data.type = null
+        data.startTime = this.dateRange[0]
+        data.endTime = this.dateRange[1]
+      }
+      if(this.orderType){
+        data.orderType = this.orderType
+      }
+      if(this.orderMedium){
+        data.orderMedium = this.orderMedium
+      }
+      if(this.companyId){
+        data.companyId = this.companyId
+      }
+      if(this.deptId){
+        data.deptId = this.deptId
+      }
+      storeOrderStatistics(data).then((response) => {
+        this.dates = response.dates;
+        this.orderCount = response.orderCount;
+        this.payPrice = response.payPrice;
+        //表格数据
+        this.tableData = response.userTableData || [];
+        this.companyTableData = response.companyTableData || [];
+        this.deptTableData = response.deptTableData || [];
+
+        // setTimeout(() => {
+        //   this.initEchart();
+        // }, 500);
+      });
+    },
+    initEchart() {
+      var option = {
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
+          }
+        },
+        legend: {
+          data: ['订单数', '订单金额']
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: [
+          {
+            type: 'category',
+            data: this.dates
+          }
+        ],
+        yAxis: [
+          {
+            type: 'value',
+            axisLabel: {
+              formatter: '{value}个'
+            }
+          }
+        ],
+        series: [
+          {
+            name: '订单数',
+            type: 'bar',
+            emphasis: {
+              focus: 'series'
+            },
+            data: this.orderCount
+          },
+          {
+            name: '订单金额',
+            type: 'bar',
+            emphasis: {
+              focus: 'series'
+            },
+            data: this.payPrice
+          }
+        ]
+      };
+      this.chart = echarts.init(document.getElementById("echart-customer"));
+      this.chart.setOption(option, true);
+    },
+    // 表格行样式
+    tableRowClassName({ row, rowIndex }) {
+      if (row.isGroup) {
+        return 'group-row';
+      }
+      return '';
+    },
+    // 表格合并方法(如果需要的话)
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      // 可以在这里实现单元格合并逻辑
+      return {
+        rowspan: 1,
+        colspan: 1
+      };
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  border: 1px solid #e6e6e6;
+  padding: 12px;
+  height: calc(100vh - 24px); // 设置容器高度
+  display: flex;
+  flex-direction: column;
+  
+  .app-content {
+    background-color: white;
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    
+    .title {
+      padding: 20px 30px 0px 30px;
+      font-size: 18px;
+      font-weight: bold;
+      color: black;
+    }
+    
+    .search-form {
+      margin: 20px 30px 0px 30px;
+      position: sticky;
+      top: 0;
+      background-color: white;
+      z-index: 100;
+      padding: 20px 30px 0px 30px;
+      margin: 0 30px;
+      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+      flex-shrink: 0; // 防止收缩
+    }
+    
+    .data-box {
+      padding: 30px;
+      background-color: rgb(255, 255, 255);
+      flex: 1;
+      overflow-y: auto; // 添加垂直滚动条
+      height: 100%;
+      
+      .echart-box {
+        margin: 0 auto;
+        text-align: center;
+      }
+      
+      .el-select {
+        margin: 5px 10px;
+      }
+      
+      .table-box {
+        margin-top: 15px;
+        .export {
+          float: right;
+          margin: 10px 0px;
+        }
+      }
+      
+      // 新增表格样式
+      .table-container {
+        margin-top: 30px;
+        .table-title {
+          font-size: 16px;
+          font-weight: bold;
+          color: #333;
+          margin-bottom: 10px;
+        }
+      }
+    }
+  }
+}
+
+#echart-customer {
+  width: 100%;
+  height: 320px
+}
+
+.vue-treeselect {
+  width: 217px;
+  height: 36px;
+}
+
+// 表格相关样式
+::v-deep .group-row {
+  background-color: #e8f5e8 !important;
+  font-weight: bold;
+}
+
+::v-deep .group-name {
+  font-weight: bold;
+  color: #333;
+}
+
+::v-deep .el-table {
+  font-size: 12px;
+
+  .el-table__header-wrapper {
+    th {
+      background-color: #f5f7fa;
+      font-weight: bold;
+      color: #333;
+    }
+  }
+
+  .el-table__body-wrapper {
+    td {
+      padding: 8px 0;
+    }
+  }
+}
+
+::v-deep .sticky-column {
+  position: sticky;
+  left: 0;
+  z-index: 2;
+  background-color: white;
+
+  // 为表头也添加样式
+  &.is-header-column {
+    background-color: #f5f7fa;
+  }
+}
+
+// 确保表格容器允许sticky定位
+::v-deep .el-table__body-wrapper {
+  overflow-x: auto;
+}
+</style>
+
+<style>
+.vue-treeselect__control {
+  display: block;
+}
+</style>

+ 512 - 0
src/views/hisStore/statistics/storeProduct.vue

@@ -0,0 +1,512 @@
+<template>
+  <div class="app-container">
+    <div class="app-content">
+      <div class="title">
+        产品销售统计
+      </div>
+      
+      <el-form class="search-form" :inline="true">
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <el-form-item label="时间:">
+              <el-select v-model="value" placeholder="请选择日期">
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+             <el-form-item label="公司名:" prop="companyId">
+              <el-select filterable v-model="companyId" @change="companyChange" placeholder="请选择公司名" clearable size="small">
+                <el-option
+                  v-for="item in companys"
+                  :key="item.companyId"
+                  :label="item.companyName"
+                  :value="item.companyId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="部门:">
+              <treeselect :clearable="false" v-model="deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="员工:">
+              <el-select filterable v-model="userIds" placeholder="请选择员工" clearable size="small">
+                <el-option
+                  v-for="item in users"
+                  :key="item.userId"
+                  :label="item.nickName"
+                  :value="item.userId">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row> 
+        
+       
+        
+    
+        
+        
+        <el-form-item label="筛选日期" prop="createTime">
+          <el-date-picker clearable size="small" style="width: 205.4px"
+            v-model="dateRange"
+            type="daterange"
+            value-format="yyyy-MM-dd"
+            start-placeholder="开始日期" end-placeholder="结束日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="cyan" icon="el-icon-search" @click="storeProduct">搜索</el-button>
+        </el-form-item>
+      </el-form>
+      
+      <div class="data-box">
+        <div class="echart-box">
+          <div id="echart-customer"></div>
+        </div>
+        
+        <!-- 产品销售统计数据表格 -->
+        <div class="table-container">
+          <h3 class="table-title">产品销售汇总</h3>
+          <!-- <div class="export">
+            <el-button type="primary" @click="handleExport">导出数据</el-button>
+          </div> -->
+          <el-table 
+            :data="tableData"
+            border
+            stripe
+            style="width: 100%; margin-top: 20px;"
+            :row-class-name="tableRowClassName"
+            :span-method="objectSpanMethod">
+            
+            <!-- 产品名称列 -->
+            <el-table-column prop="name" label="产品名称" width="100" align="center" class-name="sticky-column">
+              <template slot-scope="scope">
+                <span :class="{'group-name': scope.row.isGroup}">{{ scope.row.name }}</span>
+              </template>
+            </el-table-column>
+            
+            <!-- 动态生成订单类型列 - 使用多级表头 -->
+            <el-table-column 
+              v-for="orderType in orderTypeOptions" 
+              :key="orderType.dictValue"
+              :label="orderType.dictLabel" 
+              align="center">
+              
+              <!-- 数量子列 -->
+              <el-table-column 
+                label="数量" 
+                width="60" 
+                align="center">
+                <template slot-scope="scope">
+                  {{ getOrderData(scope.row, orderType.dictValue, 'count') }}
+                </template>
+              </el-table-column>
+              
+              <!-- 金额子列 -->
+              <el-table-column 
+                label="金额" 
+                width="80" 
+                align="center">
+                <template slot-scope="scope">
+                  {{ getOrderData(scope.row, orderType.dictValue, 'amount') }}
+                </template>
+              </el-table-column>
+              
+            </el-table-column>
+            
+          </el-table>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { storeProduct } from "@/api/hisStore/statistics";
+import { getUserListByDeptId } from "@/api/company/companyUser";
+import echarts from 'echarts';
+import resize from '../../dashboard/mixins/resize';
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyList } from "@/api/company/company";
+
+export default {
+  name: 'ContentStatistics',
+  mixins: [resize],
+  components: { Treeselect },
+  watch: {
+    // 监听deptId
+    'deptId': 'currDeptChange'
+  },
+  data() {
+    return {
+      companys: [],
+      deptOptions: [],
+      companyId: undefined,
+      deptId: undefined,
+      userIds: undefined,
+      users: [],
+      dateRange: [],
+      chart: null,
+      options: [{
+        value: '1',
+        label: '今天'
+      }, {
+        value: '2',
+        label: '昨天'
+      }, {
+        value: '3',
+        label: '本周'
+      }, {
+        value: '4',
+        label: '上周'
+      }, {
+        value: '5',
+        label: '本月'
+      }, {
+        value: '6',
+        label: '上月'
+      }, {
+        value: '7',
+        label: '本季度'
+      }, {
+        value: '8',
+        label: '上季度'
+      }, {
+        value: '9',
+        label: '本年'
+      }, {
+        value: '10',
+        label: '上年'
+      }],
+      value: '5',
+      list: [],
+      dates: [],
+      orderCount: [], // 修改变量名
+      payPrice: [], // 修改变量名
+      // 订单类型选项 - 用作表头
+      orderTypeOptions: [],
+      // 产品销售统计表格数据
+      tableData: []
+    }
+  },
+  created() {
+    getCompanyList().then(response => {
+      this.companys = response.data;
+      if (this.companys != null && this.companys.length > 0) {
+        this.companyId = this.companys[0].companyId;
+        this.getTreeselect();
+      }
+    });
+    
+    // 获取订单类型字典
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+  },
+  methods: {
+    companyChange(val) {
+      console.log(val);
+      this.companyId = val;
+      this.getTreeselect();
+    },
+    currDeptChange(val) {
+      console.log(val)
+      this.deptId = val;
+      this.getUserListByDeptId();
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      var that = this;
+      var param = { companyId: this.companyId }
+      treeselect(param).then((response) => {
+        this.deptOptions = response.data;
+        console.log(this.deptOptions)
+        if (response.data != null && response.data.length > 0) {
+          this.deptId = response.data[0].id;
+          that.storeProduct()
+        }
+      });
+    },
+    handleExport() {
+      var data;
+      if (this.userIds != undefined) {
+        data = { type: this.value, userIds: this.userIds + "", deptId: this.deptId }
+      }
+      else {
+        data = { type: this.value, deptId: this.deptId }
+      }
+      // 导出产品销售统计数据
+      console.log('导出产品销售统计数据', data);
+    },
+    getUserListByDeptId() {
+      this.userIds = undefined;
+      var data = { deptId: this.deptId };
+      getUserListByDeptId(data).then(response => {
+        this.users = response.data;
+      });
+    },
+    storeProduct() {
+      var data;
+      if (this.userIds != undefined) {
+        data = { type: this.value, userIds: this.userIds + "", deptId: this.deptId }
+      }
+      else {
+        data = { type: this.value, deptId: this.deptId }
+      }
+      if(this.dateRange && this.dateRange.length > 0){
+        data.type = null
+        data.startTime = this.dateRange[0]
+        data.endTime = this.dateRange[1]
+      }
+      
+      storeProduct(data).then((response) => {
+        this.dates = response.dates;
+        this.orderCount = response.orderCount;
+        this.payPrice = response.payPrice;
+        
+        // 处理表格数据,补全缺失的订单类型数据
+        this.tableData = this.processTableData(response.tableData || []);
+        
+        setTimeout(() => {
+          this.initEchart();
+        }, 500);
+      });
+    },
+    
+    // 新增方法:处理表格数据,为每个产品补全所有订单类型的数据
+    processTableData(rawTableData) {
+      return rawTableData.map(item => {
+        // 创建一个新的 productCounts 对象,包含所有订单类型
+        const processedProductCounts = {};
+        
+        // 遍历所有订单类型选项,为每个类型设置默认值
+        this.orderTypeOptions.forEach(orderType => {
+          const dictValue = orderType.dictValue;
+          if (item.productCounts && item.productCounts[dictValue]) {
+            // 如果原数据中存在该订单类型的数据,使用原数据
+            processedProductCounts[dictValue] = item.productCounts[dictValue];
+          } else {
+            // 如果原数据中不存在该订单类型的数据,设置默认值
+            processedProductCounts[dictValue] = {
+              count: 0,
+              amount: 0.0
+            };
+          }
+        });
+        
+        return {
+          ...item,
+          productCounts: processedProductCounts
+        };
+      });
+    },
+    
+    initEchart() {
+      var option = {
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow'
+          }
+        },
+        legend: {
+          data: ['订单数量', '金额']
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: [
+          {
+            type: 'category',
+            data: this.dates
+          }
+        ],
+        yAxis: [
+          {
+            type: 'value',
+            axisLabel: {
+              formatter: '{value}'
+            }
+          }
+        ],
+        series: [
+          {
+            name: '订单数量',
+            type: 'bar',
+            emphasis: {
+              focus: 'series'
+            },
+            data: this.orderCount // 修改为正确的变量名
+          },
+          {
+            name: '金额',
+            type: 'bar',
+            emphasis: {
+              focus: 'series'
+            },
+            data: this.payPrice // 修改为正确的变量名
+          }
+        ]
+      };
+      this.chart = echarts.init(document.getElementById("echart-customer"));
+      this.chart.setOption(option, true);
+    },
+    
+    // 修改获取订单数据的方法,适配新的数据结构
+    getOrderData(row, orderType, dataType) {
+      // 使用 productCounts 而不是 orderData
+      if (row.productCounts && row.productCounts[orderType]) {
+        const value = row.productCounts[orderType][dataType] || 0;
+        if (dataType === 'amount') {
+          return value.toFixed(2);
+        }
+        return value;
+      }
+      return dataType === 'amount' ? '0.00' : 0;
+    },
+    
+    // 表格行样式
+    tableRowClassName({ row, rowIndex }) {
+      if (row.isGroup) {
+        return 'group-row';
+      }
+      return '';
+    },
+    // 表格合并方法
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      return {
+        rowspan: 1,
+        colspan: 1
+      };
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  border: 1px solid #e6e6e6;
+  padding: 12px;
+  .app-content {
+    background-color: white;
+    .title {
+      padding: 20px 30px 0px 30px;
+      font-size: 18px;
+      font-weight: bold;
+      color: black;
+    }
+    .search-form {
+      margin: 20px 30px 0px 30px;
+    }
+    .data-box {
+      padding: 30px;
+      background-color: rgb(255, 255, 255);
+      height: 100%;
+      .echart-box {
+        margin: 0 auto;
+        text-align: center;
+      }
+      .el-select {
+        margin: 5px 10px;
+      }
+      .table-box {
+        margin-top: 15px;
+        .export {
+          float: right;
+          margin: 10px 0px;
+        }
+      }
+      // 表格样式
+      .table-container {
+        margin-top: 30px;
+        .table-title {
+          font-size: 16px;
+          font-weight: bold;
+          color: #333;
+          margin-bottom: 10px;
+        }
+        .export {
+          float: right;
+          margin: 10px 0px;
+        }
+      }
+    }
+  }
+}
+
+#echart-customer {
+  width: 100%;
+  height: 320px;
+}
+
+.vue-treeselect {
+  width: 217px;
+  height: 36px;
+}
+
+// 表格相关样式
+::v-deep .group-row {
+  background-color: #e8f5e8 !important;
+  font-weight: bold;
+}
+
+::v-deep .group-name {
+  font-weight: bold;
+  color: #333;
+}
+
+::v-deep .el-table {
+  font-size: 12px;
+  
+  .el-table__header-wrapper {
+    th {
+      background-color: #f5f7fa;
+      font-weight: bold;
+      color: #333;
+    }
+  }
+  
+  .el-table__body-wrapper {
+    td {
+      padding: 8px 0;
+    }
+  }
+}
+
+::v-deep .sticky-column {
+  position: sticky;
+  left: 0;
+  z-index: 2;
+  background-color: white;
+  
+  // 为表头也添加样式
+  &.is-header-column {
+    background-color: #f5f7fa;
+  }
+}
+
+// 确保表格容器允许sticky定位
+::v-deep .el-table__body-wrapper {
+  overflow-x: auto;
+}
+</style>
+
+<style>
+.vue-treeselect__control {
+  display: block;
+}
+</style>

+ 475 - 0
src/views/hisStore/storeOrderAudit/audit.vue

@@ -0,0 +1,475 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="所属员工" prop="companyUserName">
+            <el-input
+              v-model="queryParams.companyUserName"
+              placeholder="请输入所属员工昵称"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="收件人" prop="realName">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.realName"
+              placeholder="请输入收件人"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="手机号" prop="userPhone">
+            <el-input
+            style="width:220px"
+              v-model="queryParams.userPhone"
+              placeholder="请输入收件人手机号"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="创建时间" prop="createTimeRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="createTimeRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+        </el-col>
+
+      </el-row>
+
+       <el-row :gutter="20">
+        <el-col :span="6">
+          <el-form-item label="订单金额" prop="orderAmountRange">
+            <el-input
+            style="width:100px"
+              v-model="queryParams.orderAmountSmall"
+              placeholder="请输入订单金额"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+            <span>-</span>
+            <el-input
+            style="width:100px"
+              v-model="queryParams.orderAmountBig"
+              placeholder="请输入订单金额"
+              clearable
+              size="small"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="订单类型" prop="orderType">
+            <el-select style="width:220px"  v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" >
+              <el-option
+                    v-for="item in orderTypeOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                  />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="审核时间" prop="auditRange">
+            <el-date-picker
+            style="width:220px"
+              clearable size="small"
+              v-model="auditRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          
+        </el-col>
+
+      </el-row>
+      
+      
+      
+      
+      <!-- 订单金额 范围两个输入 -->
+      
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 使用 el-row 布局将 tabs 和 批量操作按钮放在同一行 -->
+    <el-row :gutter="10" style="margin-bottom: 10px;">
+      <el-col :span="16">
+        <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="全部" name="00"></el-tab-pane>
+          <el-tab-pane label="待审批" name="0"></el-tab-pane>
+          <el-tab-pane label="审批拒绝" name="1"></el-tab-pane>
+          <!-- <el-tab-pane label="待总后台审核" name="2"></el-tab-pane>
+          <el-tab-pane label="总后台审核拒绝" name="3"></el-tab-pane> -->
+          <el-tab-pane label="审核通过" name="4"></el-tab-pane>
+        </el-tabs>
+      </el-col>
+      <el-col :span="8" style="text-align: right;">
+        <div style="margin-top: 5px;">
+          <el-button 
+            type="primary" 
+            icon="el-icon-check" 
+            size="mini" 
+            :disabled="selectedRows.length === 0"
+            @click="handleBatchAudit"
+            v-hasPermi="['store:storeOrderAudit:audit']"
+          >
+            批量审核
+          </el-button>
+          <span style="margin-left: 10px; color: #999;">
+            已选择 {{ selectedRows.length }} 项
+          </span>
+        </div>
+      </el-col>
+    </el-row>
+
+    <el-table height="500" 
+    border 
+    v-loading="loading" 
+    :data="storeOrderAuditList" 
+    :key="tableKey"
+    class="scrollable-table"
+    @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" fixed="left"></el-table-column>
+      <el-table-column label="订单号" align="center" prop="orderCode" width="200" fixed="left" />
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属员工" align="center" prop="companyUserName" />
+      <el-table-column label="审核状态" align="center" prop="status" width="150">
+        <template slot-scope="scope">
+          <el-tag prop="status" v-for="item in statusOptions"
+                  :type="item.type"
+                  v-if="scope.row.auditStatus === item.dictValue">
+            {{item.dictLabel}}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单类型" align="center" prop="orderType" width="150" >
+          <template slot-scope="scope">
+              <el-tag prop="status" v-for="(item, index) in orderTypeOptions"    v-if="scope.row.orderType==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column label="收件人" align="center" prop="realName" />
+      <el-table-column label="送货地址" align="center" prop="userAddress" show-overflow-tooltip/>
+      <el-table-column label="实收金额" align="center" prop="payPrice">
+        <template slot-scope="scope">
+          {{ scope.row.payPrice ? parseFloat(scope.row.payPrice).toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="订单金额" align="center" prop="totalPrice">
+        <template slot-scope="scope">
+          {{ scope.row.totalPrice ? parseFloat(scope.row.totalPrice).toFixed(2) : '0.00' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="手机号" align="center" prop="userPhone"  width="150"/>
+      <el-table-column label="审核时间" align="center" prop="companyAuditTime"  width="180"/>
+      <el-table-column label="审核人" align="center" prop="companyAuditUserName" />
+      <!-- <el-table-column label="总后台审核时间" align="center" prop="adminAuditTime" />
+      <el-table-column label="总后台审核人" align="center" prop="adminAuditUserName" /> -->
+      <el-table-column label="被拒原因" align="center" prop="reason" show-overflow-tooltip />
+      <!-- <el-table-column label="提交时间" align="center" prop="createTime" /> -->
+      <el-table-column label="创建时间" align="center" prop="orderCreateTime" width="180"/>
+      <el-table-column label="操作" fixed="right" align="center" width="80" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-popover
+            v-if="scope.row.auditStatus === 0"
+            placement="right"
+            trigger="click"
+            :ref="'popover_' + scope.row.id">
+            <el-button size="mini" type="success" @click="handlePass(scope.row)">通过</el-button>
+            <el-button size="mini" type="danger" @click="handleAudit(scope.row)">拒绝</el-button>
+            <el-button
+              slot="reference"
+              size="mini"
+              type="text"
+              v-hasPermi="['store:storeOrderAudit:audit']"
+            >审核订单</el-button>
+          </el-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <el-dialog :title="show.title" :visible.sync="show.open" width="500px" append-to-body>
+      <el-form ref="auditForm" :model="auditForm" :rules="auditRules" label-width="80px">
+        <el-form-item label="拒绝原因" prop="reviewContent">
+          <el-input
+            type="textarea"
+            v-model="auditForm.reviewContent"
+            placeholder="请输入拒绝原因"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleReject">确定</el-button>
+        <el-button @click="cancelAudit">关闭</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 添加批量审核确认对话框 -->
+    <el-dialog 
+      title="批量审核确认" 
+      :visible.sync="batchAuditDialogVisible" 
+      width="500px" 
+      append-to-body
+    >
+      <p>确定要审核通过选中的 {{ selectedRows.length }} 个订单吗?</p>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="batchAuditDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="confirmBatchAudit"
+        v-hasPermi="['store:storeOrderAudit:auditBatch']">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getCompanyList } from "@/api/company/company";
+import {list, audit,auditBatch} from "@/api/hisStore/storeOrderAudit";
+
+export default {
+  name: "StoreOrderAudit",
+  data() {
+    const statusOptions = [
+      {
+        dictLabel: "待审批",
+        dictValue: 0,
+        type: ''
+      },
+      {
+        dictLabel: "审批拒绝",
+        dictValue: 1,
+        type: 'danger'
+      },
+      {
+        dictLabel: "审核通过",
+        dictValue: 4,
+        type: 'success'
+      }
+    ]
+
+    return {
+      
+      tableKey: 0,
+      showSearch: true,
+      companys: [],
+      total: 0,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyUserName: null,
+        auditStatus: null,
+        realName:null,
+        userPhone: null,
+        orderAmountSmall: null,
+        orderAmountBig: null,
+        beginTime:null,// 审单日期
+        endTime:null,
+        orderType: null,
+        auditBeginTime:null,
+        auditEndTime:null,
+      },
+      selectedRows: [], // 添加这行来存储选中的行
+       batchAuditDialogVisible: false, // 批量审核对话框显示控制
+      createTimeRange:[],
+      auditRange:[], // 审核时间
+      orderTypeOptions:[], // 订单类型
+      activeName: '00',
+      loading: false,
+      storeOrderAuditList: [],
+      statusOptions: statusOptions,
+      show: {
+        open: false,
+        title: "审核订单"
+      },
+      auditForm: {
+        auditId: null,
+        reviewType: null,
+        reviewContent: ''
+      },
+      auditRules: {
+        reviewContent: [
+          { required: true, message: "请输入拒绝原因", trigger: "blur" }
+        ]
+      },
+      currentRowId: null,
+    }
+  },
+  created() {
+    this.getDicts("store_order_type").then((response) => {
+      this.orderTypeOptions = response.data;
+    });
+    this.getCompanyOptions()
+    this.handleQuery()
+  },
+  activated() {
+    this.tableKey = Date.now()
+  },
+  methods: {
+    // 确认批量审核
+    confirmBatchAudit() {
+      // 这里需要调用批量审核接口,假设有一个批量审核的API
+      
+        const ids = this.selectedRows.map(item => item.id).join(",");
+  
+      // 示例:调用批量审核API
+      auditBatch({ids}).then(response => {
+        this.$message.success("批量审核完成");
+        this.batchAuditDialogVisible = false;
+        this.getList(); // 刷新列表
+      }).catch(error => {
+        this.$message.error("批量审核失败");
+      });
+      
+      // 由于没有提供批量审核API,这里只是演示逻辑
+      console.log("批量审核订单IDs:", auditIds);
+      this.batchAuditDialogVisible = false;
+      this.getList(); // 实际使用时需要刷新列表
+    },
+     // 批量审核处理
+    handleBatchAudit() {
+      if (this.selectedRows.length === 0) {
+        this.$message.warning("请至少选择一条数据");
+        return;
+      }
+      this.batchAuditDialogVisible = true;
+    },
+    // 多选
+    handleSelectionChange(selection) {
+      this.selectedRows = selection;
+    },
+    getCompanyOptions() {
+      getCompanyList().then(response => {
+        this.companys = response.data
+      })
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      // 手动重置时间范围
+      this.createTimeRange = [];
+      this.queryParams.beginTime = null;
+      this.queryParams.endTime = null;
+      
+      // 手动重置订单金额范围
+      this.queryParams.orderAmountSmall = null;
+      this.queryParams.orderAmountBig = null;
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    getList() {
+      this.loading = true
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.beginTime=this.createTimeRange[0]
+        this.queryParams.endTime=this.createTimeRange[1]
+      }
+      if(this.auditRange!=null&&this.auditRange.length==2){
+        this.queryParams.auditBeginTime=this.auditRange[0]
+        this.queryParams.auditEndTime=this.auditRange[1]
+      }
+      list(this.queryParams).then(response => {
+        const {rows, total} = response
+        this.storeOrderAuditList = rows
+        this.total = total
+        this.loading = false
+      })
+    },
+    handleClick(tab) {
+      this.queryParams.auditStatus = tab.name === '00' ? null : tab.name
+      this.handleQuery()
+    },
+    handleAudit(row) {
+      this.currentRowId = row.id
+      this.auditForm.auditId = row.id;
+      this.auditForm.reviewType = 0;
+      this.show.open = true;
+    },
+    handlePass(row) {
+      this.currentRowId = row.id
+      this.auditForm.auditId = row.id;
+      this.auditForm.reviewType = 1;
+      this.submitAudit();
+    },
+    handleReject() {
+      this.$refs["auditForm"].validate(valid => {
+        if (valid) {
+          this.submitAudit();
+        }
+      });
+    },
+    submitAudit() {
+      audit(this.auditForm).then(response => {
+        const {msg} = response
+        this.msgSuccess(msg);
+        this.show.open = false;
+        this.$refs['popover_' + this.currentRowId].doClose();
+        this.getList();
+        this.resetAuditForm();
+      });
+    },
+    cancelAudit() {
+      this.show.open = false;
+      this.resetAuditForm();
+    },
+    resetAuditForm() {
+      this.auditForm = {
+        auditId: null,
+        reviewType: null,
+        reviewContent: ''
+      };
+      this.$refs["auditForm"]?.resetFields();
+    }
+  }
+}
+</script>
+
+<style scoped>
+.scrollable-table {
+  display: block;
+  width: 100%;
+}
+
+.scrollable-table ::v-deep .el-table__body-wrapper {
+  overflow-x: auto;
+  overflow-y: auto;
+}
+
+.scrollable-table ::v-deep .el-table__header-wrapper {
+  overflow-x: auto;
+  overflow-y: hidden;
+}
+</style>

+ 51 - 2
src/views/qw/externalContact/deptIndex.vue

@@ -334,8 +334,17 @@
       <el-table-column label="描述信息" align="center" prop="description" />
       <el-table-column label="标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="name in scope.row.tagIdsName"  style="display: inline;">
-            <el-tag type="success">{{ name }}</el-tag>
+          <div class="tag-container">
+            <div class="tag-list">
+              <el-tag
+                v-for="name in scope.row.tagIdsName"
+                :key="name"
+                type="success"
+                size="small"
+              >
+                {{ name }}
+              </el-tag>
+            </div>
           </div>
         </template>
       </el-table-column>
@@ -2094,4 +2103,44 @@ export default {
   background: rgba(0, 0, 0, 0.2);
   border-radius: 3px;
 }
+
+.tag-container {
+  max-height: 120px;
+  overflow-y: auto;
+  padding: 1px;
+  border: 1px solid #ebeef5;
+  border-radius: 1px;
+  background-color: #fafafa;
+}
+.tag-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+.scroll-hint {
+  text-align: center;
+  color: #909399;
+  font-size: 12px;
+  padding: 1px 0;
+}
+.container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 10px;
+}
+.title {
+  text-align: center;
+  color: #303133;
+  margin-bottom: 30px;
+}
+.demo-table {
+  width: 100%;
+  margin-bottom: 30px;
+}
+.instructions {
+  background-color: #f5f7fa;
+  padding: 15px;
+  border-radius: 1px;
+  margin-bottom: 20px;
+}
 </style>

+ 57 - 3
src/views/qw/externalContact/index.vue

@@ -344,10 +344,24 @@
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
       <el-table-column label="描述信息" align="center" prop="description" />
-      <el-table-column label="标签" align="center" prop="tagIdsName" width="250px">
+      <el-table-column label="标签" align="center" prop="tagIdsName" width="300px">
+<!--        <template slot-scope="scope">-->
+<!--          <div v-for="name in scope.row.tagIdsName"  style="display: inline;">-->
+<!--          <el-tag type="success">{{ name }}</el-tag>-->
+<!--          </div>-->
+<!--        </template>-->
         <template slot-scope="scope">
-          <div v-for="name in scope.row.tagIdsName"  style="display: inline;">
-          <el-tag type="success">{{ name }}</el-tag>
+          <div class="tag-container">
+            <div class="tag-list">
+              <el-tag
+                v-for="name in scope.row.tagIdsName"
+                :key="name"
+                type="success"
+                size="small"
+              >
+                {{ name }}
+              </el-tag>
+            </div>
           </div>
         </template>
       </el-table-column>
@@ -1974,4 +1988,44 @@ export default {
   background: rgba(0, 0, 0, 0.2);
   border-radius: 3px;
 }
+
+.tag-container {
+  max-height: 120px;
+  overflow-y: auto;
+  padding: 1px;
+  border: 1px solid #ebeef5;
+  border-radius: 1px;
+  background-color: #fafafa;
+}
+.tag-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+.scroll-hint {
+  text-align: center;
+  color: #909399;
+  font-size: 12px;
+  padding: 1px 0;
+}
+.container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 10px;
+}
+.title {
+  text-align: center;
+  color: #303133;
+  margin-bottom: 30px;
+}
+.demo-table {
+  width: 100%;
+  margin-bottom: 30px;
+}
+.instructions {
+  background-color: #f5f7fa;
+  padding: 15px;
+  border-radius: 1px;
+  margin-bottom: 20px;
+}
 </style>

+ 52 - 2
src/views/qw/externalContact/myExternalContact.vue

@@ -338,8 +338,17 @@
       <el-table-column label="描述信息" align="center" prop="description" />
       <el-table-column label="标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="name in scope.row.tagIdsName" style="display: inline;">
-            <el-tag type="success">{{ name }}</el-tag>
+          <div class="tag-container">
+            <div class="tag-list">
+              <el-tag
+                v-for="name in scope.row.tagIdsName"
+                :key="name"
+                type="success"
+                size="small"
+              >
+                {{ name }}
+              </el-tag>
+            </div>
           </div>
         </template>
       </el-table-column>
@@ -2073,4 +2082,45 @@ export default {
   background: rgba(0, 0, 0, 0.2);
   border-radius: 3px;
 }
+
+
+.tag-container {
+  max-height: 120px;
+  overflow-y: auto;
+  padding: 1px;
+  border: 1px solid #ebeef5;
+  border-radius: 1px;
+  background-color: #fafafa;
+}
+.tag-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+.scroll-hint {
+  text-align: center;
+  color: #909399;
+  font-size: 12px;
+  padding: 1px 0;
+}
+.container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 10px;
+}
+.title {
+  text-align: center;
+  color: #303133;
+  margin-bottom: 30px;
+}
+.demo-table {
+  width: 100%;
+  margin-bottom: 30px;
+}
+.instructions {
+  background-color: #f5f7fa;
+  padding: 15px;
+  border-radius: 1px;
+  margin-bottom: 20px;
+}
 </style>

+ 5 - 4
src/views/qw/qwUserVoiceLogTotal/index.vue

@@ -19,9 +19,9 @@
                    :loading="companyUserOptionsLoading">
           <el-option
             v-for="item in companyUserOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value">
+            :key="item.dictValue"
+            :label="item.dictLabel"
+            :value="item.dictValue">
           </el-option>
         </el-select>
       </el-form-item>
@@ -508,8 +508,9 @@ export default {
     /** 查询企微用户通话记录列表 */
     getList() {
       this.loading = true;
+      this.status = 0;
       const { qwUserName, ...queryParams } = this.queryParams;
-      listQwUserVoiceLog(queryParams).then(response => {
+      listQwUserVoiceLogTotal(queryParams).then(response => {
         this.qwUserVoiceLogList = response.rows;
         this.total = response.total;
         this.loading = false;

+ 51 - 2
src/views/qw/tagGroup/index.vue

@@ -95,8 +95,15 @@
       <el-table-column label="名称" align="center" prop="name" />
       <el-table-column label="排序" align="center" prop="order" />
       <el-table-column label="标签" align="center" prop="tag" >
-        <template slot-scope="scope" >
-            <el-tag type="success" v-for="i in scope.row.tag" :key="i.id" style="margin: 2px 5px 0 0;">{{i.name}}</el-tag>
+<!--        <template slot-scope="scope" >-->
+<!--            <el-tag type="success" v-for="i in scope.row.tag" :key="i.id" style="margin: 2px 5px 0 0;">{{i.name}}</el-tag>-->
+<!--        </template>-->
+        <template slot-scope="scope">
+          <div class="tag-container">
+            <div class="tag-list">
+              <el-tag type="success" v-for="i in scope.row.tag" :key="i.id" style="margin: 2px 5px 0 0;">{{i.name}}</el-tag>
+            </div>
+          </div>
         </template>
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -381,3 +388,45 @@ export default {
   }
 };
 </script>
+<style scoped>
+
+.tag-container {
+  max-height: 400px;
+  overflow-y: auto;
+  padding: 1px;
+  border: 1px solid #ebeef5;
+  border-radius: 1px;
+  background-color: #fafafa;
+}
+.tag-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+.scroll-hint {
+  text-align: center;
+  color: #909399;
+  font-size: 12px;
+  padding: 1px 0;
+}
+.container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 10px;
+}
+.title {
+  text-align: center;
+  color: #303133;
+  margin-bottom: 30px;
+}
+.demo-table {
+  width: 100%;
+  margin-bottom: 30px;
+}
+.instructions {
+  background-color: #f5f7fa;
+  padding: 15px;
+  border-radius: 1px;
+  margin-bottom: 20px;
+}
+</style>

+ 1 - 1
src/views/store/inquiryOrder/list.vue

@@ -403,7 +403,7 @@ export default {
       });
 
       getWxaCodeInquiryOrderUnLimit(row.orderId).then(response => {
-        this.codeImage='data:image/jpeg;base64,'+response.data
+        this.codeImage=response.url
         this.payInquiryOrder.open=true;
         this.payInquiryOrder.name=row.title;
         loadingRock.close();

+ 2 - 1
src/views/store/inquiryOrder/myList.vue

@@ -528,7 +528,8 @@ export default {
       });
 
       getWxaCodeInquiryOrderUnLimit(row.orderId).then(response => {
-        this.codeImage='data:image/jpeg;base64,'+response.data
+        // this.codeImage='data:image/jpeg;base64,'+response.data
+        this.codeImage=response.url
         this.payInquiryOrder.open=true;
         this.payInquiryOrder.name=row.title;
         loadingRock.close();

+ 65 - 3
src/views/store/packageOrder/myList.vue

@@ -189,7 +189,15 @@
                       @click="handledetails(scope.row)"
                     >详情
           </el-button>
-
+          <el-button
+            v-if="scope.row.isPay==0"
+            size="mini"
+            type="text"
+            @click="handlePayOrder(scope.row)"
+            icon="el-icon-coin"
+            v-hasPermi="['store:inquiryOrder:wxaCodeInquiryOrder']"
+          >生成付款二维码
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -274,11 +282,30 @@
          <packageOrderDetails  ref="Details" />
        </el-drawer>
 
+    <el-dialog :title="payPackageOrder.title" v-if="payPackageOrder.open"  :visible.sync="payPackageOrder.open" width="450px"  append-to-body>
+      <div style="padding-bottom:15px;" >
+        <img :src="codeImage" width="400px">
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="downloadImage(codeImage, payPackageOrder.name+'.png')">下载二维码</el-button>
+      </div>
+    </el-dialog>
+
   </div>
 </template>
 
 <script>
-import { listPackageOrder, getPackageOrder, delPackageOrder, addPackageOrder, updatePackageOrder, exportPackageOrder,myListPackageOrder,myExportPackageOrder } from "@/api/store/packageOrder";
+import {
+  listPackageOrder,
+  getPackageOrder,
+  delPackageOrder,
+  addPackageOrder,
+  updatePackageOrder,
+  exportPackageOrder,
+  myListPackageOrder,
+  myExportPackageOrder,
+  getWxaCodePackageOrderUnLimit
+} from "../../../api/store/packageOrder";
 import packageOrderDetails from '../components/packageOrderDetails.vue';
 import { getTask } from "@/api/common";
 export default {
@@ -289,7 +316,14 @@ export default {
       show:{
               open:false,
             },
-	  sourceOptions:[],
+
+      codeImage:null,
+      payPackageOrder:{
+        open:false,
+        title:"付款二维码",
+        name:null,
+      },
+	    sourceOptions:[],
       actName:"10",
       // 遮罩层
       loading: true,
@@ -400,6 +434,34 @@ export default {
                  this.$refs.Details.getDetails(row.orderId);
             }, 1);
         },
+
+    handlePayOrder(row){
+
+      let loadingRock = this.$loading({
+        lock: true,
+        text: '生成二维码中~~请不要刷新页面!!',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      });
+
+      getWxaCodePackageOrderUnLimit(row.orderId).then(response => {
+        this.codeImage=response.url
+        this.payPackageOrder.open=true;
+        this.payPackageOrder.name=row.title;
+        loadingRock.close();
+      }).finally(res=>{
+        loadingRock.close();
+      })
+    },
+
+    downloadImage(imageSrc, fileName) {
+      const link = document.createElement('a');
+      link.href = imageSrc;
+      link.download = fileName || '付款二维码.png';
+      document.body.appendChild(link);
+      link.click();
+      document.body.removeChild(link);
+    },
     change(){
           if(this.startTime!=null){
             this.queryParams.sTime=this.startTime[0];