| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- <template>
- <div class="form-wrap">
- <el-form
- class="search-box"
- ref="form"
- :model="form"
- :inline="true"
- label-width="100px">
- <div class="block-title">
- 查询条件
- </div>
- <el-form-item
- label="起始时间"
- required
- verify
- prop="timeBegin">
- <el-date-picker
- v-model="form.timeBegin"
- type="datetime"
- placeholder="选择日期时间">
- </el-date-picker>
- </el-form-item>
- <el-form-item
- label="截止时间"
- required
- verify
- prop="timeEnd">
- <el-date-picker
- default-time="23:59:59"
- v-model="form.timeEnd"
- type="datetime"
- placeholder="选择日期时间">
- </el-date-picker>
- </el-form-item>
- <el-form-item
- label="票种列表"
- prop="ticketTypeIdList"
- >
- <el-select
- v-model="form.ticketTypeIdList"
- multiple
- collapse-tags
- filterable
- clearable
- placeholder="请选择"
- @change="selectAll">
- <el-option
- :value="0"
- label="全部票种">
- </el-option>
- <el-option
- v-for="item in ticketTypeList"
- :key="item.id"
- :value="item.id"
- :label="item.name">
- </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"
- >
- <el-select
- v-model="form.otaSourceNameList"
- placeholder="请选择"
- multiple
- clearable
- >
- <el-option
- v-for="(item,idx) in saleChannel"
- :key="idx"
- :label="item"
- :value="item"
- >
- </el-option>
- </el-select>
- </el-form-item>
- <!-- <el-form-item
- label="票状态列表"
- prop="ticketStatus">
- <el-select
- v-model="form.ticketStatus"
- multiple
- collapse-tags
- clearable
- placeholder="请选择">
- <el-option
- v-for="item in ticketStatusDic"
- :key="item.value"
- :label="item.label"
- :value="item.value">
- </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="分组筛选"
- style="width:100%">
- <el-checkbox-group
- v-model="selectKeys"
- :min="0"
- :max="4">
- <draggable :list="groupKeys">
- <el-checkbox
- :key="item.value"
- :label="item.value"
- v-for="(item) in groupKeys"
- :disabled="disabled(item)"
- >
- {{ item.label }}
- </el-checkbox>
- </draggable>
- </el-checkbox-group>
- (可拖拽排序)
- </el-form-item>
- <div class="btn-wrap">
- <el-button
- @click="reset">
- 重置
- </el-button>
- <el-button
- :disabled="loading"
- type="primary"
- @click="getSaleStatistic">
- 搜索
- </el-button>
- <el-button
- type="primary"
- @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">
- <el-table
- border
- stripe
- :key="tableIndex"
- v-loading="loading"
- :data="tableData"
- :span-method="objectSpanMethod">
- <el-table-column
- v-for="(item) in finalGroup"
- :key="item.value"
- :prop="item.prop || item.value"
- :label="item.label">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('salePrice')"
- prop="salePrice"
- label="售票金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('saleSettlementPrice')"
- prop="saleSettlementPrice"
- label="售票结算金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('saleNum')"
- prop="saleNum">
- <template
- slot="header">
- 售票张数
- <Tip msg="一码多人时算一张"></Tip>
- </template>
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('saleCheckNum')"
- prop="saleCheckNum"
- label="售票人数">
- <template
- slot="header">
- 售票人数
- <Tip msg="一码多人时算多张"></Tip>
- </template>
- </el-table-column>
- <!-- <el-table-column
- prop="actualCheckNum"
- label="售票总人次">
- <template
- slot="header">
- 售票总人次
- <Tip msg="售票人数 × 票种人数"></Tip>
- </template>
- </el-table-column> -->
- <el-table-column
- v-if="isColumnVisible('cancelPrice')"
- prop="cancelPrice"
- label="退票金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('cancelSettlementPrice')"
- prop="cancelSettlementPrice"
- label="退票结算金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('cancelNum')"
- width="100"
- prop="cancelNum"
- label="退票张数">
- <template
- slot="header">
- 退票张数
- <Tip msg="一码多人时算一张"></Tip>
- </template>
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('cancelCheckNum')"
- prop="cancelCheckNum"
- label="退票人数">
- <template
- slot="header">
- 退票人数
- <Tip msg="一码多人时算多张"></Tip>
- </template>
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('actualPrice')"
- prop="actualPrice"
- label="实售金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('actualSettlementPrice')"
- prop="actualSettlementPrice"
- label="实售结算金额">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('actualNum')"
- prop="actualNum"
- label="实售张数">
- </el-table-column>
- <el-table-column
- v-if="isColumnVisible('actualCheckNum')"
- prop="actualCheckNum"
- label="实售人数">
- </el-table-column>
- <!-- <el-table-column
- prop="actual_multi_people"
- width="110"
- label="实售总人次">
- <template slot-scope="scope">
- {{ scope.row.actualCheckNum - scope.row.cancel_multi_people }}
- </template>
- </el-table-column> -->
- <!-- <el-table-column
- v-if="selectKeys.includes('ticketTypeName')"
- prop="ticketTypeName"
- label="票种">
- </el-table-column>
- <el-table-column
- v-if="selectKeys.includes('adminName')"
- prop="adminName"
- label="售票员">
- </el-table-column>
- <el-table-column
- v-if="selectKeys.includes('otaSourceName')"
- prop="otaSourceName"
- label="销售渠道">
- </el-table-column>
- <el-table-column
- v-if="selectKeys.includes('payChannel')"
- prop="payChannel"
- 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 { getScenic, getTicketTypeList } from '@/api/ticketType'
- import { getOrderStatistics } from '@/api/order'
- import { exportCustomizeOrderStatistics } from '@/api/queryReport'
- import { ticketStatusDic } from '@/assets/staticData'
- import { getSystemConfigList } from '@/api/systemConfig'
- import { addUserConfig, getUserConfig } from '@/api/configSetting'
- import draggable from 'vuedraggable'
- 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: 'salePrice', label: '售票金额' },
- { value: 'saleSettlementPrice', label: '售票结算金额' },
- { value: 'saleNum', label: '售票张数' },
- { value: 'saleCheckNum', label: '售票人数' },
- { value: 'cancelPrice', label: '退票金额' },
- { value: 'cancelSettlementPrice', label: '退票结算金额' },
- { value: 'cancelNum', label: '退票张数' },
- { value: 'cancelCheckNum', label: '退票人数' },
- { value: 'actualPrice', label: '实售金额' },
- { value: 'actualSettlementPrice', label: '实售结算金额' },
- { value: 'actualNum', label: '实售张数' },
- { value: 'actualCheckNum', label: '实售人数' }
- ]
- const STAT_KEY = 'orderSaleStatistics'
- export default {
- computed: {
- ticketCategoryList () {
- return this.$store.state.app.ticketCategory
- },
- salesList () {
- return this.$store.state.user.salesList
- },
- saleChannel () {
- return this.$store.state.app.saleChannel
- },
- payChannelOptions () {
- return this.$store.getters.payChannelOptions
- },
- userScenic () {
- return this.$store.state.app.account.managerScenicMatrix ? this.$store.state.app.account.managerScenicMatrix : this.scenicList
- }
- },
- components: {
- Tip,
- draggable
- },
- data () {
- return {
- dialogVisible: false,
- selectedColumns: fixedColumns.map(i => i.value),
- tempSelectedColumns: fixedColumns.map(i => i.value),
- fixedColumns,
- finalGroup: [
- { value: 'ticketTypeName', label: '票种', prop: 'ticketTypeName' },
- { value: 'adminName', label: '售票员', prop: 'adminName' },
- { value: 'payChannel', label: '支付方式' }
- ],
- selectKeys: ['ticketTypeName', 'adminName', 'payChannel'],
- ticketStatusDic,
- ticketTypeList: [],
- oldTicketTypeOptions: [[]],
- oldTicketCateOptions: [[]],
- scenicList: [],
- ticketSpotList: [],
- groupKeys,
- 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')),
- isStorage: null,
- ticketTypeIdList: [],
- ticketStatus: [],
- orderCategory: '',
- otaSourceNameList: [], // 渠道id
- payChannelList: [],
- removeSubtotal: true,
- adminIdList: [], // 售票员id
- scenicIdList: [], // 景点id
- groupByList: ['ticketTypeName'],
- pageSize: 10,
- pageNum: 1
- },
- tableData: [],
- loading: false,
- orderTagList: [],
- ticketTagList: [],
- OrderIndexArr: [],
- index: 0,
- tableIndex: 1
- }
- },
- async created () {
- this.getTicketTypeList()
- this.getScenicList()
- this.getSaleStatistic()
- this.loadUserConfig()
- const res = await getSystemConfigList()
- /*
- const orderTagList = res.list.find(v => v.configKey === 'orderTagList')?.configValue || []
- this.orderTagList = orderTagList.replace(/\s+/g, '').split(',')
- */
- this.orderTagList = (res.data || []).find(v => v.configKey === 'orderTagList')?.configValue?.replace(/\s+/g, '')?.split(',') || []
- },
- methods: {
- 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)
- },
- // 单元格颜色边框设置
- handleCellStyle ({ row, column, rowIndex, columnIndex }) {
- if (columnIndex > 4 && columnIndex <= 8) {
- if (columnIndex === 8) {
- return 'greenBg boldBorder'
- }
- return 'greenBg'
- }
- if (columnIndex > 8 && columnIndex <= 12) {
- if (columnIndex === 12) {
- return 'redBg boldBorder'
- }
- return 'redBg'
- }
- if (columnIndex === 4) {
- return 'boldBorder'
- }
- },
- disabled (item) {
- if (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
- }
- },
- 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
- },
- selectAllCate (val) {
- let allValues = this.orderCategory.map(i => i.id)
- allValues.unshift(0) // 添加全部
- // 用来储存上一次的值,可以进行对比
- const oldVal = this.oldTicketCateOptions.length === 1 ? [] : this.oldTicketCateOptions[1]
- // 若是全部选择
- if (val.includes(0)) this.form.orderCategory = allValues
- // 取消全部选中 上次有 当前没有 表示取消全选
- if (oldVal.includes(0) && !val.includes(0)) this.form.orderCategory = []
- // 点击非全部选中 需要排除全部选中 以及 当前点击的选项
- // 新老数据都有全部选中
- if (oldVal.includes(0) && val.includes(0)) {
- const index = val.indexOf(0)
- val.splice(index, 1) // 排除全选选项
- this.form.orderCategory = val
- }
- // 全选未选 但是其他选项全部选上 则全选选上 上次和当前 都没有全选
- if (!oldVal.includes(0) && !val.includes(0)) {
- if (val.length === allValues.length - 1) this.form.orderCategory = [0].concat(val)
- }
- // 储存当前最后的结果 作为下次的老数据
- this.oldTicketCateOptions[1] = this.form.orderCategory
- },
- reset () {
- this.$refs.form.resetFields()
- },
- reportExport () {
- this.$confirm(`是否要导出明细数据`, '确认提示', {
- confirmButtonText: '是',
- cancelButtonText: '否',
- type: 'warning'
- }).then(() => {
- this.handleExport({
- ...this.form,
- export: true,
- exportDetail: true
- })
- }).catch(() => {
- this.handleExport({
- ...this.form,
- export: true,
- exportDetail: false
- })
- })
- },
- handleExport (params) {
- exportCustomizeOrderStatistics(params).then(() => {
- this.$message.success('导出成功。')
- this.goToDownload()
- }, () => {
- this.$message.success('导出失败。')
- })
- },
- // 获取票种列表
- getTicketTypeList () {
- return getTicketTypeList({
- pageNum: 1,
- pageSize: 999
- }).then(res => {
- this.ticketTypeList = res.data?.records || []
- })
- },
- // 获取景点列表
- getScenicList () {
- return getScenic().then(res => {
- this.scenicList = res.data?.records || []
- })
- },
- // 获取表格数据
- getSaleStatistic () {
- if (this.form.timeBegin) {
- this.form.timeBegin = moment(this.form.timeBegin).format('YYYY-MM-DD HH:mm:ss')
- } else {
- this.$message.error('请选择起始时间')
- return
- }
- if (this.form.timeEnd) {
- this.form.timeEnd = moment(this.form.timeEnd).format('YYYY-MM-DD HH:mm:ss')
- } else {
- this.$message.error('请选择截止时间')
- return
- }
- this.loading = true
- this.tableData = []
- this.tableIndex++
- let groupArray = []
- let orderIndexArr = []
- this.finalGroup = this.groupKeys.filter(i => {
- return this.selectKeys.includes(i.value)
- })
- this.form.groupByList = this.finalGroup.map(i => i.value)
- getOrderStatistics(this.form).then(res => {
- this.tableData = res.data || []
- this.finalGroup.forEach(i => {
- groupArray.push({})
- })
- groupArray.forEach((group, index) => {
- const keyName = this.finalGroup[index].prop || this.finalGroup[index].value
- this.tableData.forEach((el, index) => {
- if (el[keyName] === '小计') {
- this.index++
- }
- !group[el[keyName] + '_' + this.index] && (group[el[keyName] + '_' + this.index] = [])
- group[el[keyName] + '_' + this.index].push(index)
- })
- 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
- sessionStorage.setItem('统计表-自定义售票统计-查询条件', JSON.stringify(this.form)) // 下次记住
- sessionStorage.setItem('统计表-自定义售票统计-查询条件-selectKeys', JSON.stringify(this.selectKeys)) // 下次记住
- })
- },
- totalRowClassName ({ row, rowIndex }) {
- for (let key in row) {
- if (row[key] === '小计') {
- return 'table-total-row table-total-row2'
- }
- if (row[key] === '总计') {
- return 'table-total-row'
- }
- }
- },
- 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
- for (let i = 0; i < this.OrderIndexArr[columnIndex].length; i++) {
- let element = this.OrderIndexArr[columnIndex][i]
- for (let j = 0; j < element.length; j++) {
- let item = element[j]
- if (rowIndex === item) {
- if (j === 0) {
- return {
- rowspan: element.length,
- colspan: 1
- }
- } else if (j !== 0) {
- return {
- rowspan: 0,
- colspan: 0
- }
- }
- }
- }
- }
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- </style>
|