lion 2 years ago
parent 11f84e5755
commit 52386230f7

@ -2,6 +2,6 @@
ENV = 'development'
# base api
#VUE_APP_BASE_API = https://yybtest.ali251.langye.net/
VUE_APP_BASE_DEV_API = https://yunyubang.ali251.langye.net/
VUE_APP_BASE_API = https://yunyubang.ali251.langye.net/
VUE_APP_BASE_API = https://yybtest.ali251.langye.net/
#VUE_APP_BASE_DEV_API = https://yunyubang.ali251.langye.net/
#VUE_APP_BASE_API = https://yunyubang.ali251.langye.net/

@ -39,3 +39,12 @@ export function destroy(params){
params
})
}
export function activeIndex(params){
return request({
method:'get',
url:'/api/admin/member/active-index',
params
})
}

@ -343,6 +343,38 @@
</div>
</div>
</template>
<template v-slot:illustration>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;"></span>插图
</div>
<div class="xy-table-item-content">
<div v-if="form.illustration" style="position: relative;">
<img :src="form.illustration" class="avatar">
<Button
shape="circle"
icon="md-close"
type="error"
size="small"
class="img__delete"
@click="form.illustration = ''"></Button>
</div>
<el-upload
v-else
accept="picture"
:limit="1"
class="avatar-uploader"
list-type="picture-card"
:action="action"
:show-file-list="true"
:on-error="uploadFail"
:on-success="uploadSuccess2"
:before-upload="uploadBefore">
<i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</div>
</template>
<template v-slot:sort>
<div class="xy-table-item">
<div class="xy-table-item-label">
@ -429,6 +461,7 @@ companykeyword:"",
// applyDate:[],
// money:0.00,
activePlaybill:"",
illustration:'',
sort:0,
content:"",
},
@ -461,6 +494,9 @@ companykeyword:"",
activePlaybill:[
{required:true,message:'请上传活动海报'}
],
// illustration:[
// {required:true,message:''}
// ],
content:[
{required:true,message:'请输入活动内容'}
]
@ -556,6 +592,10 @@ companykeyword:"",
console.log(response)
this.form.activePlaybill = response.url
},
uploadSuccess2(response){
console.log(response)
this.form.illustration = response.url
},
uploadBefore(file){
console.log(file)
if((file.size/1000) > 2024){
@ -622,6 +662,7 @@ companykeyword:"",
applyDate:[res.apply_start,res.apply_end],
// money:Number(res.money),
activePlaybill:res.active_playbill,
illustration:res.illustration,
sort:res.sort,
content:res?.content,
}
@ -682,6 +723,7 @@ companykeyword:"",
apply_start:this.form.applyDate[0],
apply_end:this.form.applyDate[1],
active_playbill:this.form.activePlaybill,
illustration:this.form.illustration,
sort:this.form.sort,
content: replaceAll(this.form.content,'../storage/files',`${process.env.VUE_APP_BASE_API}storage/files`)
@ -725,6 +767,7 @@ companykeyword:"",
apply_start:this.form.applyDate[0],
apply_end:this.form.applyDate[1],
active_playbill:this.form.activePlaybill,
illustration:this.form.illustration,
sort:this.form.sort,
content: replaceAll(this.form.content,'../storage/files',`${process.env.VUE_APP_BASE_API}storage/files`),
// audit_status:1

@ -160,6 +160,11 @@
prop: "spread_member_phone",
label: "推广人号码",
width: 120
},
{
prop: "remark",
label: "备注",
width: 120
}
],

