Commit cf7b62dc by crushh

update: dist

parent d53c046c
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -679,7 +679,7 @@ img::after {
white-space: nowrap;
text-overflow: ellipsis;
}
.subTitle {
.mini-sub-title {
width: 100%;
height: 40px;
display: flex;
......
<template>
<div class="member-group-container">
<div class="echo-member-group" v-if="echoFlag">
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......
<template>
<div class="ruleFilter">
<div class="echo-member-group" v-if="echoFlag">
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......
......@@ -187,8 +187,26 @@ export const stopGame = params => requests(PREFIX + '/game-pro/stop-game', param
// 转换成页面链接
export const getPageLink = params => requests('api-admin/get-page-link', params, true, false, 'get');
// 游戏活动分页查询-统计
export const pageStatistics = params => requests(PREFIX + 'game-pro/page-statistics', params, true, false, 'post');
// 活动基础数据-拆盲盒
export const getGameOverview = params => requests(PREFIX + '/game-data/get-game-overview', params, true, false, 'get');
// 游戏活动分页查询-统计
export const pageStatistics = params => requests(PREFIX + 'game-pro/page-statistics', params, true, false, 'post');
// 游戏卡券核销数据-拆盲盒
export const getGameCardWriteOff = params => requests(PREFIX + '/game-data/get-game-card-write-off', params, true, false, 'get');
// 游戏奖品数据-拆盲盒
export const getGamePrize = params => requests(PREFIX + 'game-data/get-game-prize', params, true, false, 'get');
// 游戏活动基础数据明细-拆盲盒
export const getGameDataDetail = params => requests(PREFIX + '/game-data/get-game-detail', params, true, false, 'get');
//游戏活动基础明细导出-拆盲盒
export const exportGameDetail = config.api + PREFIX + '/game-data/export-game-detail';
// 奖品明细-拆盲盒
export const getPrizeDetail = params => requests(PREFIX + '/game-data/get-game-prize-detail', params, true, false, 'get');
//奖品明细导出-拆盲盒
export const exportGamePrizeDetail = config.api + PREFIX + '/game-data/export-game-prize-detail';
......@@ -61,7 +61,7 @@
<script>
import { aiTransformStoreGroupSplit, getActivityDetail, aiStoreTransfer, aiStoreTransferNoBelong, aiStoreTransferStatistics, exportAiStoreTransfer, aiStoreGroupTransfer, aiStoreGroupTransferStatistics, exportAiStoreGroupTransfer } from '@/service/api/aiApi.js';
import TargetGroup from '@/views/ai/ai-data-report/target-group.vue';
import TargetGroup from '@/components/target-group.vue';
import { numFormat } from '@/utils/index.js';
const tableHead = [
......
......@@ -61,7 +61,7 @@
<script>
import { aiOutboundStoreGroupSplit, getActivityDetail, aiStoreOutboundRank, aiStoreOutboundRankNoBelong, aiStoreOutboundStatistics, exportAiStoreOutbound, aiStoreGroupOutboundRank, aiStoreGroupOutboundStatistics, exportAiStoreGroupOutbound } from '@/service/api/aiApi.js';
import TargetGroup from '@/views/ai/ai-data-report/target-group.vue';
import TargetGroup from '@/components/target-group.vue';
import { numFormat } from '@/utils/index.js';
let tableHead = [
......
......@@ -71,7 +71,7 @@ import G2 from '@antv/g2';
import DataSet from '@antv/data-set';
import { numFormat } from '@/utils/index.js';
import { getOutBound, getIntentionLabel, getBillAnalysis, getCallDuration } from '@/service/api/aiApi.js';
import TargetGroup from './target-group.vue';
import TargetGroup from '@/components/target-group.vue';
export default {
name: 'AiData',
......
......@@ -71,7 +71,7 @@
<script>
import { getPlanStatistics, getMemberCrowd, getComparativeData } from '@/service/api/aiApi.js';
import { numFormat } from '@/utils/index.js';
import TargetGroup from './target-group.vue';
import TargetGroup from '@/components/target-group.vue';
export default {
name: 'Conversion',
......
......@@ -7,7 +7,7 @@
<template>
<card-profit-sum :list="list" />
<div class="title" style="margin-top:20px">
<h2 class="subtitle">卡券核销</h2>
<h2 class="mini-sub-title">卡券核销</h2>
<span>卡券核销情况统计通过当前智能营销计划投放的卡券,顾客使用该卡券消费的情况。即使消费时间已经过了收益有效期也会统计在内</span>
</div>
<el-table :data="tableData" v-if="tableData.length > 0" style="margin:20px 0 20px" max-height="710" header-cell-class-name="card-profit-header">
......
......@@ -25,7 +25,7 @@
</el-form-item>
<el-form-item label="抽奖样式">
<div class="lottery">
<div class="tips">图片建议尺寸{{ baseForm.prizeStyleJsonSize0 }}或等比图片,格式 jpg/png/gif,大小 {{ prizeStyleJsonSize1 }}M 以内。</div>
<div class="tips">图片建议尺寸{{ baseForm.prizeStyleJsonSize0 }}或等比图片,格式 jpg/png/gif,大小 {{ baseForm.prizeStyleJsonSize1 }}M 以内。</div>
<div v-for="item in baseForm.prizeStyleJson" :key="item.index">
<div class="imgContent">
<div class="imageOrigin">
......@@ -33,7 +33,7 @@
<div style="display: flex;">
<img :src="item.imageNoSelectUrl" alt="未选中效果" style="width: 120px;height: 120px;" />
<div class="imgBtn">
<el-upload class="avatar-uploader" action="123" :show-file-list="false" :before-upload="file => beforeAvatarUpload(file, 'imageNoSelectUrl', prizeStyleJsonSize1)">
<el-upload class="avatar-uploader" action="123" :show-file-list="false" :before-upload="file => beforeAvatarUpload(file, 'imageNoSelectUrl', baseForm.prizeStyleJsonSize1)">
<el-button type="text">替换</el-button>
</el-upload>
<el-button type="text" @click="replace('imageNoSelectUrl', item.index)">重置</el-button>
......@@ -45,7 +45,7 @@
<div style="display: flex;">
<img :src="item.imageSelectUrl" alt="选中效果" style="width: 120px;height: 120px;" />
<div class="imgBtn">
<el-upload class="avatar-uploader" action="123" :show-file-list="false" :before-upload="file => beforeAvatarUpload(file, 'imageSelectUrl', prizeStyleJsonSize1)">
<el-upload class="avatar-uploader" action="123" :show-file-list="false" :before-upload="file => beforeAvatarUpload(file, 'imageSelectUrl', baseForm.prizeStyleJsonSize1)">
<el-button type="text">替换</el-button>
</el-upload>
<el-button type="text" @click="replace('imageSelectUrl', item.index)">重置</el-button>
......@@ -253,7 +253,7 @@ export default {
},
beforeAvatarUpload(file, key, size1 = 1) {
const arr = ['image/gif', 'image/jpeg', 'image/png'];
const limit = file.size / 1024 / 1024 < 2;
const limit = file.size / 1024 / 1024 < size1;
if (!arr.includes(file.type)) {
this.$message.warning('只能上传jpg/png/gif格式文件!');
return false;
......@@ -332,7 +332,7 @@ export default {
},
handleListen() {
this.isPlay = !this.isPlay;
this.backMusicOptions.forEach(item => {
this.backMusicOptionsComputed.forEach(item => {
if (item.materialValue == this.baseForm.backMusicUrlObj.materialValue) {
music.src = this.baseForm.backMusicUrlObj.materialValue;
this.isPlay ? music.play() : music.pause();
......
......@@ -112,7 +112,7 @@
<div class="shareBox" v-if="form.gameRuleInfo.playConditionFlag == 1">
<div v-for="item in form.gameRuleConditionList" :key="item.conditionType">
<div v-if="item.conditionType == 2" class="shareSection">
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......@@ -123,7 +123,7 @@
<p>{{ item.conditionJson.type == 21 ? '总赠送' : '每日赠送' }}: {{ item.conditionJson.value }}次游戏次数</p>
</div>
<div v-if="item.conditionType == 0" class="shareSection">
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......@@ -135,7 +135,7 @@
<p>提示客户获取积分路径: {{ item.conditionJson.mpUrlView.name }}</p>
</div>
<div v-if="item.conditionType == 1">
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......
......@@ -159,11 +159,11 @@ export default {
const prizeNoticeStockVal = (rule, value, callback) => {
if (this.prizeForm.prizeNoticeFlag == 1) {
if (!new RegExp('([1-9]{1}\\d{0,9})|(0{1})').test(value)) {
callback(new Error('请输入不超过1000000的数字'));
callback(new Error('最大值1000000'));
return;
}
if (value < 0 || value > 1000000) {
callback(new Error('请输入不超过1000000的数字'));
if (value <= 0 || value > 1000000) {
callback(new Error('最大值1000000'));
return;
}
}
......@@ -171,9 +171,9 @@ export default {
};
return {
rules: {
winChance: { type: 'number', required: true, message: '请输入不超过100的数字', max: 100, min: 0 },
prizeNumber: { type: 'number', required: true, message: '请输入不超过1000000的数字', max: 1000000, min: 1 },
prizeStock: { type: 'number', required: true, message: '请输入不超过1000000的数字', max: 1000000, min: 0 },
winChance: { type: 'number', required: true, message: '最大值100', max: 100, min: 0 },
prizeNumber: { type: 'number', required: true, message: '最大值1000000', max: 1000000, min: 1 },
prizeStock: { type: 'number', required: true, message: '最大值1000000', max: 1000000, min: 0 },
prizeNoticeStock: { validator: prizeNoticeStockVal },
prizeName: { type: 'string', required: true, message: '请输入奖品名称' },
prizeType: { required: true, message: '请选择奖品类型' }
......@@ -296,11 +296,11 @@ export default {
return (rule, value, callback) => {
if (row.prizeType == 1) {
if (!new RegExp('([1-9]{1}\\d{0,9})|(0{1})').test(value)) {
callback(new Error('请输入不超过1000000的数字'));
callback(new Error('最大值1000000'));
return;
}
if (value < 0 || value > 1000000) {
callback(new Error('请输入不超过1000000的数字'));
callback(new Error('最大值1000000'));
return;
}
}
......@@ -401,12 +401,11 @@ export default {
item.prizeRate = prizeRate.toFixed(2);
}
});
const rateTotal = this.prizeForm.gamePrizeList.map(item => (item.prizeType != 0 ? item.prizeRate : 0)).reduce((pre, current) => Number(pre) + Number(current));
console.log(rateTotal);
let prizeArr = this.prizeForm.gamePrizeList.filter(item => item.prizeType == 0);
prizeArr.forEach(item => {
console.log(item);
const prizeRate = (100 - rateTotal) / prizeArr.length || 0;
const prizeRate = (100 - this.prizeForm.winChance) / prizeArr.length || 0;
item.prizeRate = prizeRate.toFixed(2);
});
this.prizeForm.gamePrizeList = this.prizeForm.gamePrizeList.splice(0);
......
......@@ -74,7 +74,7 @@
<el-form-item label="关注回复" :prop="'gameRuleConditionList.' + index + '.conditionJson.' + 'subscribeMsg'" label-width="80px" :rules="rules.subscribeMsg"> <el-input maxlength="20" :disabled="isDisabled" show-word-limit v-model="item.conditionJson.subscribeMsg" /> </el-form-item>
</div>
<div>
<div class="subTitle">
<div class="mini-sub-title">
<div class="line"></div>
<div class="text">
<div class="space-between">
......@@ -215,7 +215,7 @@ export default {
rules: {
memberType: { required: true, message: '请选择' },
memberDesc: { type: 'string', required: true, message: '未配置游戏说明', trigger: 'blur' },
memberDesc: { type: 'string', required: true, message: '请输入适用人群说明', trigger: 'blur' },
playTimes: { type: 'number', required: true, message: '请输入不超过1000的数字', max: 1000, min: 1 },
playConditionFlag: { required: true },
mpUrlView: { validator: mpUrlViewVal },
......@@ -350,7 +350,7 @@ export default {
},
beforeAvatarUpload(file, key, size1 = 1) {
const arr = ['image/gif', 'image/jpeg', 'image/png'];
const limit = file.size / 1024 / 1024 < 2;
const limit = file.size / 1024 / 1024 < size1;
if (!arr.includes(file.type)) {
this.$message.warning('只能上传jpg/png/gif格式文件!');
return false;
......
<template>
<section class="dm-wrap" v-loading="loading">
<div class="pt20 pb20 clearfix">
<el-date-picker class="w256" v-model="form.dateTime" value-format="yyyy-MM-dd" @change="refresh" type="daterange" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
<el-input v-model="form.search" class="w260" placeholder="请输入会员号/手机号/昵称" clearable @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
<el-button icon="iconfont fz14 icon-cp-xiazai" type="primary" class="fr" @click="handleExport" size="small" :disabled="!total"> 查询结果导出</el-button>
</div>
<el-table tooltipEffect="light" :data="tableList" style="width:100%">
<el-table-column label="基本信息" min-width="214" show-overflow-tooltip fixed="left">
<div slot-scope="{ row }" class="member-info">
<img class="member-logo" v-if="row.memberImage" :src="row.memberImage" alt="" />
<svg aria-hidden="true" v-else class="member-logo">
<use xlink:href="#icon-user-default"></use>
</svg>
<div>
<p class="member-name">
<template v-if="row.memberNick">
{{ row.memberNick || '--' }}
</template>
<span class="member-subname" v-if="row.memberName">
{{ row.memberNick ? `(${row.memberName})` : row.memberName }}
</span>
</p>
<p class="member-name" v-if="row.phoneNum">{{ row.phoneNum }}</p>
</div>
</div>
</el-table-column>
<el-table-column label="会员卡号" min-width="130px" prop="cardNum" show-overflow-tooltip :formatter="(row, col, val) => val || '--'"></el-table-column>
<el-table-column label="服务门店" min-width="210" prop="mainStoreName">
<template slot-scope="{ row }">
{{ row.mainStoreName }}
<br />
{{ row.mainStoreCode }}
</template>
</el-table-column>
<el-table-column label="中奖次数" min-width="96" prop="winCnt"></el-table-column>
<el-table-column label="分享次数" min-width="96" prop="shareCnt"></el-table-column>
<el-table-column label="裂变新用户" min-width="112" prop="invitationMemberCnt"></el-table-column>
<el-table-column label="消耗积分" min-width="96" prop="useIntegralCnt"></el-table-column>
<el-table-column min-width="88" prop="isNewMember">
<template slot="header">
新会员
<el-tooltip placement="top" content="用户自身是否通过本次游戏注册成为会员">
<i class="iconfont icon-QuestionCircleOutlined"></i>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="首次参与时间" min-width="114" prop="firstPlayTime" fixed="right">
<template slot-scope="{ row }">
{{ formatDateTimeByType(row.firstPlayTime, 'yyyy-MM-dd') }}
<br />
{{ formatDateTimeByType(row.firstPlayTime, 'HH-mm-ss') }}
</template>
</el-table-column>
</el-table>
<dm-pagination v-show="tableList.length" background class="dm-pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="form.pageNum" :page-sizes="[20, 40, 60, 80]" :page-size="form.pageSize" layout="total, sizes, prev, pager, next" :total="total"></dm-pagination>
<vue-gic-export-excel :dialogVisible.sync="dialogVisible" :dataArr="tableList" :type="2" :excelUrl="exportGameDetail" :params="params" projectName="marketing"></vue-gic-export-excel>
</section>
</template>
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { getGameDataDetail, exportGameDetail } from '@/service/api/gameApi.js';
export default {
data() {
return {
tableList: [],
form: {
pageNum: 1,
pageSize: 20,
gameId: this.$route.params.id,
dateTime: [],
search: ''
},
formatDateTimeByType,
total: 0,
dialogVisible: false,
exportGameDetail,
params: {},
loading: false
};
},
mounted() {
this.getTableList();
},
methods: {
handleExport() {
this.dialogVisible = true;
this.params = {
gameId: this.$route.params.id,
search: this.form.search
};
if (this.form.dateTime && this.form.dateTime.length) {
this.params.startTime = this.form.dateTime[0];
this.params.endTime = this.form.dateTime[1];
}
},
refresh() {
this.form.pageNum = 1;
this.getTableList();
},
handleSizeChange(val) {
this.form.pageSize = val;
this.getTableList();
},
handleCurrentChange(val) {
this.form.pageNum = val;
this.getTableList();
},
getTableList() {
const params = { ...this.form };
this.loading = true;
if (params.dateTime && params.dateTime.length) {
params.startTime = params.dateTime[0];
params.endTime = params.dateTime[1];
}
delete params.dateTime;
getGameDataDetail(params)
.then(res => {
const { result } = res;
this.tableList = result.result;
this.total = result.totalCount;
})
.finally(() => {
this.loading = false;
});
}
}
};
</script>
<style lang="scss" scoped>
.member-info {
display: flex;
justify-content: flex-start;
align-items: center;
.member-logo {
flex-shrink: 0;
margin-right: 10px;
width: 40px;
height: 40px;
border-radius: 40px;
overflow: hidden;
}
.member-name {
font-size: 14px;
font-weight: 400;
color: #303133;
line-height: 20px;
.member-subname {
color: #909399;
}
}
}
</style>
<template>
<section class="dm-wrap" v-loading="loading">
<div class="pt20 pb20 clearfix">
<el-input v-model="form.prizeName" class="w260" placeholder="请输入奖品名称" clearable @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
<el-input v-model="form.search" class="w260" placeholder="请输入姓名/昵称/手机号/会员卡号" clearable @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
<el-date-picker class="w256" v-model="form.dateTime" value-format="yyyy-MM-dd" @change="refresh" type="daterange" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
<el-select class="w160" v-model="form.prizeType" placeholder="所有游戏状态" @change="refresh" clearable>
<el-option v-for="(v, i) in prizeTypeOptions" :key="i" :label="v.label" :value="v.value"></el-option>
</el-select>
<el-button icon="iconfont fz14 icon-cp-xiazai" type="primary" class="fr" @click="handleExport" size="small" :disabled="!total"> 查询结果导出</el-button>
</div>
<el-table tooltipEffect="light" :data="tableList" style="width:100%">
<el-table-column label="奖品名称" min-width="204" prop="prizeName" fixed="left" show-overflow-tooltip :formatter="(row, col, val) => val || '--'"></el-table-column>
<el-table-column label="奖品类型" min-width="183" prop="prizeType" :formatter="(row, col, val) => prizeTypeObj[val]"></el-table-column>
<el-table-column label="中奖会员" min-width="214">
<div slot-scope="{ row }" class="member-info">
<img class="member-logo" v-if="row.memberImage" :src="row.memberImage" alt="" />
<svg aria-hidden="true" v-else class="member-logo">
<use xlink:href="#icon-user-default"></use>
</svg>
<div>
<p class="member-name">
<template v-if="row.memberNick">
{{ row.memberNick || '--' }}
</template>
<span class="member-subname" v-if="row.memberName">
{{ row.memberNick ? `(${row.memberName})` : row.memberName }}
</span>
</p>
<p class="member-name" v-if="row.memberMobile">{{ row.memberMobile }}</p>
</div>
</div>
</el-table-column>
<el-table-column label="会员卡号" min-width="184" prop="memberCard" :formatter="(row, col, val) => val || '--'"></el-table-column>
<el-table-column label="兑奖方式" min-width="184" prop="exchangeTypeName" :formatter="(row, col, val) => val || '--'"></el-table-column>
<el-table-column label="中奖时间" min-width="183" prop="prizeTime" fixed="right">
<template slot-scope="{ row }">
{{ formatDateTimeByType(row.prizeTime, 'yyyy-MM-dd') }}
<br />
{{ formatDateTimeByType(row.prizeTime, 'HH-mm-ss') }}
</template>
</el-table-column>
</el-table>
<dm-pagination v-show="tableList.length" background class="dm-pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="form.pageNum" :page-sizes="[20, 40, 60, 80]" :page-size="form.pageSize" layout="total, sizes, prev, pager, next" :total="total"></dm-pagination>
<vue-gic-export-excel :dialogVisible.sync="dialogVisible" :dataArr="tableList" :type="2" :excelUrl="exportGamePrizeDetail" :params="params" projectName="marketing"></vue-gic-export-excel>
</section>
</template>
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { getPrizeDetail, exportGamePrizeDetail } from '@/service/api/gameApi.js';
export default {
data() {
return {
tableList: [],
form: {
prizeName: '',
pageNum: 1,
pageSize: 20,
gameId: this.$route.params.id,
dateTime: [],
search: '',
prizeType: ''
},
prizeTypeOptions: [
{
label: '积分',
value: 1
},
{
label: '卡券',
value: 2
}
],
prizeTypeObj: {
1: '积分',
2: '卡券'
},
formatDateTimeByType,
total: 0,
dialogVisible: false,
exportGamePrizeDetail,
params: {},
loading: false
};
},
mounted() {
this.getTableList();
},
methods: {
handleExport() {
this.dialogVisible = true;
const { search, prizeType, prizeName } = this.form;
this.params = {
gameId: this.$route.params.id,
search,
prizeType,
prizeName
};
if (this.form.dateTime && this.form.dateTime.length) {
this.params.startTime = this.form.dateTime[0];
this.params.endTime = this.form.dateTime[1];
}
},
refresh() {
this.form.pageNum = 1;
this.getTableList();
},
handleSizeChange(val) {
this.form.pageSize = val;
this.getTableList();
},
handleCurrentChange(val) {
this.form.pageNum = val;
this.getTableList();
},
getTableList() {
const params = { ...this.form };
this.loading = true;
if (params.dateTime && params.dateTime.length) {
params.startTime = params.dateTime[0];
params.endTime = params.dateTime[1];
}
delete params.dateTime;
getPrizeDetail(params)
.then(res => {
const { result } = res;
this.tableList = result.result;
this.total = result.totalCount;
})
.finally(() => {
this.loading = false;
});
}
}
};
</script>
<style lang="scss" scoped>
.member-info {
display: flex;
justify-content: flex-start;
align-items: center;
.member-logo {
flex-shrink: 0;
margin-right: 10px;
width: 40px;
height: 40px;
border-radius: 40px;
overflow: hidden;
}
.member-name {
font-size: 14px;
font-weight: 400;
color: #303133;
line-height: 20px;
.member-subname {
color: #909399;
}
}
}
</style>
<template>
<div class="statistics">
<div class="report-module">
<dm-sub-title>活动信息</dm-sub-title>
<div class="mt20">
<el-descriptions column="4">
<el-descriptions-item label="活动名称"> {{ baseData.gameName }}</el-descriptions-item>
<el-descriptions-item label="活动类型">盲盒</el-descriptions-item>
<el-descriptions-item label="活动状态"><span :class="gameStatusClass[baseData.status]"></span> {{ gameStatus[baseData.status] }}</el-descriptions-item>
<el-descriptions-item label="活动有效期">{{ baseData.gameTimeStr }}</el-descriptions-item>
</el-descriptions>
</div>
</div>
<div class="report-module">
<dm-sub-title title-align="space-between">
<div>
活动数据
<el-button class="check-detail" @click="toDetailPage(1)">查看详情</el-button>
</div>
</dm-sub-title>
<el-row :gutter="20">
<el-col :span="6" v-for="(el, index) in activityData" :key="index">
<target-group :data-list="el"></target-group>
</el-col>
</el-row>
</div>
<div class="report-module">
<dm-sub-title>
卡券核销
</dm-sub-title>
<el-row :gutter="20">
<el-col :span="6" v-for="(el, index) in cardData" :key="index">
<target-group :data-list="el"></target-group>
</el-col>
</el-row>
</div>
<div class="report-module">
<dm-sub-title title-align="space-between">
<div>
奖品数据
<el-button class="check-detail" @click="toDetailPage(2)">查看详情</el-button>
</div>
</dm-sub-title>
<el-radio-group class="customize mt20 mb20" v-model="dimension" @change="radioChange">
<el-radio-button label="1" value="1">卡券</el-radio-button>
<el-radio-button label="2" value="2">积分</el-radio-button>
</el-radio-group>
<el-table :data="prizeList" style="width:100%" :key="dimension">
<el-table-column v-for="v in tableHeader" :show-overflow-tooltip="v.tooltip" :width="v.width" :min-width="v.minWidth" :align="v.align" :key="v.prop" :prop="v.prop" :label="v.label" :formatter="v.formatter" :sortable="v.sortable" :fixed="v.fixed">
<template slot-scope="scope">
<span v-if="v.formatter" v-html="v.formatter(scope.row)"></span>
<span v-else>{{ scope.row[v.prop] }}</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
import { numFormat, formatDateTimeByType } from '@/utils/index.js';
import { getGameOverview, getGameCardWriteOff, getGameDetail, getGamePrize } from '@/service/api/gameApi.js';
import TargetGroup from '@/components/target-group.vue';
const tableHead = [
{
label: '奖品名称',
minWidth: '206',
prop: 'prizeName',
formatter: function(row) {
return `<span class="ellipsis-l2">${row.prizeName ? row.prizeName : '- -'}</span>`;
}
},
{
label: '库存',
prop: 'prizeTotalStock',
minWidth: '88',
formatter: function(row) {
return `<span>${row.prizeTotalStock ? row.prizeTotalStock.toLocaleString() : '- -'}</span>`;
}
},
{
label: '中奖人数',
prop: 'prizeWinningMNum',
minWidth: '116',
formatter: function(row) {
return `<span>${row.prizeWinningMNum ? row.prizeWinningMNum.toLocaleString() : '- -'}</span>`;
}
},
{
label: '中奖率',
prop: 'prizeWinningRate',
minWidth: '120',
formatter: function(row) {
return `<span>${!isNaN(row.prizeWinningRate) ? row.prizeWinningRate + '%' : '- -'}</span>`;
}
},
{
label: '领取数',
prop: 'receivedMNum',
minWidth: '100',
formatter: function(row) {
return `<span>${row.receivedMNum ? row.receivedMNum.toLocaleString() : '- -'}</span>`;
}
},
{
label: '核销数量',
prop: 'writeOffNum',
minWidth: '120',
formatter: function(row) {
return `<span>${row.writeOffNum ? row.writeOffNum.toLocaleString() : '- -'}</span>`;
}
},
{
label: '核销人数',
prop: 'writeOffMNum',
minWidth: '120',
formatter: function(row) {
return `<span>${row.writeOffMNum ? row.writeOffMNum.toLocaleString() : '- -'}</span>`;
}
},
{
label: '核销率',
prop: 'writeOffRate',
minWidth: '100',
formatter: function(row) {
return `<span>${!isNaN(row.writeOffRate) ? row.writeOffRate + '%' : '- -'}</span>`;
}
},
{
label: '客单价',
prop: 'perCustomerTransaction',
minWidth: '100',
formatter: function(row) {
return `<span>${row.perCustomerTransaction ? row.perCustomerTransaction.toLocaleString() : '- -'}</span>`;
}
},
{
label: '连带率',
prop: 'jointRate',
minWidth: '100',
formatter: function(row) {
return `<span>${row.jointRate ? row.jointRate : '- -'}</span>`;
},
fixed: 'right'
}
];
const pointHead = [
{
label: '奖品名称',
minWidth: '206',
prop: 'prizeName',
formatter: function(row) {
return `<span class="ellipsis-l2">${row.prizeName ? row.prizeName : '- -'}</span>`;
}
},
{
label: '中奖人数',
prop: 'prizeWinningMNum',
minWidth: '116',
formatter: function(row) {
return `<span>${row.prizeWinningMNum ? row.prizeWinningMNum.toLocaleString() : '- -'}</span>`;
}
},
{
label: '中奖率',
prop: 'prizeWinningRate',
minWidth: '120',
formatter: function(row) {
return `<span>${row.prizeWinningRate ? row.prizeWinningRate + '%' : '- -'}</span>`;
}
},
{
label: '累计中奖积分',
prop: 'cumulativeIntegral',
minWidth: '100',
formatter: function(row) {
return `<span>${row.cumulativeIntegral ? row.cumulativeIntegral : '- -'}</span>`;
},
fixed: 'right'
}
];
export default {
components: { TargetGroup },
data() {
return {
gameStatus: {
0: '未开始',
1: '进行中',
2: '已结束',
3: '已终止'
},
gameStatusClass: {
0: 'dm-status--info',
1: 'dm-status--primary--flash',
2: 'dm-status--info',
3: 'dm-status--error'
},
baseData: {},
dimension: '1',
// type number:数字、time:时间、amount:金额、rate:百分比
originActivityData: [
[
{
label: '浏览人数',
value: '',
key: 'browseCnt',
type: 'number'
},
{
label: '参与人数',
value: '',
key: 'palyCnt',
type: 'number'
}
],
[
{
label: '中奖人数',
value: '',
key: 'winCnt',
type: 'number'
},
{
label: '中奖率',
tips: '中奖人数/参与人数',
value: '',
key: 'winRate',
type: 'rate'
}
],
[
{
label: '分享人数',
value: '',
key: 'shareCnt',
type: 'number'
},
{
label: '新增会员',
value: '',
key: 'openCardCnt',
type: 'number'
}
],
[
{
label: '总消耗积分',
value: '',
key: 'integralUseCnt',
type: 'number'
}
]
],
activityData: [],
originCardData: [
[
{
label: '订单总金额',
value: '',
tips: '订单实付金额',
key: 'orderAmount',
type: 'number'
},
{
label: '参与用户订单数',
value: '',
key: 'orderNum',
type: 'number'
}
],
[
{
label: '领取数量',
value: '',
key: 'receivedNum',
type: 'number'
},
{
label: '核销数量',
value: '',
key: 'writeOffNum',
type: 'number'
}
],
[
{
label: '核销人数',
value: '',
key: 'writeOffMNum',
type: 'number'
},
{
label: '新用户核销人数',
value: '',
key: 'newWriteOffMNum',
type: 'number'
}
],
[
{
label: '核销率',
value: '',
key: 'writeOffRate',
type: 'rate'
}
],
[
{
label: '客单价',
value: '',
key: 'perCustomerTransaction',
type: 'number'
},
{
label: '连带率',
value: '',
key: 'jointRate',
type: 'number'
}
]
],
cardData: [],
prizeList: [],
tableHeader: [],
gameId: this.$route.params.id
};
},
mounted() {
const gameId = this.$route.params.id;
this.getGameOverview(gameId);
this.getGameCardWriteOff(gameId);
this.getGameDetail(gameId);
this.getGamePrize(1);
},
computed: {},
methods: {
toDetailPage(type) {
console.log(type);
if (type == 1) {
this.$router.push(`/game/cmh/statistics/activityDetail/${this.gameId}`);
} else {
this.$router.push(`/game/cmh/statistics/prizeDetail/${this.gameId}`);
}
},
radioChange(data) {
console.log(data);
this.getGamePrize(data);
},
getGameOverview(gameId) {
getGameOverview({ gameId }).then(res => {
const { result } = res;
this.activityData = this.handleData(this.originActivityData, result || {});
});
},
getGameCardWriteOff(gameId) {
getGameCardWriteOff({ gameId }).then(res => {
const { result } = res;
this.cardData = this.handleData(this.originCardData, result || {});
});
},
getGameDetail(gameId) {
getGameDetail({ gameId }).then(res => {
const {
result: { startDate, endDate, gameName, status }
} = res;
let startDateStr = formatDateTimeByType(startDate, 'yyyy-MM-dd');
let endDateStr = formatDateTimeByType(endDate, 'yyyy-MM-dd');
let gameTimeStr = startDateStr + ' 至 ' + endDateStr;
this.baseData = { gameTimeStr, gameName, status };
});
},
getGamePrize(prizeType) {
if (prizeType == 1) {
this.tableHeader = tableHead;
} else {
this.tableHeader = pointHead;
}
getGamePrize({ gameId: this.$route.params.id, prizeType }).then(res => {
const { result } = res;
this.prizeList = result;
});
},
handleData(data, obj) {
return data
.map(el => {
return el.filter(item => {
const value = obj[item.key];
switch (item.type) {
case 'number':
item.value = numFormat(value);
break;
case 'time':
item.value = '--';
if (typeof value == 'number') {
const h = Math.floor(value / 3600)
.toString()
.padStart(2, '0');
const m = Math.floor((value % 3600) / 60)
.toString()
.padStart(2, '0');
const s = (value % 60).toString().padStart(2, '0');
item.value = `${h}:${m}:${s}`;
}
break;
case 'amount':
item.value = numFormat(value);
break;
case 'rate':
item.value = !isNaN(value) ? value + '%' : '- -';
break;
}
return true;
// 活动不发送挂机短信时,数据指标不展示短信发送总数和发送成功数的字段
// 活动未开启活动分析时,数据指标展示活动费用
// return !((this.aiDataShow.smsFlag == 0 && item.key == 'sentMessagesNumber') || (this.aiDataShow.smsFlag == 0 && item.key == 'sentSuccessfullyNumber') || (this.aiDataShow.analyseFlag != 0 && item.key == 'activityCost'));
});
})
.filter(el => el.length > 0);
}
}
};
</script>
<style lang="scss" scoped>
.statistics {
background-color: #f7f8fa;
.report-module {
padding: 16px 20px 20px 20px;
background-color: #fff;
+ .report-module {
margin-top: 16px;
}
.title-tip {
margin-left: 4px;
font-size: 12px;
font-weight: 400;
color: #606266;
line-height: 17px;
}
.check-detail {
margin-left: 16px;
color: #2f54eb;
background: #ebeffe;
border: none;
&:hover {
background: #dee3fc;
}
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment