Commit 6360b553 by 无尘

feat: 增加页面

parent 33c5df0d
......@@ -13,6 +13,7 @@
"version": "conventional-changelog -p angular -i changelog.md -s -r 0 && git add changelog.md"
},
"dependencies": {
"clipboard": "^2.0.4",
"echarts": "^4.4.0",
"element-ui": "^2.12.0",
"file-saver": "^1.3.8",
......
/*
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-12 10:18:29
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 15:16:11
*/
/**
* 判断字符长度
* @param: str
*/
export default {
/*
/**
* 一个汉字算两个字符,一个英文字母或数字算一个字符
*/
getByteLen: function(val) {
getByteLen: function (val) {
let valStr = val == '' || val == null ? '' : val;
let len = 0;
for (let i = 0; i < val.length; i++) {
let a = val.charAt(i);
for (let i = 0; i < valStr.length; i++) {
let a = valStr.charAt(i);
if (a.match(/[^\x00-\xff]/gi) != null) {
len += 2;
} else {
......@@ -19,13 +28,14 @@ export default {
}
return len;
},
/*
/**
* 一个汉字算一个字,一个英文字母或数字算半个字
*/
getZhLen: function(val) {
getZhLen: function (val) {
let valStr = val == '' || val == null ? '' : val;
let len = 0;
for (let i = 0; i < val.length; i++) {
let a = val.charAt(i);
for (let i = 0; i < valStr.length; i++) {
let a = valStr.charAt(i);
if (a.match(/[^\x00-\xff]/gi) != null) {
len += 1;
} else {
......@@ -36,7 +46,7 @@ export default {
},
/*暂无用*/
cutStr: function(str, len, type) {
cutStr: function (str, len, type) {
let char_length = 0;
for (let i = 0; i < str.length; i++) {
let son_str = str.charAt(i);
......@@ -53,40 +63,42 @@ export default {
}
},
/*
/**
* 限制字数用, 一个汉字算一个字,两个英文/字母算一个字
*/
getByteVal: function(val, max) {
getByteVal: function (val, max) {
let valStr = val == '' || val == null ? '' : val;
let returnValue = '';
let byteValLen = 0;
for (let i = 0; i < val.length; i++) {
if (val[i].match(/[^\x00-\xff]/gi) != null) byteValLen += 1;
for (let i = 0; i < valStr.length; i++) {
if (valStr[i].match(/[^\x00-\xff]/gi) != null) byteValLen += 1;
else byteValLen += 0.5;
if (byteValLen > max) break;
returnValue += val[i];
returnValue += valStr[i];
}
return returnValue;
},
/*
/**
* 限制字符数用, 一个汉字算两个字符,一个英文/字母算一个字符
*/
getCharVal: function(val, max) {
getCharVal: function (val, max) {
let valStr = val == '' || val == null ? '' : val;
let returnValue = '';
let byteValLen = 0;
for (let i = 0; i < val.length; i++) {
if (val[i].match(/[^\x00-\xff]/gi) != null) byteValLen += 2;
for (let i = 0; i < valStr.length; i++) {
if (valStr[i].match(/[^\x00-\xff]/gi) != null) byteValLen += 2;
else byteValLen += 1;
if (byteValLen > max) break;
returnValue += val[i];
returnValue += valStr[i];
}
return returnValue;
},
/*
/**
* 正则校验,校验非负数字
*/
regPos: function(v) {
regPos: function (v) {
let regTest = /^\d+(\.\d+)?$/;
return regTest.test(v);
}
......
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 14:20:50
-->
<!--
<active-step :activeStep="activeStep" :stepData="stepData" ></active-step>
import activeStep from '@/components/active-config/active-step.vue';
-->
<template>
<div class="active-step-content font-0">
<div
:class="['active-step-cell inline-block border-box', index + 1 == activeStep ? 'active-step' : '', item.hasSet ? 'active-hasset': '']"
v-for="(item, index) in stepData"
:key="index + item.stepName"
:style="{ width: 100 / stepData.length + '%', 'max-width': 100 / stepData.length + '%' }"
>
<div class="active-step-cell_inner border-box">
<div
v-if="index < stepData.length - 1"
class="active-step-cell_line"
></div>
<div class="active-step-cell_title">
<div class="el-step__icon is-text inline-block text-center">
<i
v-if="item.hasSet"
class="el-icon-check font-14 color-1890ff flex flex-pack-center flex-align-center"
></i>
<div
v-else
class="el-step__icon-inner font-14 flex flex-pack-center flex-align-center"
>{{ index + 1 }}</div>
</div>
<div class="active-step-cell_txt p-lr-10 bg-fff inline-block font-16">{{ item.stepName }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'active-step',
props: {
activeStep: {
type: [Number, String],
default() {
return 1;
}
},
stepData: {
type: [Array, Object],
default() {
return []
}
}
},
data() {
return {
/* activeStep: 1,
stepData: [
{
stepName: '基础信息',
hasSet: false
},
{
stepName: '前端配置',
hasSet: false
},
{
stepName: '后端配置',
hasSet: false
},
{
stepName: '定义返回',
hasSet: false
}
], */
}
},
methods: {
},
}
</script>
<style lang="less" scoped>
.active-step-content {
.active-step-cell {
padding: 0 10px;
.bg-fff {
background: #fff;
}
.active-step-cell_inner {
position: relative;
width: 100%;
padding-right: 10px;
.active-step-cell_line {
position: absolute;
height: 1px;
top: 11px;
left: 0;
right: 0;
background: #c0c4cc;
z-index: 0;
}
.active-step-cell_title {
position: relative;
z-index: 1;
.el-step__icon {
border: 1px solid #c0c4cc;
color: #c0c4cc;
.el-step__icon-inner {
width: 22px;
height: 23px;
}
}
.active-step-cell_txt {
position: relative;
z-index: 1;
color: #909399;
}
}
}
&.active-step {
.active-step-cell_inner {
.active-step-cell_line {
background: #1890ff;
}
.active-step-cell_title {
.el-step__icon {
color: #fff;
border-color: #1890ff;
background: #1890ff;
}
.active-step-cell_txt {
color: #303133;
}
}
}
}
&.active-hasset {
.active-step-cell_inner {
.active-step-cell_line {
background: #1890ff;
}
.active-step-cell_title {
.el-step__icon {
color: #fff;
border-color: #1890ff;
background: #1890ff;
}
.el-icon-check {
width: 98%;
height: 98%;
color: #1890ff;
background: #fff;
border-radius: 50%;
}
.active-step-cell_txt {
color: #606266;
}
}
}
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 15:56:59
-->
<!--
<base-config @submitNext="submitNext"></base-config>
import baseConfig from '@/components/active-config/base-config.vue';
-->
<template>
<div class="base-config-content">
<div class="config-title font-14 color-303133">基本信息</div>
<el-form
label-width="114px"
:model="activeInfoData"
ref="baseForm"
:rules="rules"
>
<el-form-item
label="活动名称:"
prop="activeName"
>
<limitInput
:inputWidth="350"
:disflag="$route.query.interfaceId ? true : false"
:inputValue.sync="activeInfoData.activeName"
:holder="'请输入活动名称'"
:getByType="'word'"
:maxLength="30"
> </limitInput>
</el-form-item>
<el-form-item
label="活动有效期:"
prop="dateRange"
>
<el-date-picker
class="m-l-10"
prefix-icon="el-icon-time"
v-model="activeInfoData.dateRange"
@change="changeDate"
:editable="false"
:value-format="'yyyy-MM-dd'"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
> </el-date-picker>
</el-form-item>
<el-form-item class="m-t-50">
<el-button
type="primary"
@click="returnBack"
>返回</el-button>
<el-button
type="primary"
@click="submitForm('baseForm')"
>下一步</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import limitInput from '@/components/limit-input.vue';
export default {
name: 'base-config',
props: {
},
components: {
limitInput
},
data() {
return {
activeInfoData: {
activeName: '',
dateRange: []
},
rules: {
activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
dateRange: [{ required: true, message: '请选择活动有效期', trigger: 'blur' }]
}
}
},
methods: {
/**
* 日期
*/
changeDate(e) {
const that = this;
if (!e) {
that.activeInfoData.dateRange = [];
}
},
/**
* 返回
*/
returnBack() {
this.$router.go(-1);
},
/**
* 下一步
*/
submitForm(formName) {
const that = this;
that.$refs[formName].validate(valid => {
if (valid) {
that.$emit('submitNext', that.activeInfoData);
that.$store.dispatch('saveBaseInfo', that.activeInfoData);
} else {
return false;
}
});
}
},
}
</script>
<style lang="less" scoped>
.base-config-content {
padding: 48px 0 0 0;
.config-title {
font-weight: 600;
margin-bottom: 30px;
}
.m-t-50 {
margin-top: 50px;
}
.el-form-item {
/deep/ .el-form-item__label {
color: #606266;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:13:41
-->
<!--
<card-config @submitBack="submitBack" @submitNext="submitNext"></card-config>
import cardConfig from '@/components/active-config/card-config.vue';
-->
<template>
<div class="card-config-content">
<div class="config-title font-14 color-303133">小程序卡片配置</div>
<el-form
label-width="114px"
:model="activeInfoData"
ref="cardForm"
:rules="rules"
>
<el-form-item
label="活动名称:"
prop="activeName"
>
<limitInput
:inputWidth="350"
:disflag="$route.query.interfaceId ? true : false"
:inputValue.sync="activeInfoData.activeName"
:holder="'请输入活动名称'"
:getByType="'word'"
:maxLength="30"
> </limitInput>
</el-form-item>
<el-form-item
label="活动有效期:"
prop="dateRange"
>
<el-date-picker
class="m-l-10"
prefix-icon="el-icon-time"
v-model="activeInfoData.dateRange"
@change="changeDate"
:editable="false"
:value-format="'yyyy-MM-dd'"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
> </el-date-picker>
</el-form-item>
<el-form-item class="m-t-50">
<el-button
type="primary"
@click="submitBack"
>上一步</el-button>
<el-button
type="primary"
@click="submitForm('cardForm')"
>下一步</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import limitInput from '@/components/limit-input.vue';
export default {
name: 'card-config',
props: {
},
components: {
limitInput
},
data() {
return {
activeInfoData: {
activeName: '',
dateRange: []
},
rules: {
activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
dateRange: [{ required: true, message: '请选择活动有效期', trigger: 'blur' }]
}
}
},
methods: {
/**
* 日期
*/
changeDate(e) {
const that = this;
if (!e) {
that.activeInfoData.dateRange = [];
}
},
/**
* 上一步
*/
submitBack() {
const that = this;
that.$emit('submitBack');
},
/**
* 下一步
*/
submitForm(formName) {
const that = this;
that.$refs[formName].validate(valid => {
if (valid) {
that.$emit('submitNext', that.activeInfoData);
that.$store.dispatch('saveCardInfo', that.activeInfoData);
} else {
return false;
}
});
}
},
}
</script>
<style lang="less" scoped>
.card-config-content {
padding: 48px 0 0 0;
.config-title {
font-weight: 600;
margin-bottom: 30px;
}
.m-t-50 {
margin-top: 50px;
}
.el-form-item {
/deep/ .el-form-item__label {
color: #606266;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:13:33
-->
<!--
<center-config @submitBack="submitBack" @submitNext="submitNext"></center-config>
import centerConfig from '@/components/active-config/center-config.vue';
-->
<template>
<div class="center-config-content">
<div class="config-title font-14 color-303133">活动中心配置</div>
<el-form
label-width="114px"
:model="activeInfoData"
ref="centerForm"
:rules="rules"
>
<el-form-item
label="活动名称:"
prop="activeName"
>
<limitInput
:inputWidth="350"
:disflag="$route.query.interfaceId ? true : false"
:inputValue.sync="activeInfoData.activeName"
:holder="'请输入活动名称'"
:getByType="'word'"
:maxLength="30"
> </limitInput>
</el-form-item>
<el-form-item
label="活动有效期:"
prop="dateRange"
>
<el-date-picker
class="m-l-10"
prefix-icon="el-icon-time"
v-model="activeInfoData.dateRange"
@change="changeDate"
:editable="false"
:value-format="'yyyy-MM-dd'"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
> </el-date-picker>
</el-form-item>
<el-form-item class="m-t-50">
<el-button
type="primary"
@click="submitBack"
>上一步</el-button>
<el-button
type="primary"
@click="submitForm('centerForm')"
>下一步</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import limitInput from '@/components/limit-input.vue';
export default {
name: 'center-config',
props: {
},
components: {
limitInput
},
data() {
return {
activeInfoData: {
activeName: '',
dateRange: []
},
rules: {
activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
dateRange: [{ required: true, message: '请选择活动有效期', trigger: 'blur' }]
}
}
},
methods: {
/**
* 日期
*/
changeDate(e) {
const that = this;
if (!e) {
that.activeInfoData.dateRange = [];
}
},
/**
* 上一步
*/
submitBack() {
const that = this;
that.$emit('submitBack');
},
/**
* 下一步
*/
submitForm(formName) {
const that = this;
that.$refs[formName].validate(valid => {
if (valid) {
that.$emit('submitNext', that.activeInfoData);
that.$store.dispatch('saveCenterInfo', that.activeInfoData);
} else {
return false;
}
});
}
},
}
</script>
<style lang="less" scoped>
.center-config-content {
padding: 48px 0 0 0;
.config-title {
font-weight: 600;
margin-bottom: 30px;
}
.m-t-50 {
margin-top: 50px;
}
.el-form-item {
/deep/ .el-form-item__label {
color: #606266;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:11:30
-->
<!--
<poster-config @submitBack="submitBack" @submitNext="submitNext"></poster-config>
import posterConfig from '@/components/active-config/poster-config.vue';
-->
<template>
<div class="poster-config-content">
<div class="config-title font-14 color-303133">分享海报配置</div>
<el-form
label-width="114px"
:model="activeInfoData"
ref="posterForm"
:rules="rules"
>
<el-form-item
label="活动名称:"
prop="activeName"
>
<limitInput
:inputWidth="350"
:disflag="$route.query.interfaceId ? true : false"
:inputValue.sync="activeInfoData.activeName"
:holder="'请输入活动名称'"
:getByType="'word'"
:maxLength="30"
> </limitInput>
</el-form-item>
<el-form-item
label="活动有效期:"
prop="dateRange"
>
<el-date-picker
class="m-l-10"
prefix-icon="el-icon-time"
v-model="activeInfoData.dateRange"
@change="changeDate"
:editable="false"
:value-format="'yyyy-MM-dd'"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
> </el-date-picker>
</el-form-item>
<el-form-item class="m-t-50">
<el-button
type="primary"
@click="submitBack"
>上一步</el-button>
<el-button
type="primary"
@click="submitForm('posterForm')"
>下一步</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import limitInput from '@/components/limit-input.vue';
export default {
name: 'poster-config',
props: {
},
components: {
limitInput
},
data() {
return {
activeInfoData: {
activeName: '',
dateRange: []
},
rules: {
activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
dateRange: [{ required: true, message: '请选择活动有效期', trigger: 'blur' }]
}
}
},
methods: {
/**
* 日期
*/
changeDate(e) {
const that = this;
if (!e) {
that.activeInfoData.dateRange = [];
}
},
/**
* 上一步
*/
submitBack() {
const that = this;
that.$emit('submitBack');
},
/**
* 下一步
*/
submitForm(formName) {
const that = this;
that.$refs[formName].validate(valid => {
if (valid) {
that.$emit('submitNext', that.activeInfoData);
that.$store.dispatch('savePosterInfo', that.activeInfoData);
} else {
return false;
}
});
}
},
}
</script>
<style lang="less" scoped>
.poster-config-content {
padding: 48px 0 0 0;
.config-title {
font-weight: 600;
margin-bottom: 30px;
}
.m-t-50 {
margin-top: 50px;
}
.el-form-item {
/deep/ .el-form-item__label {
color: #606266;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-18 10:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:17:10
-->
<!--
<reward-config @submitBack="submitBack" @submitNext="submitNext"></reward-config>
import rewardConfig from '@/components/active-config/reward-config.vue';
-->
<template>
<div class="reward-config-content">
<div class="config-title font-14 color-303133">奖励配置</div>
<el-form
label-width="114px"
:model="activeInfoData"
ref="rewardForm"
:rules="rules"
>
<el-form-item
label="活动名称:"
prop="activeName"
>
<limitInput
:inputWidth="350"
:disflag="$route.query.interfaceId ? true : false"
:inputValue.sync="activeInfoData.activeName"
:holder="'请输入活动名称'"
:getByType="'word'"
:maxLength="30"
> </limitInput>
</el-form-item>
<el-form-item
label="活动有效期:"
prop="dateRange"
>
<el-date-picker
class="m-l-10"
prefix-icon="el-icon-time"
v-model="activeInfoData.dateRange"
@change="changeDate"
:editable="false"
:value-format="'yyyy-MM-dd'"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
> </el-date-picker>
</el-form-item>
<el-form-item class="m-t-50">
<el-button
type="primary"
@click="submitBack"
>上一步</el-button>
<el-button
type="primary"
@click="submitForm('rewardForm')"
>确认新建</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import limitInput from '@/components/limit-input.vue';
import { _debounce } from '@/common/js/public';
export default {
name: 'reward-config',
props: {
},
components: {
limitInput
},
data() {
return {
activeInfoData: {
activeName: '',
dateRange: []
},
rules: {
activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
dateRange: [{ required: true, message: '请选择活动有效期', trigger: 'blur' }]
}
}
},
methods: {
/**
* 日期
*/
changeDate(e) {
const that = this;
if (!e) {
that.activeInfoData.dateRange = [];
}
},
/**
* 上一步
*/
submitBack() {
const that = this;
that.$store.dispatch('saveRewardInfo', that.activeInfoData);
that.$emit('submitBack');
},
/**
* 下一步
*/
submitForm: _debounce(function(formName) {
const that = this;
that.$refs[formName].validate(valid => {
if (valid) {
that.$store.dispatch('clearActiveData');
} else {
return false;
}
});
},500),
}
}
</script>
<style lang="less" scoped>
.reward-config-content {
padding: 48px 0 0 0;
.config-title {
font-weight: 600;
margin-bottom: 30px;
}
.m-t-50 {
margin-top: 50px;
}
.el-form-item {
/deep/ .el-form-item__label {
color: #606266;
}
}
}
</style>
......@@ -18,30 +18,24 @@ import dataStatisticsChild from '@/components/active/data-statistics-child.vue';
<div class="data-statistics-left">
<ul class="flex flex-column flex-pack-center flex-align-center">
<li class="flex-1 flex flex-pack-center flex-align-center">
<div class="data-statistics-icon"><img
src=""
alt=""
></div>
<div class="data-statistics-icon"><img src="" alt="" /></div>
<div class="data-statistics-txt flex flex-column">
<div class="font-14 color-606266">活动曝光量</div>
<div class="font-22 color-303133 p-t-10">287,123</div>
</div>
</li>
<li class="flex-1 flex flex-pack-center flex-align-center">
<div class="data-statistics-icon"><img
src=""
alt=""
></div>
<div class="data-statistics-icon"><img src="" alt="" /></div>
<div class="data-statistics-txt flex flex-column">
<div class="font-14 color-606266">参与人数</div>
<div class="font-22 color-303133 p-t-10">287,123</div>
</div>
</li>
<li class="flex-1 flex flex-pack-center flex-align-center">
<div class="data-statistics-icon"><img
src=""
alt=""
></div>
<div class="data-statistics-icon"><img src="" alt="" /></div>
<div class="data-statistics-txt flex flex-column">
<div class="font-14 color-606266">受邀人数</div>
<div class="font-22 color-303133 p-t-10">287,123</div>
......@@ -51,31 +45,24 @@ import dataStatisticsChild from '@/components/active/data-statistics-child.vue';
</div>
<div class="data-right-wrap">
<div class="data-right-top flex">
<div class="data-statistics-middle border-box m-l-20">
<div class="data-statistics-middle flex-1 border-box m-l-20">
<div class="font-14 color-606266">参与率</div>
<div class="font-22 color-303133 p-t-5">70%</div>
<div class="data-percentage">
<div
class="data-percentage-inner"
:style="{'width': '70%'}"
></div>
<div class="data-percentage-inner" :style="{ width: '70%' }"></div>
</div>
</div>
<div class="data-statistics-right border-box m-l-20">
<div class="data-statistics-right flex-1 border-box m-l-20">
<div class="font-14 color-606266">传播系数</div>
<div class="font-22 color-303133 p-t-5">4.0</div>
</div>
</div>
<div class="data-right-bottom">
<bar-chart
:barChartData="barChartData"
:charHeight="charHeight"
></bar-chart>
<bar-chart :barChartData="barChartData" :charHeight="charHeight"></bar-chart>
</div>
<!--<div class="chart-title font-12 color-000 text-center">- 近15天趋势图 -</div>-->
</div>
</div>
</div>
</template>
<script>
......@@ -86,13 +73,12 @@ export default {
barChartData: {
type: [Array, Object],
default() {
return {}
return {};
}
}
},
components: { barChart },
data() {
return {
charHeight: '220px'
};
......@@ -130,6 +116,7 @@ export default {
}
.data-right-wrap {
width: 100%;
.data-right-bottom {
margin-top: 40px;
}
......@@ -141,7 +128,7 @@ export default {
.data-statistics-middle {
position: relative;
min-width: 216px;
height: 90px;
height: 85px;
background: #f3f6f9;
padding: 10px 20px 0 20px;
.data-percentage {
......@@ -160,7 +147,7 @@ export default {
.data-statistics-right {
position: relative;
min-width: 216px;
height: 90px;
height: 85px;
padding: 10px 20px 0 20px;
background: #f3f6f9;
}
......
......@@ -4,7 +4,7 @@
* @Author: 无尘
* @Date: 2019-11-13 16:37:02
* @LastEditors: 无尘
* @LastEditTime: 2019-11-14 14:30:20
* @LastEditTime: 2019-11-15 16:15:50
-->
<!--
<funnel-chart :funnelData="funnelData"></funnel-chart>
......@@ -15,7 +15,7 @@ import funnelChart from '@/components/active/funnel-chart.vue';
<template>
<div class="funnel-chart">
<div class="funnel-chart-body">
<div class="funnel-chart-body flex">
<div class="chart-left">
<div class="trapezoid-bg">
<div class="space-line h-20 r-60"></div>
......@@ -64,7 +64,10 @@ export default {
<style lang="less" scoped>
.funnel-chart {
width: 595px;
min-width: 595px;
height: 346px;
padding: 40px 0 0 52px;
margin-left: 38px;
background: rgba(245, 247, 250, 1);
&::after {
overflow: hidden;
......@@ -160,7 +163,7 @@ export default {
position: relative;
width: 216px;
height: 269px;
float: left;
// float: left;
.trapezoid-bg {
position: relative;
width: 216px;
......@@ -196,13 +199,13 @@ export default {
top: 50%;
right: -36%;
width: 81px;
height: 2px;
height: 1px;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
// border-top: 1px solid #dcdfe6;
// border-bottom: 1px solid #dcdfe6;
background: #dcdfe6;
border-bottom: 1px solid #dcdfe6;
// background: #dcdfe6;
z-index: 1;
}
&.r-60 {
......@@ -236,7 +239,7 @@ export default {
.chart-right {
position: relative;
width: 327px;
float: left;
// float: left;
.chart-text {
position: relative;
width: 327px;
......
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:46:16
-->
<!--
<out-date-active :barChartData="barChartData" :funnelData="funnelData"></out-date-active>
import outDateActive from '@/components/active/out-date-active.vue';
-->
<template>
<div class="out-date-active flex flex-space-between">
<data-statistics-child :barChartData="barChartData"></data-statistics-child>
<funnel-chart :funnelData="funnelData"></funnel-chart>
</div>
</template>
<script>
import dataStatisticsChild from '@/components/active/data-statistics-child.vue';
import funnelChart from '@/components/active/funnel-chart.vue';
export default {
name: 'card-table',
props: {
barChartData: {
type: [Array, Object],
default() {
return {}
}
},
funnelData: {
type: [Array, Object],
default() {
return {}
}
}
},
components: {
funnelChart,
dataStatisticsChild
},
data() {
return {
}
},
methods: {
},
}
</script>
<style lang="less" scoped>
.out-date-active {
width: 100%;
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:46:16
-->
<!--
<card-log></card-log>
import cardLog from '@/components/data-details/card-log.vue';
-->
<template>
<div class="card-log">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%', minHeight: tableH }"
>
<el-table-column
prop=""
label="奖励时间"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="奖励来源"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
label="受邀人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="奖励内容"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
</el-table>
<div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div>
</div>
</template>
<script>
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'card-log',
data() {
return {
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.card-log {
width: 100%;
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:46:16
-->
<!--
<invite-log></invite-log>
import inviteLog from '@/components/data-details/invite-log.vue';
-->
<template>
<div class="invite-log">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%', minHeight: tableH }"
>
<el-table-column
label="受邀人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="受邀时间"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="转化进度"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
</el-table>
<div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div>
</div>
</template>
<script>
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'invite-log',
data() {
return {
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.invite-log {
width: 100%;
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:46:16
-->
<!--
<invite-table></invite-table>
import inviteTable from '@/components/data-details/invite-table.vue';
-->
<template>
<div class="invite-table">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%'}"
>
<el-table-column
label="邀请人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="参与时间"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="邀请人数"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="积分收益"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.code || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="卡券收益"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.messageCount }}</template>
</el-table-column>
</el-table>
<div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div>
</div>
</template>
<script>
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'invite-table',
data() {
return {
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.invite-table {
width: 100%;
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:45:16
-->
<!--
<invited-table :funnelData="funnelData"></invited-table>
import invitedTable from '@/components/data-details/invited-table.vue';
-->
<template>
<div class="invited-table">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%'}"
>
<el-table-column
label="受邀人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="受邀时间"
show-overflow-tooltip
sortable
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
label="邀请人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="转化进度"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
</el-table>
<div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div>
</div>
</template>
<script>
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'invited-table',
data() {
return {
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.invited-table {
width: 100%;
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 11:46:16
-->
<!--
<point-log></point-log>
import pointLog from '@/components/data-details/point-log.vue';
-->
<template>
<div class="point-log">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%', minHeight: tableH }"
>
<el-table-column
prop=""
label="奖励时间"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="奖励来源"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
<el-table-column
label="受邀人信息"
show-overflow-tooltip
>
<template slot-scope="scope">
<div class="cell">
<img
src=""
alt=""
/>><span class="font-14 color-606266">{{ scope.row.name || '--' }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="奖励额度"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
</el-table>
<div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div>
</div>
</template>
<script>
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'point-log',
data() {
return {
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.point-log {
width: 100%;
}
</style>
<!--
限制输入框组件
<limitInput
:inputWidth="500"
:limitClass="'limit-color'"
:disflag='!childItem.fieldEdited'
:inputValue.sync="ruleForm.addressDetail"
:holder="'请输入详细地址'"
:getByType="'word'"
:maxLength="40">
</limitInput>
-->
<template>
<div
:class="['input-line-cell', limitClass]"
:style="{ width: inputWidth + 'px' }"
>
<el-input
:style="{ width: inputWidth + 'px' }"
v-model="itemValue"
:disabled="disflag"
:placeholder="holder"
@blur="inputBlur()"
@focus="inputFocus()"
@keyup.native="value => toInput(value)"
> </el-input>
<span class="tip"><span class="len_span">{{ inputNum }}</span>/{{ limitLength }}</span>
</div>
</template>
<script>
import strLength from '@/common/js/strlen';
export default {
name: 'limitinput',
props: {
// 传入 input value
inputValue: {
type: [String, Number],
default() {
return '';
}
},
// 限制长度
maxLength: {
type: Number,
default: 10
},
// input 长度
inputWidth: {
type: Number,
default: 500
},
// 字或字符判断类型
getByType: {
type: String,
default: 'word' // word: 字, char: 字符
},
holder: {
type: String,
default: '请输入'
},
disflag: {
type: Boolean,
default: false
},
limitClass: {
type: String,
default: ''
}
},
data() {
return {
inputNum: 0,
limitLength: 10,
itemValue: ''
};
},
methods: {
/* eslint-disable */
inputFocus(num) {},
// 输入
toInput: function(value) {
const that = this;
let temp = '';
if (that.getByType == 'word') {
temp = strLength.getByteVal(value.target.value, that.limitLength);
that.itemValue = temp.trim();
that.inputNum = strLength.getZhLen(that.itemValue);
} else {
temp = strLength.getCharVal(value.target.value, that.limitLength);
that.itemValue = temp.trim();
that.inputNum = strLength.getByteLen(that.itemValue);
}
that.$emit('update:inputValue', that.itemValue);
},
inputBlur() {
const that = this;
that.$emit('update:inputValue', that.itemValue);
}
},
watch: {
maxLength: function(newData, oldData) {
const that = this;
that.limitLength = newData;
},
inputValue: function(newData, oldData) {
let that = this;
that.itemValue = newData || '';
if (that.getByType == 'word') {
that.inputNum = strLength.getZhLen(that.itemValue);
} else {
that.inputNum = strLength.getByteLen(that.itemValue);
}
}
},
/* 接收数据 */
mounted() {
let that = this;
that.limitLength = that.maxLength;
that.itemValue = that.inputValue || '';
if (that.getByType == 'word') {
that.inputNum = strLength.getZhLen(that.inputValue);
} else {
that.inputNum = strLength.getByteLen(that.inputValue);
}
}
};
</script>
<style lang="less" scoped>
.input-line-cell {
position: relative;
display: inline-block;
&.limit-color {
.tip {
color: rgba(255, 255, 255, 0.7);
}
}
}
.w-340 {
width: 340px;
/deep/ .el-input__inner {
font-size: 14px;
color: #fff;
background-color: rgba(255, 255, 255, 0.1);
}
}
.el-input {
/deep/ .el-input__inner {
font-size: 14px;
color: #606266;
background-color: rgba(255, 255, 255, 0.1);
}
&.is-disabled {
opacity: 0.5;
}
.is-disabled {
/deep/ .el-input__inner {
font-size: 14px;
color: #fff;
background-color: rgba(255, 255, 255, 0.1);
}
}
}
.tip {
position: absolute;
top: 2px;
right: 10px;
display: inline-block;
line-height: 32px;
text-align: right;
font-size: 12px;
color: #c0c4cc;
}
</style>
<!--
限制文本框组件
<limit-textarea
:inputWidth="500"
:inputValue.sync="ruleForm.addressDetail"
:holder="'请输入详细地址'"
:getByType="'word'"
:disInput=""
:maxLength="40">
</limit-textarea>
-->
<template>
<div
class="input-line-cell"
:style="{ width: inputWidth + 'px' }"
>
<el-input
:style="{ width: inputWidth + 'px' }"
v-model="itemValue"
:placeholder="holder"
type="textarea"
:rows="3"
:disabled="disInput"
@blur="inputBlur()"
@focus="inputFocus()"
@keyup.native="value => toInput(value)"
> </el-input>
<span class="tip"><span class="len_span">{{ inputNum }}</span>/{{ limitLength }}</span>
</div>
</template>
<script>
import strLength from '@/common/js/strlen';
export default {
name: 'limittextarea',
props: {
inputValue: {
// 传入 input value
type: String,
default: ''
},
maxLength: {
// 限制长度
type: Number,
default: 10
},
inputWidth: {
// input 长度
type: Number,
default: 500
},
getByType: {
// 字或字符判断类型
type: String,
default: 'word' // word: 字, char: 字符
},
holder: {
type: String,
default: '请输入'
},
disInput: {
type: Boolean,
default: false
}
},
data() {
return {
inputNum: 0,
limitLength: 10,
itemValue: ''
};
},
methods: {
/* eslint-disable */
inputFocus(num) {},
// 输入
toInput: function(value) {
const that = this;
let temp = '';
if (that.getByType == 'word') {
temp = strLength.getByteVal(value.target.value, that.limitLength);
that.itemValue = temp.trim();
that.inputNum = strLength.getZhLen(that.itemValue);
} else {
temp = strLength.getCharVal(value.target.value, that.limitLength);
that.itemValue = temp.trim();
that.inputNum = strLength.getByteLen(that.itemValue);
}
that.$emit('update:inputValue', that.itemValue);
},
inputBlur() {
const that = this;
that.$emit('update:inputValue', that.itemValue);
}
},
watch: {
maxLength: function(newData, oldData) {
const that = this;
that.limitLength = newData;
},
inputValue: function(newData, oldData) {
const that = this;
that.itemValue = newData;
if (that.getByType == 'word') {
that.inputNum = strLength.getZhLen(that.itemValue);
}else {
that.inputNum = strLength.getByteLen(that.itemValue);
}
}
},
/* 接收数据 */
mounted() {
const that = this;
that.limitLength = that.maxLength;
that.itemValue = that.inputValue || '';
if (that.getByType == 'word') {
that.inputNum = strLength.getZhLen(that.inputValue);
}else {
that.inputNum = strLength.getByteLen(that.inputValue);
}
}
};
</script>
<style lang="less" scoped>
.input-line-cell {
position: relative;
display: inline-block;
}
.w-340 {
width: 340px;
/deep/ .el-input__inner {
font-size: 14px;
color: #fff;
background-color: rgba(255, 255, 255, 0.1);
}
}
.el-textarea {
/deep/ .el-textarea__inner {
font-size: 14px;
color: #606266;
background-color: rgba(255, 255, 255, 0.1);
resize: none;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '\5FAE\8F6F\96C5\9ED1', Arial, sans-serif;
}
&.is-disabled {
opacity: 0.5;
}
}
.el-input {
.is-disabled {
/deep/ .el-input__inner {
font-size: 14px;
color: #fff;
background-color: rgba(255, 255, 255, 0.1);
}
}
}
.tip {
position: absolute;
bottom: -4px;
right: 10px;
display: inline-block;
line-height: 32px;
text-align: right;
font-size: 12px;
color: #c0c4cc;
}
</style>
......@@ -4,7 +4,7 @@
* @Author: 无尘
* @Date: 2019-11-12 10:18:30
* @LastEditors: 无尘
* @LastEditTime: 2019-11-12 11:25:42
* @LastEditTime: 2019-11-18 11:23:30
*/
// import Vue from 'vue';
import Router from 'vue-router';
......@@ -32,45 +32,91 @@ const errorPage = r => {
});
};
export const constantRouterMap = [
{
path: '/',
name: 'index',
redirect: 'shareIndex',
component: _import('index', 'index'),
children: [
// 分享首页
{
path: '/shareIndex',
name: '分享首页',
component: _import('shareIndex', 'index'),
meta: {
title: '分享首页'
}
export const constantRouterMap = [{
path: '/',
name: 'index',
redirect: 'shareIndex',
component: _import('index', 'index'),
children: [
// 分享首页
{
path: '/shareIndex',
name: '分享首页',
component: _import('shareIndex', 'index'),
meta: {
title: '分享首页'
}
]
},
{
path: '/403',
name: '无权访问',
component: errorPage
},
{
path: '/404',
name: 'error404',
component: errorPage
},
{
path: '/500',
name: 'error500',
component: errorPage
},
{ path: '*', redirect: '/404', hidden: true }
},
{
path: '/createActive',
name: '创建完成',
component: _import('activeConfig', 'index'),
meta: {
title: '创建完成'
}
},
// 活动创建完成
{
path: '/createCompletion',
name: '创建完成',
component: _import('activeConfig', 'createCompletion'),
meta: {
title: '创建完成'
}
},
{
path: '/dataDetail',
name: '数据明细',
component: _import('dataDetails', 'index'),
meta: {
title: '数据明细'
}
},
{
path: '/inviterLog',
name: '邀请人日志',
component: _import('dataDetails', 'inviterLog'),
meta: {
title: '邀请人日志'
}
},
{
path: '/invitedLog',
name: '受邀人日志',
component: _import('dataDetails', 'invitedLog'),
meta: {
title: '受邀人日志'
}
},
]
},
{
path: '/403',
name: '无权访问',
component: errorPage
},
{
path: '/404',
name: 'error404',
component: errorPage
},
{
path: '/500',
name: 'error500',
component: errorPage
},
{
path: '*',
redirect: '/404',
hidden: true
}
];
export default new Router({
mode: 'history',
base: '/share-config/',
routes: constantRouterMap,
scrollBehavior: () => ({ y: 0 })
scrollBehavior: () => ({
y: 0
})
});
/*
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-12 10:18:30
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:16:49
*/
import Vuex from 'vuex';
import Vue from 'vue';
import * as types from './types';
......@@ -10,7 +18,13 @@ export default new Vuex.Store({
title: '',
show: false,
tagRealName: '',
uniqueId: ''
uniqueId: '',
baseInfo: {}, // 基础信息
centerInfo: {}, // 活动中心配置
cardInfo: {}, // 小程序卡片配置
posterInfo: {}, // 海报配置
rewardInfo: {}, // 奖励配置
tempBackData: [] // 后端判断禁用数据
},
mutations: {
[types.LOGIN]: (state, data) => {
......@@ -32,6 +46,48 @@ export default new Vuex.Store({
},
['changeUniqueId'](state, id) {
state.uniqueId = id || '';
},
saveBase: (state, data) => {
state.baseInfo = data;
},
saveCenter: (state, data) => {
state.centerInfo = data;
},
saveCard: (state, data) => {
state.cardInfo = data;
},
savePoster: (state, data) => {
state.posterInfo = data;
},
saveReward: (state, data) => {
state.rewardInfo = data;
},
clearData: state => {
state.baseInfo = {};
state.centerInfo = {};
state.cardInfo = {};
state.posterInfo = {};
state.rewardInfo = {};
}
},
actions: {
saveBaseInfo(context, data) {
context.commit('saveBase', data);
},
saveCenterInfo(context, data) {
context.commit('saveCenter', data);
},
saveCardInfo(context, data) {
context.commit('saveCard', data);
},
savePosterInfo(context, data) {
context.commit('savePoster', data);
},
saveRewardInfo(context, data) {
context.commit('saveReward', data);
},
clearActiveData(context, data) {
context.commit('clearData');
}
}
});
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 16:07:29
-->
<template>
<div class="create-completion common-wrap">
<nav-crumb :navpath="navpath"></nav-crumb>
<div class="right-content border-box">
<div class="right-box border-box">
<div class="create-completion-icon text-center">
<img
src=""
alt=""
>
</div>
<div class="create-completion-text font-16 color-606266 text-center">活动创建成功!</div>
<div class="create-completion-btn text-center">
<el-button
class="copy-tag"
@click="copyPath"
>复制活动路径</el-button>
<el-button
type="primary"
@click="toActiveList"
>返回活动列表</el-button>
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import navCrumb from '@/components/nav/nav.vue';
import Clipboard from 'clipboard';
import showMsg from '@/common/js/showmsg';
export default {
name: 'createCompletion',
components: {
navCrumb,
},
data() {
return {
// 面包屑参数
navpath: [
{
name: '分享有礼',
path: `/shareIndex`,
/*relocation: true */
},
{
name: '新建活动',
/*relocation: true */
},
],
}
},
methods: {
copyPath() {
let clipboard = new Clipboard('.copy-tag', {
text: function() {
return `${window.location.origin}`;
}
});
clipboard.on('success', e => {
showMsg.showmsg('复制成功!', 'success');
// 释放内存
clipboard.destroy();
});
clipboard.on('error', e => {
// 不支持复制
showMsg.showmsg('该浏览器不支持复制!', 'warning');
// 释放内存
clipboard.destroy();
});
},
toActiveList() {
this.$router.push(`/shareIndex`);
}
},
}
</script>
<style lang="less" scoped>
.create-completion {
width: 100%;
.create-completion-icon {
padding-top: 159px;
img {
width: 88px;
height: 88px;
}
}
.create-completion-text {
margin-top: 18px;
}
.create-completion-btn {
margin-top: 45px;
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-18 17:08:56
-->
<template>
<div class="create-completion common-wrap">
<nav-crumb :navpath="navpath"></nav-crumb>
<div class="right-content border-box">
<div class="right-box border-box">
<div class="step-top">
<active-step
:activeStep="activeStep"
:stepData="stepData"
></active-step>
</div>
<div class="step-body">
<base-config
v-if="activeStep == '1'"
@submitNext="submitNext"
></base-config>
<center-config
v-if="activeStep == '2'"
@submitBack="submitBack"
@submitNext="submitNext"
></center-config>
<card-config
v-if="activeStep == '3'"
@submitBack="submitBack"
@submitNext="submitNext"
></card-config>
<poster-config
v-if="activeStep == '4'"
@submitBack="submitBack"
@submitNext="submitNext"
></poster-config>
<reward-config
v-if="activeStep == '5'"
@submitBack="submitBack"
@submitNext="submitNext"
></reward-config>
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import navCrumb from '@/components/nav/nav.vue';
import activeStep from '@/components/active-config/active-step.vue';
import baseConfig from '@/components/active-config/base-config.vue';
import centerConfig from '@/components/active-config/center-config.vue';
import cardConfig from '@/components/active-config/card-config.vue';
import posterConfig from '@/components/active-config/poster-config.vue';
import rewardConfig from '@/components/active-config/reward-config.vue';
export default {
name: 'createCompletion',
components: {
navCrumb,
activeStep,
baseConfig,
centerConfig,
cardConfig,
posterConfig,
rewardConfig
},
data() {
return {
// 面包屑参数
navpath: [
{
name: '分享有礼',
path: `/shareIndex`,
/*relocation: true */
},
{
name: '新建活动',
/*relocation: true */
},
],
activeStep: 1,
stepData: [
{
stepName: '基本信息',
hasSet: false
},
{
stepName: '活动中心配置',
hasSet: false
},
{
stepName: '小程序卡片配置',
hasSet: false
},
{
stepName: '分享海报配置',
hasSet: false
},
{
stepName: '奖励配置',
hasSet: false
}
],
}
},
methods: {
/**
* 下一步
*/
submitNext() {
const that = this;
that.stepData[that.activeStep - 1 ].hasSet = true;
that.activeStep++;
},
/**
* 上一步
*/
submitBack() {
const that = this;
console.log(that.activeStep)
that.activeStep--;
that.stepData[that.activeStep - 1 ].hasSet = false;
}
},
}
</script>
<style lang="less" scoped>
.create-completion {
width: 100%;
.create-completion-icon {
padding-top: 159px;
img {
width: 88px;
height: 88px;
}
}
.create-completion-text {
margin-top: 18px;
}
.create-completion-btn {
margin-top: 45px;
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-15 10:10:08
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 13:58:13
-->
<template>
<div class="data-detail common-wrap">
<nav-crumb :navpath="navpath"></nav-crumb>
<div class="right-content border-box">
<div class="right-box border-box">
<div class="data-detail-tab flex flex-space-between">
<div class="data-detail-radios">
<el-radio-group
v-model="tabName"
style="margin-bottom: 30px;"
>
<el-radio-button label="invite">邀请人列表</el-radio-button>
<el-radio-button label="invited">受邀人列表</el-radio-button>
</el-radio-group>
</div>
<div class="data-detail-export">
<el-button
type="primary"
icon="el-icon-upload"
>导出数据</el-button>
</div>
</div>
<div class="data-detail-table">
<invite-table v-if="tabName == 'invite'"></invite-table>
<invited-table v-if="tabName == 'invited'"></invited-table>
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import navCrumb from '@/components/nav/nav.vue';
import inviteTable from '@/components/data-details/invite-table.vue';
import invitedTable from '@/components/data-details/invited-table.vue';
// import showMsg from '@/common/js/showmsg';
export default {
name: 'dataDetail',
components: {
navCrumb,
inviteTable,
invitedTable
},
data() {
return {
tabName: 'invite',
// 面包屑参数
navpath: [
{
name: '分享有礼',
path: `/shareIndex`,
/*relocation: true */
},
{
name: '数据明细',
/*relocation: true */
},
],
}
},
methods: {
},
}
</script>
<style lang="less" scoped>
.data-detail {
width: 100%;
.data-detail-tab {
width: 100%;
height: 32px;
}
.data-detail-table {
margin-top: 20px;
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-12 11:02:27
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 13:36:56
-->
<template>
<div class="invited-log common-wrap">
<nav-crumb :navpath="navpath"></nav-crumb>
<div class="right-content border-box">
<div class="right-box border-box">
<div class="invited-data">
<div class="invited-data-img flex flex-align-center flex-pack-center"><img
src=""
alt=""
></div>
<div class="invited-data-name text-center font-14 color-606266">-123-</div>
</div>
<div class="invited-log-table">
<el-table
class="select-table"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
:style="{ width: '100%'}"
>
<el-table-column
prop=""
label="操作时间"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.phoneNumber || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="转化进度"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
<el-table-column
prop=""
label="详情"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
</el-table>
<!-- <div
class="block common-wrap__page text-right m-t-24"
v-if="tableData.length != 0"
>
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[20, 40, 60, 80]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
> </el-pagination>
</div> -->
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import navCrumb from '@/components/nav/nav.vue';
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'invited-log',
components: {
navCrumb,
},
data() {
return {
// 面包屑参数
navpath: [
{
name: '分享有礼',
path: `/shareIndex`,
/*relocation: true */
},
{
name: '受邀人日志',
/*relocation: true */
},
],
tabName: "invite",
// 分页参数
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
}
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getInvitedData() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.invited-log {
width: 100%;
.invited-data {
width: 100%;
height: 290px;
.invited-data-img {
width: 100px;
height: 100px;
margin: 0 auto;
img {
max-width: 100px;
max-height: 100px;
}
}
.invited-data-name {
margin-top: 10px;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-11-12 11:02:27
* @LastEditors: 无尘
* @LastEditTime: 2019-11-15 14:06:02
-->
<template>
<div class="inviter-log common-wrap">
<nav-crumb :navpath="navpath"></nav-crumb>
<div class="right-content border-box">
<div class="right-box border-box">
<div class="inviter-data">
<div class="inviter-data-img flex flex-align-center flex-pack-center"><img
src=""
alt=""
></div>
<div class="inviter-data-name text-center font-14 color-606266">-123-</div>
<div class="inviter-data-datas">
<ul class="inviter-data-wrap flex">
<li class="flex-1">
<div class="font-14 color-606266">邀请人数</div>
<div class="font-20 color-303133 m-t-10">20</div>
</li>
<li class="flex-1">
<div class="font-14 color-606266">积分收益</div>
<div class="font-20 color-303133 m-t-10">20</div>
</li>
<li class="flex-1">
<div class="font-14 color-606266">卡券收益</div>
<div class="font-20 color-303133 m-t-10">20</div>
</li>
</ul>
</div>
</div>
<div class="inviter-log-tab flex flex-space-between">
<div class="data-detail-radios">
<el-radio-group
v-model="tabName"
style="margin-bottom: 30px;"
>
<el-radio-button label="invite">邀请日志</el-radio-button>
<el-radio-button label="point">积分收益明细</el-radio-button>
<el-radio-button label="card">卡券收益明细</el-radio-button>
</el-radio-group>
</div>
<div class="data-detail-export">
<el-button
type="primary"
icon="el-icon-upload"
>导出数据</el-button>
</div>
</div>
<div class="inviter-log-tables m-t-20">
<invite-log v-if="tabName == 'invite'"></invite-log>
<point-log v-if="tabName == 'point'"></point-log>
<card-log v-if="tabName == 'card'"></card-log>
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import pointLog from '@/components/data-details/point-log.vue';
import cardLog from '@/components/data-details/card-log.vue';
import inviteLog from '@/components/data-details/invite-log.vue';
import navCrumb from '@/components/nav/nav.vue';
import { getRequest } from '@/api/api';
import errMsg from '@/common/js/error';
export default {
name: 'invite-table',
data() {
return {
tabName: "invite",
// 面包屑参数
navpath: [
{
name: '分享有礼',
path: `/shareIndex`,
/*relocation: true */
},
{
name: '邀请人日志',
/*relocation: true */
},
],
}
},
components: {
navCrumb,
inviteLog,
pointLog,
cardLog
},
methods: {
/**
* 分页---页码变化
*/
handleSizeChange(val) {
const that = this;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getInviterData() {
const that = this;
let para = {
brandId: that.activeBrand
};
getRequest('/haoban-app-member-web/customer/find_message_list', para)
.then(res => {
let resData = res.data;
if (resData.errorCode == 1) {
that.tableData = resData.result.list || [];
that.total = resData.result.total;
return false;
}
errMsg.errorMsg(resData);
})
.catch(function(error) {
that.$message.error({
duration: 1000,
message: error.message
});
});
}
},
}
</script>
<style lang="less" scoped>
.inviter-log {
width: 100%;
.inviter-data {
width: 100%;
height: 290px;
.inviter-data-img {
width: 100px;
height: 100px;
margin: 0 auto;
img {
max-width: 100px;
max-height: 100px;
}
}
.inviter-data-name {
margin-top: 10px;
}
.inviter-data-datas {
width: 100%;
.inviter-data-wrap {
width: 50%;
margin: 27px auto 0 auto;
li {
width: 33.333333%;
padding-left: 14%;
}
}
}
}
.inviter-log-tab {
height: 32px;
}
}
</style>
......@@ -107,45 +107,27 @@ export default {
.right-content {
width: 100%;
padding: 24px;
padding: 20px;
min-height: 615px;
}
&.near-store-contain {
.right-content {
min-height: 570px;
}
}
/deep/ .el-tabs__nav {
z-index: 1;
}
}
.content-body .left-menu {
-ms-flex: 0 0 200px;
flex: 0 0 200px;
width: 200px;
height: 100%;
background: #020b21;
transition: all 0.2s ease;
position: fixed;
z-index: 5;
}
.common-wrap {
position: relative;
width: 100%;
height: 100%;
overflow-y: auto;
.right-content {
/*width: 100%;*/
padding: 24px;
min-height: calc(100% - 240px);
padding: 20px;
min-height: calc(100vh - 256px);
.right-box {
padding: 20px;
min-height: calc(100vh - 296px);
background: #fff;
padding: 24px;
}
}
}
......@@ -160,6 +142,7 @@ export default {
/* 表格为空 */
/deep/ .el-table__empty-block {
height: 256px;
padding: 80px;
}
}
......@@ -169,7 +152,7 @@ export default {
.el-table__empty-text {
width: auto;
margin-bottom: 80px;
margin-bottom: 0px;
&::before {
content: ' ';
display: block;
......
......@@ -4,30 +4,86 @@
* @Author: 无尘
* @Date: 2019-11-12 10:59:45
* @LastEditors: 无尘
* @LastEditTime: 2019-11-14 17:32:00
* @LastEditTime: 2019-11-18 18:23:39
-->
<template>
<div class="share-index">
<data-statistics-child :barChartData="barChartData"></data-statistics-child>
<funnel-chart :funnelData="funnelData"></funnel-chart>
<bar-chart
:barChartData="barChartData"
:charHeight="charHeight"
></bar-chart>
<data-statistics></data-statistics>
<div class="share-index common-wrap">
<div class="right-content border-box">
<div class="right-box border-box">
<data-statistics-child :barChartData="barChartData"></data-statistics-child>
<funnel-chart :funnelData="funnelData"></funnel-chart>
<bar-chart
:barChartData="barChartData"
:charHeight="charHeight"
></bar-chart>
<data-statistics
:barChartData="barChartData"
:funnelData="funnelData"
></data-statistics>
<out-date-active
:barChartData="barChartData"
:funnelData="funnelData"
></out-date-active>
<div class="separator-space">- 以下为已结束活动 - </div>
<div class="finished-active border-box">
<ul>
<template v-for="(item, index) in finishedData">
<li
:class="[selectItem]"
@click.stop="selectLi(item)"
:key="index+'data'"
>
<div class="finished-active-title flex flex-space-between">
<div class="active-title-left">
<div class="active-title-name font-18 color-303133">活动名称活动名称活动名称活动名称活动名称活动名称</div>
<div class="active-title-date font-14 color-909399 m-t-5">2019.10.01 12:00 - 2019.10.02 12:00</div>
</div>
<div class="active-title-right">
<el-button
type="primary"
plain
>活动配置</el-button>
<el-button
type="primary"
plain
@click="handleCopy(index, item)"
>复制路径</el-button>
<el-button
type="primary"
plain
>数据明细</el-button>
</div>
</div>
<div
v-if="selectItem == item.id"
class="finished-active-body"
>
<out-date-active
:barChartData="barChartData"
:funnelData="funnelData"
></out-date-active>
</div>
</li>
</template>
</ul>
</div>
</div>
</div>
<vue-gic-footer></vue-gic-footer>
</div>
</template>
<script>
import outDateActive from '@/components/active/out-date-active.vue';
import dataStatisticsChild from '@/components/active/data-statistics-child.vue';
import dataStatistics from '@/components/active/data-statistics.vue';
import barChart from '@/components/active/bar-chart.vue';
import funnelChart from '@/components/active/funnel-chart.vue';
import Clipboard from 'clipboard';
import showMsg from '@/common/js/showmsg';
export default {
name: 'share-index',
components: {
outDateActive,
funnelChart,
barChart,
dataStatistics,
......@@ -47,15 +103,82 @@ export default {
{ '日期': '1/5', '访问用户': 3192, '下单用户': 3192, '传播系数': 0.323 },
{ '日期': '1/6', '访问用户': 3593, '下单用户': 3293, '传播系数': 0.78 }
]
}
},
selectItem: '',
finishedData: [
{
id: 1,
},
{
id: 2,
}
]
}
},
methods: {
/**
* 选择 li
*/
selectLi(item) {
const that = this;
that.selectItem = item.id;
},
/**
* 复制路径
*/
handleCopy(index, row) {
let clipboard = new Clipboard('.copy-tag', {
text: function() {
return `${window.location.origin}/?articleId=${row.articleId}`;
}
});
clipboard.on('success', e => {
showMsg.showmsg('复制成功!', 'success');
// 释放内存
clipboard.destroy();
});
clipboard.on('error', e => {
// 不支持复制
showMsg.showmsg('该浏览器不支持自动复制!', 'warning');
// 释放内存
clipboard.destroy();
});
},
},
}
</script>
<style lang="less" scoped>
.share-index {
.separator-space {
width: 100%;
height: 60px;
line-height: 60px;
text-align: center;
font-size: 14px;
color: #909399;
}
// 结束活动
.finished-active {
width: 100%;
padding: 0 42px 48px 46px;
background: #fff;
li {
&.li-border {
padding: 0 20px;
box-shadow: 0px 0px 8px 3px rgba(154, 170, 201, 0.11);
border-radius: 4px;
border: 1px solid rgba(220, 223, 230, 1);
}
}
.finished-active-title {
padding: 27px 0 20px 0;
border-bottom: 1px solid #dcdfe6;
}
.finished-active-body {
padding: 20px 0;
}
}
}
</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