@ -68,6 +68,55 @@
</div>
</div>
<div class="box box3">
<div class="boxtitle">
活动统计
</div>
<div class="bline"></div>
<div class="boxcontentsubtitle">当日下单/取消</div>
<div class="boxcontent">
<div class="boxcontentitem">
<div class="boxcontentitem-big">
<count-to separator="" :start-val="0" :end-val="totaldata.order.order_list.total.order_date.total_active"
:duration="3600" />
</div>
</div>
<div class="boxcontentitem">
<div class="boxcontentitem-big">
<count-to separator="" :start-val="0" :end-val="totaldata.order.order_list.total.order_date.active_canceled"
:duration="3600" />
</div>
</div>
</div>
<div class="boxcline"></div>
<div class="boxcontentsubtitle">当前下单/取消</div>
<div class="boxcontent">
<div class="boxcontentitem">
<div class="boxcontentitem-big">
<count-to separator="" :start-val="0" :end-val="totaldata.order.order_list.total.order_month.total_active"
:duration="3600" />
<div class="boxcontentitem-small">
</div>
<div class="boxcontentitem-small">
</div>
</div>
</div>
<div class="boxcontentitem">
<div class="boxcontentitem-big">
<count-to separator="" :start-val="0" :end-val="totaldata.order.order_list.total.order_month.active_canceled"
:duration="3600" />
</div>
<div class="boxcontentitem-small">
</div>
<div class="boxcontentitem-small">
</div>
</div>
</div>
</div>
<div class="box box2">
<div class="boxtitle">
@ -213,7 +262,8 @@
display: flex;
//justify-content: space-around;
align-items: center;
justify-content: center;
min-height:120px;
.boxline {
width: 1px;
height: 4.0625rem;
@ -276,6 +326,9 @@
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
.boxcontent{
min-height:auto
}
}
.box3 {

@ -83,23 +83,29 @@
},
lineArr: {
xArr: [],
legendArr: ["客户", "订单", "成交额"],
legendArr: ["客户", "订单", "活动", "成交额"],
series: [{
name: '客户',
type: 'line',
stack: 'Total',
// stack: 'Total',
data: []
},
{
name: '订单',
type: 'line',
stack: 'Total',
// stack: 'Total',
data: []
},
{
name: '活动',
type: 'line',
// stack: 'Total',
data: []
},
{
name: '成交额',
type: 'line',
stack: 'Total',
// stack: 'Total',
data: []
}
]
@ -168,7 +174,8 @@
for (var m of res) {
that.lineArr.series[1].data.push(m.order_total);
that.lineArr.series[2].data.push(m.paid_money_total);
that.lineArr.series[2].data.push(m.active_total);
that.lineArr.series[3].data.push(m.paid_money_total);
}
}).catch((res) => {})

@ -6,7 +6,7 @@
<div style="display: flex">
<Input v-model="select.keyword" class="select" style="width: 200px; margin-right: 10px"
placeholder="关键字搜索" />
<el-checkbox style="margin-left: 10px;line-height:36px" v-model="select.next_follow_time"></el-checkbox>
<el-checkbox style="margin-left: 10px;line-height:36px" v-model="select.next_follow_time"></el-checkbox>
<Button class="select" type="primary" style="margin-right: 10px;margin-left: 10px;" @click="searchOrder"></Button>
<xy-selectors @search="searchOrder" @reset="resetsearch">
<template>
@ -132,7 +132,8 @@
<template v-slot:btns>
<el-table-column fixed="right" label="操作" width="320" header-align="center">
<template slot-scope="scope">
<actions :row="scope.row" @log="showLog(scope.row)" @refresh="getOrders"></actions>
<!-- <actions :row="scope.row" @log="showLog(scope.row)" @refresh="getOrders"></actions> -->
<actions :row="scope.row" @log="showLog(scope.row)"></actions>
<!-- <Button icon="ios-chatbubbles-outline" type="primary" style="margin-left: 10px;margin-bottom: 6px;" size="small" ghost>跟进</Button>-->
<!-- <Button v-show="scope.row.state_name == ''" icon="ios-paper-plane-outline" type="primary" style="margin-left: 10px;margin-bottom: 6px;" size="small" ghost>分发</Button>-->
<!-- <Button v-show="scope.row.state_name == ''" icon="ios-close" type="primary" style="margin-left: 10px;margin-bottom: 6px;" size="small" ghost>取消</Button>-->
@ -144,7 +145,9 @@
</xy-table>
<orderLog :id="selectId" :is-show.sync="isShowLog" @refresh="getOrders"></orderLog>
<orderEdit :id="selectId" :is-show.sync="isShowEdit" @refresh="getOrders"></orderEdit>
<!-- <orderEdit :id="selectId" :is-show.sync="isShowEdit" @refresh="getOrders"></orderEdit> -->
<orderEdit :id="selectId" :is-show.sync="isShowEdit"></orderEdit>
</div>
</template>
@ -652,7 +655,7 @@
this.select.is_merchant = is_merchant ? 1 : 0;
let is_next_follow_time = this.select.next_follow_time
this.select.next_follow_time = is_next_follow_time ? 1 : 0;
this.select.next_follow_time = is_next_follow_time ? 1 : '';
let order_paid = this.select.order_paid
this.select.order_paid = order_paid ? 1 : '';

