Commit 91cb6775 by 无尘

feat: 增加应用组件

parent f235d933
/*
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-08-27 09:29:13
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 10:19:09
*/
import getFetch from './get-fetch.js';
let api = {
getGroupList: '/department-list', // 获取 gic 分组列表
getStoreList: '/store-list', // 获取 gic 门店
getAssignStatus: '/app-distribute-status', // 获取分配状态
getNavChain: '/get-chain', // 获取面包屑
getMemberList: {
url: '/app-get-member-info-list', // 获取会员列表
method: 'post',
useFormData: true,
},
getClerkList: '/clerk-list', // 获取导购列表
};
api = getFetch(api, '/hb-manage-web');
export default api;
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-08-25 15:06:31
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 10:21:58
-->
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-08-25 15:06:31
* @LastEditors: 无尘
* @LastEditTime: 2020-08-25 15:10:27
-->
<!--
* @Descripttion: 分配导购
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-04-14 09:50:16
* @LastEditors: 无尘
* @LastEditTime: 2020-06-29 16:53:41
-->
<!--
<customer-assign v-if="assignShow" :brandId="brandId" :clerkId="clerkId" :searchParams="searchInput" :chooseAll="selectRadio" :departObj="departObj" :multipleData="multipleSelection" @closeText="closeText" @submitText="submitText"></customer-assign>
import customerAssign from '@/components/app/my-customer/customer-assign.vue';
-->
<template>
<el-dialog title="批量分配会员" :visible.sync="dialogVisible" width="600px" :before-close="handleClose">
<div class="assign-table">
<div class="check-all border-box flex flex-space-between">
<div class="font-14 color-606266"><el-checkbox :disabled="clerkOptions.length > assignPeople || unbindFlag" :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox></div>
<div class="font-14 color-606266">
<el-checkbox v-model="checked" @change="changeHand">手动分配</el-checkbox> <span class="span-line"></span>
<span
>可分配会员 <span class="color-303133">{{ assignPeople }}</span></span
>
</div>
</div>
<div>
<ul class="clerk-list-ul">
<el-checkbox-group v-model="checkedClerks" @change="handleCheckedChange">
<template v-for="(item, index) in clerkOptions">
<li class="clerk-cell font-14 color-606266" :key="index + 'clerk'">
<el-checkbox :disabled="item.disabled" :label="item.clerkId" @change="changeCell($event, item)">{{ item.clerkName }}</el-checkbox
><span v-if="!item.bindFlag" class="font-14 color-f56c6c p-l-20">未关联企微用户</span>
<span v-if="!checked && checkedClerks.includes(item.clerkId)" class="p-l-20">
分配会员 <span class="color-303133">{{ item.memberCount }}</span></span
>
<span v-if="checked && checkedClerks.includes(item.clerkId)" class="p-l-20 p-r-10">分配会员 </span><el-input-number v-if="checked && checkedClerks.includes(item.clerkId)" class="w-100" v-model="item.memberCount" controls-position="right" @blur="blurNum" @change="handleChange" :step="1" step-strictly :min="1" :max="999999999"></el-input-number><span v-if="checked && checkedClerks.includes(item.clerkId)" class="p-l-10"></span>
</li>
</template>
</el-checkbox-group>
</ul>
<div class="flex flex-space-between m-t-20">
<div class="font-14 color-909399">最多分配会员 5000 人</div>
<div class="font-14 color-606266">
分配总数 <span :class="[totalPeople != 0 && totalPeople != assignPeople ? 'color-f5222d' : 'color-2f54eb']">{{ totalPeople }}</span>
</div>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="toCancel">取消</el-button>
<el-button :disabled="totalPeople != assignPeople" :loading="loadBtn" type="primary" @click="submitForm('ruleForm')">确定</el-button>
</div>
</el-dialog>
</template>
<script>
import { _debounce } from '@/common/js/public';
import fetch from '@/api/my-customer-app.js';
const { saveAssign, getMembercount, getClerkList } = fetch;
import showMsg from '@/common/js/showmsg';
import errMsg from '@/common/js/error';
export default {
components: {},
props: {
brandId: {
type: String,
default() {
return '';
}
},
clerkId: {
type: String,
default() {
return '';
}
},
searchParams: {
type: String,
default() {
return '';
}
},
editRow: {
type: Object,
default() {
return {};
}
},
multipleData: {
type: [ Array, Object ],
default() {
return [];
}
},
chooseAll: {
type: [ String, Number ],
default() {
return '0';
}
},
// 选中节点
departObj: {
type: Object,
default() {
return {
departmentId: '',
departmentName: '',
wxDepartmentId: '',
parentId: '',
isStore: '',
staffCount: '',
bindFlag: '',
loading: false
};
}
}
},
data() {
return {
staffName: localStorage.getItem('haoBanUser') ? JSON.parse(localStorage.getItem('haoBanUser')).staffName : '',
dialogVisible: true,
unbindFlag: false,
checked: false, // 手动
checkAll: false,
isIndeterminate: false,
// 导购
clerkOptions: [
/* {
clerkId: 1,
clerlName: '1',
memberCount: 1
} */
],
checkedClerks: [],
totalPeople: 0, // 分配总数
assignPeople: 0, // 可分配会员
loadBtn: false
};
},
mounted() {
const that = this;
if (Object.keys(that.departObj).length) {
that.getClerkData();
that.setNum();
}
},
methods: {
/**
* 单个值改变
* @param {Boolean} e
* @param {Object} item
*/
changeCell(e, item) {
const that = this;
that.$nextTick(() => {
if (e) {
// 如果选择的导购中人数和分配会员人数相同了,再选择就不能再选了
if (that.checkedClerks.length == that.assignPeople) {
that.clerkOptions.forEach((ele, index) => {
if (!that.checkedClerks.includes(ele.clerkId)) {
ele.disabled = true;
}
});
return false;
}
} else {
that.clerkOptions.forEach((ele, index) => {
ele.disabled = !ele.bindFlag ? true : false;
});
}
});
},
/**
* 手动分配选择
* @param {Boolean} e
*/
async changeHand(e) {
const that = this;
if (!e) {
// 非手动 需要分配
await that.calcNum();
await that.totalCalc();
} else {
that.totalCalc();
}
},
/**
* 手动值改变,计算总数
*/
handleChange() {
const that = this;
that.totalCalc();
},
blurNum() {
const that = this;
that.totalCalc();
},
totalCalc() {
const that = this;
let num = 0;
that.clerkOptions.forEach((ele, index) => {
if (that.checkedClerks.includes(ele.clerkId)) {
num += ele.memberCount;
}
});
that.totalPeople = num;
},
/**
* 单选
* @param {Array} value
*/
async handleCheckedChange(value) {
const that = this;
let checkedCount = value.length;
that.checkAll = checkedCount === that.clerkOptions.length;
that.isIndeterminate = checkedCount > 0 && checkedCount < that.clerkOptions.length;
if (!that.checked) {
// 非手动 需要分配
await that.calcNum();
await that.totalCalc();
} else {
that.totalCalc();
}
},
/**
* 全选
* @param {Array} value
*/
async handleCheckAllChange(value) {
const that = this;
that.checkedClerks = value ? that.clerkOptions.map(ele => ele.clerkId) : [];
that.isIndeterminate = false;
if (!that.checked) {
// 非手动 需要分配
await that.calcNum();
await that.totalCalc();
} else {
that.totalCalc();
}
},
calcNum() {
const that = this;
// 这里需要注意商 == 0 情况
if (!that.checkedClerks.length) {
return false;
}
let averageNum = Math.floor(that.assignPeople / that.checkedClerks.length);
let leftNum = that.assignPeople % that.checkedClerks.length;
let arr = [];
that.clerkOptions.forEach((ele, index) => {
ele.memberCount = averageNum;
if (that.checkedClerks.includes(ele.clerkId)) {
arr.push(index);
}
});
that.clerkOptions.forEach((ele, index) => {
arr.forEach((el, key) => {
if (el == index && key < leftNum) {
ele.memberCount = ele.memberCount + 1;
}
});
});
},
/**
* 获取导购
*/
getClerkData() {
const that = this;
const para = {
enterpriseId: that.brandId,
wxEnterpriseRelatedId: that.wxEnterpriseRelatedId,
storeId: that.departObj.storeId
};
getClerkList(para)
.then(res => {
if (res.code == '0000') {
res.result.forEach(ele => {
ele.memberCount = 1;
ele.disabled = ele.bindFlag ? false : true; // 未绑定的禁止选择
if (!ele.bindFlag) {
that.unbindFlag = true; // 存在未绑定禁止全选
}
});
that.clerkOptions = res.result || [];
}else {
errMsg.errorMsg(res);
}
})
.catch(function(error) {
});
},
/**
* 获取会员数量
*/
getMemberData() {
const that = this;
const para = {
enterpriseId: that.brandId,
wxEnterpriseRelatedId: that.wxEnterpriseRelatedId,
storeId: that.departObj.storeId,
clerkId: that.clerkId,
keyword: that.searchParams
};
getMembercount(para)
.then(res => {
if (res.code == '0000') {
that.assignPeople = res.result || [];
}else {
errMsg.errorMsg(res);
}
})
.catch(function(error) {
});
},
resetData() {
const that = this;
that.checkedClerks = [];
that.totalPeople = 0; // 分配总数
that.assignPeople = 0; // 可分配会员
that.checked = false;
},
toCancel() {
const that = this;
that.resetData();
that.$emit('closeText');
},
handleClose(done) {
const that = this;
that.resetData();
that.$emit('closeText');
},
/**
* 保存
*/
submitForm: _debounce(function() {
const that = this;
that.postSave();
}, 300),
postSave() {
const that = this;
let clerkIds = [];
that.clerkOptions.forEach(ele => {
if (that.checkedClerks.includes(ele.clerkId) && ele.memberCount != 0) {
clerkIds.push(ele);
}
});
that.loadBtn = true;
const data = {
enterpriseId: that.brandId,
chooseAll: that.chooseAll,
storeId: that.departObj.storeId,
clerkId: that.clerkId,
keyword: that.searchParams,
memberIds: that.chooseAll == 1 ? '' : Object.keys(that.editRow).length ? that.editRow.memberId : that.multipleData.map(ele => ele.memberId).join(','),
clerkIds: JSON.stringify(clerkIds),
staffName: that.staffName
};
saveAssign(data)
.then(res => {
that.loadBtn = false;
if (res.code == '0000') {
showMsg.showmsg('操作成功', 'success');
that.resetData();
that.$emit('submitText');
} else {
errMsg.errorMsg(res);
}
})
.catch(error => {
that.loadBtn = false;
});
},
/**
* 设置人数和获取数量判断
*/
setNum() {
const that = this;
if (Object.keys(that.editRow).length) {
that.assignPeople = 1;
} else {
that.chooseAll == 0 ? (that.assignPeople = that.multipleData.length) : that.getMemberData();
}
}
},
watch: {
departObj(newData) {
const that = this;
if (Object.keys(newData).length) {
that.getClerkData();
that.setNum();
}
}
}
};
</script>
<style lang="less" scoped>
.w-100 {
width: 100px;
}
.w-402 {
width: 402px;
}
.m-b-20 {
margin-bottom: 20px;
}
.p-l-18 {
padding-left: 18px;
}
.span-line {
position: relative;
padding: 0 15px;
&::after {
content: '';
position: absolute;
top: 5px;
height: 11px;
width: 1px;
background: #c4c6cf;
}
}
.color-f5222d {
color: #f5222d;
}
.clerk-list-ul {
min-height: 40px;
max-height: 400px;
overflow-y: auto;
}
.check-all {
background: rgba(245, 247, 250, 1);
height: 36px;
line-height: 36px;
padding: 0 10px;
}
.clerk-cell {
height: 40px;
line-height: 40px;
padding: 0 10px;
border-bottom: 1px solid #e4e7ed;
}
</style>
<!--
* @Descripttion: 门店分组
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-08-14 16:51:07
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 09:32:24
-->
<!--
<org-tree v-if="item.children.length" :itemData="item.children" @getSelectData="getSelectData"></org-tree>
import orgTree from '@/components/app/my-customer/org-tree.vue';
getSelectData(obj) {
const that = this;
that.departObj = obj;
that.selectRadio = 0;
that.showMember = false;
that.storeObj = {};
// 判断是不是门店
that.currentPage = 1;
that.tableData = [];
that.clerkOptions = [];
that.clerkId = '0'; // 导购
that.searchInput = '';
that.multipleSelection = [];
},
-->
<template>
<ul :class="['gic-tree-body']">
<li v-for="(item, index) in itemData" :key="index + 'gic'">
<div :class="['li-cell cursor-pointer', departObj.storeGroupId == item.storeGroupId ? 'li-cell-active' : '']">
<div :style="{ 'margin-left': (item.groupLevel + 1) * 20 + 'px' }" :class="['li-cell-inner border-box cursor-pointer']" @click="toggleExpand(item)">
<span :class="['font-12 color-606266', item.isStore == 1 || !item.hasSonNode ? 'color-fff' : '', item.expand ? 'el-icon-caret-bottom' : 'el-icon-caret-right']"></span><span v-if="item.loading" class="el-tree-node__loading-icon el-icon-loading"></span><span class="font-14 color-606266 p-l-10">{{ item.label }}</span>
</div>
</div>
<li-row v-show="!!item.children.length && item.expand" :departObj="departObj" :itemObj="item" :itemData="item.children" @getSelectData="getSelectData"></li-row>
</li>
</ul>
</template>
<script>
export default {
name: 'li-row',
props: {
brandId: {
type: String,
default() {
return '';
}
},
itemData: {
type: [ Object, Array ],
default() {
return [];
}
},
itemObj: {
type: [ Object, Array ],
default() {
return [];
}
},
// 选中节点
departObj: {
type: Object,
default() {
return {
departmentId: '',
departmentName: '',
wxDepartmentId: '',
parentId: '',
isStore: '',
staffCount: '',
bindFlag: '',
loading: false
};
}
}
},
data() {
return {
};
},
beforeDestroy() {
this.tempArr = [];
},
methods: {
/**
* 获取选中部门/门店数据
* @param {Object} obj
*/
getSelectData(obj) {
const that = this;
that.selectData = obj;
that.$emit('getSelectData', obj);
},
/**
* 展开或者关闭下级
* @param {Object} item
*/
async toggleExpand(item) {
const that = this;
item.expand = item.expand ? false : true;
that.$emit('getSelectData', item);
}
}
};
</script>
<style lang="less" scoped>
.m-l-20 {
margin-left: 20px;
}
.li-cell {
position: relative;
line-height: 32px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.color-fff {
color: #fff;
}
&.li-cell-active {
background: rgba(47, 84, 235, 0.05);
span {
color: #2f54eb;
}
.color-fff {
color: rgba(47, 84, 235, 0.05);
}
}
}
.li-cell-inner {
line-height: 32px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.w-110 {
width: 110px;
}
.w-320 {
width: 320px;
}
.m-t-14 {
margin-top: 14px;
}
.child-row {
padding-left: 10px;
}
</style>
<!--
* @Descripttion : 当前组件信息
* @Author : 无尘
* @Date : 2020-08-13 14:02:22
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 09:48:39
* @FilePath : haoban-4\src\components\app\my-customer\store-list.vue
-->
<!--
<store-list :brandId="brandId" :departObj="departObj" @getStore="getStore"></store-list>
import storeList from '@/components/app/my-customer/store-list.vue';
-->
<template>
<div class="depart-list-body">
<div class="depart-name-wrap m-b-20">
<div class="font-14 color-303133">门店 {{ total }}</div>
<div class="flex flex-space-between m-t-20">
<div>
<el-input placeholder="请输入门店名称/代码" maxlength="50" prefix-icon="el-icon-search" v-model="searchInput" class="w-274" @keyup.native="value => toInput(value, searchInput)" clearable @clear="clearInput"></el-input>
</div>
<div class="to-log flex m-t-20"></div>
</div>
</div>
<div class="depart-children-list border-box m-t-18">
<div class="m-t-20">
<el-table class="select-table" ref="multipleTable" :data="tableData" tooltip-effect="dark" :style="{ width: '100%'}">
<el-table-column class="cursor-pointer" label="门店名称" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.storeName || '--' }}</template>
</el-table-column>
<el-table-column class="cursor-pointer" prop="" label="门店类型" show-overflow-tooltip>
<template slot-scope="scope">{{ storeType[scope.row.storeType] || '--' }}</template>
</el-table-column>
<el-table-column class="cursor-pointer" prop="" label="门店分组" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.storeGroupName || '--' }}
</template>
</el-table-column>
<el-table-column prop="" label="操作" show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" @click="showMember(scope.row)">查看会员</el-button>
</template>
</el-table-column>
</el-table>
<div class="block common-wrap__page text-right m-t-24" v-if="tableData.length != 0">
<dm-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"> </dm-pagination>
</div>
</div>
</div>
</div>
</template>
<script>
import { _debounce } from '@/common/js/public';
import fetch from '@/api/my-customer-app.js';
const { getStoreList } = fetch;
import errMsg from '@/common/js/error';
// import showMsg from '@/common/js/showmsg';
export default {
name: 'StoreList',
components: {},
props: {
brandId: {
type: String,
default() {
return '';
}
},
departObj: {
type: Object,
default() {
return {
departmentId: '',
departmentName: '',
wxDepartmentId: '',
parentId: '',
isStore: '',
staffCount: '',
bindFlag: ''
};
}
}
},
data() {
return {
nameVisible: false,
departmentName: this.departObj.departmentName || '',
searchInput: '',
storeType: {
'0': '自营',
'1': '联营',
'2': '代理(加盟)',
'3': '代销',
'4': '托管'
},
// 分页参数
currentPage: 1,
pageSize: 20,
total: 0,
tableData: []
};
},
mounted() {
const that = this;
if (Object.keys(that.departObj)) {
that.currentPage = 1;
that.getTableList();
}
},
methods: {
/**
* 查看会员
* @param {Object} item
*/
showMember(item) {
const that = this;
that.$emit('getStore', item);
},
/**
* 输入
*/
toInput: _debounce(function() {
const that = this;
that.currentPage = 1;
that.getTableList();
}, 500),
// 搜索清除
clearInput() {
const that = this;
that.currentPage = 1;
that.getTableList();
},
/**
* 分页---页码变化
* @param {Number} val
*/
handleSizeChange(val) {
const that = this;
that.currentPage = 1;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
* @param {Number} val
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取列表数据
*/
getTableList() {
const that = this;
let para = {
departmentId: that.departObj.storeGroupId,
enterpriseId: that.brandId,
searchName: that.searchInput || '', // 搜索字段
pageNum: that.currentPage, // 当前页
pageSize: that.pageSize // 一页显示个数
};
getStoreList( 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
});
});
}
},
watch: {
departObj(newData, oldData) {
const that = this;
if (Object.keys(newData)) {
that.currentPage = 1;
that.getTableList();
}
},
brandId(newData) {
const that = this;
if (newData) {
that.searchInput = '';
}
}
}
};
</script>
<style lang="less" scoped>
.m-b-20 {
margin-bottom: 20px;
}
.w-274 {
width: 274px;
}
</style>
......@@ -4,10 +4,10 @@
* @Author: 无尘
* @Date: 2018-10-10 14:44:45
* @LastEditors: 无尘
* @LastEditTime: 2020-08-18 18:22:13
* @LastEditTime: 2020-08-27 09:27:35
-->
<template>
<div class="navwrap border-box flex flex-space-between">
<div class="nav-wrap border-box flex flex-space-between">
<el-breadcrumb separator-class="el-icon-arrow-right">
<template v-for="(item, index) in navpath">
<template v-if="!!item.path">
......@@ -45,18 +45,6 @@ export default {
return [];
}
},
slotFlag: {
type: Boolean,
default: false
},
navtip: {
type: Boolean,
default: false
},
subNavText: {
type: String,
default: ''
}
},
data() {
return {
......@@ -130,7 +118,7 @@ export default {
</script>
<style type="text/less" lang="less" scoped>
.navwrap {
.nav-wrap {
height: 48px;
line-height: 48px;
padding: 0 20px;
......@@ -139,35 +127,7 @@ export default {
line-height: 48px;
}
}
.boxbttom {
border-bottom: 1px solid #e4e7ed;
}
.boxshow {
border-bottom: 1px solid #e4e7ed;
box-shadow: 5px -1px 5px #dfdfdf;
}
.navtitle {
margin: 24px 0 0 0;
font-size: 20px;
color: #303133;
font-weight: 500;
}
.navtip {
width: 100%;
height: 38px;
line-height: 38px;
font-size: 13px;
border-radius: 2px;
color: #606266;
background-color: #f4f4f5;
}
.navmTop {
margin-top: 25px;
}
.navtipcolor {
margin: 0 12px;
color: #2f54eb;
}
.el-breadcrumb__inner.is-link:hover,
.el-breadcrumb__inner a:hover {
color: #2f54eb;
......
......@@ -4,10 +4,10 @@
* @Author: 无尘
* @Date: 2018-10-10 14:44:45
* @LastEditors: 无尘
* @LastEditTime: 2020-08-17 09:34:12
* @LastEditTime: 2020-08-27 09:27:00
-->
<template>
<div class="navwrap border-box">
<div class="nav-wrap border-box">
<el-breadcrumb separator-class="el-icon-arrow-right">
<template v-for="(item, index) in navpath">
<template v-if="!!item.path">
......@@ -34,18 +34,6 @@ export default {
default: function() {
return [];
}
},
slotFlag: {
type: Boolean,
default: false
},
navtip: {
type: Boolean,
default: false
},
subNavText: {
type: String,
default: ''
}
},
data() {
......@@ -79,38 +67,10 @@ export default {
</script>
<style scoped>
.navwrap {
.nav-wrap {
padding: 12px 20px;
}
.boxbttom {
border-bottom: 1px solid #e4e7ed;
}
.boxshow {
border-bottom: 1px solid #e4e7ed;
box-shadow: 5px -1px 5px #dfdfdf;
}
.navtitle {
margin: 24px 0 0 0;
font-size: 20px;
color: #303133;
font-weight: 500;
}
.navtip {
width: 100%;
height: 38px;
line-height: 38px;
font-size: 13px;
border-radius: 2px;
color: #606266;
background-color: #f4f4f5;
}
.navmTop {
margin-top: 25px;
}
.navtipcolor {
margin: 0 12px;
color: #2f54eb;
}
.el-breadcrumb__inner.is-link:hover, .el-breadcrumb__inner a:hover {
color: #2f54eb;
}
......
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2020-08-20 14:36:37
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 10:26:54
-->
<template>
<div class="app-detail-wrap">
<div class="border-box">
<div class="list-body flex">
<div class="list-left border-box">
<org-tree v-if="gicData.length" :brandId="brandId" :departObj="departObj" :itemData="gicData" @getSelectData="getSelectData"></org-tree>
</div>
<div class="list-right p-20 border-box">
<store-list v-if="!showMember" :brandId="brandId" :departObj="departObj" @getStore="getStore"></store-list>
<div v-if="showMember" class="list-right-body">
<div role="navigation" class="el-breadcrumb m-b-20">
<span class="el-breadcrumb__item" v-for="(item, index) in navData" :key="index + 'nav'"
><span role="link" class="el-breadcrumb__inner is-link" @click="changeDepart(item, index)"
><span class="el-breadcrumb__inner is-link font-14 color-606266">
{{ index == navData.length - 1 ? item.storeName : item.storeGroupName }}
</span></span
><i v-if="index != navData.length - 1" class="el-breadcrumb__separator el-icon-arrow-right"></i
></span>
</div>
<div class="table-top flex flex-space-between">
<div>
<el-select class="w-168" v-model="clerkId" placeholder="" @change="changeCondition">
<el-option label="全部" value="0"></el-option>
<el-option label="无归属" value="-1"></el-option>
<el-option v-for="item in clerkOptions" :key="item.clerkId" :label="item.clerkName" :value="item.clerkId"> </el-option> </el-select
><el-input placeholder="请输入会员姓名/手机号/卡号" maxlength="50" prefix-icon="el-icon-search" v-model="searchInput" class="w-264 m-l-10" style="width: 264px;" clearable @clear="clearSearch" @keyup.native="value => toInput(value, searchInput)"> </el-input>
</div>
<el-button type="primary" @click="toAssign">批量分配会员</el-button>
</div>
<div class="table-body m-t-20">
<el-table class="select-table" ref="multipleTable" v-loading="loading" :data="tableData" tooltip-effect="dark" :style="{ width: '100%' }" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="45"> </el-table-column>
<el-table-column width="25">
<template slot="header">
<el-dropdown style="line-height: 10px; padding: 0; margin-left: -15px; transform: translateY(4px); -webkit-transform: translateY(4px);" @command="handleCommand" placement="bottom-start">
<span class="el-dropdown-link"><i class="iconfont icongengduo"></i> </span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="0"><span :style="{ color: selectRadio == 0 ? '#2f54eb' : '#606266' }">选择当页</span></el-dropdown-item>
<el-dropdown-item command="1"><span :style="{ color: selectRadio == 1 ? '#2f54eb' : '#606266' }">选择全部</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
<el-table-column label="会员姓名" width="120" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.memberName || '--' }}</template>
</el-table-column>
<el-table-column prop="" label="会员等级">
<template slot-scope="scope">{{ scope.row.gradeName || '--' }}</template>
</el-table-column>
<el-table-column prop="" label="消费总额" show-overflow-tooltip>
<template slot-scope="scope"
>{{ scope.row.costFee }} {{ scope.row.costFee == null && scope.row.costFee != 0 ? '--' : '' }}</template
>
</el-table-column>
<el-table-column prop="" label="最近消费时间" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.lastCostTime | timeStampToYmd }} {{ !scope.row.lastCostTime ? '--' : '' }}
</template>
</el-table-column>
<el-table-column prop="" label="生日" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.birthday || '--' }}</template>
</el-table-column>
<el-table-column prop="" label="所属导购" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.clerkName || '--' }}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" @click="toAssignMember(scope.$index, scope.row)">分配</el-button>
</template>
</el-table-column>
</el-table>
<div class="block common-wrap__page text-right m-t-24" v-if="tableData.length != 0">
<dm-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"> </dm-pagination>
</div>
</div>
</div>
</div>
</div>
</div>
<customer-assign v-if="assignShow" :brandId="brandId" :clerkId="clerkId" :searchParams="searchInput" :editRow="editRow" :chooseAll="selectRadio" :departObj="storeObj" :multipleData="multipleSelection" @closeText="closeText" @submitText="submitText"></customer-assign>
</div>
</template>
<script>
import orgTree from '@/components/app/my-customer/org-tree.vue';
import customerAssign from '@/components/app/my-customer/customer-assign.vue';
import storeList from '@/components/app/my-customer/store-list.vue';
// import showMsg from '@/common/js/showmsg';
import errMsg from '@/common/js/error';
import { _debounce } from '@/common/js/public';
import fetch from '@/api/my-customer-app.js';
const { getGroupList, getMemberList, getNavChain, getAssignStatus, getClerkList } = fetch;
export default {
name: 'CustomerAssignPage',
components: { orgTree, customerAssign, storeList },
props: {
brandId: {
type: String,
default() {
return '';
}
},
tabType: {
type: String,
default() {
return '1';
}
},
activeGroupId: {
type: String,
default() {
return '';
}
}
},
data() {
return {
projectName: '', // 当前项目名
wxEnterpriseRelatedId: localStorage.getItem('userInfos') ? JSON.parse(localStorage.getItem('userInfos')).wxEnterpriseId : '',
departObj: {}, // 选中的部门、门店
gicData: [], // gic
clerkId: '0', // 导购
searchInput: '',
clerkOptions: [], // 导购下拉列表
tableData: [],
currentPage: 1,
pageSize: 20,
total: 0,
loading: false,
selectRadio: 0, // 0:选择当页; 1:选择全部
multipleSelection: [],
assignShow: false,
// 是否显示会员列表
showMember: false,
storeObj: {},
gicDataCopy: [],
chainData: [],
navData: []
};
},
mounted() {
const that = this;
that.$emit('showTab', '2');
if (that.brandId) {
that.getGicData(that.brandId);
}
},
methods: {
/**
* 面包屑选择分组
* @param {Object} obj
* @param {Array} copyData
*/
async setParent(obj, copyData) {
const that = this;
for (let i = 0; i < copyData.length; i++) {
if (obj.parentGroupId == copyData[i].storeGroupId) {
copyData[i].expand = true;
if (copyData[i].parentGroupId != 0) {
await that.setParent(copyData[i], copyData);
}
}
}
},
/**
* 面包屑选择分组
* @param {Object} item
*/
async changeDepart(item) {
const that = this;
if (!!item.storeId) {
return false;
}
that.departObj = item;
that.showMember = false;
// 重新组装树形部门
let copyData = JSON.parse(JSON.stringify(that.gicDataCopy));
for (let i = 0; i < copyData.length; i++) {
if (that.departObj.parentGroupId == copyData[i].storeGroupId) {
copyData[i].expand = true;
if (copyData[i].parentGroupId != 0) {
await that.setParent(copyData[i], copyData);
}
}
}
that.gicData = await that.treeData(JSON.parse(JSON.stringify(copyData)));
that.gicData[0].expand = true;
},
/**
* 获取会员数据
* @param {Object} obj
*/
getStore(obj) {
const that = this;
that.storeObj = obj;
that.showMember = true;
that.getClerkData();
that.getTableList();
that.toGetNavData();
},
/**
* 是否在分配中
*/
async assignStatus() {
const that = this;
return new Promise((resolve, reject) => {
let para = {
storeId: that.storeObj.storeId
};
getAssignStatus(para)
.then(res => {
if (res.code == '0000') {
resolve(res.result);
return;
}
errMsg.errorMsg(res);
resolve(false);
})
.catch(function(error) {
resolve(false);
});
});
},
/**
* 关闭分配
*/
closeText() {
const that = this;
that.assignShow = false;
that.selectRadio = 0;
that.multipleSelection = [];
that.editRow = {};
that.$refs.multipleTable.clearSelection();
},
/**
* 完成分配回调
*/
submitText() {
const that = this;
that.selectRadio = 0;
that.multipleSelection = [];
that.assignShow = false;
that.$refs.multipleTable.clearSelection();
that.currentPage = 1;
that.getTableList();
// 后端分配是异步的,列表不会很快显示分配的导购
that.$alert('会员分配中,请稍候查看', '', {
confirmButtonText: '确定',
callback: action => {
that.currentPage = 1;
that.getTableList();
let t = setTimeout(function() {
that.currentPage = 1;
that.getTableList();
clearTimeout(t);
}, 1000);
}
});
},
/**
* 输入
*/
toInput: _debounce(function(e, value) {
const that = this;
that.currentPage = 1;
that.getTableList();
}, 500),
/**
* 搜索标签清空
*/
clearSearch() {
const that = this;
that.currentPage = 1;
that.getTableList();
},
/**
* 每次选中一个树中节点,把当前数据返回,
* 获取选中部门
* @param {Object} obj
*/
getSelectData(obj) {
const that = this;
that.departObj = obj;
that.selectRadio = 0;
that.showMember = false;
that.storeObj = {};
// 判断是不是门店
that.currentPage = 1;
that.tableData = [];
that.clerkOptions = [];
that.clerkId = '0'; // 导购
that.searchInput = '';
that.multipleSelection = [];
},
/**
* 表格选择
* @param {Array} val
*/
handleSelectionChange(val) {
this.multipleSelection = val;
},
/**
* 显示选择本页/全部
* @param {String} command
*/
handleCommand(command) {
this.selectRadio = command;
},
/**
* 分配
* @param {Number} index
* @param {Object} row
*/
async toAssignMember(index, row) {
const that = this;
const flag = await that.assignStatus();
if (flag) {
that.$message.error({
duration: 1000,
message: '会员正在分配中,请稍后再试'
});
return false;
}
that.editRow = row;
// 如果选中一个分配,就要把批量已选的全部置空
that.selectRadio = 0;
that.multipleSelection = [];
that.$refs.multipleTable.clearSelection();
that.assignShow = true;
},
/**
* 批量分配
*/
async toAssign() {
const that = this;
that.editRow = {};
const flag = await that.assignStatus();
if (flag) {
that.$message.error({
duration: 1000,
message: '会员正在分配中,请稍后再试'
});
return false;
}
if (!that.multipleSelection.length) {
that.$message.error({
duration: 1000,
message: '请选择会员'
});
return false;
}
that.assignShow = true;
},
/**
* 简单数组-->父子数组对象
* @param {Array} data
*/
async treeData(data) {
let tree = data.filter(father => {
// 循环所有项
let branchArr = data.filter(child => {
return father.storeGroupId == child.parentGroupId; // 返回每一项的子级数组
});
if (branchArr.length > 0) {
father.hasSonNode = true;
father.children = branchArr; // 如果存在子级,则给父级添加一个children属性,并赋值
} else {
father.hasSonNode = false;
father.children = [];
}
return father.parentGroupId == 0; // 返回第一层
});
return tree;
},
/**
* 获取 gic 数据
*/
getGicData() {
const that = this;
let para = {
enterpriseId: that.brandId,
wxEnterpriseRelatedId: that.wxEnterpriseRelatedId
};
getGroupList(para)
.then(async res => {
if (res.result.length) {
res.result.forEach(ele => {
ele.loading = false;
ele.expand = false;
ele.children = [];
ele.label = ele.storeGroupName;
if (ele.parentGroupId == 0) {
ele.expand = true;
that.departObj = ele;
}
});
that.gicDataCopy = JSON.parse(JSON.stringify(res.result));
that.gicData = await that.treeData(JSON.parse(JSON.stringify(res.result)));
}
})
.catch(function(error) {
});
},
/**
* 条件
*/
changeCondition() {
const that = this;
that.currentPage = 1;
that.getTableList();
},
/**
* 分页---页码变化
* @param {Number} val
*/
handleSizeChange(val) {
const that = this;
that.currentPage = 1;
that.pageSize = val;
that.getTableList();
},
/**
* 分页---当前页变化
* @param {Number} val
*/
handleCurrentChange(val) {
const that = this;
that.currentPage = val;
that.getTableList();
},
/**
* 获取面包屑
*/
toGetNavData() {
const that = this;
let params = {
departmentId: that.storeObj.storeGroupId
};
getNavChain( params)
.then(res => {
if (res.code == '0000') {
that.navData = res.result || [];
that.navData.push(that.storeObj);
return false;
}
errMsg.errorMsg(res);
})
.catch(function(error) {
});
},
/**
* 获取导购列表
*/
getClerkData() {
const that = this;
const para = {
enterpriseId: that.brandId,
wxEnterpriseRelatedId: that.wxEnterpriseRelatedId,
storeId: that.storeObj.storeId
};
getClerkList(para)
.then(res => {
that.clerkOptions = res.result || [];
})
.catch(function(error) {
});
},
/**
* 获取列表数据(只有门店才有)
*/
getTableList() {
const that = this;
const para = {
enterpriseId: that.brandId,
wxEnterpriseRelatedId: that.wxEnterpriseRelatedId,
pageNum: that.currentPage,
pageSize: that.pageSize,
storeId: that.storeObj.storeId,
clerkId: that.clerkId,
keyword: that.searchInput
};
getMemberList(para)
.then(res => {
that.tableData = res.result.result || [];
that.total = res.result.totalCount;
})
.catch(function(error) {
});
}
},
watch: {
brandId: function(newData, oldData) {
const that = this;
if (newData) {
that.showMember = false;
that.currentPage = 1;
that.tableData = [];
that.clerkOptions = [];
that.clerkId = '0'; // 导购
that.searchInput = '';
that.selectRadio = 0;
that.multipleSelection = [];
that.storeObj = {};
that.getGicData(that.brandId);
}
}
}
};
</script>
<style lang="less" scoped>
.w-500 {
width: 500px;
}
.w-195 {
width: 195px;
}
.color-1890ff {
color: #2f54eb;
}
.p-20 {
padding: 20px;
}
.p-l-38 {
padding-left: 38px;
}
.p-l-199 {
padding-left: 199px;
}
.m-b-10 {
margin-bottom: 10px;
}
.el-breadcrumb__inner.is-link:hover,
.el-breadcrumb__inner a:hover {
color: #2f54eb;
}
.app-detail-wrap {
height: 100%;
background: #fff;
.list-body {
position: relative;
width: 100%;
.list-left {
position: relative;
width: 300px;
min-width: 300px;
max-width: 300px;
padding: 20px 0 0 0px;
}
.list-right {
position: relative;
min-width: calc(100% - 300px);
min-height: calc(100vh - 94px);
border-left: 1px solid #e4e7ed;
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2019-03-20 14:36:37
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 09:47:35
-->
<template>
<div class="my-customer-wrap common-set-wrap">
<nav-crumb :navpath="navpath" @selectBrandId="selectBrandId"> </nav-crumb>
<div class="right-content">
<div class="right-box" style="min-height: calc(100vh - 112px);">
<div class="apps-content flex" style="min-height: calc(100vh - 112px);">
<div class="apps-content-left w-157" style="min-height: calc(100vh - 112px);">
<common-detail-left :tabListData="tabListData" :activeSelTab="activeSelTab" @setSelectTab="setSelectTab"> </common-detail-left>
</div>
<div class="apps-content-right">
<transition name="fade" mode="out-in">
<router-view :brandId="activeBrand" :activeGroupId="activeGroup" :tabType="activeTab" @showTab="showTab"> </router-view>
</transition>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import navCrumb from '@/components/nav/nav-app.vue';
import commonDetailLeft from '@/components/app/app-detail-left.vue';
// import errMsg from '@/common/js/error';
// import showMsg from '@/common/js/showmsg';
export default {
name: 'reviewed',
components: {
navCrumb,
commonDetailLeft
},
data() {
return {
bgHeight: window.screen.availHeight - 380 + 'px',
activeSelTab: '1',
activeTab: '1',
// 面包屑参数
navpath: [
{
name: '首页',
path: '/index'
},
{
name: '我的顾客',
path: ''
}
],
tabListData: [
{
tabId: '1',
tabName: '会员基础设置',
icon: 'iconjichushezhi',
onlyIconActive: false,
children: [
{
tabId: '11',
tabName: '会员展示设置',
icon: ''
},
{
tabId: '12',
tabName: '会员分组设置',
icon: ''
},
{
tabId: '13',
tabName: '会员搜索设置',
icon: ''
},
{
tabId: '14',
tabName: '会员详情设置',
icon: ''
}
]
},
{
tabId: '2',
tabName: '我的顾客列表',
icon: 'icongukeguanliicon'
}
],
activeBrand: '', // 商户(品牌) id
activeGroup: '', // 商户(品牌) groupId
};
},
mounted() {
document.documentElement.style.backgroundColor = '#f0f2f5';
},
destroyed() {
document.documentElement.style.backgroundColor = '#fff';
},
methods: {
/**
* 路由跳转
* @param {String} path
*/
changeRoute(path) {
this.$router.push(path);
},
/**
* 选择后返回menuUrl,做各路由判断
* @param {Object} item
*/
setSelectTab(item) {
const that = this;
that.activeTab = item.menuUrl;
if (item.target == 1) {
if (item.menuUrl.indexOf('http') != -1) {
window.open(item.menuUrl);
}else {
window.open(`/haoban-4/#${item.menuUrl}`);
}
}else {
that.$router.push(item.menuUrl);
}
},
/**
* 各路由返回 menuUrl
* @param {String} menuUrl
*/
showTab(menuUrl) {
const that = this;
that.activeTab = menuUrl;
that.activeSelTab = menuUrl;
that.tabListData.forEach(ele => {
if (ele.menuUrl == menuUrl) {
ele.onlyIconActive = false;
}
if (!!ele.children) {
ele.children.forEach(el => {
if (el.menuUrl == menuUrl) {
ele.onlyIconActive = true;
}
if (!!el.children) {
el.children.forEach(item => {
if (item.menuUrl == menuUrl) {
ele.onlyIconActive = true;
}
});
}
});
}
});
}
},
watch: {
activeBrand: function(newData, oldData) {
const that = this;
that.activeBrand = newData;
},
activeGroup: function(newData, oldData) {
const that = this;
that.activeGroup = newData;
}
}
};
</script>
<style type="text/scss" lang="scss" scoped>
.bg-82C5FF {
background: #82c5ff;
}
.color-508CEE {
color: #508cee;
}
.color-FF585C {
color: #ff585c;
}
.line-h-18 {
line-height: 18px;
}
.tooltip-text {
width: 100%;
white-space: pre-wrap;
word-break: break-all;
}
.my-customer-wrap {
height: 100%;
}
.right-content {
/*width: 100%;*/
padding: 0 20px 20px 20px;
min-height: calc(100% - 160px);
.right-box {
background: #fff;
min-height: 500px;
padding: 0px;
.apps-content {
.apps-content-left {
min-width: 157px;
height: 100%;
background: #fff;
overflow-x: hidden;
overflow-y: auto;
.apps-content-left__title {
height: 55px;
line-height: 55px;
padding: 0 0 0 18px;
}
.tab-left-list-cell {
position: relative;
text-align: left;
margin-top: 15px;
height: 30px;
line-height: 30px;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
&:hover {
background: rgba(24, 144, 255, 0.06);
i {
color: #2f54eb;
}
}
&.active-tab {
background: rgba(24, 144, 255, 0.06);
&::before {
content: ' ';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background: #2f54eb;
z-index: 1;
}
i {
color: #2f54eb;
}
}
.child-tab-left-list {
li {
position: relative;
text-align: left;
height: 30px;
line-height: 30px;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
&:hover {
background: rgba(24, 144, 255, 0.06);
i {
color: #2f54eb;
}
}
&.active-tab {
background: rgba(24, 144, 255, 0.06);
&::before {
content: ' ';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background: #2f54eb;
z-index: 1;
}
i {
color: #2f54eb;
}
}
}
}
}
}
.apps-content-right {
width: calc(100% - 120px);
padding-left: 10px;
background: #f0f2f5;
.daily-set-wrap {
height: 100%;
background: #fff;
}
.app-detail-wrap {
height: 100%;
background: #fff;
}
.common-set-wrap {
height: 100%;
background: #fff;
}
}
}
}
}
</style>
<!--
* @Descripttion: 当前组件信息
* @version: 1.0.0
* @Author: 无尘
* @Date: 2018-10-10 14:44:45
* @LastEditors: 无尘
* @LastEditTime: 2020-08-27 09:46:47
-->
<template>
<div class="enterprise-wrap">
<!-- 公共头部菜单插件 -->
<vue-office-header :projectName="projectName" @collapseTag="collapseTag" @toRouterView="toRouterView"> </vue-office-header>
<div class="enterprise-wrap__body">
<div id="content" class="content">
<div class="content-body" :style="{ height: contentHeight }">
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</div>
</div>
</div>
</template>
<script>
import vueOfficeHeader from '@/components/vue-office-header.vue';
export default {
name: 'AppIndexPage',
components: {
vueOfficeHeader
},
data() {
return {
projectName: 'haoban-manage-web', // 当前项目名
collapseFlag: false, // 折叠参数
contentHeight: window.screen.availHeight - 5 + 'px'
};
},
mounted() {
const that = this;
that.contentHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 64 + 'px';
},
methods: {
/**
* 路由跳转
* @param {Object} val
*/
toRouterView(val) {
let that = this;
// 模拟检查数据
// //有两个参数
// {
// name:,
// path:
// }
that.$router.push({
path: val.path
});
},
/**
* 折叠事件
* @param {Boolean} val
*/
collapseTag(val) {
let that = this;
that.collapseFlag = val;
}
},
computed: {}
};
</script>
<style lang="less" scoped>
.enterprise-wrap {
background: #f0f2f5;
.enterprise-wrap__body {
.content {
padding-top: 46px;
min-width: 1400px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
}
}
</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