68 Commits

Author SHA1 Message Date
lcc 902ab2b403 修改专题配置 2024-08-26 11:31:53 +08:00
lcc a8e3edce9a 增加私域专题底部图片配置 2024-08-22 17:35:24 +08:00
lcc 1f263ae30b 修改专题模块 2024-08-12 23:24:46 +08:00
lcc 111efc1b40 修改专题 2024-08-11 18:26:44 +08:00
lcc 5654eca107 修改专题模块 2024-08-09 16:23:11 +08:00
lcc 8f6dcd2884 增加模块类型 2024-08-08 16:36:36 +08:00
lcc 0c6d0b22ae 修改报名状态修改判断 2024-08-08 11:52:00 +08:00
lcc 55ee6f735a 增加配置报名处理方式 2024-08-07 18:10:02 +08:00
小鱼开发 511a5908f5 1 2024-08-04 16:33:50 +08:00
lcc bc4bdda418 修改专题 2024-07-29 19:23:52 +08:00
lcc 3d53c51cd0 修改专题 2024-07-28 17:51:10 +08:00
lcc b858ac3ed0 增加私域专题模块 2024-07-26 14:08:55 +08:00
小鱼开发 a55e221e4b 77 2024-07-12 22:29:44 +08:00
小鱼开发 e66ba02af3 level 2024-06-25 17:49:53 +08:00
chenrx 92e14f6c22 活动配置新增订单归属 2024-06-17 14:07:59 +08:00
chenrx da563d7b12 修改活动配置1 2024-06-14 17:50:14 +08:00
chenrx f80deebb51 修改活动配置 2024-06-14 16:31:51 +08:00
xiaoyu 27b8f6343c logo 2023-09-03 20:08:42 +08:00
dengbw b1b6628af7 加黑名单 2023-06-13 09:39:06 +08:00
dengbw d21e1bfba7 修改删除方式 2023-05-19 11:48:59 +08:00
lccsw 2e18807dff 修改url 2023-05-18 14:16:11 +08:00
dengbw eb68274d45 修改删除方式 2023-05-15 17:44:00 +08:00
dengbw 48c6ed2d2c 分组管理加导出 2023-05-06 17:35:11 +08:00
dengbw 02b60dd9aa 加抽奖屏幕显示 2023-05-06 09:52:34 +08:00
dengbw fbfea04384 订单加时间搜索2 2023-05-05 15:31:14 +08:00
dengbw 0e9ff425ae 订单加时间搜索 2023-05-05 11:32:14 +08:00
dengbw e6463f7ba2 订单加导入 2023-04-27 11:47:55 +08:00
dengbw 560821e9c7 订单加内部人员 2023-03-24 15:46:05 +08:00
dengbw 82ca0f6348 列表分组动态显示2 2023-03-23 17:19:52 +08:00
dengbw 2a0dda7de3 列表分组动态显示 2023-03-23 16:15:56 +08:00
dengbw d8cecb1b54 数据统计默认第一个商品2 2023-03-21 16:37:58 +08:00
dengbw 0b98dad3f1 数据统计默认第一个商品 2023-03-21 15:00:26 +08:00
dengbw fc222664ef 活动加报名预约3 2023-03-17 17:27:24 +08:00
dengbw 2042e9b875 活动加报名预约2 2023-03-17 14:16:25 +08:00
dengbw 38d764a9a4 活动加报名预约 2023-03-17 13:45:58 +08:00
dengbw e409438388 修改活动 2023-03-07 16:06:14 +08:00
dengbw cc86158f6e 新增黑名单 2023-03-07 14:10:13 +08:00
dengbw 80be328353 新增客户列表 2023-03-03 10:00:55 +08:00
dengbw 23cf8a7e36 新增核销记录 2023-02-23 15:50:29 +08:00
dengbw d925d7d69c 新增抽奖配置2 2023-02-03 11:06:21 +08:00
dengbw 82b8f51998 新增抽奖配置 2023-02-02 17:04:08 +08:00
dengbw bfe752b20a 马甲显示限制 2023-01-28 15:43:00 +08:00
dengbw 92eb2e8fd1 活动文案调整 2023-01-28 10:36:21 +08:00
dengbw bf48619908 加复制活动 2023-01-18 14:33:38 +08:00
dengbw e853cb6ec5 加中奖名单 2023-01-09 10:07:44 +08:00
dengbw b1d40942d0 加直播数据统计 2023-01-05 16:56:01 +08:00
dengbw c4b147d63a 加机构管理目录 2022-12-23 14:12:37 +08:00
dengbw 35de4a5d2b 加客户筛选 2022-12-22 14:09:22 +08:00
dengbw 348c7ce808 加客户列表 2022-12-20 17:31:49 +08:00
dengbw 6070aaf59a 显示ID2 2022-12-19 16:18:18 +08:00
dengbw 176c404808 显示ID 2022-12-19 15:18:24 +08:00
dengbw 23b2c479f3 加用户马甲 2022-12-16 17:34:46 +08:00
dengbw 0524eb6c43 加统计导出 2022-12-12 17:23:57 +08:00
dengbw 1c03a24903 加顾问分组 2022-12-10 22:59:55 +08:00
dengbw 982e36c32c 加门店1级 2022-12-10 14:09:28 +08:00
dengbw 8e65b980e5 加分组订单 2022-12-09 17:40:01 +08:00
dengbw 3b6a137a33 加分组原始门店搜索 2022-12-09 14:09:50 +08:00
dengbw 67f2740a0b 加分组原始门店 2022-12-09 13:45:13 +08:00
dengbw 28ab079413 修改活动分组用户 2022-12-08 16:14:48 +08:00
dengbw 54e3df83e7 修改活动分组2 2022-12-07 17:19:59 +08:00
dengbw e4569f0fc6 修改活动分组 2022-12-07 16:54:44 +08:00
dengbw 3e24aea2af 加活动分组 2022-12-07 14:22:47 +08:00
dengbw e943490ac3 加活动ID 2022-11-24 16:48:37 +08:00
dengbw c6687f17c1 机构跟裂变团去掉性别 2022-11-24 09:38:27 +08:00
dengbw c344a38b8b 数据统计刷新4 2022-11-23 16:43:02 +08:00
dengbw 82087efced 数据统计刷新3 2022-11-23 16:05:59 +08:00
dengbw 4ab58678e0 数据统计刷新2 2022-11-23 15:55:31 +08:00
dengbw 771e7cd190 数据统计刷新 2022-11-23 15:29:58 +08:00
113 changed files with 11981 additions and 449 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
VUE_APP_API_BASE_URL=http://market.dev.liche.cn/api
VUE_APP_API_BASE_URL=http://market.lc.haodian.cn/api
#npm run serve 加载环境
+2 -2
View File
@@ -57,7 +57,7 @@
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = 'https://bo.liche.cn/favicon_liche.ico';
link.href = 'https://bo.liche.cn/favicon_hd.ico';
document.getElementsByTagName('head')[0].appendChild(link);
}else if(hostname=='dongfeng.haodian.cn'){
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
@@ -68,7 +68,7 @@
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = 'https://bo.liche.cn/favicon_liche.ico';
link.href = 'https://bo.liche.cn/favicon_hd.ico';
}
}
</script>
@@ -5,7 +5,7 @@ import request from '@/utils/request';
* @param params 查询条件
*/
export async function pageUsers(params) {
const res = await request.get('/sylive/user/page', {
const res = await request.get('/institution/organizationUser/page', {
params
});
if (res.data.code === 0) {
@@ -19,9 +19,7 @@ export async function pageUsers(params) {
* @param params 查询条件
*/
export async function listUsers(params) {
const res = await request.get('/sylive/user', {
params
});
const res = await request.post('/institution/organizationUser/list', params);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
@@ -33,7 +31,7 @@ export async function listUsers(params) {
* @param id 用户id
*/
export async function getUser(id) {
const res = await request.get('/sylive/user/' + id);
const res = await request.get('/institution/organizationUser/' + id);
if (res.data.code === 0) {
return res.data.data;
}
@@ -45,7 +43,7 @@ export async function getUser(id) {
* @param data 用户信息
*/
export async function addUser(data) {
const res = await request.post('/sylive/user', data);
const res = await request.post('/institution/organizationUser', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -57,7 +55,7 @@ export async function addUser(data) {
* @param data 用户信息
*/
export async function updateUser(data) {
const res = await request.put('/sylive/user', data);
const res = await request.put('/institution/organizationUser', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -69,20 +67,16 @@ export async function updateUser(data) {
* @param id 用户id
*/
export async function removeUser(id) {
const res = await request.delete('/sylive/user/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeUsers([id]);
}
/**
* 批量删除用户
* @param data 用户id集合
* @param ids 用户id集合
*/
export async function removeUsers(data) {
const res = await request.delete('/sylive/user/batch', {
data
export async function removeUsers(ids) {
const res = await request.delete('/institution/organizationUser/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
@@ -96,7 +90,7 @@ export async function removeUsers(data) {
* @param status 状态
*/
export async function updateUserStatus(userId, status) {
const res = await request.put('/sylive/user/status', {
const res = await request.put('/institution/organizationUser/status', {
userId,
status
});
@@ -113,7 +107,7 @@ export async function updateUserStatus(userId, status) {
* @returns {Promise<string>}
*/
export async function updateUserPassword(userId, password = '123456') {
const res = await request.put('/sylive/user/password', {
const res = await request.put('/institution/organizationUser/password', {
userId,
password
});
@@ -130,7 +124,10 @@ export async function updateUserPassword(userId, password = '123456') {
export async function importUsers(file) {
const formData = new FormData();
formData.append('file', file);
const res = await request.post('/sylive/user/import', formData);
const res = await request.post(
'/institution/organizationUser/import',
formData
);
if (res.data.code === 0) {
return res.data.message;
}
@@ -141,11 +138,11 @@ export async function importUsers(file) {
* 检查用户是否存在
* @param field 检查的字段
* @param value 字段的值
* @param id 修改时的id
* @param organizationId 机构id
*/
export async function checkExistence(field, value, id) {
const res = await request.get('/sylive/user/existence', {
params: { field, value, id }
export async function checkExistence(field, value, organizationId) {
const res = await request.get('/institution/organizationUser/existence', {
params: { field, value, organizationId }
});
if (res.data.code === 0) {
return res.data.message;
@@ -5,7 +5,7 @@ import request from '@/utils/request';
* @param params 查询条件
*/
export async function pageOrganizations(params) {
const res = await request.get('/sylive/organization/page', {
const res = await request.get('/institution/organization/page', {
params
});
if (res.data.code === 0) {
@@ -19,7 +19,7 @@ export async function pageOrganizations(params) {
* @param params 查询条件
*/
export async function listOrganizations(params) {
const res = await request.get('/sylive/organization', {
const res = await request.get('/institution/organization', {
params
});
if (res.data.code === 0) {
@@ -33,7 +33,7 @@ export async function listOrganizations(params) {
* @param params 查询条件
*/
export async function listOrganizationParent(params) {
const res = await request.get('/sylive/organization/parent', {
const res = await request.get('/institution/organization/parent', {
params
});
if (res.data.code === 0) {
@@ -47,7 +47,7 @@ export async function listOrganizationParent(params) {
* @param data 机构信息
*/
export async function addOrganization(data) {
const res = await request.post('/sylive/organization', data);
const res = await request.post('/institution/organization', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -59,7 +59,7 @@ export async function addOrganization(data) {
* @param data 机构信息
*/
export async function updateOrganization(data) {
const res = await request.put('/sylive/organization', data);
const res = await request.put('/institution/organization', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -71,9 +71,33 @@ export async function updateOrganization(data) {
* @param id 机构id
*/
export async function removeOrganization(id) {
const res = await request.delete('/sylive/organization/' + id);
return removeOrganizations([id]);
}
/**
* 批量删除机构
* @param data 机构id集合
*/
export async function removeOrganizations(ids) {
const res = await request.delete('/institution/organization/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 机构详情
* @param organizationId 机构id
*/
export async function infoOrganization(organizationId) {
const res = await request.get('/institution/organization/info', {
params: { organizationId }
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -5,7 +5,7 @@ import request from '@/utils/request';
* @param params 查询条件
*/
export async function pageTeamUser(params) {
const res = await request.get('/sylive/teamUser/page', {
const res = await request.get('/institution/teamUser/page', {
params
});
if (res.data.code === 0) {
@@ -19,9 +19,7 @@ export async function pageTeamUser(params) {
* @param params 查询条件
*/
export async function listTeamUser(params) {
const res = await request.get('/sylive/teamUser', {
params
});
const res = await request.post('/institution/teamUser/list', params);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
@@ -33,7 +31,7 @@ export async function listTeamUser(params) {
* @param id 用户id
*/
export async function getTeamUser(id) {
const res = await request.get('/sylive/teamUser/' + id);
const res = await request.get('/institution/teamUser/' + id);
if (res.data.code === 0) {
return res.data.data;
}
@@ -45,7 +43,7 @@ export async function getTeamUser(id) {
* @param data 用户信息
*/
export async function addTeamUser(data) {
const res = await request.post('/sylive/teamUser', data);
const res = await request.post('/institution/teamUser', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -57,7 +55,7 @@ export async function addTeamUser(data) {
* @param data 用户信息
*/
export async function updateTeamUser(data) {
const res = await request.put('/sylive/teamUser', data);
const res = await request.put('/institution/teamUser', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -69,7 +67,7 @@ export async function updateTeamUser(data) {
* @param id 用户id
*/
export async function removeTeamUser(id) {
const res = await request.delete('/sylive/teamUser/' + id);
const res = await request.delete('/institution/teamUser/' + id);
if (res.data.code === 0) {
return res.data.message;
}
@@ -81,7 +79,7 @@ export async function removeTeamUser(id) {
* @param data 用户id集合
*/
export async function removeTeamUsers(data) {
const res = await request.delete('/sylive/teamUser/batch', {
const res = await request.delete('/institution/teamUser/batch', {
data
});
if (res.data.code === 0) {
@@ -96,7 +94,7 @@ export async function removeTeamUsers(data) {
* @param status 状态
*/
export async function updateTeamUserStatus(userId, status) {
const res = await request.put('/sylive/teamUser/status', {
const res = await request.put('/institution/teamUser/status', {
userId,
status
});
@@ -113,7 +111,7 @@ export async function updateTeamUserStatus(userId, status) {
* @returns {Promise<string>}
*/
export async function updateTeamUserPassword(userId, password = '123456') {
const res = await request.put('/sylive/teamUser/password', {
const res = await request.put('/institution/teamUser/password', {
userId,
password
});
@@ -130,7 +128,7 @@ export async function updateTeamUserPassword(userId, password = '123456') {
export async function importTeamUser(file) {
const formData = new FormData();
formData.append('file', file);
const res = await request.post('/sylive/teamUser/import', formData);
const res = await request.post('/institution/teamUser/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
@@ -144,7 +142,7 @@ export async function importTeamUser(file) {
* @param id 修改时的id
*/
export async function checkExistence(field, value, id) {
const res = await request.get('/sylive/teamUser/existence', {
const res = await request.get('/institution/teamUser/existence', {
params: { field, value, id }
});
if (res.data.code === 0) {
@@ -5,7 +5,7 @@ import request from '@/utils/request';
* @param params 查询条件
*/
export async function pageTeams(params) {
const res = await request.get('/sylive/team/page', {
const res = await request.get('/institution/team/page', {
params
});
if (res.data.code === 0) {
@@ -19,7 +19,7 @@ export async function pageTeams(params) {
* @param params 查询条件
*/
export async function listTeams(params) {
const res = await request.get('/sylive/team', {
const res = await request.get('/institution/team', {
params
});
if (res.data.code === 0) {
@@ -33,7 +33,7 @@ export async function listTeams(params) {
* @param data 团队信息
*/
export async function addTeam(data) {
const res = await request.post('/sylive/team', data);
const res = await request.post('/institution/team', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -45,7 +45,7 @@ export async function addTeam(data) {
* @param data 团队信息
*/
export async function updateTeam(data) {
const res = await request.put('/sylive/team', data);
const res = await request.put('/institution/team', data);
if (res.data.code === 0) {
return res.data.message;
}
@@ -57,7 +57,7 @@ export async function updateTeam(data) {
* @param id 团队id
*/
export async function removeTeam(id) {
const res = await request.delete('/sylive/team/' + id);
const res = await request.delete('/institution/team/' + id);
if (res.data.code === 0) {
return res.data.message;
}
+81 -12
View File
@@ -15,17 +15,27 @@ export async function pageActivity(params) {
}
/**
* 根据id查询活动
* @param id 活动id
* 获取活动信息
* @param params 查询条件
*/
export async function getActivity(id) {
const res = await request.get('/sylive/activity/' + id);
export async function getActivityInfo(params) {
const res = await request.get('/sylive/activity/info', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询活动
* @param id 活动id
*/
export async function getActivity(id) {
return getActivityInfo({ activityId: id });
}
/**
* 查询活动列表
* @param params 查询条件
@@ -64,6 +74,18 @@ export async function updateActivity(data) {
return Promise.reject(new Error(res.data.message));
}
/**
* 复制活动
* @param id 活动id
*/
export async function copyActivity(id) {
const res = await request.get('/sylive/activity/copy/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改活动商品
* @param data 活动信息
@@ -93,20 +115,16 @@ export async function updateActivityCoupon(data) {
* @param id 活动id
*/
export async function removeActivity(id) {
const res = await request.delete('/sylive/activity/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeActivitys([id]);
}
/**
* 批量删除活动
* @param data 活动id集合
* @param ids 活动id集合
*/
export async function removeActivitys(data) {
export async function removeActivitys(ids) {
const res = await request.delete('/sylive/activity/batch', {
data
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
@@ -321,3 +339,54 @@ export async function getStatisticsStackedWatchOrder(params) {
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改抽奖配置
* @param data 信息
*/
export async function updateActivityDraw(data) {
const res = await request.put('/sylive/activity/draw', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改回访标签
* @param data 信息
*/
export async function updateActivityVisitTag(data) {
const res = await request.put('/sylive/activity/visit_tag', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改黑名单
* @param data 信息
*/
export async function updateActivityBlacklist(data) {
const res = await request.put('/sylive/activity/blacklist', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入黑名单
* @param file excel文件
*/
export async function importActivityBlacklist(file, activityId) {
const formData = new FormData();
formData.append('file', file);
formData.append('activityId', activityId);
const res = await request.post('/sylive/activity/blacklist_import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+64
View File
@@ -0,0 +1,64 @@
import request from '@/utils/request';
/**
* 分页查询黑名单
* @param params 查询条件
*/
export async function pageBlacklist(params) {
const res = await request.get('/sylive/blacklist/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加黑名单
* @param data 黑名单信息
*/
export async function addBlacklist(data) {
const res = await request.post('/sylive/blacklist', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除黑名单
* @param id 黑名单id
*/
export async function removeBlacklist(id) {
return removeBlacklists([id]);
}
/**
* 批量删除黑名单
* @param ids 黑名单id集合
*/
export async function removeBlacklists(ids) {
const res = await request.delete('/sylive/blacklist/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入黑名单
* @param file excel文件
*/
export async function importBlacklist(file, activityId) {
const formData = new FormData();
formData.append('file', file);
formData.append('activityId', activityId);
const res = await request.post('/sylive/blacklist/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+4 -8
View File
@@ -85,20 +85,16 @@ export async function updateGoodsStatus(itemId, status) {
* @param id 商品id
*/
export async function removeGoods(id) {
const res = await request.delete('/sylive/goods/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeGoodss([id]);
}
/**
* 批量删除活动
* @param data 商品id集合
* @param ids 商品id集合
*/
export async function removeGoodss(data) {
export async function removeGoodss(ids) {
const res = await request.delete('/sylive/goods/batch', {
data
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
+44
View File
@@ -0,0 +1,44 @@
import request from '@/utils/request';
/**
* 查询订单列表
* @param params 查询条件
*/
export async function listGroupsCustomer(params) {
const res = await request.get('/sylive/groupsCustomer', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
*/
export async function exportGroupsCustomer(params) {
const res = await request.get('/sylive/groupsCustomer/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入用户
* @param file excel文件
*/
export async function importGroupsCustomer(file, activityId) {
const formData = new FormData();
formData.append('file', file);
formData.append('activityId', activityId);
const res = await request.post('/sylive/groupsCustomer/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+69
View File
@@ -0,0 +1,69 @@
import request from '@/utils/request';
/**
* 查询订单列表
* @param params 查询条件
*/
export async function listGroupsExchange(params) {
const res = await request.get('/sylive/groupsExchange', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
*/
export async function exportGroupsExchange(params) {
const res = await request.get('/sylive/groupsExchange/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 操作详情
* @param params 查询条件
*/
export async function getGroupsExchangeDetail(params) {
const res = await request.get('/sylive/groupsExchange/detail', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改使用状态
* @param data 操作信息
*/
export async function updateGroupsExchangeUseStatus(data) {
const res = await request.put('/sylive/groupsExchange/status', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入用户
* @param file excel文件
*/
export async function importGroupsExchange(file) {
const formData = new FormData();
formData.append('file', file);
const res = await request.post('/sylive/groupsExchange/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+44
View File
@@ -0,0 +1,44 @@
import request from '@/utils/request';
/**
* 查询订单列表
* @param params 查询条件
*/
export async function listGroupsOrder(params) {
const res = await request.get('/sylive/groupsOrder', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
*/
export async function exportGroupsOrder(params) {
const res = await request.get('/sylive/groupsOrder/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入订单
* @param file excel文件
*/
export async function importGroupsOrder(file, activityId) {
const formData = new FormData();
formData.append('file', file);
formData.append('activityId', activityId);
const res = await request.post('/sylive/groupsOrder/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+141
View File
@@ -0,0 +1,141 @@
import request from '@/utils/request';
/**
* 根据活动id查询分组数据统计
* @param id 活动id
*/
export async function getGroupsStatistics(activityId) {
const res = await request.get('/sylive/groupsStatistics', {
params: { activityId }
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取漏头数据
* @param params 查询条件
*/
export async function getGroupsStatisticsFunnel(params) {
const res = await request.get('/sylive/groupsStatistics/funnel', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取分级数据
* @param params 查询条件
*/
export async function getGroupsStatisticsLevel(params) {
const res = await request.get('/sylive/groupsStatistics/level', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取门店数据
* @param params 查询条件
*/
export async function getGroupsStatisticsBiz(params) {
const res = await request.get('/sylive/groupsStatistics/biz', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取顾问数据
* @param params 查询条件
*/
export async function getGroupsStatisticsConsultant(params) {
const res = await request.get('/sylive/groupsStatistics/consultant', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取客户数据
* @param params 查询条件
*/
export async function getGroupsStatisticsCustomer(params) {
const res = await request.get('/sylive/groupsStatistics/customer', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取观看下单统计折线图数据
* @param params 查询条件
*/
export async function getGroupsStatisticsWatchOrder(params) {
const res = await request.get('/sylive/groupsStatistics/stacked_watchOrder', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出门店
* @param params 查询条件
*/
export async function exportGroupsStatisticsBiz(params) {
const res = await request.get('/sylive/groupsStatistics/biz_export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出顾问
* @param params 查询条件
*/
export async function exportGroupsStatisticsConsultant(params) {
const res = await request.get('/sylive/groupsStatistics/consultant_export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出客户
* @param params 查询条件
*/
export async function exportGroupsStatisticsCustomer(params) {
const res = await request.get('/sylive/groupsStatistics/customer_export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+164
View File
@@ -0,0 +1,164 @@
import request from '@/utils/request';
/**
* 分页查询用户
* @param params 查询条件
*/
export async function pageGroupsUser(params) {
const res = await request.get('/sylive/groupsUser/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询用户列表
* @param params 查询条件
*/
export async function listGroupsUser(params) {
const res = await request.get('/sylive/groupsUser', {
params
});
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询用户
* @param id 用户id
*/
export async function getGroupsUser(id) {
const res = await request.get('/sylive/groupsUser/' + id);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加用户
* @param data 用户信息
*/
export async function addGroupsUser(data) {
const res = await request.post('/sylive/groupsUser', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改用户
* @param data 用户信息
*/
export async function updateGroupsUser(data) {
const res = await request.put('/sylive/groupsUser', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除用户
* @param id 用户id
*/
export async function removeGroupsUser(id) {
return removeGroupsUsers([id]);
}
/**
* 批量删除用户
* @param ids 用户id集合
*/
export async function removeGroupsUsers(ids) {
const res = await request.delete('/sylive/groupsUser/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改用户状态
* @param groupsUserId 用户id
* @param status 状态
*/
export async function updateGroupsUserStatus(groupsUserId, status) {
const res = await request.put('/sylive/groupsUser/status', {
groupsUserId,
status
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 重置用户密码
* @param userId 用户id
* @param password 密码
* @returns {Promise<string>}
*/
export async function updateGroupsUserPassword(userId, password = '123456') {
const res = await request.put('/sylive/groupsUser/password', {
userId,
password
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入用户
* @param file excel文件
*/
export async function importGroupsUser(file) {
const formData = new FormData();
formData.append('file', file);
const res = await request.post('/sylive/groupsUser/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 检查用户是否存在
* @param field 检查的字段
* @param value 字段的值
* @param id 修改时的id
*/
export async function checkExistence(field, value, id) {
const res = await request.get('/sylive/groupsUser/existence', {
params: { field, value, id }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 同步原始门店用户
* @param groupsId 分组id
*/
export async function synchronousGroupsUser(groupsId) {
const res = await request.get('/sylive/groupsUser/synchronous', {
params: { groupsId }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+43
View File
@@ -0,0 +1,43 @@
import request from '@/utils/request';
/**
* 查询订单列表
* @param params 查询条件
*/
export async function listGroupsWin(params) {
const res = await request.get('/sylive/groupsWin', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
*/
export async function exportGroupsWin(params) {
const res = await request.get('/sylive/groupsWin/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 中奖类型
* @param params 查询条件
*/
export async function getGroupsWinType(params) {
const res = await request.get('/sylive/groupsWin/win_type', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+95
View File
@@ -0,0 +1,95 @@
import request from '@/utils/request';
/**
* 分页查询分组
* @param params 查询条件
*/
export async function pageGroups(params) {
const res = await request.get('/sylive/groups/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询分组列表
* @param params 查询条件
*/
export async function listGroups(params) {
const res = await request.get('/sylive/groups', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询上级分组列表
* @param params 查询条件
*/
export async function listGroupsParent(params) {
const res = await request.get('/sylive/groups/parent', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加分组
* @param data 分组信息
*/
export async function addGroups(data) {
const res = await request.post('/sylive/groups', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改分组
* @param data 分组信息
*/
export async function updateGroups(data) {
const res = await request.put('/sylive/groups', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除分组
* @param id 分组id
*/
export async function removeGroups(id) {
const res = await request.delete('/sylive/groups', {
data: { id }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出分组所有顾问
* @param params 查询条件
*/
export async function exportGroupsConsultant(params) {
const res = await request.get('/sylive/groups/consultant_export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+77
View File
@@ -0,0 +1,77 @@
import request from '@/utils/request';
/**
* 查询直播列表
* @param params 查询条件
*/
export async function listLive(params) {
const res = await request.get('/sylive/live', {
params
});
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 同步直播场次数据
* @param params 查询条件
*/
export async function sessionApi(params) {
const res = await request.get('/sylive/live/session_api', {
params
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 同步直播观看详情数据
* @param params 查询条件
*/
export async function viewApi(params) {
const res = await request.get('/sylive/live/view_api', {
params
});
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出直播
* @param params 查询条件
*/
export async function exportLive(params) {
const res = await request.get('/sylive/live/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function listViewlog(params) {
const res = await request.get('/sylive/live/viewlog', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function exportViewlog(params) {
const res = await request.get('/sylive/live/export_viewlog', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+164
View File
@@ -0,0 +1,164 @@
import request from '@/utils/request';
/**
* 分页查询用户
* @param params 查询条件
*/
export async function pageMembers(params) {
const res = await request.get('/sylive/members/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改马甲
* @param userId 用户id
* @param maJiaId 马甲id
*/
export async function updateMembersMaJia(userId, maJiaId) {
const res = await request.put('/sylive/members/majia', {
userId,
maJiaId
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询用户列表
* @param params 查询条件
*/
export async function listMembers(params) {
const res = await request.post('/sylive/members/list', params);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询用户
* @param id 用户id
*/
export async function getMembers(id) {
const res = await request.get('/sylive/members/' + id);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加用户
* @param data 用户信息
*/
export async function addMembers(data) {
const res = await request.post('/sylive/members', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改用户
* @param data 用户信息
*/
export async function updateMembers(data) {
const res = await request.put('/sylive/members', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除用户
* @param id 用户id
*/
export async function removeMembers(id) {
return removeMembersBatch([id]);
}
/**
* 批量删除用户
* @param ids 用户id集合
*/
export async function removeMembersBatch(ids) {
const res = await request.delete('/sylive/members/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改用户状态
* @param userId 用户id
* @param status 状态
*/
export async function updateMembersStatus(userId, status) {
const res = await request.put('/sylive/members/status', {
userId,
status
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 重置用户密码
* @param membersId 用户id
* @param password 密码
* @returns {Promise<string>}
*/
export async function updateMembersPassword(membersId, password = '123456') {
const res = await request.put('/sylive/members/password', {
membersId,
password
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导入用户
* @param file excel文件
*/
export async function importMembers(file) {
const formData = new FormData();
formData.append('file', file);
const res = await request.post('/sylive/members/import', formData);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 检查用户是否存在
* @param field 检查的字段
* @param value 字段的值
* @param organizationId 机构id
*/
export async function checkExistence(field, value, organizationId) {
const res = await request.get('/sylive/members/existence', {
params: { field, value, organizationId }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
-26
View File
@@ -1,19 +1,5 @@
import request from '@/utils/request';
/**
* 分页查询订单
* @param params 查询条件
*/
export async function pageOrder(params) {
const res = await request.get('/sylive/order/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询订单列表
* @param params 查询条件
@@ -28,18 +14,6 @@ export async function listOrder(params) {
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询订单
* @param id 订单id
*/
export async function getOrder(id) {
const res = await request.get('/sylive/order/' + id);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
+7 -11
View File
@@ -53,24 +53,20 @@ export async function updateDictionaryData(data) {
}
/**
* 删除字典数据
* @param id 字典数据id
* 删除字典
* @param id 字典id
*/
export async function removeDictionaryData(id) {
const res = await request.delete('/system/dictionaryData/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeDictionaryDataBatch([id]);
}
/**
* 批量删除字典数据
* @param data 字典数据id集合
* 删除字典
* @param ids 字典id集合
*/
export async function removeDictionaryDataBatch(data) {
export async function removeDictionaryDataBatch(ids) {
const res = await request.delete('/system/dictionaryData/batch', {
data
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
+11 -1
View File
@@ -43,7 +43,17 @@ export async function updateDictionary(data) {
* @param id 字典id
*/
export async function removeDictionary(id) {
const res = await request.delete('/system/dictionary/' + id);
return removeDictionaryBatch([id]);
}
/**
* 删除菜单
* @param ids 菜单id集合
*/
export async function removeDictionaryBatch(ids) {
const res = await request.delete('/system/dictionary/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
+11 -1
View File
@@ -43,7 +43,17 @@ export async function updateMenu(data) {
* @param id 菜单id
*/
export async function removeMenu(id) {
const res = await request.delete('/system/menu/' + id);
return removeMenus([id]);
}
/**
* 删除菜单
* @param ids 菜单id集合
*/
export async function removeMenus(ids) {
const res = await request.delete('/system/menu/batch', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
+9 -11
View File
@@ -57,20 +57,16 @@ export async function updateRole(data) {
* @param id 角色id
*/
export async function removeRole(id) {
const res = await request.delete('/system/role/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeRoles([id]);
}
/**
* 批量删除角色
* @param ids 角色id集合
*/
export async function removeRoles(data) {
export async function removeRoles(ids) {
const res = await request.delete('/system/role/batch', {
data
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
@@ -83,7 +79,9 @@ export async function removeRoles(data) {
* @param roleId 角色id
*/
export async function listRoleMenus(roleId) {
const res = await request.get('/system/roleMenu/' + roleId);
const res = await request.get('/system/roleMenu', {
params: { roleId }
});
if (res.data.code === 0) {
return res.data.data;
}
@@ -93,10 +91,10 @@ export async function listRoleMenus(roleId) {
/**
* 修改角色菜单
* @param roleId 角色id
* @param data 菜单id集合
* @param menuIds 菜单id集合
*/
export async function updateRoleMenus(roleId, data) {
const res = await request.put('/system/roleMenu/' + roleId, data);
export async function updateRoleMenus(roleId, menuIds) {
const res = await request.put('/system/roleMenu', { roleId, menuIds });
if (res.data.code === 0) {
return res.data.message;
}
+3 -7
View File
@@ -69,20 +69,16 @@ export async function updateUser(data) {
* @param id 用户id
*/
export async function removeUser(id) {
const res = await request.delete('/system/user/' + id);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
return removeUsers([id]);
}
/**
* 批量删除用户
* @param data 用户id集合
*/
export async function removeUsers(data) {
export async function removeUsers(ids) {
const res = await request.delete('/system/user/batch', {
data
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
+56
View File
@@ -0,0 +1,56 @@
import request from '@/utils/request';
/**
* 分页查询专题
* @param params 查询条件
*/
export async function pageSyTopicEnroll(params) {
const res = await request.get('/sytopic/enroll/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function pageSyTopicEnrollTypes() {
const res = await request.get('/sytopic/enroll/status', {});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function updateTopicEnrollStatus(id, status) {
const res = await request.put('/sytopic/enroll/status', {
id,
status
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 导出订单
* @param params 查询条件
*/
export async function exportTopicEnroll(params) {
const res = await request.get('/sytopic/enroll/export', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function pageSyTopicEnrollTopic() {
const res = await request.get('/sytopic/enroll/topicList', {});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+114
View File
@@ -0,0 +1,114 @@
import request from '@/utils/request';
/**
* 分页查询模块
* @param params 查询条件
*/
export async function pageSyTopicModule(params) {
const res = await request.get('/sytopic/module/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加专题
* @param data
*/
export async function addTopicModule(data) {
const res = await request.post('/sytopic/module', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改专题
* @param data
*/
export async function updateTopicModule(data) {
const res = await request.put('/sytopic/module', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除
* @param ids id集合
*/
export async function removeTopicModule(ids) {
const res = await request.delete('/sytopic/module/delete', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 获取类型列表
*/
export async function pageTopicModuleTypes(params) {
const res = await request.get('/sytopic/module/types', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 分页查询模块配置项
* @param params 查询条件
*/
export async function pageSyTopicModuleOptions(params) {
const res = await request.get('/sytopic/module/options', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加专题配置项
* @param data
*/
export async function addTopicModuleOptions(data) {
const res = await request.post('/sytopic/module/options', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除模块配置
* @param id id
*/
export async function removeTopicModuleOption(id) {
const res = await request.delete('/sytopic/module/options', {
data: { id }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
export async function updateTopicModuleStatus(data) {
const res = await request.put('/sytopic/module/status', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
+83
View File
@@ -0,0 +1,83 @@
import request from '@/utils/request';
/**
* 分页查询专题
* @param params 查询条件
*/
export async function pageSyTopic(params) {
const res = await request.get('/sytopic/topic/page', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加专题
* @param data
*/
export async function addTopic(data) {
const res = await request.post('/sytopic/topic', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改专题
* @param data
*/
export async function updateTopic(data) {
const res = await request.put('/sytopic/topic', data);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改活动状态
* @param id 专题id
* @param status 状态
*/
export async function updateTopicStatus(id, status) {
const res = await request.put('/sytopic/topic/status', {
id,
status
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除
* @param ids id集合
*/
export async function removeTopic(ids) {
const res = await request.delete('/sytopic/topic/delete', {
data: { ids }
});
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 专题详情
* @param params
*/
export async function getTopicDetail(params) {
const res = await request.get('/sytopic/topic/detail', {
params
});
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+108
View File
@@ -0,0 +1,108 @@
<!-- 上传图片组件 -->
<template>
<ele-image-upload
v-model="imgs"
:limit="limit"
:drag="true"
:multiple="multiple"
:upload-handler="onHandler"
@upload="onUpload"
/>
</template>
<script>
import EleImageUpload from 'ele-admin/es/ele-image-upload';
import request from '@/utils/request';
export default {
components: {
EleImageUpload
},
name: 'UploadImg',
props: {
limit: {
type: Number,
default: 1
},
multiple: {
type: Boolean,
default: false
},
images: {
default: null,
type: Array
}
},
data() {
return {
imgs: []
};
},
mounted() {
if (this.images && this.images.length > 0) {
this.imgs = this.images;
}
},
methods: {
emitInput() {
this.$emit('input', this.imgs);
},
onHandler(file) {
const item = {
file,
uid: file.uid,
name: file.name,
progress: 0,
status: null
};
if (!file.type.startsWith('image')) {
this.$message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('大小不能超过 2MB');
return;
}
item.url = window.URL.createObjectURL(file);
// 关键就是这里要自己 push 添加数据而不是靠 v-modal 自动更新
this.imgs.push(item);
this.onUpload(item);
},
/* 上传 item */
onUpload(item) {
let that = this;
item.status = 'uploading';
const formData = new FormData();
formData.append('file', item.file);
request({
url: '/upload',
method: 'post',
data: formData,
onUploadProgress: (e) => {
if (e.lengthComputable) {
item.progress = (e.loaded / e.total) * 100;
}
}
})
.then((res) => {
if (res.data.code === 0) {
item.status = 'done';
item.url = res.data.data.full_url;
item.fileUrl = res.data.data.url;
that.emitInput();
}
})
.catch(() => {
item.status = 'exception';
});
}
},
watch: {
imgs: function () {
this.emitInput();
},
images: function () {
this.imgs = this.images;
}
}
};
</script>
+1
View File
@@ -1,5 +1,6 @@
// 接口地址
export const API_BASE_URL = process.env.VUE_APP_API_BASE_URL;
//export const API_BASE_URL = 'http://localhost:8088/system';
// 项目名称
export const PROJECT_NAME = process.env.VUE_APP_NAME;
+2 -2
View File
@@ -136,13 +136,13 @@
let hostname = window.location.hostname;
if (hostname == 'bo.liche.cn') {
this.logo =
'https://qs.haodian.cn/web/images/project/Admin-ShiYu/logo_liche.png';
'https://qs.haodian.cn/web/images/project/Admin-ShiYu/logo_hd.png';
} else if (hostname == 'dongfeng.haodian.cn') {
this.logo =
'https://qs.haodian.cn/web/images/project/Admin-ShiYu/logo_df.png';
} else {
this.logo =
'https://qs.haodian.cn/web/images/project/Admin-ShiYu/logo_liche.png';
'https://qs.haodian.cn/web/images/project/Admin-ShiYu/logo_hd.png';
}
},
computed: {
@@ -55,12 +55,25 @@
/>
<div class="ele-text-secondary">建议尺寸100X100</div>
</el-form-item>
<el-form-item
label="线索处理:"
v-show="form.organizationType == 1 ? true : false"
>
<el-select v-model="form.enrollDeal">
<el-option value="0" label="不处理" />
<el-option value="1" label="后台客服清洗" />
<el-option value="2" label="派发理车宝" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="机构类型:" prop="organizationType">
<org-type-select v-model="form.organizationType" />
</el-form-item>
<el-form-item label="排序号:" prop="sortNumber">
<el-form-item label="机构id:" v-if="form.organizationId">
<el-input v-model="form.organizationId" disabled />
</el-form-item>
<el-form-item label="排序号:">
<el-input-number
:min="0"
:max="99999"
@@ -100,7 +113,7 @@
import {
addOrganization,
updateOrganization
} from '@/api/sylive/organization';
} from '@/api/institution/organization';
export default {
components: { OrgSelect, OrgTypeSelect, RegionsSelect, EleImageUpload },
@@ -124,7 +137,8 @@
sortNumber: null,
comments: '',
logo: [],
city: []
city: [],
enrollDeal: 0
};
return {
defaultForm,
@@ -145,13 +159,6 @@
message: '请选择机构类型',
trigger: 'blur'
}
],
sortNumber: [
{
required: true,
message: '请输入排序号',
trigger: 'blur'
}
]
},
//
@@ -6,7 +6,7 @@
:data="data"
label-key="organizationName"
value-key="organizationId"
default-expand-all
:default-expand-all="true"
:placeholder="placeholder"
@input="updateValue"
/>
@@ -29,17 +29,6 @@
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="性别:" prop="sex">
<el-select
clearable
class="ele-block"
v-model="form.sex"
placeholder="请选择性别"
>
<el-option label="男" value="1" />
<el-option label="女" value="2" />
</el-select>
</el-form-item>
<el-form-item label="姓名:" prop="uname">
<el-input
clearable
@@ -63,7 +52,11 @@
<script>
import { phoneReg } from 'ele-admin';
import OrgSelect from './org-select.vue';
import { addUser, updateUser, checkExistence } from '@/api/sylive/user';
import {
addUser,
updateUser,
checkExistence
} from '@/api/institution/organization-user';
export default {
components: { OrgSelect },
@@ -82,8 +75,7 @@
userId: null,
organizationId: null,
mobile: '',
uname: '',
sex: null
uname: ''
};
return {
defaultForm,
@@ -96,6 +88,9 @@
required: true,
trigger: 'blur',
validator: (_rule, value, callback) => {
if (this.data) {
return callback();
}
if (!value) {
return callback(new Error('请输入手机号'));
}
@@ -103,7 +98,7 @@
if (!st.test(value)) {
return callback(new Error('手机号格式不正确'));
}
checkExistence('mobile', value, this.data?.mobile)
checkExistence('mobile', value, this.form.organizationId)
.then(() => {
callback(new Error('手机号已经存在'));
})
@@ -126,12 +121,6 @@
message: '请输入姓名',
trigger: 'blur'
}
],
sex: [
{
message: '请选择性别',
trigger: 'blur'
}
]
},
//
@@ -76,7 +76,11 @@
<script>
import OrgUserSearch from './org-user-search.vue';
import OrgUserEdit from './org-user-edit.vue';
import { pageUsers, removeUser, updateUserStatus } from '@/api/sylive/user';
import {
pageUsers,
removeUser,
updateUserStatus
} from '@/api/institution/organization-user';
export default {
components: { OrgUserSearch, OrgUserEdit },
@@ -91,9 +95,9 @@
//
columns: [
{
columnKey: 'index',
type: 'index',
width: 45,
prop: 'userId',
label: 'ID',
minWidth: 45,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
@@ -112,13 +116,6 @@
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'sexName',
label: '性别',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'mobile',
label: '手机号',
@@ -148,14 +145,14 @@
label: '状态',
align: 'center',
sortable: 'custom',
width: 80,
width: 100,
resizable: false,
slot: 'status'
},
{
columnKey: 'action',
label: '操作',
width: 130,
width: 160,
align: 'center',
resizable: false,
slot: 'action',
@@ -80,10 +80,10 @@
import {
listOrganizations,
removeOrganization
} from '@/api/sylive/organization';
} from '@/api/institution/organization';
export default {
name: 'SyliveOrganization',
name: 'InstitutionOrganization',
components: { OrgUserList, OrgEdit },
data() {
return {
@@ -18,9 +18,6 @@
placeholder="请选择上级团队"
/>
</el-form-item>
<el-form-item label="所属机构:" v-show="form.parentId ? false : true">
<team-org-select v-model="form.organizationId" />
</el-form-item>
<el-form-item label="团队名称:" prop="teamName">
<el-input
clearable
@@ -29,6 +26,9 @@
placeholder="请输入团队名称"
/>
</el-form-item>
<el-form-item label="所属机构:" v-show="form.parentId ? false : true">
<team-org-select v-model="form.organizationId" />
</el-form-item>
<el-form-item label="所在城市:">
<regions-select
v-model="form.city"
@@ -56,7 +56,10 @@
<el-form-item label="团队类型:" prop="teamType">
<team-type-select v-model="form.teamType" />
</el-form-item>
<el-form-item label="排序号:" prop="sortNumber">
<el-form-item label="团队id:" v-if="form.teamId">
<el-input v-model="form.teamId" disabled />
</el-form-item>
<el-form-item label="排序号:">
<el-input-number
:min="0"
:max="99999"
@@ -94,7 +97,7 @@
import RegionsSelect from '@/components/RegionsSelect/index.vue';
import EleImageUpload from 'ele-admin/es/ele-image-upload';
import request from '@/utils/request';
import { addTeam, updateTeam } from '@/api/sylive/team';
import { addTeam, updateTeam } from '@/api/institution/team';
export default {
components: {
@@ -110,7 +113,7 @@
//
data: Object,
// id
parentId: Number,
parentId: null,
//
teamList: Array
},
@@ -145,13 +148,6 @@
message: '请选择所属机构',
trigger: 'blur'
}
],
sortNumber: [
{
required: true,
message: '请输入排序号',
trigger: 'blur'
}
]
},
//
@@ -5,6 +5,7 @@
:value="value"
class="ele-fluid"
:placeholder="placeholder"
:default-expand-all="true"
@input="updateValue"
>
<el-option
@@ -17,12 +18,12 @@
</template>
<script>
import { listOrganizationParent } from '@/api/sylive/organization';
import { listOrganizationParent } from '@/api/institution/organization';
export default {
props: {
// (v-modal)
value: String,
value: null,
//
placeholder: {
type: String,
@@ -16,7 +16,7 @@
export default {
props: {
// (v-model)
value: Number,
value: null,
//
placeholder: {
type: String,
@@ -29,17 +29,6 @@
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="性别:" prop="sex">
<el-select
clearable
class="ele-block"
v-model="form.sex"
placeholder="请选择性别"
>
<el-option label="男" value="1" />
<el-option label="女" value="2" />
</el-select>
</el-form-item>
<el-form-item label="姓名:" prop="uname">
<el-input
clearable
@@ -67,7 +56,7 @@
addTeamUser,
updateTeamUser,
checkExistence
} from '@/api/sylive/team-user';
} from '@/api/institution/team-user';
export default {
components: { TeamSelect },
@@ -86,8 +75,7 @@
userId: null,
teamId: null,
mobile: '',
uname: '',
sex: null
uname: ''
};
return {
defaultForm,
@@ -130,12 +118,6 @@
message: '请输入姓名',
trigger: 'blur'
}
],
sex: [
{
message: '请选择性别',
trigger: 'blur'
}
]
},
//
@@ -80,7 +80,7 @@
pageTeamUser,
removeTeamUser,
updateTeamUserStatus
} from '@/api/sylive/team-user';
} from '@/api/institution/team-user';
export default {
components: { TeamUserSearch, TeamUserEdit },
@@ -95,12 +95,11 @@
//
columns: [
{
columnKey: 'index',
type: 'index',
width: 45,
prop: 'userId',
label: 'ID',
minWidth: 45,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
showOverflowTooltip: true
},
{
prop: 'uname',
@@ -116,13 +115,6 @@
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'sexName',
label: '性别',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'mobile',
label: '手机号',
@@ -145,14 +137,14 @@
label: '状态',
align: 'center',
sortable: 'custom',
width: 80,
width: 100,
resizable: false,
slot: 'status'
},
{
columnKey: 'action',
label: '操作',
width: 130,
width: 160,
align: 'center',
resizable: false,
slot: 'action',
@@ -78,10 +78,10 @@
<script>
import TeamUserList from './components/team-user-list.vue';
import TeamEdit from './components/team-edit.vue';
import { listTeams, removeTeam } from '@/api/sylive/team';
import { listTeams, removeTeam } from '@/api/institution/team';
export default {
name: 'SyliveTeam',
name: 'InstitutionTeam',
components: { TeamUserList, TeamEdit },
data() {
return {
@@ -0,0 +1,382 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
width="960px"
:visible="visible"
:append-to-body="true"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
title="抽奖配置"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" :rules="rules" label-width="82px">
<el-form-item label="背景图片:" prop="bgImg">
<ele-image-upload
v-model="form.bgImg"
:limit="1"
:drag="true"
:multiple="false"
@upload="onUpload"
/>
<div class="ele-text-secondary">建议尺寸1600X900</div>
</el-form-item>
<el-form-item label="屏幕显示:">
<el-radio-group v-model="form.screenDisplay">
<el-radio :label="1">横屏</el-radio>
<el-radio :label="2">竖屏</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="短信内容:">
<el-input
v-model="form.sms"
:rows="2"
type="textarea"
placeholder="请输入中奖短信内容"
/>
<div class="ele-text-secondary">
当内容有 中奖标题 发短信时就会自动替换为抽奖类型的标题
</div>
</el-form-item>
<el-form-item label="抽奖类型:">
<el-table :data="form.winType" :border="true" style="width: 100%">
<el-table-column label="标题" align="center">
<template v-slot="{ row }">
<el-input v-model="row.title" placeholder="标题" />
</template>
</el-table-column>
<el-table-column label="标签" width="100px" align="center">
<template v-slot="{ row }">
<el-input v-model="row.tag" placeholder="标签" />
</template>
</el-table-column>
<el-table-column label="图片" width="120px" align="center">
<template v-slot="{ row }">
<ele-image-upload
v-model="row.img"
:limit="1"
:drag="true"
:multiple="false"
@upload="onUpload"
/>
</template>
</el-table-column>
<el-table-column label="参与条件" align="center">
<template v-slot="{ row }">
<el-select
v-model="row.itemIds"
placeholder="请选择商品"
clearable
multiple
class="ele-fluid"
>
<el-option
v-for="item in goodsList"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="参与抽奖" width="100px" align="center">
<template v-slot="{ row }">
<el-select v-model="row.show" class="ele-fluid">
<el-option label="否" value="0" />
<el-option label="是" value="1" />
</el-select>
</template>
</el-table-column>
<el-table-column label="是否核销" width="100px" align="center">
<template v-slot="{ row }">
<el-select v-model="row.ifCode" class="ele-fluid">
<el-option label="否" value="0" />
<el-option label="是" value="1" />
</el-select>
</template>
</el-table-column>
<el-table-column label="收货地址" width="100px" align="center">
<template v-slot="{ row }">
<el-select v-model="row.ifAddress" class="ele-fluid">
<el-option label="不需要" value="0" />
<el-option label="需要" value="1" />
</el-select>
</template>
</el-table-column>
<el-table-column
label="操作"
width="70px"
align="center"
:resizable="false"
>
<template v-slot="{ row, $index }">
<span class="ele-action">
<el-popconfirm
title="确定要删除此抽奖类型吗?"
@confirm="removeBottoms(row, $index)"
>
<template v-slot:reference>
<el-link
icon="el-icon-delete"
type="danger"
:underline="false"
>
删除
</el-link>
</template>
</el-popconfirm>
</span>
</template>
</el-table-column>
</el-table>
<el-button
icon="el-icon-plus"
style="width: 100%; margin-top: 15px"
@click="addBottoms"
>
新增抽奖类型
</el-button>
</el-form-item>
<el-form-item label="中奖人数:">
<el-table :data="form.winNum" :border="true" style="width: 100%">
<el-table-column align="center" label="人数">
<template v-slot="{ row }">
<el-input-number
:min="0"
v-model="row.value"
placeholder="请输入人数"
controls-position="right"
class="ele-fluid ele-text-left"
/>
</template>
</el-table-column>
<el-table-column
label="操作"
width="100px"
align="center"
:resizable="false"
>
<template v-slot="{ row, $index }">
<span class="ele-action">
<el-popconfirm
title="确定要删除此中奖人数吗?"
@confirm="removeWinNums(row, $index)"
>
<template v-slot:reference>
<el-link
icon="el-icon-delete"
type="danger"
:underline="false"
>
删除
</el-link>
</template>
</el-popconfirm>
</span>
</template>
</el-table-column>
</el-table>
<el-button
icon="el-icon-plus"
style="width: 100%; margin-top: 15px"
@click="addWinNums"
>
新增中奖人数
</el-button>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import EleImageUpload from 'ele-admin/es/ele-image-upload';
import request from '@/utils/request';
import { updateActivityDraw } from '@/api/sylive/activity';
import { listGoods } from '@/api/sylive/goods';
export default {
components: { EleImageUpload },
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
activityId: null,
sms: '',
screenDisplay: 1,
bgImg: [],
winNum: [],
winType: []
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
goodsList: [],
imgIndex: 1,
// 表单验证规则
rules: {
bgImg: [
{
required: true,
message: '请上传背景图',
trigger: 'blur'
}
]
},
// 提交状态
loading: false,
// 是否是修改
isUpdate: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 查询商品 */
goodsQuery() {
listGoods({ activityId: this.data.activityId, type: 0 })
.then((list) => {
this.goodsList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
updateActivityDraw(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
},
/* 添加中奖人数 */
addWinNums() {
this.form.winNum.push({ value: 0 });
},
/* 删除中奖人数 */
removeWinNums(_row, index) {
this.form.winNum.splice(index, 1);
},
addBottoms() {
let id = 1;
let length = this.form.winType.length;
if (length) {
let lengthSet = length - 1;
id = this.form.winType[lengthSet].id + 1;
}
this.form.winType.push({
id: id,
title: '',
show: '1',
tag: '',
itemIds: '',
ifCode: '0',
ifAddress: '0',
img: []
});
},
/* 删除 */
removeBottoms(_row, index) {
this.form.winType.splice(index, 1);
},
/* 上传文件之前的钩子 */
onBeforeUpload(file) {
// file 即选择后的文件
if (!file.type.startsWith('image')) {
this.$message.error('只能选择图片');
return false;
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('大小不能超过 2MB');
return false;
}
},
/* 上传文件 */
onUpload(item) {
item.status = 'uploading';
const formData = new FormData();
formData.append('file', item.file);
request({
url: '/upload',
method: 'post',
data: formData,
onUploadProgress: (e) => {
if (e.lengthComputable) {
item.progress = (e.loaded / e.total) * 100;
}
}
})
.then((res) => {
if (res.data.code === 0) {
item.status = 'done';
item.url = res.data.data.full_url;
item.fileUrl = res.data.data.url;
}
})
.catch(() => {
item.status = 'exception';
});
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.goodsQuery();
this.$util.assignObject(this.form, {
...this.data
});
this.isUpdate = true;
} else {
this.form.sms = '';
this.form.winType = [];
this.form.winNum = [];
this.form.bgImg = [];
this.isUpdate = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
<style>
.ele-image-upload-list .ele-image-upload-item {
margin-top: 2px;
margin-bottom: 2px;
}
</style>
@@ -1,7 +1,7 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="750px"
width="800px"
:visible="visible"
:append-to-body="true"
:close-on-click-modal="true"
@@ -18,34 +18,6 @@
placeholder="请输入活动标题"
/>
</el-form-item>
<el-form-item label="所属门店:">
<ele-tree-select
:data="organizationList"
label-key="organizationName"
value-key="organizationId"
v-model="form.bizIds"
:multiple="true"
:clearable="true"
placeholder="请选择所属门店"
:disabled="false"
:default-expand-all="true"
:check-strictly="false"
/>
</el-form-item>
<el-form-item label="所属团队:">
<ele-tree-select
:data="teamList"
label-key="teamName"
value-key="teamId"
v-model="form.teamIds"
:multiple="true"
:clearable="true"
placeholder="请选择所属团队"
:disabled="false"
:default-expand-all="true"
:check-strictly="false"
/>
</el-form-item>
<el-form-item label="背景图片:" prop="bgImg">
<ele-image-upload
v-model="form.bgImg"
@@ -59,6 +31,30 @@
建议尺寸1125X2000主题内容建议做在顶部0~1700像素区域
</div>
</el-form-item>
<el-form-item label="所属机构:" prop="organizationId">
<el-select
v-model="form.organizationId"
placeholder="请选择所属机构"
class="ele-fluid"
>
<el-option
v-for="item in organizationList"
:key="item.organizationId"
:label="item.organizationName"
:value="item.organizationId"
/>
</el-select>
</el-form-item>
<el-form-item label="开始时间:" prop="activityStart">
<el-date-picker
type="datetime"
v-model="form.activityStart"
placeholder="请选择活动开始时间"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
class="ele-fluid"
/>
</el-form-item>
<el-form-item label="直播频道:" prop="channelId">
<el-input
clearable
@@ -90,54 +86,11 @@
<el-form-item label="收款账户:" prop="mchId">
<activity-mch-id-select v-model="form.mchId" />
</el-form-item>
<el-form-item label="支付方式:">
<el-select
clearable
v-model="form.pay.way"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="厂商支付" :value="1" />
<el-option label="经销商支付" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="支付价格:" v-show="form.pay.way == 1 ? false : true">
<el-input
clearable
:maxlength="30"
v-model="form.pay.price"
placeholder="请输入支付价格"
/>
</el-form-item>
<el-form-item label="支付图片:" v-show="form.pay.way == 1 ? false : true">
<ele-image-upload
v-model="form.pay.img"
:limit="1"
:drag="true"
:multiple="false"
:upload-handler="payImgHandler"
@upload="onUpload"
/>
<div class="ele-text-secondary">建议尺寸750X1500</div>
</el-form-item>
<el-form-item label="直播图片:" v-show="false">
<ele-image-upload
v-model="form.channelImg"
:limit="1"
:drag="true"
:multiple="false"
:upload-handler="channelImgHandler"
@upload="onUpload"
/>
<div class="ele-text-secondary">建议尺寸690X330</div>
</el-form-item>
<el-form-item label="活动简介:" prop="introduction" v-show="false">
<el-input
v-model="form.introduction"
placeholder="请输入活动简介"
:rows="3"
type="textarea"
/>
<el-form-item label="订单归属:">
<el-radio-group v-model="form.orderType">
<el-radio :label="0">按首次</el-radio>
<el-radio :label="1">按支付</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="banner:">
<ele-image-upload
@@ -197,6 +150,160 @@
新增分享文案
</el-button>
</el-form-item>
<el-form-item label="黑名单:">
<el-radio-group v-model="form.blacklist">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="弹幕颜色:">
<el-radio-group v-model="form.barrage.color">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
<el-input
clearable
v-model="form.barrage.title"
placeholder="请输入弹幕文案"
/>
</el-form-item>
<el-form-item label="按扭文案:">
<el-input
clearable
v-model="form.button.title"
placeholder="请输入按扭文案"
/>
</el-form-item>
<el-form-item label="按钮类型:">
<el-radio-group v-model="form.signBespeak.status">
<el-radio :label="0">商品</el-radio>
<el-radio :label="1">报名</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="支付商品:">
<el-select
v-model="form.signBespeak.payItemId"
placeholder="请选择关联商品"
clearable
class="ele-fluid"
>
<el-option
v-for="item in payGoodsLists"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
</el-form-item>
<el-form-item label="报名配置:">
<el-select
v-model="form.signBespeak.itemId"
placeholder="请选择关联商品"
clearable
class="ele-fluid"
>
<el-option
v-for="item in goodsList"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
<el-input
v-model="form.signBespeak.title"
style="padding-top: 10px"
clearable
placeholder="请输入弹窗标题"
/>
<div style="padding-top: 10px">
<tinymce-editor
:init="editoption"
v-model="form.signBespeak.content"
placeholder="请输入弹窗内容"
/>
</div>
</el-form-item>
<el-form-item label="活动底部:">
<el-table :data="form.bottoms" :border="true" style="width: 100%">
<el-table-column label="标题">
<template v-slot="{ row }">
<el-input v-model="row.title" placeholder="标题" />
</template>
</el-table-column>
<el-table-column label="类型" align="center">
<template v-slot="{ row }">
<el-select v-model="row.urlType" class="ele-fluid">
<el-option label="链接" value="link" />
<el-option label="小程序" value="miniProgram" />
<el-option label="报名" value="enroll" />
<el-option label="订阅" value="appoint" />
</el-select>
</template>
</el-table-column>
<el-table-column label="链接" width="180px" align="center">
<template v-slot="{ row }">
<el-input
v-model="row.url"
placeholder="请输入链接"
:rows="2"
type="textarea"
/>
<el-input
v-if="row.urlType == 'miniProgram'"
v-model="row.miniProgramId"
placeholder="小程序原始id"
style="padding-top: 5px"
:rows="2"
type="textarea"
/>
</template>
</el-table-column>
<el-table-column label="图标" width="120px" align="center">
<template v-slot="{ row, $index }">
<ele-image-upload
v-model="row.icon"
:limit="1"
:drag="true"
:multiple="false"
:upload-handler="$index == 0 ? uploadHandler0 : uploadHandler1"
@upload="onUpload"
/>
</template>
</el-table-column>
<el-table-column
label="操作"
width="70px"
align="center"
:resizable="false"
>
<template v-slot="{ row, $index }">
<span class="ele-action">
<el-popconfirm
title="确定要删除此底部吗?"
@confirm="removeBottoms(row, $index)"
>
<template v-slot:reference>
<el-link
icon="el-icon-delete"
type="danger"
:underline="false"
>
删除
</el-link>
</template>
</el-popconfirm>
</span>
</template>
</el-table-column>
</el-table>
<el-button
icon="el-icon-plus"
style="width: 100%; margin-top: 15px"
@click="addBottoms"
>
新增活动底部菜单
</el-button>
</el-form-item>
<el-form-item label="客服链接:">
<el-input
clearable
@@ -219,7 +326,7 @@
<tinymce-editor
:init="editoption"
v-model="form.protocol"
placeholder="请输入活动协议"
placeholder="请输入协议内容"
/>
</div>
</el-form-item>
@@ -239,41 +346,55 @@
import EleImageUpload from 'ele-admin/es/ele-image-upload';
import request from '@/utils/request';
import { addActivity, updateActivity } from '@/api/sylive/activity';
import { listGoods } from '@/api/sylive/goods';
export default {
components: { TinymceEditor, ActivityMchIdSelect, EleImageUpload },
components: {
TinymceEditor,
ActivityMchIdSelect,
EleImageUpload
},
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object,
// 全部机构
organizationList: Array,
// 全部团队
teamList: Array
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
activityId: null,
bizIds: [],
teamIds: [],
title: '',
channelId: '',
dateRange: '',
introduction: '',
shareTitle: [''],
shareImg: [],
bgImg: [],
channelImg: [],
banner: [],
sharePhoto: [],
organizationId: null,
drawCode: '',
activityStart: '',
mchId: '1604032585',
protocolTitle: '',
protocol: '',
serviceLink: '',
pay: { way: 1, price: '', img: [] }
bottoms: [],
blacklist: 0,
button: { title: '' },
signBespeak: {
status: 0,
title: '',
content: '',
itemId: 0,
payItemId: ''
},
barrage: { color: 0, title: '' },
orderType: 0
};
return {
goodsList: [],
payGoodsLists: [],
editVersion: false,
editoption: {
height: 300,
@@ -294,6 +415,20 @@
trigger: 'blur'
}
],
organizationId: [
{
required: true,
message: '请选择所属机构',
trigger: 'blur'
}
],
activityStart: [
{
required: true,
message: '请选择活动开始时间',
trigger: 'blur'
}
],
bgImg: [
{
required: true,
@@ -329,6 +464,30 @@
}
},
methods: {
/* 查询商品 */
goodsQuery() {
if (!this.form.activityId) {
return false;
}
listGoods({ activityId: this.form.activityId, price: 0 })
.then((list) => {
this.goodsList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
listGoods({
activityId: this.form.activityId,
price: 0,
price_type: 'gt'
})
.then((list) => {
this.payGoodsLists = list;
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 添加海报描述 */
addShareTitle() {
this.form.shareTitle.push('');
@@ -430,27 +589,6 @@
this.form.banner.push(item);
this.onUpload(item);
},
channelImgHandler(file) {
const item = {
file,
uid: file.uid,
name: file.name,
progress: 0,
status: null
};
if (!file.type.startsWith('image')) {
this.$message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('大小不能超过 2MB');
return;
}
item.url = window.URL.createObjectURL(file);
// 关键就是这里要自己 push 添加数据而不是靠 v-modal 自动更新
this.form.channelImg.push(item);
this.onUpload(item);
},
sharePhotoHandler(file) {
const item = {
file,
@@ -472,7 +610,6 @@
this.form.sharePhoto.push(item);
this.onUpload(item);
},
/* 上传事件 */
shareImgHandler(file) {
const item = {
file,
@@ -494,6 +631,66 @@
this.form.shareImg.push(item);
this.onUpload(item);
},
/* 添加 */
addBottoms() {
if (this.form.bottoms.length >= 2) {
this.$message.error('最多添加2个活动底部菜单');
return;
}
this.form.bottoms.push({
urlType: 'link',
title: '',
url: '',
miniProgramId: '',
icon: []
});
},
/* 删除 */
removeBottoms(_row, index) {
this.form.bottoms.splice(index, 1);
},
uploadHandler0(file) {
const item = {
file,
uid: file.uid,
name: file.name,
progress: 0,
status: null
};
if (!file.type.startsWith('image')) {
this.$message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('大小不能超过 2MB');
return;
}
item.url = window.URL.createObjectURL(file);
// 关键就是这里要自己 push 添加数据而不是靠 v-modal 自动更新
this.form.bottoms[0]['icon'].push(item);
this.onUpload(item);
},
uploadHandler1(file) {
const item = {
file,
uid: file.uid,
name: file.name,
progress: 0,
status: null
};
if (!file.type.startsWith('image')) {
this.$message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('大小不能超过 2MB');
return;
}
item.url = window.URL.createObjectURL(file);
// 关键就是这里要自己 push 添加数据而不是靠 v-modal 自动更新
this.form.bottoms[1]['icon'].push(item);
this.onUpload(item);
},
/* 上传 item */
onUpload(item) {
item.status = 'uploading';
@@ -534,8 +731,9 @@
if (this.form.shareTitle.length == 0) {
this.form.shareTitle.push('');
}
this.goodsQuery();
} else {
//this.form.organizationId = this.organizationId;
this.form.bottoms = [];
this.form.bgImg = [];
this.form.shareImg = [];
this.isUpdate = false;
@@ -550,7 +748,7 @@
</script>
<style>
.ele-image-upload-list .ele-image-upload-item {
margin-top: 5px;
margin-bottom: 5px;
margin-top: 2px;
margin-bottom: 2px;
}
</style>
@@ -0,0 +1,128 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
width="930px"
:visible="visible"
:append-to-body="true"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
title="修改回访标签"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" label-width="82px">
<el-form-item label="回访标签:">
<el-table :data="form.visitTag" :border="true" style="width: 100%">
<el-table-column label="ID" align="center" width="70px">
<template v-slot="{ row }">{{ row.id }}</template>
</el-table-column>
<el-table-column label="回访标题" align="center" width="150px">
<template v-slot="{ row }">{{ row.title }}</template>
</el-table-column>
<el-table-column label="自定义文案" align="center">
<template v-slot="{ row }">
<el-input v-model="row.tag" placeholder="请输入自定义文案" />
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { updateActivityVisitTag } from '@/api/sylive/activity';
export default {
components: {},
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
activityId: null,
visitTag: []
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 提交状态
loading: false,
// 是否是修改
isUpdate: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
updateActivityVisitTag(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.$util.assignObject(this.form, {
...this.data
});
/* 升序排序 */
const visitTag = this.form.visitTag;
if (visitTag) {
this.form.visitTag = visitTag.sort((a, b) => a.id - b.id);
}
this.isUpdate = true;
} else {
this.form.visitTag = [];
this.isUpdate = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
<style>
.ele-image-upload-list .ele-image-upload-item {
margin-top: 2px;
margin-bottom: 2px;
}
</style>
+122 -71
View File
@@ -53,28 +53,35 @@
<i class="el-icon-arrow-down"></i>
</el-link>
<template v-slot:dropdown>
<el-dropdown-menu>
<el-dropdown-menu v-if="row.groups == 1">
<el-dropdown-item command="gro">分组数据统计</el-dropdown-item>
<el-dropdown-item command="live">直播数据统计</el-dropdown-item>
</el-dropdown-menu>
<el-dropdown-menu v-else>
<el-dropdown-item command="org">机构数据统计</el-dropdown-item>
<el-dropdown-item command="team">团队数据统计</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-link
type="primary"
:underline="false"
icon="el-icon-shopping-cart-full"
@click="openOrder(row.activityId)"
>
订单
</el-link>
<el-link
type="primary"
:underline="false"
icon="el-icon-_share"
@click="openCode(row)"
>
链接
</el-link>
<el-dropdown @command="(command) => dropMore(command, row)">
<el-link type="primary" :underline="false" icon="el-icon-_share">
更多
<i class="el-icon-arrow-down"></i>
</el-link>
<template v-slot:dropdown>
<el-dropdown-menu v-if="row.groups == 1">
<el-dropdown-item command="order">订单列表</el-dropdown-item>
<el-dropdown-item command="win">中奖名单</el-dropdown-item>
<el-dropdown-item command="exchange">核销记录</el-dropdown-item>
<el-dropdown-item command="customer">客户列表</el-dropdown-item>
<el-dropdown-item command="code">活动链接</el-dropdown-item>
</el-dropdown-menu>
<el-dropdown-menu v-else>
<el-dropdown-item command="order">订单列表</el-dropdown-item>
<el-dropdown-item command="code">活动链接</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown @command="(command) => dropClick(command, row)">
<el-link type="primary" :underline="false" icon="el-icon-edit">
修改
@@ -84,6 +91,15 @@
<el-dropdown-menu>
<el-dropdown-item command="activity">修改活动</el-dropdown-item>
<el-dropdown-item command="goods">修改商品</el-dropdown-item>
<el-dropdown-item v-if="row.groups == 1" command="groups">
修改分组
</el-dropdown-item>
<el-dropdown-item command="copy">复制活动</el-dropdown-item>
<el-dropdown-item command="draw">抽奖配置</el-dropdown-item>
<el-dropdown-item command="visitTag">回访标签</el-dropdown-item>
<el-dropdown-item command="blacklist" v-if="row.blacklist">
黑名单
</el-dropdown-item>
<!--
<el-dropdown-item command="item">修改权益商品</el-dropdown-item>
<el-dropdown-item command="coupon">修改券</el-dropdown-item>
@@ -93,7 +109,7 @@
</el-dropdown>
<el-popconfirm
class="ele-action"
title="确定要删除此用户吗?"
title="确定要删除此活动吗?"
@confirm="remove(row)"
>
<template v-slot:reference>
@@ -110,7 +126,6 @@
:data="current"
:visible.sync="showEdit"
:organization-list="organizationList"
:team-list="teamList"
@done="reload"
/>
<!-- 编辑商品弹窗 -->
@@ -127,6 +142,17 @@
/>
<!-- 二维码 -->
<qr-code :visible.sync="showCode" :data="current" />
<!-- 抽奖配置弹窗 -->
<activity-draw
:data="current"
:visible.sync="showEditDraw"
@done="reload"
/>
<activity-visit-tag
:data="current"
:visible.sync="showEditVisitTag"
@done="reload"
/>
</div>
</template>
@@ -136,32 +162,33 @@
import ActivityEdit from './components/activity-edit.vue';
import ActivityItem from './components/activity-item.vue';
import ActivityCoupon from './components/activity-coupon.vue';
import ActivityDraw from './components/activity-draw.vue';
import ActivityVisitTag from './components/activity-visit-tag';
import {
pageActivity,
removeActivity,
removeActivitys,
copyActivity,
updateActivityStatus
} from '@/api/sylive/activity';
import { listOrganizations } from '@/api/sylive/organization';
import { listTeams } from '@/api/sylive/team';
import { listOrganizationParent } from '@/api/institution/organization';
export default {
name: 'syliveActivity',
components: {
ActivityVisitTag,
QrCode,
ActivitySearch,
ActivityEdit,
ActivityItem,
ActivityCoupon
ActivityCoupon,
ActivityDraw
},
data() {
return {
// 加载状态
loading: true,
// 门店数据
organizationList: [],
// 团队数据
teamList: [],
// 表格列配置
columns: [
{
@@ -172,9 +199,9 @@
fixed: 'left'
},
{
columnKey: 'index',
type: 'index',
width: 45,
prop: 'activityId',
label: 'ID',
minWidth: 40,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
@@ -184,14 +211,14 @@
label: '标题',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 150
minWidth: 200
},
{
prop: 'channelId',
label: '直播频道',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 70,
minWidth: 60,
slot: 'nickname'
},
{
@@ -199,14 +226,14 @@
label: '直播开始时间',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 100
minWidth: 90
},
{
prop: 'createTime',
label: '创建时间',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 100,
minWidth: 90,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
@@ -240,6 +267,9 @@
showEditItem: false,
// 是否显示编辑券弹窗
showEditCoupon: false,
// 是否显示编辑券弹窗
showEditDraw: false,
showEditVisitTag: false,
// 是否显示二维码弹窗
showCode: false
};
@@ -255,56 +285,87 @@
this.showEdit = true;
} else if (command === 'item') {
this.current = row.item;
this.current.activityId = row.activityId;
this.showEditItem = true;
} else if (command === 'coupon') {
this.current = row.coupon;
this.current.activityId = row.activityId;
this.showEditCoupon = true;
} else if (command === 'draw') {
this.current = row.draw;
this.current.activityId = row.activityId;
this.showEditDraw = true;
} else if (command === 'visitTag') {
this.current = {
visitTag: row.visitTag,
activityId: row.activityId
};
this.showEditVisitTag = true;
} else if (command === 'blacklist') {
this.$router.replace('/sylive/blacklist?id=' + row.activityId);
} else if (command === 'goods') {
this.$router.replace('/sylive/goods?id=' + row.activityId);
} else if (command === 'groups') {
this.$router.replace('/sylive/groups?id=' + row.activityId);
} else if (command === 'copy') {
const loading = this.$loading({ lock: true });
copyActivity(row.activityId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
}
},
/* 打开数据统计页 */
dropStatistics(command, row) {
var url = '';
if (command === 'org') {
if (command === 'gro') {
url = '/sylive/groups-statistics?id=' + row.activityId;
} else if (command === 'live') {
url = '/sylive/live?id=' + row.activityId;
} else if (command === 'org') {
url = '/sylive/activity/statistics?id=' + row.activityId;
this.$router.replace(url);
} else if (command === 'team') {
url = '/sylive/activity/statistics-team?id=' + row.activityId;
}
this.$router.replace(url);
},
/* 打开更多页 */
dropMore(command, row) {
let url = '';
if (command === 'order') {
if (row.groups == 1) {
url = '/sylive/groups-order?id=' + row.activityId;
} else {
url = '/sylive/order?id=' + row.activityId;
}
this.$router.replace(url);
} else if (command === 'win') {
url = '/sylive/groups-win?id=' + row.activityId;
this.$router.replace(url);
} else if (command === 'exchange') {
url = '/sylive/groups-exchange?id=' + row.activityId;
this.$router.replace(url);
} else if (command === 'customer') {
url = '/sylive/groups-customer?id=' + row.activityId;
this.$router.replace(url);
} else if (command === 'code') {
this.current = row;
this.showCode = true;
}
},
/* 查询机构 */
organizationQuery() {
this.loading = true;
listOrganizations({ unOrganizationType: 4 })
listOrganizationParent({ parentId: 0 })
.then((list) => {
this.loading = false;
this.organizationList = this.$util.toTreeData({
data: list,
idField: 'organizationId',
parentIdField: 'parentId'
});
this.organizationList = list;
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 查询团队 */
teamQuery() {
this.loading = true;
listTeams({ unTeamType: 3 })
.then((list) => {
this.loading = false;
this.teamList = this.$util.toTreeData({
data: list,
idField: 'teamId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
@@ -312,7 +373,6 @@
datasource({ page, limit, where, order }) {
if (page == 1) {
this.organizationQuery();
this.teamQuery();
}
return pageActivity({ ...where, ...order, page, limit });
},
@@ -320,15 +380,6 @@
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 打开二维码弹窗 */
openCode(row) {
this.current = row;
this.showCode = true;
},
/* 打开活动订单页 */
openOrder(activityId) {
this.$router.replace('/sylive/order?id=' + activityId);
},
/* 删除 */
remove(row) {
const loading = this.$loading({ lock: true });
@@ -155,6 +155,20 @@
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics-team') {
return;
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -139,6 +139,20 @@
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics-team') {
return;
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,104 @@
<template>
<el-card shadow="never" v-if="watchOrderOption.legend.data.length > 0">
<div>
<v-chart
ref="watchOrder"
style="width: 100%; height: 500px"
:option="watchOrderOption"
/>
</div>
</el-card>
</template>
<script>
import { getStatisticsStackedWatchOrder } from '@/api/sylive/activity';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { LineChart } from 'echarts/charts';
import {
LegendComponent,
GridComponent,
ToolboxComponent,
TooltipComponent
} from 'echarts/components';
import VChart from 'vue-echarts';
import 'echarts-wordcloud';
import { echartsMixin } from '@/utils/echarts-mixin';
use([
CanvasRenderer,
GridComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
LineChart
]);
export default {
components: { VChart },
mixins: [echartsMixin(['watchOrder'])],
data() {
return {
watchOrderOption: {
legend: {
data: []
}
} //折线图
};
},
methods: {
//区域统计折线图
getStatisticsStackedWatchOrder() {
this.watchOrderOption = { legend: { data: [] } };
const activityId = this.$route.query.id;
const type = 1;
getStatisticsStackedWatchOrder({
activityId,
type
}).then((res) => {
this.watchOrderOption = {
tooltip: {
trigger: 'axis'
},
legend: {
padding: [13, 260, 0, 40],
data: res.legendData
},
grid: {
left: '3%',
right: '4%',
top: '10%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: res.xAxisData
},
yAxis: {
type: 'value'
},
series: res.yAxisSeries
};
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics-team') {
return;
}
this.getStatisticsStackedWatchOrder();
},
immediate: true
}
}
};
</script>
@@ -124,6 +124,7 @@
</el-card>
</el-col>
</el-row>
<watchOrderLinechart />
<el-card
shadow="never"
header="浏览人数排名"
@@ -355,12 +356,18 @@
import { echartsMixin } from '@/utils/echarts-mixin';
import BizTable from './components/biz-table.vue';
import ConsultantTable from './components/consultant-table.vue';
import watchOrderLinechart from './components/watchOrder-linechart.vue';
use([CanvasRenderer, TooltipComponent, FunnelChart]);
export default {
name: 'SyliveActivityStatisticsTeam',
components: { VChart, BizTable, ConsultantTable },
components: {
VChart,
BizTable,
ConsultantTable,
watchOrderLinechart
},
mixins: [echartsMixin(['funnelChart'])],
data() {
return {
@@ -216,9 +216,6 @@
} //折线图
};
},
created() {
this.getStatisticsStackedArea();
},
methods: {
/* 表格数据源 */
datasource({ page, limit, order }) {
@@ -248,6 +245,7 @@
//区域统计折线图
getStatisticsStackedArea() {
this.areaChartOption = { legend: { data: [] } };
const activityId = this.$route.query.id;
let kpi = this.kpi;
getStatisticsStackedArea({
@@ -292,6 +290,21 @@
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics') {
return;
}
this.getStatisticsStackedArea();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -155,6 +155,20 @@
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics') {
return;
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -139,6 +139,20 @@
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics') {
return;
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -45,17 +45,16 @@
} //折线图
};
},
created() {
this.getStatisticsStackedWatchOrder();
},
methods: {
//区域统计折线图
getStatisticsStackedWatchOrder() {
this.watchOrderOption = { legend: { data: [] } };
const activityId = this.$route.query.id;
const type = 0;
getStatisticsStackedWatchOrder({
activityId
activityId,
type
}).then((res) => {
console.log(res);
this.watchOrderOption = {
tooltip: {
trigger: 'axis'
@@ -88,6 +87,18 @@
};
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/activity/statistics') {
return;
}
this.getStatisticsStackedWatchOrder();
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,110 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="750px"
:visible="visible"
:append-to-body="true"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
title="添加黑名单"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" :rules="rules" label-width="82px">
<el-form-item label="手机号:" prop="mobile">
<el-input
clearable
:maxlength="60"
v-model="form.mobile"
placeholder="请输入手机号"
/>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { addBlacklist } from '@/api/sylive/blacklist';
export default {
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
blacklistId: null,
activityId: null,
mobile: ''
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 表单验证规则
rules: {
mobile: [
{
required: true,
message: '请输入手机号',
trigger: 'blur'
}
]
},
// 提交状态
loading: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
addBlacklist(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
this.form.activityId = this.data.activityId;
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,103 @@
<!-- 导入弹窗 -->
<template>
<ele-modal
width="520px"
title="导入黑名单"
:visible="visible"
@update:visible="updateVisible"
>
<el-upload
drag
action=""
class="ele-block"
v-loading="loading"
accept=".xls,.xlsx"
:show-file-list="false"
:before-upload="doUpload"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处, <em>点击上传</em></div>
<template v-slot:tip>
<div class="el-upload__tip ele-text-center">
<span>只能上传xlsxlsx文件, </span>
<el-link
download
:href="url"
type="primary"
:underline="false"
style="vertical-align: baseline"
>
下载模板
</el-link>
</div>
</template>
</el-upload>
</ele-modal>
</template>
<script>
import { importBlacklist } from '@/api/sylive/blacklist';
import { API_BASE_URL } from '@/config/setting';
export default {
props: {
// 是否打开弹窗
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
return {
// 导入请求状态
loading: false,
// 导入模板下载地址
url: API_BASE_URL.replace('api', '') + 'temp/blacklist.xlsx'
};
},
methods: {
/* 上传 */
doUpload(file) {
if (
![
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
].includes(file.type)
) {
this.$message.error('只能选择 excel 文件');
return false;
}
if (file.size / 1024 / 1024 > 5) {
this.$message.error('大小不能超过 5MB');
return false;
}
this.loading = true;
let activityId = this.data.activityId;
importBlacklist(file, activityId)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
return false;
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
}
};
</script>
<style lang="scss" scoped>
.ele-block {
:deep(.el-upload),
:deep(.el-upload-dragger) {
width: 100%;
}
}
</style>
@@ -0,0 +1,62 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 8, md: 16 } : { span: 8 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
data() {
// 默认表单数据
const defaultWhere = {
mobile: ''
};
return {
// 表单数据
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
}
}
};
</script>
+239
View File
@@ -0,0 +1,239 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<blacklist-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
:selection.sync="selection"
cache-key="syliveActivityBlacklistTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
icon="el-icon-plus"
class="ele-btn-icon"
@click="openEdit()"
>
新建
</el-button>
<el-button
size="small"
type="danger"
icon="el-icon-delete"
class="ele-btn-icon"
@click="removeBatch"
>
删除
</el-button>
<el-button
size="small"
icon="el-icon-upload2"
class="ele-btn-icon"
@click="openImport"
>
导入
</el-button>
</template>
<!-- 操作列 -->
<template v-slot:action="{ row }">
<el-popconfirm
class="ele-action"
title="确定要删除此手机号吗?"
@confirm="remove(row)"
>
<template v-slot:reference>
<el-link type="danger" :underline="false" icon="el-icon-delete">
删除
</el-link>
</template>
</el-popconfirm>
</template>
</ele-pro-table>
</el-card>
<!-- 编辑弹窗 -->
<blacklist-edit :data="current" :visible.sync="showEdit" @done="reload" />
<!-- 导入弹窗 -->
<blacklist-import
:data="current"
:visible.sync="showImport"
@done="reload"
/>
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import BlacklistSearch from './components/blacklist-search.vue';
import BlacklistEdit from './components/blacklist-edit.vue';
import BlacklistImport from './components/blacklist-import';
import { getActivity } from '@/api/sylive/activity';
import {
pageBlacklist,
removeBlacklist,
removeBlacklists
} from '@/api/sylive/blacklist';
const ROUTE_PATH = '/sylive/blacklist';
export default {
name: 'syliveBlacklist',
components: { BlacklistSearch, BlacklistEdit, BlacklistImport },
data() {
return {
// 加载状态
title: '黑名单',
loading: true,
// 表格选中数据
selection: [],
// 当前编辑数据
current: null,
// 是否显示编辑弹窗
showEdit: false,
showImport: false,
activityId: null,
// 表格列配置
columns: [
{
columnKey: 'selection',
type: 'selection',
width: 45,
align: 'center',
fixed: 'left'
},
{
prop: 'blacklistId',
label: 'ID',
width: 80,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
},
{
prop: 'mobile',
label: '手机号',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 150
},
{
prop: 'createTime',
label: '创建时间',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 120,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
columnKey: 'action',
label: '操作',
width: 200,
align: 'center',
resizable: false,
slot: 'action'
}
]
};
},
methods: {
/* 表格数据源 */
datasource({ page, limit, where, order }) {
const activityId = this.activityId;
return pageBlacklist({ ...where, ...order, page, limit, activityId });
},
query() {
this.activityId = Number(this.$route.query.id);
if (!this.activityId) {
return;
}
this.loading = true;
getActivity(this.activityId)
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.title = data.title + '-黑名单';
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 打开导入弹窗 */
openImport() {
this.current = { activityId: this.activityId };
this.showImport = true;
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 显示编辑 */
openEdit() {
this.current = { activityId: this.activityId };
this.showEdit = true;
},
/* 删除 */
remove(row) {
const loading = this.$loading({ lock: true });
removeBlacklist(row.blacklistId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
},
/* 批量删除 */
removeBatch() {
if (!this.selection.length) {
this.$message.error('请至少选择一条数据');
return;
}
this.$confirm('确定要删除选中的黑名单吗?', '提示', {
type: 'warning'
})
.then(() => {
const loading = this.$loading({ lock: true });
removeBlacklists(this.selection.map((d) => d.blacklistId))
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
})
.catch(() => {});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
this.query();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -19,19 +19,19 @@
/>
</el-form-item>
<el-form-item label="商品价格:" prop="price">
<el-input
clearable
:maxlength="60"
<el-input-number
v-model="form.price"
placeholder="请输入商品价格"
controls-position="right"
:min="0"
style="width: 150px; margin-right: 10px"
/>
</el-form-item>
<el-form-item label="库存数:" prop="stock">
<el-input
clearable
:maxlength="60"
<el-input-number
v-model="form.stock"
placeholder="请输入库存数"
controls-position="right"
:min="0"
style="width: 150px; margin-right: 10px"
/>
</el-form-item>
<el-form-item label="商品图片:" prop="banner">
@@ -80,6 +80,12 @@
class="ele-fluid"
/>
</el-form-item>
<el-form-item label="是否核销:">
<el-radio-group v-model="form.ifCode">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="收货地址:">
<el-radio-group v-model="form.ifAddress">
<el-radio :label="0">不需要</el-radio>
@@ -91,7 +97,6 @@
v-model="form.sort"
controls-position="right"
:min="0"
:max="100"
style="width: 150px; margin-right: 10px"
/>
</el-form-item>
@@ -134,13 +139,14 @@
activityId: null,
type: 0,
title: '',
price: '',
stock: '',
price: 0,
stock: 0,
banner: [],
dateRange: '',
useRange: '',
dateRange: [],
useRange: [],
sort: 0,
ifAddress: 0,
ifCode: 0,
descrip: ''
};
return {
+2 -2
View File
@@ -248,7 +248,7 @@
/* 删除 */
remove(row) {
const loading = this.$loading({ lock: true });
removeGoods(row.activityId)
removeGoods(row.itemId)
.then((msg) => {
loading.close();
this.$message.success(msg);
@@ -270,7 +270,7 @@
})
.then(() => {
const loading = this.$loading({ lock: true });
removeGoodss(this.selection.map((d) => d.activityId))
removeGoodss(this.selection.map((d) => d.itemId))
.then((msg) => {
loading.close();
this.$message.success(msg);
@@ -0,0 +1,101 @@
<!-- 用户导入弹窗 -->
<template>
<ele-modal
width="520px"
title="导入客户"
:visible="visible"
@update:visible="updateVisible"
>
<el-upload
drag
action=""
class="ele-block"
v-loading="loading"
accept=".xls,.xlsx"
:show-file-list="false"
:before-upload="doUpload"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处, <em>点击上传</em></div>
<template v-slot:tip>
<div class="el-upload__tip ele-text-center">
<span>只能上传xlsxlsx文件, </span>
<el-link
download
:href="url"
type="primary"
:underline="false"
style="vertical-align: baseline"
>
下载模板
</el-link>
</div>
</template>
</el-upload>
</ele-modal>
</template>
<script>
import { importGroupsCustomer } from '@/api/sylive/groups-customer';
import { API_BASE_URL } from '@/config/setting';
export default {
props: {
// 是否打开弹窗
visible: Boolean
},
data() {
return {
// 导入请求状态
loading: false,
// 导入模板下载地址
url: API_BASE_URL.replace('api', '') + 'temp/customer.xlsx'
};
},
methods: {
/* 上传 */
doUpload(file) {
if (
![
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
].includes(file.type)
) {
this.$message.error('只能选择 excel 文件');
return false;
}
if (file.size / 1024 / 1024 > 5) {
this.$message.error('大小不能超过 5MB');
return false;
}
this.loading = true;
const activityId = this.$route.query.id;
importGroupsCustomer(file, activityId)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
return false;
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
}
};
</script>
<style lang="scss" scoped>
.ele-block {
:deep(.el-upload),
:deep(.el-upload-dragger) {
width: 100%;
}
}
</style>
@@ -0,0 +1,222 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="门店:">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="where.bizId"
:clearable="true"
placeholder="请选择"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="客户姓名:">
<el-input clearable v-model="where.name" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="状态:">
<el-select
clearable
v-model="where.status"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="(option, index) in data.statusAry"
:key="index"
:value="option.value"
:label="option.label"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="回访标签:">
<el-select
clearable
v-model="where.visitTagId"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="(option, index) in data.visitTagAry"
:key="index"
:value="option.value"
:label="option.label"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="创建时间:">
<el-date-picker
unlink-panels
v-model="dateRange"
range-separator="-"
type="datetimerange"
end-placeholder="结束日期"
start-placeholder="开始日期"
:picker-options="pickerOptions"
value-format="yyyy-MM-dd HH:mm:ss"
class="ele-fluid"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listGroups } from '@/api/sylive/groups';
export default {
props: {
data: Object
},
data() {
// 默认表单数据
const defaultWhere = {
name: '',
mobile: '',
status: '',
visitTagId: ''
};
return {
activityId: null,
// 门店数据
groupsList: [],
// 商品数据
goodsList: [],
// 表单数据
where: { ...defaultWhere },
// 日期范围选择
dateRange: [],
// 日期时间选择器快捷项
pickerOptions: {
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}
]
}
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {},
methods: {
/* 搜索 */
search() {
if (!this.dateRange) {
this.dateRange = [];
}
const [createTimeStart, createTimeEnd] = this.dateRange;
this.$emit('search', {
...this.where,
createTimeStart,
createTimeEnd
});
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.dateRange = [];
this.search();
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-customer') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
this.groupsQuery();
},
immediate: true
}
}
};
</script>
+192
View File
@@ -0,0 +1,192 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<gro-customer-search :data="activityInfo" @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
cache-key="syliveCustomerTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-dcustomerload"
@click="exportData"
>
导出客户
</el-button>
<el-button
size="small"
icon="el-icon-upload2"
class="ele-btn-icon"
@click="openImport"
>
导入客户
</el-button>
</template>
<template v-slot:useStatus="{ row }">
<span
:class="row.useStatus == 2 ? 'ele-text-success' : 'ele-text-danger'"
>
{{ row.useStatusName }}
</span>
</template>
<template v-slot:action="{ row }">
<el-link
v-if="row.useStatus != 1"
type="primary"
:underline="false"
icon="el-icon-view"
@click="openDetail(row)"
>
详情
</el-link>
</template>
</ele-pro-table>
</el-card>
<!-- 导入弹窗 -->
<gro-customer-import :visible.sync="showImport" @done="reload" />
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import GroCustomerSearch from './components/gro-customer-search.vue';
import { getActivityInfo } from '@/api/sylive/activity';
import {
listGroupsCustomer,
exportGroupsCustomer
} from '@/api/sylive/groups-customer';
import { utils, writeFile } from 'xlsx';
import GroCustomerImport from './components/gro-customer-import';
const ROUTE_PATH = '/sylive/groups-customer';
export default {
name: 'syliveGroupsCustomer',
components: {
GroCustomerImport,
GroCustomerSearch
},
data() {
return {
title: '客户列表',
activityId: null,
activityInfo: { statusAry: [], visitTagAry: [] },
// 加载状态
loading: true,
showDetail: false,
showStatus: false,
showImport: false,
current: [],
currentStatus: {},
useType: 0,
// 表格列配置
columns: []
};
},
methods: {
/* 打开导入弹窗 */
openImport() {
this.showImport = true;
},
/* 表格数据源 */
async datasource({ page, limit, where, order }) {
this.useType = where ? where.useType : 0;
const result = await listGroupsCustomer({
...where,
...order,
page,
limit,
activityId: this.activityId
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
query() {
this.loading = true;
getActivityInfo({
activityId: Number(this.activityId),
type: 'customer'
})
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.activityInfo = data;
this.title = data.title + '的客户列表';
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.useType = where ? where.useType : 0;
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.activityId;
exportGroupsCustomer({ ...where, ...order, activityId })
.then((data) => {
loading.close();
const array = [data.columns];
data.list.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,97 @@
<!-- 详情弹窗 -->
<template>
<ele-modal
title="操作详情"
width="680px"
:visible="visible"
@update:visible="updateVisible"
>
<el-form
v-for="(item, index) in data"
:key="index"
size="mini"
label-width="82px"
class="ele-form-detail"
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="审核人:">
<div class="ele-text-secondary">
{{ item.adminName }}
</div>
</el-form-item>
<el-form-item label="审核时间:">
<div class="ele-text-secondary">
{{ item.adminTime }}
</div>
</el-form-item>
<el-form-item label="审核状态:">
<div class="ele-text-secondary">
{{ item.ifCheckName }}
</div>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="申请人:">
<div class="ele-text-secondary">
{{ item.cfName }}
</div>
</el-form-item>
<el-form-item label="申请时间:">
<div class="ele-text-secondary">
{{ item.cfTime }}
</div>
</el-form-item>
<el-form-item label="收货地址:" v-if="item.address">
<div class="ele-text-secondary">
{{ item.address }}
</div>
</el-form-item>
<el-form-item label="描述:" v-if="item.descrip">
<el-input
:disabled="true"
v-model="item.descrip"
:rows="2"
type="textarea"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item v-if="item.logistics.length > 0" label="物流信息:">
<text-ellipsis :content="item.logistics" class="ele-text-secondary" />
</el-form-item>
<div style="margin: 12px 0" v-if="index != 0">
<el-divider />
</div>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">关闭</el-button>
</template>
</ele-modal>
</template>
<script>
import TextEllipsis from './text-ellipsis.vue';
export default {
components: { TextEllipsis },
props: {
// 弹窗是否打开
visible: Boolean,
// 数据
data: []
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
}
};
</script>
@@ -0,0 +1,100 @@
<!-- 用户导入弹窗 -->
<template>
<ele-modal
width="520px"
title="导入审核"
:visible="visible"
@update:visible="updateVisible"
>
<el-upload
drag
action=""
class="ele-block"
v-loading="loading"
accept=".xls,.xlsx"
:show-file-list="false"
:before-upload="doUpload"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处, <em>点击上传</em></div>
<template v-slot:tip>
<div class="el-upload__tip ele-text-center">
<span>只能上传xlsxlsx文件, </span>
<el-link
download
:href="url"
type="primary"
:underline="false"
style="vertical-align: baseline"
>
下载模板
</el-link>
</div>
</template>
</el-upload>
</ele-modal>
</template>
<script>
import { importGroupsExchange } from '@/api/sylive/groups-exchange';
import { API_BASE_URL } from '@/config/setting';
export default {
props: {
// 是否打开弹窗
visible: Boolean
},
data() {
return {
// 导入请求状态
loading: false,
// 导入模板下载地址
url: API_BASE_URL.replace('api', '') + 'temp/exchange.xlsx'
};
},
methods: {
/* 上传 */
doUpload(file) {
if (
![
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
].includes(file.type)
) {
this.$message.error('只能选择 excel 文件');
return false;
}
if (file.size / 1024 / 1024 > 5) {
this.$message.error('大小不能超过 5MB');
return false;
}
this.loading = true;
importGroupsExchange(file)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
return false;
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
}
};
</script>
<style lang="scss" scoped>
.ele-block {
:deep(.el-upload),
:deep(.el-upload-dragger) {
width: 100%;
}
}
</style>
@@ -0,0 +1,183 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="门店:">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="where.bizId"
:clearable="true"
placeholder="请选择"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="商品:">
<el-select
clearable
v-model="where.itemId"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="item in goodsList"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="姓名:">
<el-input clearable v-model="where.uname" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="核销类型:">
<el-select
clearable
v-model="where.useType"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="订单" :value="0" />
<el-option label="抽奖" :value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="状态:">
<el-select
clearable
v-model="where.useStatus"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="审核中" :value="1" />
<el-option label="通过" :value="2" />
<el-option label="驳回" :value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listGroups } from '@/api/sylive/groups';
import { listGoods } from '@/api/sylive/goods';
export default {
data() {
// 默认表单数据
const defaultWhere = {
uname: '',
mobile: '',
useType: 0,
bizId: ''
};
return {
activityId: null,
// 门店数据
groupsList: [],
// 商品数据
goodsList: [],
// 表单数据
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {},
methods: {
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询商品 */
goodsQuery() {
listGoods({ activityId: this.activityId })
.then((list) => {
this.goodsList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-exchange') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
this.groupsQuery();
this.goodsQuery();
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,118 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="750px"
:visible="visible"
:append-to-body="true"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
:title="form.useStatus == 2 ? '审核通过' : '审核驳回'"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" label-width="82px">
<el-form-item label="物流单号:" prop="title" v-if="form.useStatus == 2">
<el-input
clearable
:maxlength="60"
v-model="form.descrip"
placeholder="请输入物流单号"
/>
</el-form-item>
<el-form-item label="驳回理由:" prop="title" v-else>
<el-input
clearable
v-model="form.descrip"
:rows="2"
type="textarea"
placeholder="请输入驳回理由"
/>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { updateGroupsExchangeUseStatus } from '@/api/sylive/groups-exchange';
export default {
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
cfId: null,
type: null,
useStatus: 0,
descrip: ''
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 提交状态
loading: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save() {
if (this.form.useStatus != 2 && !this.form.descrip) {
this.$message.error('请输入驳回理由');
return;
}
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
updateGroupsExchangeUseStatus(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data.cfId) {
this.$util.assignObject(this.form, {
...this.data
});
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,69 @@
<!-- 文本超出隐藏 -->
<template>
<div
:class="[
'demo-text-ellipsis ele-bg-white ele-border-lighter',
{ expanded: expanded }
]"
>
<div>
<table>
<tr v-for="(item, index) in content" :key="index">
<td>
<b>{{ item.time }}</b>{{ item.status }}
</td>
</tr>
</table>
</div>
<div
class="demo-text-ellipsis-footer ele-border-lighter ele-bg-white"
@click="expanded = !expanded"
>
<i :class="expanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
</div>
</div>
</template>
<script>
export default {
props: {
content: []
},
data() {
return {
expanded: false
};
}
};
</script>
<style lang="scss" scoped>
.demo-text-ellipsis {
border-radius: 4px;
padding: 6px 12px 20px 12px;
position: relative;
border-width: 1px;
border-style: solid;
word-break: break-all;
&:not(.expanded) {
max-height: 128px;
overflow: hidden;
}
}
.demo-text-ellipsis-footer {
border-top-width: 1px;
border-top-style: solid;
position: absolute;
bottom: 0;
left: 0;
right: 0;
line-height: 1.3;
text-align: center;
font-size: 14px;
cursor: pointer;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
</style>
+274
View File
@@ -0,0 +1,274 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<gro-exchange-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
cache-key="syliveExchangeTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-dexchangeload"
@click="exportData"
>
导出核销
</el-button>
<el-button
size="small"
icon="el-icon-upload2"
class="ele-btn-icon"
@click="openImport"
>
导入审核
</el-button>
</template>
<template v-slot:useStatus="{ row }">
<span
:class="row.useStatus == 2 ? 'ele-text-success' : 'ele-text-danger'"
>
{{ row.useStatusName }}
</span>
</template>
<template v-slot:action="{ row }">
<el-link
v-if="row.useStatus != 1"
type="primary"
:underline="false"
icon="el-icon-view"
@click="openDetail(row)"
>
详情
</el-link>
<el-popconfirm
v-if="row.useStatus == 1 && !row.ifAddress"
class="ele-action"
title="确定要通过吗?"
@confirm="remove(row, 2)"
>
<template v-slot:reference>
<el-link
type="primary"
:underline="false"
icon="el-icon-finished"
>
通过
</el-link>
</template>
</el-popconfirm>
<el-link
v-if="row.useStatus == 1 && row.ifAddress"
type="primary"
:underline="false"
icon="el-icon-finished"
@click="setStatus(row, 2)"
>
通过
</el-link>
<el-link
v-if="row.useStatus == 1"
type="danger"
:underline="false"
icon="el-icon-circle-close"
@click="setStatus(row, 3)"
>
驳回
</el-link>
</template>
</ele-pro-table>
</el-card>
<!-- 详情弹窗 -->
<gro-exchange-detail :visible.sync="showDetail" :data="current" />
<!-- 导入弹窗 -->
<gro-exchange-import :visible.sync="showImport" @done="reload" />
<!-- 审核弹窗 -->
<gro-exchange-status
:visible.sync="showStatus"
:data="currentStatus"
@done="reload"
/>
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import GroExchangeSearch from './components/gro-exchange-search.vue';
import { getActivity } from '@/api/sylive/activity';
import {
getGroupsExchangeDetail,
listGroupsExchange,
updateGroupsExchangeUseStatus,
exportGroupsExchange
} from '@/api/sylive/groups-exchange';
import { utils, writeFile } from 'xlsx';
import GroExchangeDetail from './components/gro-exchange-detail.vue';
import GroExchangeStatus from './components/gro-exchange-status';
import GroExchangeImport from './components/gro-exchange-import';
const ROUTE_PATH = '/sylive/groups-exchange';
export default {
name: 'syliveGroupsExchange',
components: {
GroExchangeImport,
GroExchangeStatus,
GroExchangeDetail,
GroExchangeSearch
},
data() {
return {
activityId: null,
// 加载状态
title: '核销记录',
loading: true,
showDetail: false,
showStatus: false,
showImport: false,
current: [],
currentStatus: {},
useType: 0,
// 表格列配置
columns: []
};
},
methods: {
/* 删除 */
remove(row, status) {
const loading = this.$loading({ lock: true });
updateGroupsExchangeUseStatus({
cfId: row.id,
type: this.useType,
useStatus: status,
descrip: ''
})
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
},
/* 打开导入弹窗 */
openImport() {
this.showImport = true;
},
/* 详情 */
openDetail(row) {
getGroupsExchangeDetail({ cfId: row.id, type: this.useType })
.then((list) => {
this.current = list;
})
.catch((e) => {
this.$message.error(e.message);
});
this.showDetail = true;
},
setStatus(row, status) {
this.showStatus = true;
this.currentStatus = {
cfId: row.id,
type: this.useType,
useStatus: status,
descrip: ''
};
},
/* 表格数据源 */
async datasource({ page, limit, where, order }) {
this.useType = where ? where.useType : 0;
const result = await listGroupsExchange({
...where,
...order,
page,
limit,
activityId: this.activityId
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
query() {
this.loading = true;
getActivity(Number(this.activityId))
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.title = data.title + '的核销记录';
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.useType = where ? where.useType : 0;
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.activityId;
exportGroupsExchange({ ...where, ...order, activityId })
.then((data) => {
loading.close();
const array = [data.columns];
data.list.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,101 @@
<!-- 导入弹窗 -->
<template>
<ele-modal
width="520px"
title="导入订单"
:visible="visible"
@update:visible="updateVisible"
>
<el-upload
drag
action=""
class="ele-block"
v-loading="loading"
accept=".xls,.xlsx"
:show-file-list="false"
:before-upload="doUpload"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处, <em>点击上传</em></div>
<template v-slot:tip>
<div class="el-upload__tip ele-text-center">
<span>只能上传xlsxlsx文件, </span>
<el-link
download
:href="url"
type="primary"
:underline="false"
style="vertical-align: baseline"
>
下载模板
</el-link>
</div>
</template>
</el-upload>
</ele-modal>
</template>
<script>
import { importGroupsOrder } from '@/api/sylive/groups-order';
import { API_BASE_URL } from '@/config/setting';
export default {
props: {
// 是否打开弹窗
visible: Boolean
},
data() {
return {
// 导入请求状态
loading: false,
// 导入模板下载地址
url: API_BASE_URL.replace('api', '') + 'temp/order.xlsx'
};
},
methods: {
/* 上传 */
doUpload(file) {
if (
![
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
].includes(file.type)
) {
this.$message.error('只能选择 excel 文件');
return false;
}
if (file.size / 1024 / 1024 > 5) {
this.$message.error('大小不能超过 5MB');
return false;
}
this.loading = true;
const activityId = this.$route.query.id;
importGroupsOrder(file, activityId)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
return false;
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
}
};
</script>
<style lang="scss" scoped>
.ele-block {
:deep(.el-upload),
:deep(.el-upload-dragger) {
width: 100%;
}
}
</style>
@@ -0,0 +1,255 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="门店:">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="where.bizId"
:clearable="true"
placeholder="请选择"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="商品:">
<el-select
clearable
v-model="where.itemId"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="item in goodsList"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="姓名:">
<el-input clearable v-model="where.uname" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<el-form-item label="订单类型:">
<el-select
clearable
v-model="where.type"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="权益" :value="0" />
<el-option label="商品" :value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<el-form-item label="状态:">
<el-select
clearable
v-model="where.status"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="未支付" :value="0" />
<el-option label="已支付" :value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<el-form-item label="内部人员:">
<el-select
clearable
v-model="where.insiders"
placeholder="请选择"
class="ele-fluid"
>
<el-option label="是" :value="1" />
<el-option label="否" :value="2" />
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="创建时间:">
<el-date-picker
unlink-panels
v-model="dateRange"
range-separator="-"
type="datetimerange"
end-placeholder="结束日期"
start-placeholder="开始日期"
:picker-options="pickerOptions"
value-format="yyyy-MM-dd HH:mm:ss"
class="ele-fluid"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listGroups } from '@/api/sylive/groups';
import { listGoods } from '@/api/sylive/goods';
export default {
data() {
// 默认表单数据
const defaultWhere = {
status: 1,
uname: '',
mobile: '',
type: '',
bizId: '',
insiders: ''
};
return {
activityId: null,
// 门店数据
groupsList: [],
// 商品数据
goodsList: [],
// 表单数据
where: { ...defaultWhere },
// 日期范围选择
dateRange: [],
// 日期时间选择器快捷项
pickerOptions: {
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}
]
}
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {},
methods: {
/* 搜索 */
search() {
if (!this.dateRange) {
this.dateRange = [];
}
const [createTimeStart, createTimeEnd] = this.dateRange;
this.$emit('search', {
...this.where,
createTimeStart,
createTimeEnd
});
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.dateRange = [];
this.search();
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询商品 */
goodsQuery() {
listGoods({ activityId: this.activityId })
.then((list) => {
this.goodsList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-order') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
this.groupsQuery();
this.goodsQuery();
},
immediate: true
}
}
};
</script>
+159
View File
@@ -0,0 +1,159 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<gro-order-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
cache-key="syliveOrderTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
<el-button
size="small"
icon="el-icon-upload2"
class="ele-btn-icon"
@click="openImport"
>
导入
</el-button>
</template>
</ele-pro-table>
</el-card>
<!-- 导入弹窗 -->
<gro-order-import :visible.sync="showImport" @done="reload" />
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import GroOrderSearch from './components/gro-order-search.vue';
import { getActivity } from '@/api/sylive/activity';
import {
listGroupsOrder,
exportGroupsOrder
} from '@/api/sylive/groups-order';
import { utils, writeFile } from 'xlsx';
import GroOrderImport from './components/gro-order-import';
const ROUTE_PATH = '/sylive/groups-order';
export default {
name: 'syliveGroupsOrder',
components: { GroOrderSearch, GroOrderImport },
data() {
return {
activityId: null,
// 加载状态
title: '权益订单',
loading: true,
showImport: false,
// 表格列配置
columns: []
};
},
methods: {
/* 打开导入弹窗 */
openImport() {
this.showImport = true;
},
/* 表格数据源 */
async datasource({ page, limit, where, order }) {
const result = await listGroupsOrder({
...where,
...order,
page,
limit,
activityId: this.activityId
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
query() {
this.loading = true;
getActivity(Number(this.activityId))
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.title = data.title + '的分组订单';
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.activityId;
exportGroupsOrder({ ...where, ...order, activityId })
.then((data) => {
loading.close();
const array = [data.columns];
data.list.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,180 @@
<template>
<el-card shadow="never">
<!-- 数据表格 -->
<ele-pro-table
ref="table"
title="门店统计"
:columns="columns"
:datasource="datasource"
size="mini"
>
<template v-slot:toolkit>
<div class="list-tool-item">
<el-select
v-model="day"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.days"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<div class="list-tool-item">
<el-select
v-model="itemId"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
</template>
</ele-pro-table>
</el-card>
</template>
<script>
import {
getGroupsStatisticsBiz,
exportGroupsStatisticsBiz
} from '@/api/sylive/groups-statistics';
import { utils, writeFile } from 'xlsx';
export default {
props: { data: Object },
data() {
return {
activityId: null,
// 表格选中数据
day: '',
itemId: '',
selection: [],
// 表格列配置
columns: []
};
},
methods: {
/* 表格数据源 */
async datasource({ page, limit, order }) {
const result = await getGroupsStatisticsBiz({
...order,
page,
limit,
activityId: this.activityId,
day: this.day,
itemId: this.itemId,
levels: this.data.levels
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
/* 导出数据 */
exportData() {
const array = [];
const arrayItem = [];
this.columns.forEach((d) => {
arrayItem.push(d.label);
});
array.push(arrayItem);
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
exportGroupsStatisticsBiz({
...where,
...order,
activityId: this.activityId,
day: this.day,
itemId: this.itemId,
levels: this.data.levels
})
.then((data) => {
loading.close();
data.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
'门店统计.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
},
/* 更新选中数据 */
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-statistics') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
setTimeout(() => {
if (!this.itemId && this.data.goods[0]) {
this.itemId = this.data.goods[0]['value'];
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
}, 1500);
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.list-tool-divider {
padding: 0 12px;
}
</style>
@@ -0,0 +1,178 @@
<template>
<el-card shadow="never">
<!-- 数据表格 -->
<ele-pro-table
ref="table"
title="顾问统计"
:columns="columns"
:datasource="datasource"
size="mini"
>
<template v-slot:toolkit>
<div class="list-tool-item">
<el-select
v-model="day"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.days"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<div class="list-tool-item">
<el-select
v-model="itemId"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
</template>
</ele-pro-table>
</el-card>
</template>
<script>
import {
getGroupsStatisticsConsultant,
exportGroupsStatisticsConsultant
} from '@/api/sylive/groups-statistics';
import { utils, writeFile } from 'xlsx';
export default {
props: { data: Object },
data() {
return {
activityId: null,
day: '',
itemId: '',
// 表格列配置
columns: []
};
},
methods: {
/* 表格数据源 */
async datasource({ page, limit, order }) {
const result = await getGroupsStatisticsConsultant({
...order,
page,
limit,
activityId: this.activityId,
day: this.day,
itemId: this.itemId,
levels: this.data.levels
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
/* 导出数据 */
exportData() {
const array = [];
const arrayItem = [];
this.columns.forEach((d) => {
arrayItem.push(d.label);
});
array.push(arrayItem);
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
exportGroupsStatisticsConsultant({
...where,
...order,
activityId: this.activityId,
day: this.day,
itemId: this.itemId,
levels: this.data.levels
})
.then((data) => {
loading.close();
data.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
'顾问统计.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
},
/* 更新选中数据 */
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-statistics') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
setTimeout(() => {
if (!this.itemId && this.data.goods[0]) {
this.itemId = this.data.goods[0]['value'];
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
}, 1600);
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.list-tool-divider {
padding: 0 12px;
}
</style>
@@ -0,0 +1,213 @@
<template>
<el-card shadow="never">
<!-- 数据表格 -->
<ele-pro-table
ref="table"
title="客户列表"
:columns="columns"
:datasource="datasource"
size="mini"
>
<template v-slot:toolkit>
<div class="list-tool-item">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="groupsId"
:clearable="true"
placeholder="归属"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
@input="updateValue"
/>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<div class="list-tool-item">
<el-select
clearable
v-model="insiders"
placeholder="内部人员"
class="ele-fluid"
@input="updateValue"
>
<el-option label="是" :value="1" />
<el-option label="否" :value="2" />
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<div class="list-tool-item">
<el-select
v-model="itemId"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
</template>
</ele-pro-table>
</el-card>
</template>
<script>
import {
getGroupsStatisticsCustomer,
exportGroupsStatisticsCustomer
} from '@/api/sylive/groups-statistics';
import { listGroups } from '@/api/sylive/groups';
import { utils, writeFile } from 'xlsx';
export default {
props: { data: Object },
data() {
return {
//分组数据
groupsList: [],
activityId: null,
insiders: null,
groupsId: null,
itemId: '',
// 表格列配置
columns: []
};
},
methods: {
/* 表格数据源 */
async datasource({ page, limit, order }) {
const result = await getGroupsStatisticsCustomer({
...order,
page,
limit,
activityId: this.activityId,
groupsId: this.groupsId,
insiders: this.insiders,
itemId: this.itemId,
levels: this.data.levels
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 导出数据 */
exportData() {
const array = [];
const arrayItem = [];
this.columns.forEach((d) => {
arrayItem.push(d.label);
});
array.push(arrayItem);
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
exportGroupsStatisticsCustomer({
...where,
...order,
activityId: this.activityId,
groupsId: this.groupsId,
insiders: this.insiders,
itemId: this.itemId,
levels: this.data.levels
})
.then((data) => {
loading.close();
data.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
'客户列表.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
},
/* 更新选中数据 */
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-statistics') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
setTimeout(() => {
if (!this.itemId && this.data.goods[0]) {
this.itemId = this.data.goods[0]['value'];
}
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
}, 1700);
this.groupsQuery();
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.list-tool-divider {
padding: 0 12px;
}
</style>
@@ -0,0 +1,292 @@
<template>
<el-card shadow="never">
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:title="title"
:columns="columns"
:datasource="datasource"
:need-page="false"
size="mini"
>
<template v-slot:toolkit>
<div class="list-tool-item">
<el-select
v-model="day"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.days"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
<div class="list-tool-item">
<el-select
v-model="itemId"
clearable
class="ele-fluid"
@input="updateValue"
>
<el-option
v-for="item in data.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
<div class="list-tool-divider">
<el-divider direction="vertical" />
</div>
</template>
</ele-pro-table>
<div
style="position: relative; margin-top: 40px"
v-if="areaChartOption.legend.data.length > 0"
>
<div
style="
position: absolute;
top: 0;
right: 40px;
width: 200px;
z-index: 1;
"
>
<el-select
class="ele-fluid"
v-model="tempkpi"
placeholder="请选择"
@change="changeKpi($event)"
>
<el-option
v-for="(option, index) in kpioption"
:key="index"
:value="option.kpi"
:label="option.title"
/>
</el-select>
</div>
<v-chart
ref="areaChart"
style="width: 100%; height: 500px"
:option="areaChartOption"
/>
</div>
</el-card>
</template>
<script>
import { getGroupsStatisticsLevel } from '@/api/sylive/groups-statistics';
import { getStatisticsStackedArea } from '@/api/sylive/activity';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { LineChart } from 'echarts/charts';
import {
LegendComponent,
GridComponent,
ToolboxComponent,
TooltipComponent
} from 'echarts/components';
import VChart from 'vue-echarts';
import 'echarts-wordcloud';
import { echartsMixin } from '@/utils/echarts-mixin';
use([
CanvasRenderer,
GridComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
LineChart
]);
export default {
components: { VChart },
mixins: [echartsMixin(['areaChart'])],
props: { data: Object, level: Number, title: String },
data() {
return {
activityId: null,
// 表格选中数据
day: '',
itemId: '',
selection: [],
// 表格列配置
columns: [
{
prop: 'groupsName',
label: '名称',
align: 'center',
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'biz',
label: '参与门店数',
align: 'center',
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'browse',
label: '浏览数(人)',
align: 'center',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 120
},
{
prop: 'subscribe',
label: '预约数(人)',
align: 'center',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 120
},
{
prop: 'beforeOrder',
label: '留资数(单)',
align: 'center',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 120
},
{
prop: 'order',
label: '订单数(单)',
align: 'center',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 120
}
],
kpi: 'browse',
tempkpi: 'browse',
kpioption: [
{
kpi: 'browse',
title: '浏览数'
},
{
kpi: 'subscribe',
title: '预约数'
}
],
areaChartOption: {
legend: {
data: []
}
} //折线图
};
},
methods: {
/* 表格数据源 */
datasource({ page, limit, order }) {
return getGroupsStatisticsLevel({
...order,
page,
limit,
activityId: this.activityId,
day: this.day,
itemId: this.itemId,
level: this.level
});
},
//切换区域统计折线图
changeKpi(value) {
if (value != this.kpi) {
this.kpi = value;
this.getStatisticsStackedArea();
}
},
//区域统计折线图
getStatisticsStackedArea() {
if (this.activityId) {
//暂时屏蔽
return;
}
this.areaChartOption = { legend: { data: [] } };
getStatisticsStackedArea({
activityId: this.activityId,
kpi: this.kpi
}).then((res) => {
this.areaChartOption = {
tooltip: {
trigger: 'axis'
},
legend: {
x: 'left',
padding: [13, 260, 0, 40],
data: res.legendData
},
grid: {
left: '3%',
right: '4%',
top: res.legendData.length < 15 ? '14%' : '17%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: res.xAxisData
},
yAxis: {
type: 'value'
},
series: res.yAxisSeries
};
});
},
/* 更新选中数据 */
updateValue() {
this.$refs.table.reload({ page: 1 });
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-statistics') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (!this.itemId && this.data.goods[0]) {
this.itemId = this.data.goods[0]['value'];
}
this.getStatisticsStackedArea();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.list-tool-divider {
padding: 0 12px;
}
</style>
@@ -0,0 +1,107 @@
<template>
<el-card shadow="never" v-if="watchOrderOption.legend.data.length > 0">
<div>
<v-chart
ref="watchOrder"
style="width: 100%; height: 500px"
:option="watchOrderOption"
/>
</div>
</el-card>
</template>
<script>
import { getGroupsStatisticsWatchOrder } from '@/api/sylive/groups-statistics';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { LineChart } from 'echarts/charts';
import {
LegendComponent,
GridComponent,
ToolboxComponent,
TooltipComponent
} from 'echarts/components';
import VChart from 'vue-echarts';
import 'echarts-wordcloud';
import { echartsMixin } from '@/utils/echarts-mixin';
use([
CanvasRenderer,
GridComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
LineChart
]);
export default {
components: { VChart },
mixins: [echartsMixin(['watchOrder'])],
data() {
return {
activityId: null,
watchOrderOption: {
legend: {
data: []
}
} //折线图
};
},
methods: {
//区域统计折线图
query() {
this.watchOrderOption = { legend: { data: [] } };
getGroupsStatisticsWatchOrder({
activityId: this.activityId
}).then((res) => {
this.watchOrderOption = {
tooltip: {
trigger: 'axis'
},
legend: {
padding: [13, 260, 0, 40],
data: res.legendData
},
grid: {
left: '3%',
right: '4%',
top: '10%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: res.xAxisData
},
yAxis: {
type: 'value'
},
series: res.yAxisSeries
};
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-statistics') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,413 @@
<template>
<div class="ele-body ele-body-card" v-loading="loading">
<el-row :gutter="15">
<el-col
v-for="(item, index) in statistics.activityData1.list"
:key="index"
:style="statistics.activityData1.style"
>
<el-card class="analysis-chart-card" shadow="never">
<template v-slot:header>
<div class="ele-cell">
<div class="ele-cell-content">{{ item.name }}</div>
</div>
</template>
<div class="analysis-chart-card-num ele-text-heading">
{{ item.value }}
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col
v-for="(item, index) in statistics.activityData2.list"
:key="index"
:style="statistics.activityData2.style"
>
<el-card :class="item.url != '' ? 'el-header_add' : ''" shadow="never">
<template v-slot:header>
<div class="ele-cell" @click="openPiechart(item.url, item.name)">
<div class="ele-cell-content">{{ item.name }}</div>
<i class="el-icon-arrow-right" v-if="item.url != ''"></i>
</div>
</template>
<div
class="analysis-chart-card-num ele-text-heading"
@click="openPiechart(item.url, item.name)"
>
{{ item.value }}
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col
v-bind="styleResponsive ? { lg: 3, md: 8 } : { span: 3 }"
style="width: 50%"
>
<el-card shadow="never" body-style="padding: 0px">
<div class="ele-table-tool ranking-order-header">
<div class="ele-table-tool-title">
<div class="ele-table-tool-title-label">
<h6 style="font-size: 15px">
{{ preheatingChartOption.title }}
</h6>
</div>
</div>
<div class="list-tool-item">
<el-select
v-model="itemIdPreheating"
clearable
class="ele-fluid"
@input="queryFunnel('left')"
>
<el-option
v-for="item in statistics.tableData.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
</div>
<div
style="width: 500px; margin: 0 auto; padding-top: 7px"
v-if="preheatingChartOption.title"
>
<v-chart
ref="funnelChart"
style="width: 500px; height: 303px"
:option="preheatingChartOption.chartOption"
/>
</div>
<ele-empty v-else v-show="true"></ele-empty>
</el-card>
</el-col>
<el-col
v-bind="styleResponsive ? { lg: 3, md: 8 } : { span: 3 }"
style="width: 50%"
>
<el-card shadow="never" body-style="padding: 0px">
<div class="ele-table-tool ranking-order-header">
<div class="ele-table-tool-title">
<div class="ele-table-tool-title-label">
<h6 style="font-size: 15px">{{ liveChartOption.title }}</h6>
</div>
</div>
<div class="list-tool-item">
<el-select
v-model="itemIdLive"
clearable
class="ele-fluid"
@input="queryFunnel('right')"
>
<el-option
v-for="item in statistics.tableData.goods"
:key="item.value"
:value="item.value"
:label="item.name"
/>
</el-select>
</div>
</div>
<div
style="width: 500px; margin: 0 auto; padding-top: 7px"
v-if="liveChartOption.title"
>
<v-chart
ref="funnelChart"
style="width: 500px; height: 303px"
:option="liveChartOption.chartOption"
/>
</div>
<ele-empty v-else v-show="true"></ele-empty>
</el-card>
</el-col>
</el-row>
<watchOrderLinechart />
<level-table
v-for="(item, index) in statistics.levelData"
:key="index"
:data="statistics.tableData"
:level="item.value"
:title="item.title"
/>
<biz-table :data="statistics.tableData" />
<consultant-table :data="statistics.tableData" />
<customer-table :data="statistics.tableData" />
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import {
getGroupsStatistics,
getGroupsStatisticsFunnel
} from '@/api/sylive/groups-statistics';
const ROUTE_PATH = '/sylive/groups-statistics';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { FunnelChart } from 'echarts/charts';
import { TooltipComponent } from 'echarts/components';
import VChart from 'vue-echarts';
import 'echarts-wordcloud';
import { echartsMixin } from '@/utils/echarts-mixin';
import LevelTable from './components/level-table.vue';
import BizTable from './components/biz-table.vue';
import ConsultantTable from './components/consultant-table.vue';
import CustomerTable from './components/customer-table.vue';
import watchOrderLinechart from './components/watchOrder-linechart.vue';
use([CanvasRenderer, TooltipComponent, FunnelChart]);
export default {
name: 'SyliveGroupsStatistics',
components: {
VChart,
LevelTable,
BizTable,
ConsultantTable,
CustomerTable,
watchOrderLinechart
},
mixins: [echartsMixin(['funnelChart'])],
data() {
return {
activityId: null,
itemIdRanking: '',
itemIdPreheating: '',
itemIdLive: '',
statistics: {
activityData1: { list: [], style: '' },
activityData2: { list: [], style: '' },
levelData: [],
tableData: { days: [], goods: [], levels: [] }
},
loading: true,
browseRank: { area: [], biz: [], consultant: [] },
subscribeRank: { area: [], biz: [], consultant: [] },
watchRank: { area: [], biz: [], consultant: [] },
orderRank: { area: [], biz: [], consultant: [] },
// 词云图表配置
preheatingChartOption: { title: '', chartOption: {} },
liveChartOption: { title: '', chartOption: {} }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 打开饼状图 */
openPiechart(url, title) {
if (url != '') {
this.$router.replace(url + '&title=' + title);
}
},
query() {
this.loading = true;
getGroupsStatistics(Number(this.activityId))
.then((data) => {
this.loading = false;
this.$util.assignObject(this.statistics, {
...data
});
if (data.tableData.goods[0]) {
this.itemIdPreheating = data.tableData.goods[0]['value'];
this.itemIdLive = data.tableData.goods[0]['value'];
}
this.queryFunnel();
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
setPageTabTitle(data.title + '的分组数据统计');
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
queryFunnel(show) {
let itemId = '';
if (show == 'left') {
itemId = this.itemIdPreheating;
} else if (show == 'right') {
itemId = this.itemIdLive;
} else {
itemId = this.itemIdPreheating;
}
getGroupsStatisticsFunnel({
activityId: this.activityId,
show: show,
itemId: itemId
}).then((data) => {
//浏览转化漏斗((预热阶段)
if (data.funnelPreheating.title) {
this.preheatingChartOption.title = data.funnelPreheating.title;
this.preheatingChartOption.chartOption = {
series: [
{
name: 'Expected',
type: 'funnel',
top: '1%',
bottom: '5%',
left: '2%',
width: '72%',
label: {
position: 'right',
formatter: '{b}'
},
labelLine: {
show: false
},
itemStyle: {
opacity: 0.7
},
data: data.funnelPreheating.expectedData
},
{
name: 'Actual',
type: 'funnel',
top: '1%',
bottom: '5%',
left: '7%',
width: '62%',
maxSize: '62%',
label: {
position: 'inside',
formatter: '{c}',
color: '#000'
},
itemStyle: {
opacity: 0.4,
borderColor: '#fff',
borderWidth: 1
},
data: data.funnelPreheating.actualData,
z: 100
}
]
};
}
//浏览转化漏斗(直播阶段)
if (data.funnelLive.title) {
this.liveChartOption.title = data.funnelLive.title;
this.liveChartOption.chartOption = {
series: [
{
name: 'Expected',
type: 'funnel',
top: '1%',
bottom: '5%',
left: '2%',
width: '72%',
label: {
position: 'right',
formatter: '{b}'
},
labelLine: {
show: false
},
itemStyle: {
opacity: 0.7
},
data: data.funnelLive.expectedData
},
{
name: 'Actual',
type: 'funnel',
top: '1%',
bottom: '5%',
left: '7%',
width: '62%',
maxSize: '62%',
label: {
position: 'inside',
formatter: '{c}',
color: '#000'
},
itemStyle: {
opacity: 0.4,
borderColor: '#fff',
borderWidth: 1
},
data: data.funnelLive.actualData,
z: 100
}
]
};
}
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
/* 人数分布排名 */
.monitor-user-count-item {
margin-bottom: 8px;
:deep(.el-progress-bar__outer) {
background: none;
}
.ele-cell-content {
padding-right: 10px;
}
}
.analysis-chart-card-num {
font-size: 30px;
}
.analysis-chart-card-content {
height: 40px;
box-sizing: border-box;
margin-bottom: 12px;
}
.analysis-chart-card-text {
padding-top: 12px;
}
.workplace-table-card {
:deep(.el-table tbody > .el-table__row:last-child td) {
border-bottom: none;
}
:deep(.el-table:before) {
display: none;
}
}
.el-header_add .ele-cell {
color: #409eff;
cursor: pointer;
}
.el-header_add .analysis-chart-card-num {
color: #409eff;
cursor: pointer;
}
.ranking-order-header {
border-bottom: 1px solid var(--border-color-lighter);
box-sizing: border-box;
padding: 10px 17px;
}
</style>
@@ -0,0 +1,187 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="门店:">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="where.bizId"
:clearable="true"
placeholder="请选择"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="商品:">
<el-select
clearable
v-model="where.itemId"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="item in goodsList"
:key="item.itemId"
:value="item.itemId"
:label="item.title"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="姓名:">
<el-input clearable v-model="where.uname" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="中奖类型:">
<el-select
clearable
v-model="where.winType"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="item in winTypeList"
:key="item.id"
:value="item.id"
:label="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listGroups } from '@/api/sylive/groups';
import { listGoods } from '@/api/sylive/goods';
import { getGroupsWinType } from '@/api/sylive/groups-win';
export default {
data() {
// 默认表单数据
const defaultWhere = {
uname: '',
mobile: '',
winType: '',
bizId: ''
};
return {
activityId: null,
// 门店数据
groupsList: [],
// 商品数据
goodsList: [],
winTypeList: [],
// 表单数据
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {
this.groupsWinTypeQuery();
},
methods: {
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
},
/* 查询中奖类型 */
groupsWinTypeQuery() {
getGroupsWinType({ activityId: this.activityId })
.then((list) => {
this.winTypeList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询商品 */
goodsQuery() {
listGoods({ activityId: this.activityId })
.then((list) => {
this.goodsList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/groups-win') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
this.groupsQuery();
this.goodsQuery();
},
immediate: true
}
}
};
</script>
+140
View File
@@ -0,0 +1,140 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<gro-win-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
cache-key="syliveWinTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-dwinload"
@click="exportData"
>
导出
</el-button>
</template>
</ele-pro-table>
</el-card>
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import GroWinSearch from './components/gro-win-search.vue';
import { getActivity } from '@/api/sylive/activity';
import { listGroupsWin, exportGroupsWin } from '@/api/sylive/groups-win';
import { utils, writeFile } from 'xlsx';
const ROUTE_PATH = '/sylive/groups-win';
export default {
name: 'syliveGroupsWin',
components: { GroWinSearch },
data() {
return {
activityId: null,
// 加载状态
title: '中奖名单',
loading: true,
// 表格列配置
columns: []
};
},
methods: {
/* 表格数据源 */
async datasource({ page, limit, where, order }) {
const result = await listGroupsWin({
...where,
...order,
page,
limit,
activityId: this.activityId
});
if (!order.sort && result.columns) {
this.columns = result.columns;
}
return { count: result.count, list: result.list };
},
query() {
this.loading = true;
getActivity(Number(this.activityId))
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.title = data.title + '的中奖名单';
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.activityId;
exportGroupsWin({ ...where, ...order, activityId })
.then((data) => {
loading.close();
const array = [data.columns];
data.list.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.query();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,233 @@
<!-- 分组编辑弹窗 -->
<template>
<ele-modal
width="680px"
:visible="visible"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
:title="isUpdate ? '修改分组' : '添加分组'"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" :rules="rules" label-width="82px">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="上级分组:">
<gro-select
v-model="form.parentId"
:data="groupsList"
placeholder="请选择上级分组"
/>
</el-form-item>
<el-form-item label="分组名称:" prop="groupsName">
<el-input
clearable
:maxlength="20"
v-model="form.groupsName"
placeholder="请输入分组名称"
/>
</el-form-item>
<el-form-item label="分组id:" v-if="form.groupsId">
<el-input v-model="form.groupsId" disabled />
</el-form-item>
<el-form-item label="排序号:">
<el-input-number
:min="0"
:max="99999"
v-model="form.sortNumber"
controls-position="right"
placeholder="请输入排序号"
class="ele-fluid ele-text-left"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="用户来源:">
<el-radio-group v-model="form.userFrom">
<el-radio :label="0">机构</el-radio>
<el-radio :label="1">团队</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="form.userFrom == 0 ? '是否门店:' : '是否团队:'">
<el-radio-group v-model="form.ifBiz">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="form.userFrom == 0 && form.ifBiz == 1"
label="原始门店:"
>
<ele-tree-select
:data="organizationList"
label-key="organizationName"
value-key="organizationId"
v-model="form.originalBizId"
placeholder="请选择门店"
size="small"
:filterable="true"
:multiple="false"
:clearable="true"
:disabled="false"
:expand-on-click-node="true"
:check-strictly="false"
@change="onChange"
/>
</el-form-item>
<el-form-item
label="统计类型:"
v-if="!form.parentId"
prop="statisticsType"
>
<el-select
clearable
v-model="form.statisticsType"
placeholder="请选择统计类型"
class="ele-fluid"
>
<el-option
v-for="item in statisticsTypeList"
:key="item.dictId"
:value="item.dictId"
:label="item.dictName"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import GroSelect from './gro-select.vue';
import { addGroups, updateGroups } from '@/api/sylive/groups';
import { infoOrganization } from '@/api/institution/organization';
export default {
components: { GroSelect },
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object,
// 上级id
parentId: Number,
// 活动id
activityId: Number,
// 分组数据
groupsList: Array,
// 统计类型数据
statisticsTypeList: Array,
// 门店数据
organizationList: Array
},
data() {
const defaultForm = {
groupsId: null,
parentId: null,
groupsName: '',
userFrom: 0,
ifBiz: 0,
statisticsType: null,
sortNumber: null,
originalBizId: null
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 表单验证规则
rules: {
groupsName: [
{
required: true,
message: '请输入分组名称',
trigger: 'blur'
}
],
statisticsType: [
{
required: true,
message: '请选择统计类型',
trigger: 'blur'
}
]
},
// 提交状态
loading: false,
// 是否是修改
isUpdate: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
onChange(value) {
let organizationId = Number(value);
if (organizationId) {
infoOrganization(organizationId)
.then((re) => {
this.form.groupsName = re.organizationName;
})
.catch(() => {});
}
},
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form,
activityId: this.activityId || 0,
parentId: this.form.parentId || 0
};
const saveOrUpdate = this.isUpdate ? updateGroups : addGroups;
saveOrUpdate(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.$util.assignObject(this.form, this.data);
this.isUpdate = true;
} else {
this.form.parentId = this.parentId;
this.isUpdate = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,35 @@
<!-- 分组选择下拉框 -->
<template>
<ele-tree-select
clearable
:value="value || ''"
:data="data"
label-key="groupsName"
value-key="groupsId"
:default-expand-all="true"
:placeholder="placeholder"
@input="updateValue"
/>
</template>
<script>
export default {
props: {
// 选中的数据(v-model)
value: Number,
// 提示信息
placeholder: {
type: String,
default: '请选择分组'
},
// 分组数据
data: Array
},
methods: {
/* 更新选中数据 */
updateValue(value) {
this.$emit('input', value);
}
}
};
</script>
@@ -0,0 +1,349 @@
<template>
<ele-modal
width="70%"
:visible="visible"
title="添加分组用户"
@update:visible="updateVisible"
>
<div class="ele-body" style="padding: 0px">
<el-card shadow="never" body-style="padding: 0px;">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { md: 12 } : { span: 12 }">
<!-- 未选择的用户数据表格 -->
<ele-pro-table
:datasource="unChooseUsers"
:columns="columns"
sub-title=""
height="535px"
emptyText="无未选用户"
:toolkit="[]"
layout="total, prev, pager, next, jumper"
>
<template v-slot:toolkit>
<el-row :gutter="15">
<el-col style="width: 45%">
<ele-tree-select
v-show="userFrom == 0 ? true : false"
:data="organizationList"
label-key="organizationName"
value-key="organizationId"
v-model="organizationIds"
:multiple="true"
:clearable="true"
placeholder="请选择机构"
:disabled="false"
size="small"
:check-strictly="false"
/>
<ele-tree-select
v-show="userFrom == 1 ? true : false"
:data="teamList"
label-key="teamName"
value-key="teamId"
v-model="teamIds"
:multiple="true"
:clearable="true"
placeholder="请选择团队"
:disabled="false"
size="small"
:check-strictly="false"
/>
</el-col>
<el-col style="width: 25%">
<el-input
clearable
v-model="keyword"
placeholder="姓名或手机"
size="small"
/>
</el-col>
<el-col style="width: 12%">
<el-button
class="ele-btn-icon"
size="small"
@click="search"
>
搜索
</el-button>
</el-col>
<el-col style="width: 18%">
<el-button
class="ele-btn-icon"
size="small"
@click="addAll"
>
全部添加
</el-button>
</el-col>
</el-row>
</template>
<template v-slot:action="{ row }">
<el-button size="mini" @click="add(row)">添加</el-button>
</template>
</ele-pro-table>
</el-col>
<el-col v-bind="styleResponsive ? { md: 12 } : { span: 12 }">
<!-- 已选择的用户数据表格 -->
<ele-pro-table
:datasource="chooseUsers"
:columns="columns"
sub-title="已选用户:"
height="535px"
emptyText="未选择用户"
:toolkit="[]"
layout="total, prev, pager, next, jumper"
>
<template v-slot:toolkit>
<el-button
type="primary"
class="ele-btn-icon"
:loading="loading"
size="small"
@click="save"
>
保存已选用户
</el-button>
<el-button
size="small"
type="danger"
plain
class="ele-btn-icon"
@click="removeAll"
>
全部移除
</el-button>
</template>
<template v-slot:action="{ row }">
<el-button type="danger" plain size="mini" @click="remove(row)">
移除
</el-button>
</template>
</ele-pro-table>
</el-col>
</el-row>
</el-card>
</div>
</ele-modal>
</template>
<script>
import { listUsers } from '@/api/institution/organization-user';
import { listTeamUser } from '@/api/institution/team-user';
import { addGroupsUser } from '@/api/sylive/groups-user';
export default {
name: 'groupsUserAdd',
props: {
// 全部机构
organizationList: Array,
// 全部团队
teamList: Array,
// 分组id
groupsId: Number,
// 用户来源
userFrom: Number,
// 活动id
activityId: Number,
// 弹窗是否打开
visible: Boolean
},
data() {
return {
organizationIds: [],
teamIds: [],
keyword: null,
// 加载状态
loading: false,
// 全部用户
classes: [],
// 已选择的用户数据
chooseUsers: [],
// 表格列配置
columns: []
};
},
computed: {
/* 未选择的用户数据 */
unChooseUsers() {
return this.classes.filter((d) => this.chooseUsers.indexOf(d) === -1);
},
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {},
methods: {
/* 获取机构用户 */
search() {
if (this.userFrom == 1) {
this.queryTeam();
} else {
this.query();
}
},
/* 获取机构用户 */
query() {
if (this.organizationIds.length <= 0 && !this.keyword) {
this.$message.error('请选择机构/姓名或手机');
return;
}
if (this.keyword) {
this.organizationIds = [];
}
listUsers({
activityId: this.activityId,
organizationIds: this.organizationIds,
keyword: this.keyword
})
.then((data) => {
this.classes = [];
if (this.chooseUsers.length > 0) {
data.forEach((item) => {
let choose = false;
this.chooseUsers.forEach((d) => {
if (item.userId == d.userId) {
choose = true;
}
});
if (!choose) {
this.classes.push(item);
}
});
} else {
this.classes = data;
}
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 获取团队用户 */
queryTeam() {
if (this.teamIds.length <= 0 && !this.keyword) {
this.$message.error('请选择团队/姓名或手机');
return;
}
if (this.keyword) {
this.teamIds = [];
}
listTeamUser({
activityId: this.activityId,
teamIds: this.teamIds,
keyword: this.keyword
})
.then((data) => {
this.classes = [];
if (this.chooseUsers.length > 0) {
data.forEach((item) => {
let choose = false;
this.chooseUsers.forEach((d) => {
if (item.userId == d.userId) {
choose = true;
}
});
if (!choose) {
this.classes.push(item);
}
});
} else {
this.classes = data;
}
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 添加 */
add(row) {
if (row.groups == 1) {
this.$message.error('此用户已添加过分组了');
return;
}
this.chooseUsers.push(row);
},
/* 移除 */
remove(row) {
this.chooseUsers.splice(this.chooseUsers.indexOf(row), 1);
},
/* 添加全部 */
addAll() {
this.unChooseUsers.forEach((d) => {
if (d.groups == 0) {
this.chooseUsers.push(d);
}
});
},
/* 移除所有 */
removeAll() {
this.chooseUsers.splice(0, this.chooseUsers.length);
},
save() {
if (this.chooseUsers.length <= 0) {
this.$message.error('未选择用户');
return;
}
addGroupsUser({
groupsId: this.groupsId,
userFrom: this.userFrom,
activityId: this.activityId,
chooseUsers: this.chooseUsers
})
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
this.columns = [
{
columnKey: 'action',
label: '操作',
width: 100,
align: 'center',
slot: 'action'
},
{
prop: 'uname',
label: '姓名',
showOverflowTooltip: true,
minWidth: 100
},
{
prop: 'mobile',
label: '手机号',
showOverflowTooltip: true,
minWidth: 100
},
{
prop: this.userFrom == 0 ? 'organizationName' : 'teamName',
label: this.userFrom == 0 ? '机构' : '团队',
showOverflowTooltip: true,
minWidth: 150
}
];
if (visible) {
//
} else {
this.organizationIds = [];
this.teamIds = [];
this.keyword = null;
this.classes = [];
this.chooseUsers = [];
}
}
}
};
</script>
@@ -0,0 +1,184 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="680px"
:visible="visible"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
:title="isUpdate ? '修改用户' : '添加用户'"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" :rules="rules" label-width="82px">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="所属机构:" prop="organizationId">
<gro-select
:data="organizationList"
placeholder="请选择所属机构"
v-model="form.organizationId"
/>
</el-form-item>
<el-form-item label="手机号:" prop="mobile">
<el-input
clearable
:maxlength="11"
:disabled="isUpdate"
v-model="form.mobile"
placeholder="请输入手机号"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="姓名:" prop="uname">
<el-input
clearable
:maxlength="20"
v-model="form.uname"
placeholder="请输入姓名"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { phoneReg } from 'ele-admin';
import GroSelect from './gro-select.vue';
import {
addUser,
updateUser,
checkExistence
} from '@/api/institution/organization-user';
export default {
components: { GroSelect },
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object,
// 全部机构
organizationList: Array,
// 机构id
organizationId: Number
},
data() {
const defaultForm = {
userId: null,
organizationId: null,
mobile: '',
uname: ''
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 表单验证规则
rules: {
mobile: [
{
required: true,
trigger: 'blur',
validator: (_rule, value, callback) => {
if (!value) {
return callback(new Error('请输入手机号'));
}
const st = new RegExp(phoneReg);
if (!st.test(value)) {
return callback(new Error('手机号格式不正确'));
}
checkExistence('mobile', value, this.data?.mobile)
.then(() => {
callback(new Error('手机号已经存在'));
})
.catch(() => {
callback();
});
}
}
],
organizationId: [
{
required: true,
message: '请选择所属机构',
trigger: 'blur'
}
],
uname: [
{
required: true,
message: '请输入姓名',
trigger: 'blur'
}
]
},
// 提交状态
loading: false,
// 是否是修改
isUpdate: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
const saveOrUpdate = this.isUpdate ? updateUser : addUser;
saveOrUpdate(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.$util.assignObject(this.form, {
...this.data
});
this.isUpdate = true;
} else {
this.form.organizationId = this.organizationId;
this.isUpdate = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,249 @@
<template>
<div>
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
height="calc(100vh - 265px)"
full-height="calc(100vh - 116px)"
tool-class="ele-toolbar-form"
cache-key="systemOrgUserTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<gro-user-search @search="reload">
<el-button
v-if="data.userFrom == 0 && data.ifBiz == 1"
size="small"
type="primary"
icon="el-icon-plus"
class="ele-btn-icon"
@click="synchronous()"
>
同步原始门店
</el-button>
<el-button
v-else
size="small"
type="primary"
icon="el-icon-plus"
class="ele-btn-icon"
@click="openAdd()"
>
添加
</el-button>
</gro-user-search>
</template>
<!-- 角色列 -->
<template v-slot:roleName="{ row }">
<el-tag type="primary" size="mini">
{{ row.roleName }}
</el-tag>
</template>
<!-- 状态列 -->
<template v-slot:status="{ row }">
<el-switch
:active-value="0"
:inactive-value="1"
v-model="row.status"
@change="editStatus(row)"
/>
</template>
<!-- 操作列 -->
<template v-slot:action="{ row }">
<el-popconfirm
class="ele-action"
title="确定要删除此用户吗?"
@confirm="remove(row)"
>
<template v-slot:reference>
<el-link type="danger" :underline="false" icon="el-icon-delete">
删除
</el-link>
</template>
</el-popconfirm>
</template>
</ele-pro-table>
<!-- 编辑弹窗 -->
<gro-user-add
:visible.sync="showAdd"
:user-from="data.userFrom"
:groups-id="groupsId"
:activity-id="data.activityId"
:organization-list="organizationList"
:team-list="teamList"
@done="reload"
/>
</div>
</template>
<script>
import GroUserSearch from './gro-user-search.vue';
import GroUserAdd from './gro-user-add.vue';
import {
pageGroupsUser,
removeGroupsUser,
synchronousGroupsUser,
updateGroupsUserStatus
} from '@/api/sylive/groups-user';
export default {
components: { GroUserSearch, GroUserAdd },
props: {
data: Object,
// 分组id
groupsId: Number,
// 全部分组
groupsList: Array,
// 全部团队
teamList: Array,
// 全部机构
organizationList: Array
},
data() {
return {
// 表格列配置
columns: [
{
prop: 'userId',
label: 'ID',
minWidth: 45,
align: 'center',
showOverflowTooltip: true
},
{
prop: 'uname',
label: '姓名',
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'nickname',
label: '微信昵称',
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'mobile',
label: '手机号',
showOverflowTooltip: true,
minWidth: 110
},
{
prop: 'roleName',
label: '角色',
showOverflowTooltip: true,
minWidth: 70,
slot: 'roleName'
},
{
prop: 'createTime',
label: '创建时间',
showOverflowTooltip: true,
minWidth: 120,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'status',
label: '状态',
align: 'center',
width: 110,
resizable: false,
slot: 'status'
},
{
columnKey: 'action',
label: '操作',
width: 120,
align: 'center',
resizable: false,
slot: 'action',
showOverflowTooltip: true
}
],
// 当前编辑数据
current: null,
// 是否显示添加弹窗
showAdd: false,
// 是否显示编辑弹窗
showEdit: false
};
},
methods: {
/* 表格数据源 */
datasource({ page, limit, where, order }) {
return pageGroupsUser({
...where,
...order,
page,
limit,
groupsId: this.groupsId,
activityId: this.data.activityId
});
},
/* 同步原始门店 */
synchronous() {
if (!this.data.originalBizId) {
this.$message.error('分组未选择原始门店');
return;
}
const loading = this.$loading({ lock: true });
synchronousGroupsUser(this.groupsId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 显示添加 */
openAdd() {
this.showAdd = true;
},
/* 删除 */
remove(row) {
const loading = this.$loading({ lock: true });
removeGroupsUser(row.groupsUserId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
},
/* 更改状态 */
editStatus(row) {
const loading = this.$loading({ lock: true });
updateGroupsUserStatus(row.groupsUserId, row.status)
.then((msg) => {
loading.close();
this.$message.success(msg);
})
.catch((e) => {
loading.close();
row.status = !row.status ? 1 : 0;
this.$message.error(e.message);
});
}
},
watch: {
// 监听机构id变化
groupsId() {
this.reload();
}
}
};
</script>
@@ -0,0 +1,79 @@
<!-- 搜索表单 -->
<template>
<el-form
size="small"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="10">
<el-col v-bind="styleResponsive ? { md: 6 } : { span: 6 }">
<el-form-item>
<el-input
clearable
size="small"
v-model="where.uname"
placeholder="请输入姓名"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { md: 6 } : { span: 6 }">
<el-form-item>
<el-input
clearable
size="small"
v-model="where.nickname"
placeholder="请输入微信昵称"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { md: 8 } : { span: 8 }">
<el-form-item>
<el-button
size="small"
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<slot></slot>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
data() {
// 默认表单数据
const defaultWhere = {
uname: '',
nickname: ''
};
return {
// 表单数据
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
}
}
};
</script>
+302
View File
@@ -0,0 +1,302 @@
<template>
<div class="ele-body">
<el-card shadow="never" v-loading="loading">
<ele-split-layout
width="330px"
allow-collapse
:right-style="{ overflow: 'hidden' }"
>
<div>
<!-- 操作按钮 -->
<ele-toolbar class="ele-toolbar-actions">
<div style="margin: 5px 0">
<el-button
size="small"
type="primary"
icon="el-icon-plus"
class="ele-btn-icon"
@click="openEdit()"
>
添加
</el-button>
<el-button
size="small"
type="warning"
icon="el-icon-edit"
class="ele-btn-icon"
:disabled="!current"
@click="openEdit(current)"
>
修改
</el-button>
<el-button
size="small"
type="danger"
icon="el-icon-delete"
class="ele-btn-icon"
:disabled="!current"
@click="remove"
>
删除
</el-button>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
</div>
</ele-toolbar>
<div class="ele-border-lighter sys-groups-list">
<el-tree
ref="tree"
:data="data"
highlight-current
node-key="groupsId"
:props="{ label: 'groupsName' }"
:expand-on-click-node="false"
:default-expand-all="true"
@node-click="onNodeClick"
/>
</div>
</div>
<template v-slot:content>
<gro-user-list
v-if="current"
:data="current"
:groups-id="current.groupsId"
:organization-list="organizationList"
:team-list="teamList"
/>
</template>
</ele-split-layout>
</el-card>
<!-- 编辑弹窗 -->
<gro-edit
:visible.sync="showEdit"
:data="editData"
:activity-id="activityId"
:parent-id="parentId"
:groups-list="data"
:statistics-type-list="statisticsTypeList"
:organization-list="organizationList"
@done="query"
/>
</div>
</template>
<script>
import GroUserList from './components/gro-user-list.vue';
import GroEdit from './components/gro-edit.vue';
import {
listGroups,
removeGroups,
exportGroupsConsultant
} from '@/api/sylive/groups';
import { listOrganizations } from '@/api/institution/organization';
import { listTeams } from '@/api/institution/team';
import { listDictionaries } from '@/api/system/dictionary';
import { utils, writeFile } from 'xlsx';
const ROUTE_PATH = '/sylive/groups';
export default {
name: 'SyliveGroups',
components: { GroUserList, GroEdit },
data() {
return {
// 加载状态
loading: true,
// 列表数据
data: [],
// 选中数据
current: null,
// 机构数据
organizationList: [],
// 团队数据
teamList: [],
// 统计类型数据
statisticsTypeList: [],
// 是否显示表单弹窗
showEdit: false,
// 编辑回显数据
editData: null,
// 上级id
parentId: null,
// 活动id
activityId: null
};
},
created() {
this.organizationQuery();
this.teamQuery();
this.statisticsTypeQuery();
},
methods: {
/* 查询 */
query() {
this.loading = true;
listGroups({ activityId: this.activityId })
.then((list) => {
this.loading = false;
this.data = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
this.$nextTick(() => {
this.onNodeClick(this.data[0]);
});
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 查询机构 */
organizationQuery() {
listOrganizations({
unOrganizationType: 4,
activityId: this.activityId
})
.then((list) => {
this.organizationList = this.$util.toTreeData({
data: list,
idField: 'organizationId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询团队 */
teamQuery() {
listTeams({ unTeamType: 3 })
.then((list) => {
this.teamList = this.$util.toTreeData({
data: list,
idField: 'teamId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 查询统计类型 */
statisticsTypeQuery() {
listDictionaries({ dictCode: 'groups_level' })
.then((list) => {
this.statisticsTypeList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 选择数据 */
onNodeClick(row) {
if (row) {
this.current = row;
this.parentId = row.groupsId;
this.$refs.tree.setCurrentKey(row.groupsId);
} else {
this.current = null;
this.parentId = null;
}
},
/* 显示编辑 */
openEdit(item) {
this.editData = item;
this.showEdit = true;
},
/* 删除 */
remove() {
this.$confirm('确定要删除选中的分组吗?', '提示', {
type: 'warning'
})
.then(() => {
const loading = this.$loading({ lock: true });
removeGroups(this.current.groupsId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.query();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
})
.catch(() => {});
},
/* 导出数据 */
exportData() {
const loading = this.$loading({ lock: true });
const activityId = this.activityId;
exportGroupsConsultant({ activityId })
.then((data) => {
loading.close();
const array = [data.columns];
data.list.forEach((d) => {
let arrayItem = [];
for (let key in d) {
arrayItem.push(d[key]);
}
array.push(arrayItem);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
'分组顾问' + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = Number(activityId);
this.query();
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.sys-groups-list {
height: calc(100vh - 264px);
box-sizing: border-box;
border-width: 1px;
border-style: solid;
overflow: auto;
}
.sys-groups-list :deep(.el-tree-node__content) {
height: 40px;
& > .el-tree-node__expand-icon {
margin-left: 10px;
}
}
</style>
@@ -0,0 +1,67 @@
<!-- 搜索表单 -->
<template>
<el-form label-width="77px" class="ele-form-search">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 3, md: 6 } : { span: 3 }">
<el-form-item label="频道:">{{ channelId }}</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="场次id:">
<el-input clearable v-model="sessionId" placeholder="请输入场次id" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 8, md: 16 } : { span: 8 }">
<div class="ele-form-actions">
<el-button type="primary" :loading="loading" @click="sessionApiQuery">
同步场次数据
</el-button>
<el-button @click="viewlogClick">频道观看日志</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { sessionApi } from '@/api/sylive/live';
export default {
props: {
channelId: null
},
data() {
return {
loading: false,
sessionId: ''
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
viewlogClick() {
const activityId = this.$route.query.id;
this.$router.replace('/sylive/live/viewlog?id=' + activityId);
},
/* 查询同步直播场次数据 */
sessionApiQuery() {
const activityId = this.$route.query.id;
sessionApi({
activityId: activityId,
channelId: this.channelId,
sessionId: this.sessionId
})
.then((msg) => {
this.$message.success(msg);
this.$emit('search');
})
.catch((e) => {
this.$message.error(e.message);
});
}
}
};
</script>
@@ -0,0 +1,128 @@
<!-- 详情弹窗 -->
<template>
<ele-modal
title="同步观看数据"
width="680px"
:visible="visible"
@update:visible="updateVisible"
>
<el-form size="mini" label-width="82px" class="ele-form-detail">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="频道:">
<div class="ele-text-secondary">
{{ data.channelId }}
</div>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="场次ID:">
<div class="ele-text-secondary">
{{ data.sessionId }}
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="同步场次:">
<div class="ele-text-secondary">
{{ data.sessionTime }}
</div>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="同步观看:">
<div class="ele-text-secondary">
{{ data.viewlogTime }}
</div>
</el-form-item>
</el-col>
</el-row>
<div style="margin: 12px 0">
<el-divider />
</div>
<el-form-item label="同步进度:" v-if="loading">
<el-progress :percentage="percent" style="padding-top: 7px" />
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">关闭</el-button>
<el-button type="primary" :loading="loading" @click="save('do')">
点击同步数据>>>
</el-button>
</template>
</ele-modal>
</template>
<script>
import { viewApi } from '@/api/sylive/live';
export default {
props: {
// 弹窗是否打开
visible: Boolean,
data: Object
},
data() {
return {
// 提交状态
loading: false,
doing: true,
percent: 0,
page: 1
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save(command) {
if (command == 'do') {
this.loading = true;
this.doing = true;
this.percent = 0;
this.page = 1;
}
if (!this.doing) {
return;
}
viewApi({
activityId: this.data.activityId,
channelId: this.data.channelId,
sessionId: this.data.sessionId,
page: this.page
})
.then((data) => {
this.percent = data.percent;
if (data.nextPageNumber) {
this.page = data.nextPageNumber;
this.save('next');
} else {
this.loading = false;
this.updateVisible(false);
this.$emit('done');
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 更新visible */
updateVisible(value) {
if (!value) {
this.loading = false;
this.doing = false;
this.percent = 0;
this.page = 1;
}
this.$emit('update:visible', value);
}
}
};
</script>
+281
View File
@@ -0,0 +1,281 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<live-search :channelId="channelId" @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
:need-page="false"
cache-key="syliveLiveTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
v-show="false"
>
导出
</el-button>
</template>
<!-- 操作列 -->
<template v-slot:action="{ row }">
<el-link
type="primary"
:underline="false"
icon="el-icon-view"
@click="openSession('view', row)"
>
观看日志
</el-link>
<el-link
type="primary"
:underline="false"
icon="el-icon-edit"
@click="openSession('viewApi', row)"
>
同步观看
</el-link>
</template>
</ele-pro-table>
</el-card>
<!-- 同步观看弹窗 -->
<live-viewapi :data="current" :visible.sync="showViewApi" @done="reload" />
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import LiveSearch from './components/live-search.vue';
import { getActivity } from '@/api/sylive/activity';
import { listLive, exportLive } from '@/api/sylive/live';
import { utils, writeFile } from 'xlsx';
import LiveViewapi from './components/live-viewapi';
const ROUTE_PATH = '/sylive/live';
export default {
name: 'syliveLive',
components: { LiveViewapi, LiveSearch },
data() {
return {
activityId: null,
title: '直播数据',
// 当前编辑数据
current: {
activityId: '',
channelId: '',
sessionId: '',
sessionTime: '',
viewlogTime: ''
},
channelId: null,
loading: true,
showViewApi: false,
// 表格列配置
columns: [
{
prop: 'sessionId',
label: '场次ID',
showOverflowTooltip: true,
minWidth: 60
},
{
prop: 'startTime',
label: '开始时间',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'endTime',
label: '结束时间',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'duration',
label: '直播时长',
showOverflowTooltip: true,
minWidth: 70
},
{
prop: 'liveUV',
label: '观看人数',
showOverflowTooltip: true,
minWidth: 70
},
{
prop: 'livePV',
label: '观看次数',
showOverflowTooltip: true,
minWidth: 70
},
{
prop: 'totalPlayDuration',
label: '观看时长',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'sessionTime',
label: '同步场次时间',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'viewlogTime',
label: '同步观看时间',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
columnKey: 'action',
label: '操作',
width: 220,
align: 'center',
resizable: false,
slot: 'action'
}
]
};
},
methods: {
openSession(command, row) {
if (command == 'view') {
const to1 = '/sylive/live/viewlog?id=' + this.activityId;
const to2 = '&sessionId=' + row.sessionId;
this.$router.replace(to1 + to2);
} else {
row.activityId = this.activityId;
this.current = row;
this.showViewApi = true;
}
},
/* 表格数据源 */
datasource({ page, limit, where, order }) {
const activityId = this.activityId;
return listLive({ ...where, ...order, page, limit, activityId });
},
activityQuery() {
this.loading = true;
getActivity(this.activityId)
.then((data) => {
this.loading = false;
// 修改页签标题
if (this.$route.path === ROUTE_PATH) {
this.title = data.title + '的直播数据';
this.channelId = data.channelId;
setPageTabTitle(this.title);
}
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const array = [
[
'订单号',
'姓名',
'手机号',
'商品标题',
'订单价格',
'付款时间',
'创建时间',
'区域',
'门店',
'顾问',
'订单类型',
'来源',
'状态',
'所选经销商',
'地址'
]
];
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.$route.query.id;
exportLive({ ...where, ...order, activityId })
.then((data) => {
loading.close();
data.forEach((d) => {
array.push([
d.sid,
d.uname,
d.mobile,
d.itemTitle,
d.totalPrice,
this.$util.toDateString(d.payTime),
this.$util.toDateString(d.createTime),
d.area,
d.stores,
d.consultant,
d.typeName,
d.cfromName,
d.statusName,
d.biz,
d.address
]);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
this.activityQuery();
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,115 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="门店:">
<ele-tree-select
:data="groupsList"
label-key="groupsName"
value-key="groupsId"
v-model="where.bizId"
:clearable="true"
placeholder="请选择"
:disabled="false"
:default-expand-all="false"
:expand-on-click-node="false"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 4, md: 8 } : { span: 4 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listGroups } from '@/api/sylive/groups';
export default {
data() {
// 默认表单数据
const defaultWhere = {
status: 1,
uname: '',
mobile: '',
type: '',
bizId: ''
};
return {
activityId: null,
// 门店数据
groupsList: [],
// 表单数据
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {},
methods: {
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
},
/* 查询分组 */
groupsQuery() {
listGroups({ activityId: this.activityId })
.then((list) => {
this.groupsList = this.$util.toTreeData({
data: list,
idField: 'groupsId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== '/sylive/live/viewlog') {
return;
}
const activityId = this.$route.query.id;
if (!activityId || activityId == this.activityId) {
return;
}
this.activityId = activityId;
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
this.groupsQuery();
},
immediate: true
}
}
};
</script>
+203
View File
@@ -0,0 +1,203 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<viewlog-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
cache-key="syliveViewlogTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
class="ele-btn-icon"
icon="el-icon-download"
@click="exportData"
>
导出
</el-button>
</template>
</ele-pro-table>
</el-card>
</div>
</template>
<script>
import { setPageTabTitle } from '@/utils/page-tab-util';
import ViewlogSearch from './components/viewlog-search.vue';
import { listViewlog, exportViewlog } from '@/api/sylive/live';
import { utils, writeFile } from 'xlsx';
const ROUTE_PATH = '/sylive/live/viewlog';
export default {
name: 'syliveLiveViewlog',
components: { ViewlogSearch },
data() {
return {
activityId: null,
sessionId: null,
// 加载状态
title: '观看日志',
loading: true,
// 表格列配置
columns: [
{
prop: 'userId',
label: 'userId',
minWidth: 45,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
},
{
prop: 'uname',
label: '昵称',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'createTime',
label: '观看开始时间',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'playDuration',
label: '观看时长',
showOverflowTooltip: true,
minWidth: 100
},
{
prop: 'consultant',
label: '顾问',
showOverflowTooltip: true,
minWidth: 60
},
{
prop: 'levelName1',
label: '战区',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'levelName2',
label: '战队',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'stores',
label: '门店',
showOverflowTooltip: true,
minWidth: 80
}
]
};
},
methods: {
/* 表格数据源 */
datasource({ page, limit, where, order }) {
const activityId = this.activityId;
const sessionId = this.sessionId;
return listViewlog({
...where,
...order,
page,
limit,
activityId,
sessionId
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 导出数据 */
exportData() {
const array = [
[
'userId',
'昵称',
'观看开始时间',
'观看时长',
'顾问',
'战区',
'战队',
'门店'
]
];
const loading = this.$loading({ lock: true });
this.$refs.table.doRequest(({ where, order }) => {
const activityId = this.activityId;
exportViewlog({ ...where, ...order, activityId })
.then((data) => {
loading.close();
data.forEach((d) => {
array.push([
d.userId,
d.uname,
this.$util.toDateString(d.createTime),
d.playDuration,
d.consultant,
d.levelName1,
d.levelName2,
d.stores
]);
});
writeFile(
{
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: utils.aoa_to_sheet(array)
}
},
this.title + '.xlsx'
);
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
});
}
},
watch: {
$route: {
handler(route) {
const { path } = route;
if (path !== ROUTE_PATH) {
return;
}
const activityId = this.$route.query.id;
const sessionId = this.$route.query.sessionId;
if (
!activityId ||
(activityId == this.activityId && sessionId == this.sessionId)
) {
return;
}
this.activityId = activityId;
this.sessionId = sessionId;
if (this.sessionId) {
this.title = '场次观看日志';
} else {
this.title = '频道观看日志';
}
setPageTabTitle(this.title);
if (this.$refs.table) {
this.$refs.table.reload({ page: 1 });
}
},
immediate: true
}
}
};
</script>
@@ -0,0 +1,192 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="680px"
:visible="visible"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
:title="isUpdate ? '修改用户' : '添加用户'"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" :rules="rules" label-width="82px">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="所属机构:" prop="organizationId">
<ele-tree-select
:data="organizationList"
label-key="organizationName"
value-key="organizationId"
v-model="form.organizationId"
:multiple="false"
:clearable="true"
placeholder="请选择所属机构"
:disabled="false"
:default-expand-all="true"
size="small"
:check-strictly="false"
/>
</el-form-item>
<el-form-item label="手机号:" prop="mobile">
<el-input
clearable
:maxlength="11"
:disabled="isUpdate"
v-model="form.mobile"
placeholder="请输入手机号"
/>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="姓名:" prop="uname">
<el-input
clearable
:maxlength="20"
v-model="form.uname"
placeholder="请输入姓名"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { phoneReg } from 'ele-admin';
import {
addMembers,
updateMembers,
checkExistence
} from '@/api/sylive/members';
export default {
components: {},
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object,
// 全部机构
organizationList: Array
},
data() {
const defaultForm = {
userId: null,
organizationId: null,
mobile: '',
uname: ''
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
// 表单验证规则
rules: {
mobile: [
{
required: true,
trigger: 'blur',
validator: (_rule, value, callback) => {
if (this.data) {
return callback();
}
if (!value) {
return callback(new Error('请输入手机号'));
}
const st = new RegExp(phoneReg);
if (!st.test(value)) {
return callback(new Error('手机号格式不正确'));
}
checkExistence('mobile', value, this.form.organizationId)
.then(() => {
callback(new Error('手机号已经存在'));
})
.catch(() => {
callback();
});
}
}
],
organizationId: [
{
required: true,
message: '请选择所属机构',
trigger: 'blur'
}
],
uname: [
{
required: true,
message: '请输入姓名',
trigger: 'blur'
}
]
},
// 提交状态
loading: false,
// 是否是修改
isUpdate: false
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
const data = {
...this.form
};
const saveUpdate = this.isUpdate ? updateMembers : addMembers;
saveUpdate(data)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.$util.assignObject(this.form, {
...this.data
});
this.isUpdate = true;
} else {
this.form.organizationId = null;
this.isUpdate = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,31 @@
<template>
<div style="max-width: 200px">
<el-input
clearable
size="small"
v-model="where.keywords"
placeholder="输入关键字搜索"
prefix-icon="el-icon-search"
@change="search"
/>
</div>
</template>
<script>
export default {
data() {
return {
// 搜索表单
where: {
keywords: ''
}
};
},
methods: {
// 搜索
search() {
this.$emit('search', this.where);
}
}
};
</script>
@@ -0,0 +1,191 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="680px"
:visible="visible"
:close-on-click-modal="true"
custom-class="ele-dialog-form"
:title="isMaJia ? '修改马甲' : '披上马甲'"
@update:visible="updateVisible"
>
<el-form ref="form" :model="form" label-width="82px">
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
<el-form-item label="选择马甲:">
<ele-table-select
ref="select"
v-model="form.maJiaId"
:multiple="false"
:clearable="true"
:placeholder="isMaJia ? '马甲已删除请保存' : '请选择'"
value-key="userId"
label-key="maJiaShow"
:table-config="tableConfig"
:popper-width="580"
:init-value="initValue"
>
<!-- 角色列 -->
<template v-slot:roleName="{ row }">
<el-tag type="primary" size="mini">
{{ row.roleName }}
</el-tag>
</template>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<members-majia-search @search="search" />
</template>
</ele-table-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template v-slot:footer>
<el-button @click="updateVisible(false)">取消</el-button>
<el-button type="primary" :loading="loading" @click="save">
保存
</el-button>
</template>
</ele-modal>
</template>
<script>
import { pageMembers, updateMembersMaJia } from '@/api/sylive/members';
import MembersMajiaSearch from './members-majia-search.vue';
export default {
components: { MembersMajiaSearch },
props: {
// 弹窗是否打开
visible: Boolean,
// 修改回显的数据
data: Object
},
data() {
const defaultForm = {
maJiaId: null
};
return {
defaultForm,
// 表单数据
form: { ...defaultForm },
tableConfig: {
datasource({ page, limit, where, order }) {
return pageMembers({ ...where, ...order, page, limit });
},
columns: [
{
prop: 'userId',
label: 'ID',
showOverflowTooltip: true,
minWidth: 60
},
{
prop: 'uname',
label: '姓名',
showOverflowTooltip: true,
minWidth: 90
},
{
prop: 'nickname',
label: '微信昵称',
showOverflowTooltip: true,
minWidth: 90
},
{
prop: 'mobile',
label: '手机号',
showOverflowTooltip: true,
minWidth: 90
},
{
prop: 'organizationName',
label: '机构',
showOverflowTooltip: true,
minWidth: 120
},
{
prop: 'roleName',
label: '角色',
showOverflowTooltip: true,
minWidth: 60,
slot: 'roleName'
}
],
pageSize: 5,
pageSizes: [5, 10, 15, 20],
rowClickChecked: true,
rowClickCheckedIntelligent: false,
toolkit: ['reload', 'columns'],
size: 'small',
toolStyle: { padding: '0 10px' }
},
// 提交状态
loading: false,
// 是否是修改
isUpdate: false,
// 是否有马甲
isMaJia: false,
// 回显值
initValue: undefined
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
methods: {
// 搜索
search(where) {
this.$refs.select.reload({
where: where,
page: 1
});
},
/* 保存编辑 */
save() {
this.$refs.form.validate((valid) => {
if (!valid) {
return false;
}
this.loading = true;
updateMembersMaJia(this.data.userId, this.form.maJiaId)
.then((msg) => {
this.loading = false;
this.$message.success(msg);
this.updateVisible(false);
this.$emit('done');
})
.catch((e) => {
this.loading = false;
this.$message.error(e.message);
});
});
},
/* 更新visible */
updateVisible(value) {
this.$emit('update:visible', value);
}
},
watch: {
visible(visible) {
if (visible) {
if (this.data) {
this.initValue = {
userId: this.data.maJiaId,
maJiaShow: this.data.maJiaName
};
this.isMaJia = this.data.maJiaId ? true : false;
} else {
this.form.maJiaId = null;
this.isMaJia = false;
}
} else {
this.$refs.form.clearValidate();
this.form = { ...this.defaultForm };
}
}
}
};
</script>
@@ -0,0 +1,102 @@
<!-- 搜索表单 -->
<template>
<el-form
label-width="77px"
class="ele-form-search"
@keyup.enter.native="search"
@submit.native.prevent
>
<el-row :gutter="15">
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="姓名:">
<el-input clearable v-model="where.uname" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="手机号:">
<el-input clearable v-model="where.mobile" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 5, md: 10 } : { span: 5 }">
<el-form-item label="机构:">
<el-select
clearable
v-model="where.topOrgId"
placeholder="请选择"
class="ele-fluid"
>
<el-option
v-for="item in organizationTopList"
:key="item.organizationId"
:label="item.organizationName"
:value="item.organizationId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
<div class="ele-form-actions">
<el-button
type="primary"
icon="el-icon-search"
class="ele-btn-icon"
@click="search"
>
查询
</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { listOrganizationParent } from '@/api/institution/organization';
export default {
data() {
// 默认表单数据
const defaultWhere = {
topOrgId: null,
uname: '',
mobile: ''
};
return {
// 表单数据
organizationTopList: [],
where: { ...defaultWhere }
};
},
computed: {
// 是否开启响应式布局
styleResponsive() {
return this.$store.state.theme.styleResponsive;
}
},
created() {
this.organizationParentQuery();
},
methods: {
/* 查询顶级机构 */
organizationParentQuery() {
listOrganizationParent({ parentId: 0 })
.then((list) => {
this.organizationTopList = list;
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 搜索 */
search() {
this.$emit('search', this.where);
},
/* 重置 */
reset() {
this.where = { ...this.defaultWhere };
this.search();
}
}
};
</script>
+292
View File
@@ -0,0 +1,292 @@
<template>
<div class="ele-body">
<el-card shadow="never">
<!-- 搜索表单 -->
<members-search @search="reload" />
<!-- 数据表格 -->
<ele-pro-table
ref="table"
:columns="columns"
:datasource="datasource"
:selection.sync="selection"
cache-key="systemMembersTable"
>
<!-- 表头工具栏 -->
<template v-slot:toolbar>
<el-button
size="small"
type="primary"
icon="el-icon-plus"
class="ele-btn-icon"
@click="openEdit()"
>
新建
</el-button>
<el-button
size="small"
type="danger"
icon="el-icon-delete"
class="ele-btn-icon"
@click="removeBatch"
>
删除
</el-button>
</template>
<!-- 角色列 -->
<template v-slot:roleName="{ row }">
<el-tag type="primary" size="mini">
{{ row.roleName }}
</el-tag>
</template>
<!-- 状态列 -->
<template v-slot:status="{ row }">
<el-switch
:active-value="0"
:inactive-value="1"
v-model="row.status"
@change="editStatus(row)"
/>
</template>
<!-- 操作列 -->
<template v-slot:action="{ row }">
<el-link
type="primary"
:underline="false"
icon="el-icon-edit"
@click="openEdit(row)"
>
修改
</el-link>
<el-popconfirm
class="ele-action"
title="确定要删除此用户吗?"
@confirm="remove(row)"
>
<template v-slot:reference>
<el-link type="danger" :underline="false" icon="el-icon-delete">
删除
</el-link>
</template>
</el-popconfirm>
<el-link
v-if="row.maJia"
type="primary"
:underline="false"
icon="el-icon-edit"
@click="openMaJia(row)"
>
{{ row.maJiaId ? '修改马甲' : '披上马甲' }}
</el-link>
</template>
</ele-pro-table>
</el-card>
<!-- 编辑弹窗 -->
<members-edit
:data="current"
:visible.sync="showEdit"
:organization-list="organizationList"
@done="reload"
/>
<!-- 马甲弹窗 -->
<members-majia :data="current" :visible.sync="showMaJia" @done="reload" />
</div>
</template>
<script>
import MembersSearch from './components/members-search.vue';
import MembersEdit from './components/members-edit.vue';
import MembersMajia from './components/members-majia.vue';
import { listOrganizations } from '@/api/institution/organization';
import {
pageMembers,
removeMembers,
removeMembersBatch,
updateMembersStatus
} from '@/api/sylive/members';
export default {
name: 'SystemMembers',
components: { MembersSearch, MembersEdit, MembersMajia },
data() {
return {
organizationList: [],
// 表格列配置
columns: [
{
columnKey: 'selection',
type: 'selection',
width: 45,
align: 'center'
},
{
prop: 'userId',
label: 'ID',
minWidth: 45,
align: 'center',
showOverflowTooltip: true,
fixed: 'left'
},
{
prop: 'uname',
label: '姓名',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'nickname',
label: '微信昵称',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'mobile',
label: '手机号',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 80
},
{
prop: 'organizationName',
label: '机构',
showOverflowTooltip: true,
minWidth: 130
},
{
prop: 'roleName',
label: '角色',
showOverflowTooltip: true,
minWidth: 60,
slot: 'roleName'
},
{
prop: 'createTime',
label: '创建时间',
sortable: 'custom',
showOverflowTooltip: true,
minWidth: 100,
formatter: (_row, _column, cellValue) => {
return this.$util.toDateString(cellValue);
}
},
{
prop: 'status',
label: '状态',
align: 'center',
sortable: 'custom',
width: 100,
resizable: false,
slot: 'status'
},
{
columnKey: 'action',
label: '操作',
width: 250,
align: 'center',
resizable: false,
slot: 'action',
showOverflowTooltip: true
}
],
// 表格选中数据
selection: [],
// 当前编辑数据
current: null,
// 是否显示编辑弹窗
showEdit: false,
// 是否显示马甲弹窗
showMaJia: false
};
},
created() {
this.organizationQuery();
},
methods: {
/* 表格数据源 */
datasource({ page, limit, where, order }) {
return pageMembers({ ...where, ...order, page, limit });
},
/* 查询机构 */
organizationQuery() {
listOrganizations()
.then((list) => {
this.organizationList = this.$util.toTreeData({
data: list,
idField: 'organizationId',
parentIdField: 'parentId'
});
})
.catch((e) => {
this.$message.error(e.message);
});
},
/* 刷新表格 */
reload(where) {
this.$refs.table.reload({ page: 1, where: where });
},
/* 打开编辑弹窗 */
openEdit(row) {
this.current = row;
this.showEdit = true;
},
/* 打开马甲弹窗 */
openMaJia(row) {
this.current = row;
this.showMaJia = true;
},
/* 删除 */
remove(row) {
const loading = this.$loading({ lock: true });
removeMembers(row.userId)
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
},
/* 批量删除 */
removeBatch() {
if (!this.selection.length) {
this.$message.error('请至少选择一条数据');
return;
}
this.$confirm('确定要删除选中的用户吗?', '提示', {
type: 'warning'
})
.then(() => {
const loading = this.$loading({ lock: true });
removeMembersBatch(this.selection.map((d) => d.userId))
.then((msg) => {
loading.close();
this.$message.success(msg);
this.reload();
})
.catch((e) => {
loading.close();
this.$message.error(e.message);
});
})
.catch(() => {});
},
/* 更改状态 */
editStatus(row) {
const loading = this.$loading({ lock: true });
updateMembersStatus(row.userId, row.status)
.then((msg) => {
loading.close();
this.$message.success(msg);
})
.catch((e) => {
loading.close();
row.status = !row.status ? 1 : 0;
this.$message.error(e.message);
});
}
}
};
</script>

Some files were not shown because too many files have changed in this diff Show More