@ -72,7 +72,19 @@
const result = Array.from(new Set(_data))
this.select.product_type_list = result
},
removeType(e) {},
removeType(e) {
this.$nextTick(()=>{
let _arr = this.$refs.typeCas.getCheckedNodes()
console.log("_arr",_arr)
let _data = []
for(var k of _arr){
_data.push(k.value)
}
const result = Array.from(new Set(_data))
this.select.product_type_list = result
})
},
async initTotal() {
const res = await typeCount({
start_date: '2000-01-01',
@ -81,6 +93,8 @@
this.list = res.return_list.total
},
async getTotal() {
console.log("this.select.product_type_list111",this.select.product_type_list)
const res = await typeCount({
start_date: this.select.start_date,
end_date: this.select.end_date,

@ -12,13 +12,13 @@
<div class="selector-item">
<div class="selector-item__label">区域</div>
<Select clearable v-model="select.area" style="width: 100px;" placeholder="选择区域搜索">
<Option v-for="item in areas" :value="item">{{item}}</Option>
<Option v-for="item in areas" :value="item.value">{{item.value}}</Option>
</Select>
</div>
<div class="selector-item">
<div class="selector-item__label">建卡医院</div>
<Select clearable v-model="select.hospital" style="width: 100px;" placeholder="选择建卡医院搜索">
<Option v-for="item in arrHospital" :value="item">{{item}}</Option>
<Option v-for="item in arrHospital" :value="item.value">{{item.value}}</Option>
</Select>
<!-- <Input clearable v-model="select.hospital" style="width: 100px;" placeholder="建卡医院搜索" /> -->
</div>
@ -71,6 +71,12 @@
<Input clearable v-model="select.order_count" style="width: 50px;margin:0 3px" placeholder="" />
<div class="selector-item__label">及以上</div>
</div>
<div class="selector-item">
<div class="selector-item__label">活动情况</div>
<Select clearable v-model="select.active_member" style="width: 100px;" placeholder="选择建卡医院搜索">
<Option v-for="item in activeStatus" :value="item.id">{{item.label}}</Option>
</Select>
</div>
<div class="selector-item">
<Button type="primary" @click="doSearch"></Button>
</div>
@ -98,6 +104,7 @@
index,
destroy
} from '@/api/member'
import {getparameteritem} from '@/api/system/dictionary.js'
import {
parseTime
} from "@/utils"
@ -131,16 +138,37 @@
start_date:'',
end_date:'',
product_pid:'',
product_type_list:[]
product_type_list:[],
active_member:''
},
arrHospital: ["市立医院", "苏大附一院", "苏大附二院","附二浒关院区", "中医院", "第五人民医院", "苏州市第七人民医院", "明基医院", "九龙医院", "娄葑医院",
"吴中人民医院", "甪直人民医院", "相城人民医院", "相城区第二人民医院", "吴江第一人民医院", "吴江第二人民医院", "盛泽医院", "其他"
],
arrHospital: [],
activeStatus:[{
id:'',
label:'全部'
},{
id:1,
label:'活动下单'
},{
id:2,
label:'产品、活动下单'
}],
dateRange:[],
dateRangeCancel:[],
dateRangeReg:[],
areas: ["吴中区", "吴江区", "姑苏区", "工业园区", "高新区", "相城区", "昆山", "常熟", "张家港", "太仓"],
areas: [],
statusNames:[{
id:0,
name:'申请取消'
},{
id:1,
name:'待核销'
},{
id:2,
name:'已取消'
},{
id:3,
name:'已核销'
}],
total: 0,
list: [],
table: [{
@ -235,6 +263,30 @@
}
},
{
prop: 'active',
label: '活动详情',
width: 480,
align:"left",
customFn:(row)=>{
if(row.order.length>0){
return row.active.map((k,index)=> {
for(let s of this.statusNames){
if(s.id===k.state){
k.state_name = s.name
}
}
return (<div style={{'padding':'1px'}}>
<div>
<span style={{'color':k.state==3?'red':'#000'}}>{index+1}{k.state_name}</span>-
<span>{ k.active_name}</span>
</div>
</div>)
})
}
}
},
{
prop: 'due_date',
label: '预产期',
@ -281,6 +333,7 @@
}
},
methods: {
dateChange(e){
if(e){
this.select.create_time = this.dateRange[0]
@ -321,6 +374,14 @@
this.select.pageIndex = e
this.getMembers()
},
async getArea(){
const res = await getparameteritem('area')
this.areas = res.detail
},
async getHospital(){
const res = await getparameteritem('hospital')
this.arrHospital = res.detail
},
async getMembers() {
const res = await index({
@ -342,7 +403,8 @@
start_date:this.select.start_date,
end_date:this.select.end_date,
product_pid:this.select.product_pid,
product_type_list:this.select.product_type_list
product_type_list:this.select.product_type_list,
active_member:this.select.active_member
})
this.total = res.total
this.list = res.data
@ -367,7 +429,8 @@
start_date:this.select.start_date,
end_date:this.select.end_date,
product_pid:this.select.product_pid,
product_type_list:this.select.product_type_list
product_type_list:this.select.product_type_list,
active_member:this.select.active_member
}, '用户列表.xlsx')
},
@ -395,6 +458,8 @@
},
mounted() {
this.getArea()
this.getHospital()
this.reloadUser()
},
watch:{

@ -0,0 +1,322 @@
<template>
<div style="padding: 0 20px">
<div ref="lxHeader">
<lx-header icon="md-apps" text="会员浏览统计" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
<div slot="content"></div>
<slot>
<div class="selector">
<div class="selector-item">
<div class="selector-item__label">关键词</div>
<Input v-model="select.keywords" clearable style="width: 100px;" placeholder="关键字搜索" />
</div>
<div class="selector-item">
<div class="selector-item__label">手机号</div>
<Input v-model="select.member_phone" clearable style="width: 100px;" placeholder="手机号搜索" />
</div>
<div class="selector-item">
<div class="selector-item__label">浏览时间</div>
<el-date-picker
v-model="dateRange"
@change='dateChange'
type="daterange"
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</div>
<div class="selector-item">
<div class="selector-item__label">活动分类</div>
<Select multiple filterable clearable v-model="select.active_type_id" style="" placeholder="选择活动搜索">
<Option v-for="item in activeList" :value="item.id">{{item.name}}</Option>
</Select>
</div>
<div class="selector-item">
<div class="selector-item__label">产品分类</div>
<el-cascader ref="typeCas" style="margin-left:10px;width:400px" v-model="typeCas" :options="options"
:props="props" @change="changeType" @remove-tag="removeType" clearable></el-cascader>
<!-- <Select filterable clearable v-model="select.product_type_id" style="" placeholder="选择产品搜索">
<Option v-for="item in productList" :value="item.id">{{item.name}}</Option>
</Select> -->
</div>
<div class="selector-item">
<el-checkbox v-model="select.product_more"></el-checkbox>
</div>
<div class="selector-item">
<el-checkbox v-model="select.active_more"></el-checkbox>
</div>
<div class="selector-item">
<Button type="primary" @click="doSearch"></Button>
</div>
</div>
</slot>
</lx-header>
</div>
<xy-table :total="total" @pageSizeChange="pageSizeChange" @pageIndexChange="pageChange" :list="list"
:table-item="table">
<template slot="btns">
<div></div>
</template>
</xy-table>
</div>
</template>
<script>
import {
activeIndex
} from '@/api/member'
import {
index as activeList
} from '@/api/activityType'
import {
index as getType
} from "@/api/type"
import {
Message
} from 'element-ui'
import {
parseTime
} from "@/utils"
export default {
components: {
},
data() {
return {
select: {
pageSize: 10,
pageIndex: 1,
keywords: "",
active_type_id: [],
product_type_id: [],
product_more: false,
active_more:'',
member_phone:'',
create_time:'',
over_time:'',
browse:1,
},
dateRange:[],
activeList:[],
typeCas:[],
options: [],
props: {
value: 'id',
label: 'name',
multiple: true,
checkStrictly: true
},
total: 0,
list: [],
table: [{
prop: 'name',
label: '姓名',
width: 180,
sortable: false,
fixed: 'left'
},
{
prop: 'phone',
label: '电话',
width: 220
},
{
prop: 'products',
label: '浏览产品',
width: 480,
align:'left',
customFn:(row)=>{
if(row.products.length>0){
return row.products.map((k,index)=> {
return(<div><span style={{'color':'red'}}>{k.product_count}-</span>
{k.product?k.product.name:''}
</div>)
})
}
}
},
{
prop: 'actives',
label: '浏览活动',
width: 480,
align:'left',
customFn:(row)=>{
if(row.actives.length>0){
return row.actives.map((k,index)=> {
return(<div style={{textAlign:'left'}}><span style={{color:'red'}}>{k.active_count}-</span>
{k.active?k.active.active_name:''}
</div>)
})
}
}
},
{
prop: 'due_date',
label: '预产期',
width: 200
},
{
prop: 'area',
label: '所属区域',
width: 160,
},
{
prop: 'address',
label: '住址',
align: 'left',
minWidth: 300
},
{
prop: 'hospital',
label: '建卡医院',
width: 200
},
{
prop: 'promotion',
label: '推广人员',
width: 140,
customFn: (row) => {
return ( < Tag color = {
row.promotion == 1 ? 'success' : 'error'
} > {
row.promotion == 1 ? '是' : '否'
} </Tag>)
}
},
{
prop: 'created_at',
label: '注册日期',
width: 200,
fixed:'right',
formatter: (cell, data, value) => {
return parseTime(new Date(value), '{y}-{m}-{d}')
}
}
]
}
},
methods: {
dateChange(e){
if(e){
this.select.create_time = this.dateRange[0]
this.select.over_time = this.dateRange[1]
}else{
this.select.create_time = ''
this.select.over_time = ''
}
},
pageSizeChange(e) {
this.select.pageSize = e
this.doSearch();
},
doSearch() {
this.select.pageIndex = 1
this.getMembers()
},
pageChange(e) {
this.select.pageIndex = e
this.getMembers()
},
async getActive(){
const res = await activeList({
page:1,
page_size:999
})
this.activeList = res
},
async getTypes() {
const res = await getType()
this.options = res
},
changeType(e) {
let _arr = this.$refs.typeCas.getCheckedNodes()
let _data = []
for(var k of _arr){
_data.push(k.value)
}
const result = Array.from(new Set(_data))
this.select.product_type_id = result
},
removeType(e) {
this.$nextTick(()=>{
let _arr = this.$refs.typeCas.getCheckedNodes()
let _data = []
for(var k of _arr){
_data.push(k.value)
}
const result = Array.from(new Set(_data))
this.select.product_type_id = result
})
},
async getMembers() {
const res = await activeIndex({
page_size: this.select.pageSize,
page: this.select.pageIndex,
keyword: this.select.keywords,
active_type_id: this.select.active_type_id,
product_type_id: this.select.product_type_id,
product_more: this.select.product_more ? 1 : "",
active_more: this.select.active_more ? 1 : "",
create_time:this.select.create_time,
over_time:this.select.over_time,
member_phone:this.select.member_phone,
browse:this.select.browse,
})
this.total = res.total
this.list = res.data
},
},
mounted() {
this.getActive()
this.getTypes()
this.getMembers()
},
watch:{
}
}
</script>
<style scoped lang="scss">
.selector {
display: flex;
flex-wrap: wrap;
align-items: center;
align-content: center;
&-item {
display: flex;
align-items: center;
align-content: center;
margin-top: 6px;
margin-right: 10px;
&__label {
word-break: keep-all;
}
}
}
.el-range-editor.el-input__inner{
height:32px;
width:250px;
}
.el-date-editor{
::v-deep .el-range__icon{
line-height: 26px!important;
}
::v-deep .el-range-separator{
line-height: 26px!important;
}
::v-deep .el-range__close-icon{
line-height: 26px!important;
}
}
</style>

@ -12,13 +12,13 @@
<div class="selector-item">
<div class="selector-item__label">区域</div>
<Select clearable v-model="select.area" style="width: 130px;" placeholder="选择区域搜索">
<Option v-for="item in areas" :value="item">{{item}}</Option>
<Option v-for="item in areas" :value="item.value">{{item.value}}</Option>
</Select>
</div>
<div class="selector-item">
<div class="selector-item__label">建卡医院</div>
<Select clearable v-model="select.hospital" style="width: 100px;" placeholder="选择建卡医院搜索">
<Option v-for="item in arrHospital" :value="item">{{item}}</Option>
<Option v-for="item in arrHospital" :value="item.value">{{item.value}}</Option>
</Select>
<!-- <Input clearable v-model="select.hospital" style="width: 200px;" placeholder="建卡医院搜索" /> -->
</div>
@ -56,6 +56,7 @@
index,
destroy
} from '@/api/member'
import {getparameteritem} from '@/api/system/dictionary.js'
import {
parseTime
} from "@/utils"
@ -81,10 +82,8 @@
hospital: "",
is_phone: true
},
areas: ["吴中区", "吴江区", "姑苏区", "工业园区", "高新区", "相城区", "昆山", "常熟", "张家港", "太仓"],
arrHospital: ["市立医院", "苏大附一院", "苏大附二院","附二浒关院区", "中医院", "第五人民医院", "苏州市第七人民医院", "明基医院", "九龙医院", "娄葑医院",
"吴中人民医院", "甪直人民医院", "相城人民医院", "相城区第二人民医院", "吴江第一人民医院", "吴江第二人民医院", "盛泽医院", "其他"
],
areas: [],
arrHospital: [],
total: 0,
list: [],
table: [{
@ -125,11 +124,11 @@
label: '推广人员',
width: 140,
customFn: (row) => {
return ( < Tag color = {
return ( <Tag color={
row.promotion == 1 ? 'success' : 'error'
} > {
row.promotion == 1 ? '是' : '否'
} < /Tag>)
} </Tag>)
}
},
{
@ -157,7 +156,14 @@
this.select.pageIndex = e
this.getMembers()
},
async getArea(){
const res = await getparameteritem('area')
this.areas = res.detail
},
async getHospital(){
const res = await getparameteritem('hospital')
this.arrHospital = res.detail
},
async getMembers() {
const res = await index({
page_size: this.select.pageSize,
@ -199,6 +205,8 @@
}
},
mounted() {
this.getArea()
this.getHospital()
this.getMembers()
}

Loading…
Cancel
Save