Browse Source

fix: 统计参数调整

LaveyD 5 days ago
parent
commit
099086fdb4
3 changed files with 385 additions and 73 deletions
  1. 1 1
      package.json
  2. 20 0
      src/pages/queryReport/OrderStatistic.vue
  3. 364 72
      src/pages/queryReport/checkStatistic.vue

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ticket",
-  "version": "1.0.12",
+  "version": "1.0.13",
   "private": true,
   "description": "多巴胺科技",
   "author": "",

+ 20 - 0
src/pages/queryReport/OrderStatistic.vue

@@ -34,6 +34,20 @@
         </el-date-picker>
       </el-form-item>
 
+      <el-form-item
+        label="游玩时间"
+        prop="playDate">
+        <el-date-picker
+          v-model="form.playDate"
+          style="width:240px"
+          type="daterange"
+          format="yyyy-MM-dd"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+
       <el-form-item
         label="票种列表"
         prop="ticketTypeIdList"
@@ -459,6 +473,8 @@ export default {
       form: {
         timeBegin: new Date(moment().startOf('day').format('YYYY-MM-DD HH:mm:ss')),
         timeEnd: new Date(moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')),
+        playDateBegin: '',
+        playDateEnd: '',
         isStorage: null,
         ticketTypeIdList: [],
         ticketStatus: [],
@@ -690,6 +706,10 @@ export default {
         return
       }
 
+      const [s1, e1] = this.form.playDate || []
+      this.form.playDateBegin = s1 ? moment(s1).format('YYYY-MM-DD') : ''
+      this.form.playDateEnd = e1 ? moment(e1).format('YYYY-MM-DD') : ''
+
       this.loading = true
       this.tableData = []
 

+ 364 - 72
src/pages/queryReport/checkStatistic.vue

@@ -4,12 +4,15 @@
       class="search-box"
       ref="form"
       :model="form"
-      :inline="true">
+      :inline="true"
+      label-width="100px">
       <div class="block-title">
         查询条件
       </div>
       <el-form-item
         label="起始时间"
+        required
+        verify
         prop="checkTimeBegin">
         <el-date-picker
           v-model="form.checkTimeBegin"
@@ -19,6 +22,8 @@
       </el-form-item>
       <el-form-item
         label="截止时间"
+        required
+        verify
         prop="checkTimeEnd">
         <el-date-picker
           default-time="23:59:59"
@@ -28,12 +33,34 @@
         </el-date-picker>
       </el-form-item>
       <el-form-item
-        label="票种"
-        prop="ticketTypeIdList">
+        label="游玩时间"
+        prop="playDate">
+        <el-date-picker
+          v-model="form.playDate"
+          style="width:240px"
+          type="daterange"
+          format="yyyy-MM-dd"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item
+        label="票种列表"
+        prop="ticketTypeIdList"
+      >
         <el-select
           v-model="form.ticketTypeIdList"
           multiple
-          filterable>
+          collapse-tags
+          filterable
+          clearable
+          placeholder="请选择"
+          @change="selectAll">
+          <el-option
+            :value="0"
+            label="全部票种">
+          </el-option>
           <el-option
             v-for="item in ticketTypeList"
             :key="item.id"
@@ -42,24 +69,102 @@
           </el-option>
         </el-select>
       </el-form-item>
-
+      <el-form-item
+        label="景点"
+        prop="scenicIdList"
+      >
+        <el-select
+          v-model="form.scenicIdList"
+          placeholder="请选择"
+          multiple
+          clearable
+          filterable>
+          <el-option
+            v-for="(item, idx) in scenicList"
+            :key="`scene-${idx}`"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="售票员"
+        prop="adminIdList">
+        <el-select
+          multiple
+          v-model="form.adminIdList">
+          <el-option
+            v-for="item in salesList"
+            :key="item.id"
+            :label="`${item.loginName}-${item.name}`"
+            :value="item.id">
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="订单类型"
+        prop="orderCategory"
+      >
+        <el-select
+          v-model="form.orderCategory"
+          clearable
+          placeholder="请选择">
+          <el-option
+            :value="''"
+            label="全部">
+          </el-option>
+          <el-option
+            v-for="item in ticketCategoryList"
+            :key="item.id"
+            :value="item.id"
+            :label="item.name">
+          </el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item
         label="销售渠道"
-        prop="otaSourceNameList">
+        prop="otaSourceNameList"
+      >
         <el-select
           v-model="form.otaSourceNameList"
+          placeholder="请选择"
           multiple
-          clearable>
+          clearable
+        >
           <el-option
-            v-for="(item,index) in saleChannels"
-            :key="index"
+            v-for="(item,idx) in saleChannel"
+            :key="idx"
             :label="item"
             :value="item"
           >
           </el-option>
         </el-select>
       </el-form-item>
-      <!-- 新增分组筛选项 -->
+      <el-form-item
+        label="支付方式"
+        prop="payChannelList">
+        <el-select
+          v-model="form.payChannelList"
+          filterable
+          multiple
+          clearable>
+          <el-option
+            v-for="item in payChannelOptions"
+            :key="item"
+            :label="item"
+            :value="item">
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="是否去除小计"
+        prop="removeSubtotal">
+        <el-select
+          v-model="form.removeSubtotal">
+          <el-option :value="false" label="否"></el-option>
+          <el-option :value="true" label="是"></el-option>
+        </el-select>
+      </el-form-item>
 
       <el-form-item
         label="分组筛选"
@@ -100,38 +205,102 @@
           @click="reportExport">
           导出
         </el-button>
+        <i class="el-icon-setting" style="cursor: pointer; margin-left: 10px;" title="设置显示列" @click="showColumnConfig" />
       </div>
     </el-form>
 
     <div class="table-box">
-      <!-- <div class="block-title">
-        统计结果
-      </div> -->
       <el-table
         border
         stripe
+        :key="tableIndex"
         v-loading="loading"
         :data="tableData"
         :row-class-name="totalRowClassName"
         :span-method="objectSpanMethod">
         <el-table-column
           v-for="(item) in finalGroup"
-          :key="item.prop"
-          :prop="item.prop"
+          :key="item.prop || item.value"
+          :prop="item.prop || item.value"
           :label="item.label">
         </el-table-column>
+
+        <el-table-column
+          v-if="isColumnVisible('checkCount')"
+          prop="checkCount"
+          label="检票数量">
+        </el-table-column>
+        <el-table-column
+          v-if="isColumnVisible('checkNum')"
+          prop="checkNum"
+          label="检票人数">
+        </el-table-column>
+        <el-table-column
+          v-if="isColumnVisible('checkPrice')"
+          prop="checkPrice"
+          label="检票金额">
+        </el-table-column>
+        <el-table-column
+          v-if="isColumnVisible('checkSettlementPrice')"
+          prop="checkSettlementPrice"
+          label="结算金额">
+        </el-table-column>
+        <!-- <el-table-column
+          v-if="isColumnVisible('unitPrice')"
+          prop="unitPrice"
+          label="单价">
+        </el-table-column> -->
       </el-table>
     </div>
+    <el-dialog title="选择显示列" :visible.sync="dialogVisible">
+      <el-checkbox-group v-model="tempSelectedColumns">
+        <el-checkbox v-for="column in fixedColumns" :key="column.value" :label="column.value">{{ column.label }}</el-checkbox>
+      </el-checkbox-group>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="saveUserConfig">确 定</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
+
 <script>
 import { getCheckerVerifyStatistics } from '@/api/queryReport'
-import { totalRowClassName } from '@/utils'
-import moment from 'moment'
+import { getScenic, getTicketTypeList } from '@/api/ticketType'
 import { getSaleChannelList } from '@/api/order'
-// import ReaderInput from '@/components/ReaderInput'
+import { totalRowClassName } from '@/utils'
+import { ticketStatusDic } from '@/assets/staticData'
+import { getSystemConfigList } from '@/api/systemConfig'
+import { addUserConfig, getUserConfig } from '@/api/configSetting'
 import draggable from 'vuedraggable'
-// import moment from 'moment'
+import Tip from '@/components/Tip'
+import moment from 'moment'
+
+const groupKeys = [
+  { value: 'adminName', label: '售票员', prop: 'adminName' },
+  { value: 'ticketTypeName', label: '票种', prop: 'ticketTypeName' },
+  { value: 'payChannel', label: '支付方式' },
+  { value: 'ticketTypeGroupName', label: '票种分组' },
+  { value: 'unitPrice', label: '单价', prop: 'unitPrice' },
+  { value: 'otaSourceName', label: '销售渠道' },
+  { value: 'team', label: '团体' },
+  { value: 'teamIndividual', label: '团散' },
+  { value: 'guide', label: '导游' },
+  { value: 'batch', label: '场次' },
+  { value: 'orderDateDay', label: '统计日期' },
+  { value: 'orderDateMonth', label: '统计月份' },
+  { value: 'orderDateYear', label: '统计年份' }
+]
+
+const fixedColumns = [
+  { value: 'checkCount', label: '检票数量' },
+  { value: 'checkNum', label: '检票人数' },
+  { value: 'checkPrice', label: '检票金额' },
+  { value: 'checkSettlementPrice', label: '结算金额' },
+  { value: 'unitPrice', label: '单价' }
+]
+
+const STAT_KEY = 'checkerVerifyStatistics'
 
 export default {
   name: 'checkStatistic',
@@ -150,49 +319,73 @@ export default {
     },
     userScenic () {
       return this.$store.state.app.account.managerScenicMatrix ? this.$store.state.app.account.managerScenicMatrix : this.$store.state.app.scenicList
+    },
+    ticketCategoryList () {
+      return this.$store.state.app.ticketCategory
+    },
+    salesList () {
+      return this.$store.state.user.salesList
+    },
+    payChannelOptions () {
+      return this.$store.getters.payChannelOptions
     }
   },
   components: {
+    Tip,
     draggable
   },
   data () {
     return {
-      groupKeys: [{ value: 'orderDateDay', label: '统计日期' }],
+      dialogVisible: false,
+      selectedColumns: fixedColumns.map(i => i.value),
+      tempSelectedColumns: fixedColumns.map(i => i.value),
+      fixedColumns,
+      groupKeys,
       form: {
         checkTimeBegin: new Date(moment().startOf('day').subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss')),
         checkTimeEnd: new Date(moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')),
-        ticketTypeIdList: [], //
+        playDate: [],
+        playDateBegin: '',
+        playDateEnd: '',
+        ticketTypeIdList: [],
+        scenicIdList: [],
+        adminIdList: [],
+        orderCategory: '',
         otaSourceNameList: [],
-        groupByList: [],
+        payChannelList: [],
+        removeSubtotal: true,
+        groupByList: ['ticketTypeName'],
         pageNum: 1,
         pageSize: 10
       },
       finalGroup: [
-        { prop: 'otaSourceName', label: '订单渠道' },
-        { prop: 'ticketTypeName', label: '票种名称' },
-        { prop: 'unitPrice', label: '单价' },
-        { prop: 'checkCount', label: '检票数量' },
-        { prop: 'checkNum', label: '检票人数' },
-        { prop: 'checkPrice', label: '检票金额' },
-        { prop: 'orderDateDay', label: '统计日期' },
-        { prop: 'checkSettlementPrice', label: '结算金额' }
+        { value: 'otaSourceName', label: '订单渠道', prop: 'otaSourceName' },
+        { value: 'ticketTypeName', label: '票种名称', prop: 'ticketTypeName' },
+        { value: 'unitPrice', label: '单价', prop: 'unitPrice' },
+        { value: 'checkCount', label: '检票数量', prop: 'checkCount' },
+        { value: 'checkNum', label: '检票人数', prop: 'checkNum' },
+        { value: 'checkPrice', label: '检票金额', prop: 'checkPrice' },
+        { value: 'checkSettlementPrice', label: '结算金额', prop: 'checkSettlementPrice' }
       ],
-      selectKeys: [], // 默认选中
+      selectKeys: ['otaSourceName', 'ticketTypeName', 'unitPrice'],
       tableIndex: 1,
       OrderIndexArr: [],
       tableData: [],
       deviceList: [],
       saleChannels: [],
-      // ticketTypeList: [],
+      ticketTypeListData: [],
+      scenicListData: [],
+      oldTicketTypeOptions: [[]],
       loading: false
     }
   },
   created () {
     this.getCheckStatistic()
+    this.getTicketTypeList()
+    this.getScenicList()
+    this.loadUserConfig()
     this.getSaleChannelList()
   },
-  mounted () {
-  },
   methods: {
     hideClear () {
       if (['铭投山庄'].includes(this.scenicName)) {
@@ -206,86 +399,185 @@ export default {
       }
     },
     disabled (item) {
-      if (['铭投山庄'].includes(this.scenicName)) {
-        if (this.form.keyList2.length > 1) {
-          return false
-        } else if (this.form.keyList2.length === 1) {
-          if (this.form.keyList2.includes(item.id)) {
-            return true
-          } else {
+      if (item.value && item.value.includes('orderDate')) {
+        if (this.selectKeys.find(v => v.includes('orderDate'))) {
+          if (item.value === this.selectKeys.find(v => v.includes('orderDate'))) {
             return false
+          } else {
+            return true
           }
+        } else {
+          return false
         }
       } else {
         return false
       }
     },
+    showColumnConfig () {
+      this.dialogVisible = true
+      this.loadUserConfig(false)
+    },
+    loadUserConfig (applyToTable = true) {
+      getUserConfig({ statKey: STAT_KEY }).then(config => {
+        const columns = config?.data?.columns || config?.columns || config?.data || []
+        let nextSelected = []
+        if (Array.isArray(columns) && columns.length) {
+          nextSelected = columns
+            .filter(i => Number(i.isShow) === 1)
+            .map(i => i.fieldKey)
+        } else {
+          nextSelected = fixedColumns.map(i => i.value)
+        }
+        if (applyToTable) {
+          this.selectedColumns = nextSelected
+        }
+        this.tempSelectedColumns = [...nextSelected]
+      }).catch(() => {
+        const nextSelected = fixedColumns.map(i => i.value)
+        if (applyToTable) {
+          this.selectedColumns = nextSelected
+        }
+        this.tempSelectedColumns = [...nextSelected]
+      })
+    },
+    saveUserConfig () {
+      const columns = this.fixedColumns.map(item => ({
+        fieldKey: item.value,
+        fieldName: item.label,
+        isShow: this.tempSelectedColumns.includes(item.value) ? 1 : 0
+      }))
+      addUserConfig({ statKey: STAT_KEY, fields: columns }).then(() => {
+        this.selectedColumns = [...this.tempSelectedColumns]
+        this.dialogVisible = false
+      })
+    },
+    isColumnVisible (columnKey) {
+      return this.selectedColumns.includes(columnKey)
+    },
     totalRowClassName,
     reset () {
       this.$refs.form.resetFields()
+      this.form.playDate = []
+    },
+    selectAll (val) {
+      let allValues = this.ticketTypeList.map(i => i.id)
+      allValues.unshift(0)
+      const oldVal = this.oldTicketTypeOptions.length === 1 ? [] : this.oldTicketTypeOptions[1]
+
+      if (val.includes(0)) this.form.ticketTypeIdList = allValues
+
+      if (oldVal.includes(0) && !val.includes(0)) this.form.ticketTypeIdList = []
+
+      if (oldVal.includes(0) && val.includes(0)) {
+        const index = val.indexOf(0)
+        val.splice(index, 1)
+        this.form.ticketTypeIdList = val
+      }
+
+      if (!oldVal.includes(0) && !val.includes(0)) {
+        if (val.length === allValues.length - 1) this.form.ticketTypeIdList = [0].concat(val)
+      }
+
+      this.oldTicketTypeOptions[1] = this.form.ticketTypeIdList
     },
     getSaleChannelList () {
       getSaleChannelList({ pageSize: -1, pageNum: 1 }).then((res) => {
         this.saleChannels = res?.data || []
       })
     },
-    // 获取表格数据
+    getTicketTypeList () {
+      return getTicketTypeList({
+        pageNum: 1,
+        pageSize: 999
+      }).then(res => {
+        this.ticketTypeListData = res.data?.records || []
+      })
+    },
+    getScenicList () {
+      return getScenic().then(res => {
+        this.scenicListData = res.data?.records || []
+      })
+    },
     getCheckStatistic () {
       this.loading = true
       this.tableIndex++
-      // this.finalGroup = []
-      // this.finalGroup = this.groupKeys.filter(i => {
-      //   return this.selectKeys.includes(i.value)
-      // })
 
-      if (this.selectKeys.length === 0) {
-        this.finalGroup = [
-          { prop: 'otaSourceName', label: '订单渠道' },
-          { prop: 'ticketTypeName', label: '票种名称' },
-          { prop: 'unitPrice', label: '单价' },
-          { prop: 'checkCount', label: '检票数量' },
-          { prop: 'checkNum', label: '检票人数' },
-          { prop: 'checkPrice', label: '检票金额' },
-          { prop: 'checkSettlementPrice', label: '结算金额' }
-        ]
-      } else {
-        this.finalGroup = [
-          { prop: 'orderDateDay', label: '统计日期' },
-          { prop: 'otaSourceName', label: '订单渠道' },
-          { prop: 'ticketTypeName', label: '票种名称' },
-          { prop: 'unitPrice', label: '单价' },
-          { prop: 'checkCount', label: '检票数量' },
-          { prop: 'checkNum', label: '检票人数' },
-          { prop: 'checkPrice', label: '检票金额' },
-          { prop: 'checkSettlementPrice', label: '结算金额' }
-        ]
-      }
+      this.finalGroup = this.groupKeys.filter(i => {
+        return this.selectKeys.includes(i.value)
+      })
+
+      this.form.groupByList = this.finalGroup.map(i => i.value)
 
       if (this.form.checkTimeBegin) {
         this.form.checkTimeBegin = moment(this.form.checkTimeBegin).format('YYYY-MM-DD HH:mm:ss')
       } else {
-        this.form.checkTimeBegin = ''
+        this.$message.error('请选择起始时间')
+        this.loading = false
+        return
       }
 
       if (this.form.checkTimeEnd) {
         this.form.checkTimeEnd = moment(this.form.checkTimeEnd).format('YYYY-MM-DD HH:mm:ss')
       } else {
-        this.form.checkTimeEnd = ''
+        this.$message.error('请选择截止时间')
+        this.loading = false
+        return
       }
 
+      const [s1, e1] = this.form.playDate || []
+      this.form.playDateBegin = s1 ? moment(s1).format('YYYY-MM-DD') : ''
+      this.form.playDateEnd = e1 ? moment(e1).format('YYYY-MM-DD') : ''
+
       if (!this.form.ticketTypeIdList) {
         this.form.ticketTypeIdList = []
       }
 
-      this.form.groupByList = [...this.selectKeys] || []
+      this.tableData = []
 
       getCheckerVerifyStatistics(this.form).then(res => {
-        this.tableData = res.data
+        this.tableData = res.data || []
+
+        let groupArray = []
+        let orderIndexArr = []
+
+        this.finalGroup.forEach(i => {
+          groupArray.push({})
+        })
+
+        groupArray.forEach((group, index) => {
+          const keyName = this.finalGroup[index].prop || this.finalGroup[index].value
+          let keyIdx = 0
+
+          this.tableData.forEach((el, idx) => {
+            if (el[keyName] === '小计') {
+              keyIdx++
+            }
+
+            !group[el[keyName] + '_' + keyIdx] && (group[el[keyName] + '_' + keyIdx] = [])
+            group[el[keyName] + '_' + keyIdx].push(idx)
+          })
+
+          const arr = []
+          for (let k in group) {
+            if (group[k].length > 1) {
+              arr.push(group[k])
+            }
+          }
+          orderIndexArr.push(arr)
+        })
+
+        this.OrderIndexArr = orderIndexArr
       }).finally(() => {
         this.loading = false
       })
     },
     objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
+      if (this.form.removeSubtotal) {
+        return {
+          rowspan: 1,
+          colspan: 1
+        }
+      }
       if (columnIndex < this.finalGroup.length) {
         if (!(this.OrderIndexArr[columnIndex] && this.OrderIndexArr[columnIndex].length)) return