5 次代碼提交 1e32f6020b ... e166b9bdf0

作者 SHA1 備註 提交日期
  zhengjinyi e166b9bdf0 服务商合并+推广任务 3 周之前
  zhengjinyi 40d3e7f435 修改 1 月之前
  zhengjinyi c8b4d4cc41 首页配置~ 1 月之前
  zhengjinyi e0547f8a49 Merge remote-tracking branch 'origin/developer' into developerC 1 月之前
  zhengjinyi 652388b050 商品详情用户统计 2 月之前
共有 57 個文件被更改,包括 6025 次插入402 次删除
  1. 458 0
      src/api/activity/home/home.js
  2. 25 0
      src/api/common/common.js
  3. 1 1
      src/api/contentLibrary/context.js
  4. 90 0
      src/api/serviceSettlement/group.js
  5. 27 2
      src/api/serviceSettlement/service.js
  6. 124 0
      src/api/serviceSettlement/task.js
  7. 14 0
      src/api/user/record/record.js
  8. 63 0
      src/router/modules/activity.js
  9. 74 4
      src/router/modules/serviceSettlement.js
  10. 6 0
      src/router/modules/user.js
  11. 11 12
      src/views/dataBase/components/UploadFile.vue
  12. 1 1
      src/views/finance/receipt/user.vue
  13. 228 0
      src/views/operate/home/components/exclusive-img.vue
  14. 236 0
      src/views/operate/home/components/exclusive-small-img.vue
  15. 176 0
      src/views/operate/home/components/goods-dialog.vue
  16. 176 0
      src/views/operate/home/components/goods-recom-dialog.vue
  17. 52 0
      src/views/operate/home/exclusive-image.vue
  18. 279 0
      src/views/operate/home/exclusive-img-edit.vue
  19. 285 0
      src/views/operate/home/exclusive-small-edit.vue
  20. 207 0
      src/views/operate/home/recom-goods.vue
  21. 211 0
      src/views/operate/home/zones-goods.vue
  22. 285 0
      src/views/operate/home/zones-image-edit.vue
  23. 250 0
      src/views/operate/home/zones-image.vue
  24. 294 0
      src/views/operate/home/zones-list.vue
  25. 206 0
      src/views/serviceSettlement/club/index.vue
  26. 1 1
      src/views/serviceSettlement/components/CmQrcode/index.vue
  27. 1 1
      src/views/serviceSettlement/components/goods-dialog.vue
  28. 139 0
      src/views/serviceSettlement/components/group-dialog.vue
  29. 54 0
      src/views/serviceSettlement/components/task-Item.vue
  30. 159 0
      src/views/serviceSettlement/components/task-goods-dialog.vue
  31. 140 0
      src/views/serviceSettlement/components/task-service-dialog.vue
  32. 3 3
      src/views/serviceSettlement/contract/edit.vue
  33. 7 7
      src/views/serviceSettlement/contract/index.vue
  34. 10 10
      src/views/serviceSettlement/goods/index.vue
  35. 204 0
      src/views/serviceSettlement/group/group-team.vue
  36. 204 0
      src/views/serviceSettlement/group/index.vue
  37. 75 24
      src/views/serviceSettlement/list/edit.vue
  38. 122 58
      src/views/serviceSettlement/list/index.vue
  39. 1 0
      src/views/serviceSettlement/mixin/index.js
  40. 185 0
      src/views/serviceSettlement/task/edit.vue
  41. 129 0
      src/views/serviceSettlement/task/index.vue
  42. 257 0
      src/views/serviceSettlement/task/task-details.vue
  43. 4 4
      src/views/sys/error/404.vue
  44. 1 1
      src/views/sys/icons/index.vue
  45. 2 2
      src/views/sys/menus/form.vue
  46. 66 66
      src/views/user/club-portrait/components/bar-echarts.vue
  47. 15 15
      src/views/user/club-portrait/components/club-dialog.vue
  48. 18 19
      src/views/user/club-portrait/components/hot-tips.vue
  49. 35 35
      src/views/user/club-portrait/components/pei-echarts.vue
  50. 128 129
      src/views/user/club-portrait/index.vue
  51. 0 1
      src/views/user/consult/detail.vue
  52. 0 1
      src/views/user/consult/list.vue
  53. 0 1
      src/views/user/consult/unreg-detail.vue
  54. 1 1
      src/views/user/record/components/detail-dialog.vue
  55. 137 0
      src/views/user/record/components/product-detail-dialog.vue
  56. 3 3
      src/views/user/record/list.vue
  57. 145 0
      src/views/user/record/record-product-list.vue

+ 458 - 0
src/api/activity/home/home.js

@@ -0,0 +1,458 @@
+import request from '@/utils/request'
+/**
+ * 获取商品列表(过滤)
+ * @param {*} id 专区ID
+ * @param {*} productId 商品ID
+ * @param {*} shopName 供应商名称
+ * @param {*} productName 商品名称
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function selectProductList(params) {
+  return request({
+    url: '/page/selectProductList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取推荐商品列表(过滤)
+ * @param {*} id 专区ID
+ * @param {*} productId 商品ID
+ * @param {*} shopName 供应商名称
+ * @param {*} productName 商品名称
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function recommendProductList(params) {
+  return request({
+    url: '/page/select/recommendProductList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取首页专区列表
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getPageZoneList(params) {
+  return request({
+    url: '/page/zoneList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 首页专区保存
+ * @param {*} id 专区Id
+ * @param {*} floorTitle 专区标题
+ * @param {*} floorDetail 专区描述
+ * @param {*} sort 排序
+ * @param {*} wwwEnabledStatus Pc端状态 0停用 1启用
+ * @param {*} crmEnabledStatus CRM端状态 0停用 1启用
+ * @param {*} createBy 操作人
+ * @returns
+ */
+export function savePageZone(data) {
+  return request({
+    url: '/page/saveZone',
+    method: 'post',
+    data: data
+  })
+}
+/**
+ * 删除专区
+ * @param {*} id 专区Id
+ * @returns
+ */
+export function delPageZone(params) {
+  return request({
+    url: '/page/delZone/',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 更新专区状态
+ * @param {*} id 专区Id
+ * @param {*} status 0停用 1启用
+ * @param {*} type  0www 1小程序
+ * @returns
+ */
+export function updateZoneStatus(params) {
+  return request({
+    url: '/page/updateEnabledStatus',
+    method: 'get',
+    params
+  })
+}
+/**
+/**
+ * 更新专区排序
+ * @param {*} id 专区Id
+ * @param {*} sort 排序值
+ * @returns
+ */
+export function updateZoneSort(params) {
+  return request({
+    url: '/page/updateSort',
+    method: 'get',
+    params
+  })
+}
+
+/**
+ * 获取专区商品列表
+ * @param {*} id 专区Id
+ * @param {*} productId 商品Id
+ * @param {*} shopName 供应商名称
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getZoneProductList(params) {
+  return request({
+    url: '/page/zoneProductList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 删除专区商品
+ * @param {*} id 专区Id
+ * @param {*} ids 商品Id逗号拼接
+ * @returns
+ */
+export function delZoneProduct(params) {
+  return request({
+    url: '/page/delZoneProduct',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 保存专区商品
+ * @param {*} id 专区Id
+ * @param {*} ids 商品Id逗号拼接
+ * @returns
+ */
+export function addZoneProduct(params) {
+  return request({
+    url: '/page/addZoneProduct',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区商品排序
+ * @param {*} id 专区Id
+ * @param {*} productId 商品Id
+ * @param {*} sort 排序值
+ * @returns
+ */
+export function updateProductSort(params) {
+  return request({
+    url: '/page/updateProductSort',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取专区轮播图列表
+ * @param {*} id 专区Id
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getZoneImageList(params) {
+  return request({
+    url: '/page/zoneImageList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区轮播图保存
+ * @param {*} zoneId 专区Id
+ * @param {*} imageId 轮播图Id
+ * @param {*} title 专区标题
+ * @param {*} image WWW图片
+ * @param {*} crmImage 小程序图片
+ * @param {*} link WWW跳转链接
+ * @param {*} crmLink 小程序跳转链接
+ * @param {*} wwwEnabledStatus Pc端状态 0停用 1启用
+ * @param {*} crmEnabledStatus 小程序端状态 0停用 1启用
+ * @param {*} sort 排序
+ * @returns
+ */
+export function saveZoneImage(data) {
+  return request({
+    url: '/page/saveZoneImage',
+    method: 'post',
+    data: data
+  })
+}
+/**
+ * 删除专区轮播
+ * @param {*} imageId 轮播图Id
+ * @returns
+ */
+export function delZoneImage(params) {
+  return request({
+    url: '/page/delZoneImage/',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区轮播图排序
+ * @param {*} imageId 专区Id
+ * @param {*} sort 排序值
+ * @returns
+ */
+export function updateImageSort(params) {
+  return request({
+    url: '/page/updateImageSort',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区轮播图状态更新
+ * @param {*} imageId 专区Id
+ * @param {*} status 0停用 1启用
+ * @param {*} type  0www 1小程序
+ * @returns
+ */
+export function updateImageStatus(params) {
+  return request({
+    url: '/page/updateImageStatus',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区轮播图编辑回显
+ * @param {*} imageId 轮播Id
+ * @returns
+ */
+export function getZoneImageById(params) {
+  return request({
+    url: '/page/zoneImageForm',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取首页推荐商品列表
+ * @param {*} productId 商品Id
+ * @param {*} shopName 供应商名称
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getRecommendList(params) {
+  return request({
+    url: '/page/recommendList',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 删除推荐商品
+ * @param {*} ids 商品Id逗号拼接
+ * @returns
+ */
+export function delRecommendProduct(params) {
+  return request({
+    url: '/page/recommendDel',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 保存推荐商品
+ * @param {*} ids 商品Id逗号拼接
+ * @returns
+ */
+export function addRecommendProduct(params) {
+  return request({
+    url: '/page/addRecommendProduct',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专区商品排序
+ * @param {*} productId 商品Id
+ * @param {*} sort 排序值
+ * @returns
+ */
+export function updateRecommendSort(params) {
+  return request({
+    url: '/page/recommendSort',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取首页专属广告图列表
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getTopAdvertisement(params) {
+  return request({
+    url: '/page/topAdvertisement/list',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专属广告图保存
+ * @param {*} id 广告图Id
+ * @param {*} title PC标题
+ * @param {*} crmTitle 小程序标题
+ * @param {*} image WWW图片
+ * @param {*} crmImage 小程序图片
+ * @param {*} link WWW跳转链接
+ * @param {*} crmLink 小程序跳转链接
+ * @param {*} wwwEnabledStatus Pc端状态 0停用 1启用
+ * @param {*} crmEnabledStatus 小程序端状态 0停用 1启用
+ * @param {*} sort 排序
+ * @returns
+ */
+export function saveTopAdvertisement(data) {
+  return request({
+    url: '/page/saveTopAdvertisement',
+    method: 'post',
+    data: data
+  })
+}
+/**
+ * 删除专属广告图
+ * @param {*} id 广告图Id
+ * @returns
+ */
+export function topAdvertisementDel(params) {
+  return request({
+    url: '/page/topAdvertisementDel',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专属广告图状态更新
+ * @param {*} id 广告图Id
+ * @param {*} status 0停用 1启用
+ * @param {*} type  0www 1小程序
+ * @returns
+ */
+export function updateTopStatus(params) {
+  return request({
+    url: '/page/updateTopStatus',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 专属广告图编辑回显
+ * @param {*} id 广告图Id
+ * @returns
+ */
+export function getTopAdvertisementForm(params) {
+  return request({
+    url: '/page/topAdvertisement/form',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取首页小广告图列表
+ * @param {*} pageNum 页码
+ * @param {*} pageSize 条数
+ * @returns
+ */
+export function getAdvertisement(params) {
+  return request({
+    url: '/page/advertisement/list',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 小广告图保存
+ * @param {*} id 广告图Id
+ * @param {*} title PC标题
+ * @param {*} crmTitle 小程序标题
+ * @param {*} image WWW图片
+ * @param {*} crmImage 小程序图片
+ * @param {*} link WWW跳转链接
+ * @param {*} crmLink 小程序跳转链接
+ * @param {*} wwwEnabledStatus Pc端状态 0停用 1启用
+ * @param {*} crmEnabledStatus 小程序端状态 0停用 1启用
+ * @param {*} sort 排序
+ * @returns
+ */
+export function saveAdvertisement(data) {
+  return request({
+    url: '/page/saveAdvertisement',
+    method: 'post',
+    data: data
+  })
+}
+/**
+ * 删除小广告图
+ * @param {*} id 广告图Id
+ * @returns
+ */
+export function advertisementDel(params) {
+  return request({
+    url: '/page/advertisementDel',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 小广告图排序
+ * @param {*} id 小广告图Id
+ * @param {*} sort 排序值
+ * @returns
+ */
+export function updateAdvertisementSort(params) {
+  return request({
+    url: '/page/advertisement/sort',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 小广告图状态更新
+ * @param {*} id 广告图Id
+ * @param {*} status 0停用 1启用
+ * @param {*} type  0www 1小程序
+ * @returns
+ */
+export function updateAdvertiStatus(params) {
+  return request({
+    url: '/page/updateAdvertiStatus',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 小广告图编辑回显
+ * @param {*} id 广告图Id
+ * @returns
+ */
+export function getAdvertisementForm(params) {
+  return request({
+    url: '/page/advertisement/form',
+    method: 'get',
+    params
+  })
+}

+ 25 - 0
src/api/common/common.js

@@ -0,0 +1,25 @@
+import request from '@/utils/request'
+// 获取供应商列表
+export function fetchFindShop(params) {
+  return request({
+    url: '/svip/member/findShopList',
+    method: 'get',
+    params
+  })
+}
+// 获取所有商品信息列表
+export function fetchProductList(params) {
+  return request({
+    url: '/svip/member/findProductDialogList',
+    method: 'get',
+    params
+  })
+}
+// 获取所有机构
+export function fetchClubList(params) {
+  return request({
+    url: '/svip/member/findClubList',
+    method: 'get',
+    params
+  })
+}

+ 1 - 1
src/api/contentLibrary/context.js

@@ -25,7 +25,7 @@ export const getContextDetail = (params) => request({
 })
 
 export const uploadFile = (data) => request({
-  url: '/formData/oss/MultiPictareaddData',
+  url: '/formData/MultiPictareaddData',
   method: 'POST',
   headers: {
     'Content-Type': 'multipart/form-data'

+ 90 - 0
src/api/serviceSettlement/group.js

@@ -0,0 +1,90 @@
+import request from '@/utils/request'
+/**
+ * 获取服务商列表
+ * @returns
+ */
+export function getServiceList(params) {
+  return request({
+    url: '/providers/addGroups',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 服务商团队列表
+ * @returns
+ */
+export const getTeamList = (params) => request({
+  url: '/providers/teamList',
+  method: 'get',
+  params
+})
+/**
+ * 添加服务商团队
+ * @param {*} name 团队名称
+ * @param {*} teamId 团队ID
+ * @param {*} leaderId 团队管理员ID
+ * @returns
+ */
+export const addTeam = (data) => request({
+  url: '/providers/add/team',
+  method: 'post',
+  data
+})
+/**
+ * 删除团队
+ * @param {*} id 团队ID
+ * @returns
+ */
+export const delTeam = (params) => request({
+  url: '/providers/del/team',
+  method: 'get',
+  params
+})
+
+/**
+ * 团队成员列表
+ * @param {*} id 团队ID
+ * @returns
+ */
+export const groupList = (params) => request({
+  url: '/providers/groupList',
+  method: 'get',
+  params
+})
+/**
+ * 删除成员
+ * @param {*} teamId 团队ID
+ * @param {*} spId 成员ID
+ * @returns
+ */
+export const delGroup = (params) => request({
+  url: '/providers/del/group',
+  method: 'get',
+  params
+})
+
+/**
+ * 添加成员
+ * @param {*} teamId 团队ID
+ * @param {*} spId 成员ID(逗号隔开)
+ * @returns
+ */
+export const addGroup = (params) => request({
+  url: '/providers/add/group',
+  method: 'get',
+  params
+})
+
+/**
+ * 设置团队管理员
+ * @param {*} teamId 团队ID
+ * @param {*} leaderId 组长ID
+ * @returns
+ */
+export const updateLeader = (data) => request({
+  url: '/providers/update/leader',
+  method: 'post',
+  data
+})
+

+ 27 - 2
src/api/serviceSettlement/service.js

@@ -13,7 +13,7 @@ export const getProviderList = (params) => request({
 })
 
 export const addProvider = (data) => request({
-  url: '/providers/add ',
+  url: '/providers/add',
   method: 'post',
   data
 })
@@ -25,7 +25,7 @@ export const getProviderDetail = (params) => request({
 })
 
 export const updatedStatus = (data) => request({
-  url: `/providers/updateStatus?userIds=${data.userIds}&status=${data.status}`,
+  url: `/providers/updateStatus?serviceProviderId=${data.serviceProviderId}&status=${data.status}`,
   method: 'post',
   data
 })
@@ -35,3 +35,28 @@ export const selectUploadImage = (data) => request({
   method: 'post',
   data
 })
+/**
+ * 服务商账号重置密码
+ * @param {*} userId 服务商userId
+ * @param {*} password 密码
+ * @returns
+ */
+export const updatePassword = (params) => request({
+  url: '/providers/update/pass',
+  method: 'get',
+  params
+})
+/**
+ * 服务商机构列表
+ * @param {*} spId 服务商Id
+ * @param {*} clubId 机构ID
+ * @param {*} name 机构名称
+ * @param {*} linkMan 联系人
+ * @param {*} bindMobile 手机号
+ * @returns
+ */
+export const providersClubList = (params) => request({
+  url: '/providers/clubList',
+  method: 'get',
+  params
+})

+ 124 - 0
src/api/serviceSettlement/task.js

@@ -0,0 +1,124 @@
+import request from '@/utils/request'
+/**
+ * 获取服务商任务列表
+ * @returns
+ */
+export function getTaskList(params) {
+  return request({
+    url: '/providers/task/list',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取任务分配详情服务商列表
+ * @returns
+ */
+export function getTaskProvider(params) {
+  return request({
+    url: '/providers/taskProvider/list',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取服务商列表
+ * @returns
+ */
+export function getServiceList(params) {
+  return request({
+    url: '/providers/addGroups',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 任务分配服务商过滤列表
+ * @param {*} taskId 任务id
+ * @returns
+ */
+export function getReceiveList(params) {
+  return request({
+    url: '/providers/receive/list',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 任务分配服务商过滤列表
+ * @param {*} taskId 任务id
+ * @returns
+ */
+export function getTaskDetail(params) {
+  return request({
+    url: '/providers/task/detail',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 添加任务
+ * @param {*} title 任务标题
+ * @param {*} topPic 任务封面
+ * @param {*} archiveId 内容库Id
+ * @param {*} shopId 供应商Id
+ * @param {*} startTime 开始时间
+ * @param {*} endTime 结束时间
+ * @returns
+ */
+export const addTask = (data) => request({
+  url: '/providers/add/task',
+  method: 'post',
+  data
+})
+
+/**
+ * 任务下发服务商
+ * @param {*} id 任务id
+ * @param {*} serviceProviderIds 服务商Id
+ * @returns
+ */
+export const assignTask = (params) => request({
+  url: '/providers/assign/task',
+  method: 'get',
+  params
+})
+
+/**
+ * 任务删除服务商
+ * @param {*} taskId 任务id
+ * @param {*} serviceProviderIds 服务商Id
+ * @returns
+ */
+export const taskProviderDel = (params) => request({
+  url: 'providers/taskProvider/del',
+  method: 'get',
+  params
+})
+
+/**
+ * 任务下发服务商
+ * @param {*} name 商品名称
+ * @param {*} shopName 供应商名称
+ * @param {*} productId 商品Id
+ * @param {*} pageSize 条数
+ * @param {*} pageNum 页码
+ * @returns
+ */
+export const getTaskProducts = (params) => request({
+  url: '/providers/task/products',
+  method: 'get',
+  params
+})
+/**
+ * 审核服务商任务提交
+ * @param {*} taskId 任务Id
+ * @param {*} serviceProviderId 服务商Id
+ * @param {*} auditStatus 通过 2 不通过 3
+ * @returns
+ */
+export const getTaskaAudit = (params) => request({
+  url: '/providers/task/audit',
+  method: 'get',
+  params
+})

+ 14 - 0
src/api/user/record/record.js

@@ -7,6 +7,13 @@ export function fetchRecordList(params) {
     params
   })
 }
+export function getRecordProductCount(params) {
+  return request({
+    url: '/user/behavior/record/product/count',
+    method: 'get',
+    params
+  })
+}
 export function fetchBehaviorList(params) {
   return request({
     url: '/user/behavior/record/recordList',
@@ -14,6 +21,13 @@ export function fetchBehaviorList(params) {
     params
   })
 }
+export function fetchBehaviorProductDetail(params) {
+  return request({
+    url: '/user/behavior/record/count/detail',
+    method: 'get',
+    params
+  })
+}
 
 export function importExportToday(params) {
   return request({

+ 63 - 0
src/router/modules/activity.js

@@ -10,6 +10,69 @@ const keywordLibraryRouter = {
   name: 'OperateActivity', // name必须和后台配置一致,不然匹配不到
   meta: { title: '运营专区' },
   children: [
+    {
+      path: 'zones',
+      name: 'ZonesMenu',
+      redirect: '/operate/zones',
+      alwaysShow: true,
+      component: () => import('@/views/index'),
+      meta: { title: '首页配置', useDefault: true },
+      children: [
+        {
+          path: 'zones-list',
+          name: 'ZonesList',
+          component: () => import('@/views/operate/home/zones-list'),
+          meta: { title: '专区管理' }
+        },
+        {
+          path: 'zones-goods',
+          name: 'ZonesGoods',
+          component: () => import('@/views/operate/home/zones-goods'),
+          meta: { title: '专区商品管理' },
+          hidden: true
+        },
+        {
+          path: 'zones-image',
+          name: 'ZonesImage',
+          component: () => import('@/views/operate/home/zones-image'),
+          meta: { title: '专区轮播图管理' },
+          hidden: true
+        },
+        {
+          path: 'zones-image-edit',
+          name: 'ZonesImageEdit',
+          component: () => import('@/views/operate/home/zones-image-edit'),
+          meta: { title: '专区轮播图添加' },
+          hidden: true
+        },
+        {
+          path: 'recom-goods',
+          name: 'RecomGoods',
+          component: () => import('@/views/operate/home/recom-goods'),
+          meta: { title: '商品推荐' }
+        },
+        {
+          path: 'exclusive-image',
+          name: 'ExclusiveImage',
+          component: () => import('@/views/operate/home/exclusive-image'),
+          meta: { title: '广告配置' }
+        },
+        {
+          path: 'exclusive-img-edit',
+          name: 'ExclusiveImgEdit',
+          component: () => import('@/views/operate/home/exclusive-img-edit'),
+          meta: { title: '专属广告添加/编辑' },
+          hidden: true
+        },
+        {
+          path: 'exclusive-small-edit',
+          name: 'ExclusiveSmallEdit',
+          component: () => import('@/views/operate/home/exclusive-small-edit'),
+          meta: { title: '小广告添加/编辑' },
+          hidden: true
+        }
+      ]
+    },
     {
       path: 'activity',
       name: 'ActivityMenu',

+ 74 - 4
src/router/modules/serviceSettlement.js

@@ -3,7 +3,7 @@ import Layout from '@/layout'
 export default {
   path: '/service',
   component: Layout,
-  meta: { title: '服务商入驻', icon: 'link' },
+  meta: { title: '服务商管理', icon: 'link' },
   name: 'Service',
   redirect: '/service/settlement',
   alwaysShow: true,
@@ -11,7 +11,7 @@ export default {
     {
       path: 'settlement',
       name: 'Settlement',
-      meta: { title: '入驻列表', icon: 'component' },
+      meta: { title: '服务商列表', icon: 'component' },
       redirect: '/service/settlement/list',
       component: () => import('@/views/index'),
       children: [
@@ -20,14 +20,14 @@ export default {
           hidden: true,
           component: () => import('@/views/serviceSettlement/list/index.vue'),
           name: 'SettlementList',
-          meta: { title: '入驻列表', activeMenu: '/service/settlement' }
+          meta: { title: '服务商列表', activeMenu: '/service/settlement' }
         },
         {
           path: 'edit',
           hidden: true,
           component: () => import('@/views/serviceSettlement/list/edit.vue'),
           name: 'SettlementEdit',
-          meta: { title: '编辑列表', noCache: true, activeMenu: '/service/settlement' }
+          meta: { title: '编辑服务商', noCache: true, activeMenu: '/service/settlement' }
         },
         {
           path: 'goods',
@@ -46,6 +46,23 @@ export default {
             }
           ]
         },
+        {
+          path: 'club',
+          hidden: true,
+          component: () => import('@/views/index'),
+          name: 'SettlementClub',
+          redirect: '/service/settlement/club',
+          meta: { title: '服务商机构', noCache: true, activeMenu: '/service/settlement' },
+          children: [
+            {
+              path: 'list',
+              hidden: true,
+              component: () => import('@/views/serviceSettlement/club/index.vue'),
+              name: 'SettlementClubList',
+              meta: { title: '服务商机构列表', noCache: true, activeMenu: '/service/settlement' }
+            }
+          ]
+        },
         {
           path: 'contract',
           hidden: true,
@@ -71,6 +88,59 @@ export default {
           ]
         }
       ]
+    },
+    {
+      path: 'group',
+      name: 'Group',
+      component: () => import('@/views/index'),
+      redirect: '/service/group/list',
+      meta: { title: '服务商团队', icon: 'component', activeMenu: '/service/group' },
+      children: [
+        {
+          path: 'list',
+          hidden: true,
+          component: () => import('@/views/serviceSettlement/group/index.vue'),
+          name: 'SettlementGroupList',
+          meta: { title: '服务商团队', noCache: true, activeMenu: '/service/group' }
+        },
+        {
+          path: 'group-team',
+          hidden: true,
+          component: () => import('@/views/serviceSettlement/group/group-team.vue'),
+          name: 'SettlementGroupTeam',
+          meta: { title: '团队成员', noCache: true, activeMenu: '/service/group' }
+        }
+      ]
+    },
+    {
+      path: 'task',
+      name: 'Task',
+      component: () => import('@/views/index'),
+      redirect: '/service/task/list',
+      meta: { title: '服务商推广', icon: 'component', activeMenu: '/service/task' },
+      children: [
+        {
+          path: 'list',
+          hidden: true,
+          component: () => import('@/views/serviceSettlement/task/index.vue'),
+          name: 'SettlementTaskList',
+          meta: { title: '服务商推广', noCache: true, activeMenu: '/service/task' }
+        },
+        {
+          path: 'edit',
+          hidden: true,
+          component: () => import('@/views/serviceSettlement/task/edit.vue'),
+          name: 'SettlementTaskEdit',
+          meta: { title: '添加/编辑推广', noCache: true, activeMenu: '/service/task' }
+        },
+        {
+          path: 'task-details',
+          hidden: true,
+          component: () => import('@/views/serviceSettlement/task/task-details.vue'),
+          name: 'SettlementTaskDetails',
+          meta: { title: '下发服务商', noCache: true, activeMenu: '/service/task' }
+        }
+      ]
     }
   ]
 }

+ 6 - 0
src/router/modules/user.js

@@ -29,6 +29,12 @@ const userRouter = {
       component: () => import('@/views/user/club-portrait/index'),
       meta: { title: '机构画像', noCache: true, activeMenu: '/user/list' }
     },
+    {
+      path: 'record-product-list',
+      name: 'RecordProductList',
+      component: () => import('@/views/user/record/record-product-list'),
+      meta: { title: '商品浏览统计', icon: 'international', activeMenu: '/user/list' }
+    },
     {
       path: 'detail-list',
       hidden: true,

+ 11 - 12
src/views/dataBase/components/UploadFile.vue

@@ -134,21 +134,20 @@ export default {
       const f = file.target.files[0]
       console.log(f)
       const formData = new FormData()
-      const isType = this.accept.indexOf('.pdf') !== -1
-      formData.append('multipartFile', f)
-      formData.append('type', isType ? 1 : '')
+      // const isType = this.accept.indexOf('.pdf') !== -1
+      formData.append('file', f)
+      // formData.append('type', isType ? 1 : '')
       try {
         this.$emit('change-loading')
         const data = await uploadFile(formData)
-        if (data.success || data.code === 0) {
-          this.dataList.push({ fileName: data.fileName, ossUrl: data.url, ossName: data.ossName })
-          this.$emit('success', { fileList: this.dataList })
-          this.$emit('change-loading')
-          this.$message({
-            type: 'success',
-            message: '上传成功'
-          })
-        }
+        this.dataList.push({ fileName: f.name, ossUrl: data.data, ossName: f.name })
+        this.$emit('success', { fileList: this.dataList })
+        this.$emit('change-loading')
+        this.$message({
+          type: 'success',
+          message: '上传成功'
+        })
+        // if (data.success || data.code === 0) {}
       } catch (error) {
         this.$message({
           type: 'error',

+ 1 - 1
src/views/finance/receipt/user.vue

@@ -17,7 +17,7 @@
         </el-form-item>
         <el-form-item label="收款用户类型:" prop="userType">
           <el-radio-group v-model="receiptUser.userType">
-            <el-radio :label="1">协销</el-radio>
+            <el-radio :label="1">服务商</el-radio>
             <el-radio :label="2">客服</el-radio>
             <el-radio :label="3">财务</el-radio>
             <el-radio :label="4">超级管理员</el-radio>

+ 228 - 0
src/views/operate/home/components/exclusive-img.vue

@@ -0,0 +1,228 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container" style="padding-bottom: 0;">
+      <div class="filter-control">
+        <span>网站状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>小程序状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+        <el-button type="primary" @click="handleoOerate('add')"> 添加专属广告图 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="500">
+      <el-table-column prop="title" label="轮播标题" align="center" width="200" />
+      <el-table-column prop="image" label="网站广告图" align="center">
+        <template slot-scope="{ row }">
+          <img :src="row.image" alt="" style="width: 132px; height: 60px;" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="crmImage" label="小程序广告图" align="center">
+        <template slot-scope="{ row }">
+          <img v-if="row.crmImage" :src="row.crmImage" alt="" style="width: 132px; height: 60px;" />
+          <span v-else>--</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="wwwEnabledStatus" label="网站状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.wwwEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.wwwEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column prop="crmEnabledStatus" label="小程序状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.crmEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.crmEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="220">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handleoOerate('edit', row)">
+            编辑
+          </el-button>
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDelete(row)"> 删除 </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[20]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getTopAdvertisement"
+    />
+  </div>
+</template>
+
+<script>
+
+import { getTopAdvertisement, topAdvertisementDel, updateTopStatus } from '@/api/activity/home/home'
+export default {
+  name: 'ExclusiveImg',
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      listQuery: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      timesValue: [],
+      logoForm: {
+        id: '',
+        title: '',
+        logo: ''
+      },
+      rules: {
+        title: [{ required: true, message: '请输入广告图标题', trigger: 'blur' }],
+        status: [{ required: true, message: '请设置统计状态', trigger: 'blur' }],
+        logo: [{ required: true, message: '请上传弹窗图片', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    getToken() {
+      return {
+        token: this.$store.getters.token
+      }
+    },
+    actionUrl() {
+      return process.env.VUE_APP_BASE_API + '/formData/MultiPictareaddData'
+    }
+  },
+  watch: {
+    timesValue: {
+      handler() {
+        this.getList()
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取专属广告图列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.list = []
+      this.getTopAdvertisement()
+    },
+
+    // 获取专属广告图列表
+    async getTopAdvertisement() {
+      try {
+        this.isLoading = true
+        const res = await getTopAdvertisement(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 添加专属广告图
+    handleoOerate(type, row) {
+      if (type === 'add') {
+        this.$router.push({
+          path: '/operate/zones/exclusive-img-edit',
+          query: { type: type }
+        })
+      } else {
+        this.$router.push({
+          path: '/operate/zones/exclusive-img-edit',
+          query: { id: row.id, type: type }
+        })
+      }
+    },
+    // 操作启用停用广告图
+    handleShangeStatus(id, status, type) {
+      let confirmTxt = ''
+      let paramsStatus
+      if (status === 1) {
+        confirmTxt = '确定停用该广告图?'
+        paramsStatus = 0
+      } else {
+        confirmTxt = '确定启用该广告图?'
+        paramsStatus = 1
+      }
+      this.$confirm(confirmTxt)
+        .then((_) => {
+          this.updateTopStatus(id, paramsStatus, type)
+        })
+        .catch(() => {
+          this.$notify.info({ title: '用户取消操作~', message: '' })
+        })
+    },
+    // 停用启用广告图
+    async updateTopStatus(id, paramsStatus, type) {
+      try {
+        await updateTopStatus({ id: id, status: paramsStatus, type: type })
+        this.$notify.success({ title: '更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    // 操作删除广告图
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该广告图吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.topAdvertisementDel(row)
+      } catch (error) {
+        this.$notify.info('用户取消操作~')
+      }
+    },
+    // 调用删除广告图
+    async topAdvertisementDel(row) {
+      try {
+        await topAdvertisementDel({ id: row.id })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 236 - 0
src/views/operate/home/components/exclusive-small-img.vue

@@ -0,0 +1,236 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container" style="padding-bottom: 0;">
+      <!--<div class="filter-control">
+        <span>广告图状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>-->
+      <!--<div class="filter-control">
+        <span>小程序状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>-->
+      <div class="filter-control">
+        <!--<el-button type="primary" @click="getList"> 查询 </el-button>-->
+        <el-button type="primary" @click="handleoOerate('add')"> 添加小广告图 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="500">
+      <el-table-column prop="id" label="ID" align="center" width="50" />
+      <el-table-column prop="title" label="轮播标题" align="center" />
+      <el-table-column prop="image" label="广告图" align="center">
+        <template slot-scope="{ row }">
+          <img :src="row.image" alt="" style="width: 132px; height: 60px;" />
+        </template>
+      </el-table-column>
+      <!--<el-table-column prop="crmImage" label="小程序广告图" align="center">
+        <template slot-scope="{ row }">
+          <img :src="row.crmImage" alt="" style="width: 132px; height: 60px;" />
+        </template>
+      </el-table-column>-->
+      <!--<el-table-column prop="wwwEnabledStatus" label="广告图状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.wwwEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.wwwEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>-->
+      <!--<el-table-column prop="crmEnabledStatus" label="小程序状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.crmEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.crmEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>-->
+      <el-table-column label="排序" width="70" align="center">
+        <template slot-scope="{ row }">
+          <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="handleOnInputBlur(row)" />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="220">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handleoOerate('edit', row)">
+            编辑
+          </el-button>
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDelete(row)"> 删除 </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getAdvertisement"
+    />
+  </div>
+</template>
+
+<script>
+
+import { getAdvertisement, advertisementDel, updateAdvertisementSort, updateAdvertiStatus } from '@/api/activity/home/home'
+export default {
+  name: 'ExclusiveSmallImg',
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      floorTitle: this.$route.query.floorTitle,
+      listQuery: {
+        id: this.$route.query.id,
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      timesValue: []
+    }
+  },
+  computed: {},
+  watch: {
+    timesValue: {
+      handler() {
+        this.getList()
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取小广告图列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.list = []
+      this.getAdvertisement()
+    },
+
+    // 获取小广告图列表
+    async getAdvertisement() {
+      try {
+        this.isLoading = true
+        const res = await getAdvertisement(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 添加小广告图
+    handleoOerate(type, row) {
+      if (type === 'add') {
+        this.$router.push({
+          path: '/operate/zones/exclusive-small-edit',
+          query: { type: type }
+        })
+      } else {
+        this.$router.push({
+          path: '/operate/zones/exclusive-small-edit',
+          query: { id: row.id, type: type }
+        })
+      }
+    },
+    // 操作启用停用广告图
+    handleShangeStatus(id, status, type) {
+      let confirmTxt = ''
+      let paramsStatus
+      if (status === 1) {
+        confirmTxt = '确定停用该广告图?'
+        paramsStatus = 0
+      } else {
+        confirmTxt = '确定启用该广告图?'
+        paramsStatus = 1
+      }
+      this.$confirm(confirmTxt)
+        .then((_) => {
+          this.updateAdvertiStatus(id, paramsStatus, type)
+        })
+        .catch(() => {
+          this.$notify.info({ title: '用户取消操作~', message: '' })
+        })
+    },
+    // 停用启用广告图
+    async updateAdvertiStatus(id, paramsStatus, type) {
+      try {
+        await updateAdvertiStatus({ id: id, status: paramsStatus, type: type })
+        this.$notify.success({ title: '更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    // 操作删除广告图
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该广告图吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.advertisementDel(row)
+      } catch (error) {
+        this.$notify.info('用户取消操作~')
+      }
+    },
+    // 调用删除广告图
+    async advertisementDel(row) {
+      try {
+        await advertisementDel({ id: row.id })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 广告图排序
+    async handleOnInputBlur(row) {
+      try {
+        await updateAdvertisementSort({ id: row.id, sort: row.sort })
+        this.$notify.success({ title: '排序更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 机构跳转
+    handleClubHrefLink(row) {
+      return (
+        process.env.VUE_APP_ADMIN_URL +
+        `/a/user/jumpLink/toOldAdmin?type=1&clubId=${row.clubId}&clubName=${row.corporateName}`
+      )
+    }
+  }
+}
+</script>
+
+<style>
+.tags-sms-span{
+  font-weight: bold;
+  font-size: 16px !important;
+}
+</style>

+ 176 - 0
src/views/operate/home/components/goods-dialog.vue

@@ -0,0 +1,176 @@
+<template>
+  <el-dialog title="添加商品" :visible.sync="visible" width="1200px" :close-on-click-modal="false" :show-close="false" top="8vh">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.productId= checkedInput(e,1))"
+        />
+      </div>
+      <div class="filter-control">
+        <span>商品名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="商品名称"
+          clearable
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.name= checkedInput(e,2))"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          style="width:160px;"
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.shopName= checkedInput(e,2))"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="500px"
+      border
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="商品ID" prop="productId" align="center" width="100" />
+      <el-table-column prop="mainImage" label="商品图片" align="center" width="120">
+        <template slot-scope="{ row }">
+          <el-popover v-if="row.mainImage" placement="top-start" title="" width="120" trigger="hover">
+            <img :src="row.mainImage" alt="" style="width: 80px; height: 80px" />
+            <img slot="reference" :src="row.mainImage" alt="" style="width: 40px; height: 40px" />
+          </el-popover>
+          <span v-else>---</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" prop="name" align="center" />
+      <el-table-column label="供应商" prop="shopName" align="center" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[20, 30]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="selectProductList"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle"> 取 消 </el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleConfirm"> 确 定 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { selectProductList } from '@/api/activity/home/home'
+
+export default {
+  name: 'GoodsDialog',
+  filters: {
+    NumFormat(value) {
+      // 处理金额
+      return Number(value).toFixed(2)
+    }
+  },
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        id: this.$route.query.id, // 专区ID
+        productId: '', // 商品id
+        name: '', // 商品名称
+        shopName: '', // 供应商名称
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      shopsRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.shopsRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取所有供应商列表
+    async getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.selectProductList()
+    },
+    // 获取所有商品
+    async selectProductList() {
+      try {
+        const res = await selectProductList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 选择商品
+    handleSelectionChange(row) {
+      this.shopsRadio = row
+      console.log('row', row)
+    },
+    // 确认选择商品
+    async handleConfirm() {
+      try {
+        await this.$confirm('确定添加所选商品吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.$emit('confirm', this.shopsRadio)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    },
+    // 已选择的禁用勾选框
+    selectable(row) {
+      if (row.flag) {
+        return true
+      } else {
+        return false
+      }
+    },
+    checkedInput(event, type) {
+      let pattern = ''
+      switch (type) {
+        case 1:
+          pattern = /[^\d]/g
+          break
+        case 2:
+          pattern = /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!,。?!…—&$=()-+/*{}[]]|s/g
+          break
+      }
+      return event.replace(pattern, '')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 176 - 0
src/views/operate/home/components/goods-recom-dialog.vue

@@ -0,0 +1,176 @@
+<template>
+  <el-dialog title="添加商品" :visible.sync="visible" width="1200px" :close-on-click-modal="false" :show-close="false" top="8vh">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.productId= checkedInput(e,1))"
+        />
+      </div>
+      <div class="filter-control">
+        <span>商品名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="商品名称"
+          clearable
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.name= checkedInput(e,2))"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          style="width:160px;"
+          @keyup.enter.native="getList"
+          @input="e => (listQuery.shopName= checkedInput(e,2))"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="500px"
+      border
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="商品ID" prop="productId" align="center" width="100" />
+      <el-table-column prop="mainImage" label="商品图片" align="center" width="120">
+        <template slot-scope="{ row }">
+          <el-popover v-if="row.mainImage" placement="top-start" title="" width="120" trigger="hover">
+            <img :src="row.mainImage" alt="" style="width: 80px; height: 80px" />
+            <img slot="reference" :src="row.mainImage" alt="" style="width: 40px; height: 40px" />
+          </el-popover>
+          <span v-else>---</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" prop="name" align="center" />
+      <el-table-column label="供应商" prop="shopName" align="center" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[20, 30]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="recommendProductList"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle"> 取 消 </el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleConfirm"> 确 定 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { recommendProductList } from '@/api/activity/home/home'
+
+export default {
+  name: 'GoodsDialog',
+  filters: {
+    NumFormat(value) {
+      // 处理金额
+      return Number(value).toFixed(2)
+    }
+  },
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        id: this.$route.query.id, // 专区ID
+        productId: '', // 商品id
+        name: '', // 商品名称
+        shopName: '', // 供应商名称
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      shopsRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.shopsRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取所有供应商列表
+    async getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.recommendProductList()
+    },
+    // 获取所有商品
+    async recommendProductList() {
+      try {
+        const res = await recommendProductList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 选择商品
+    handleSelectionChange(row) {
+      this.shopsRadio = row
+      console.log('row', row)
+    },
+    // 确认选择商品
+    async handleConfirm() {
+      try {
+        await this.$confirm('确定添加所选商品吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.$emit('confirm', this.shopsRadio)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    },
+    // 已选择的禁用勾选框
+    selectable(row) {
+      if (row.flag) {
+        return true
+      } else {
+        return false
+      }
+    },
+    checkedInput(event, type) {
+      let pattern = ''
+      switch (type) {
+        case 1:
+          pattern = /[^\d]/g
+          break
+        case 2:
+          pattern = /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!,。?!…—&$=()-+/*{}[]]|s/g
+          break
+      }
+      return event.replace(pattern, '')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 52 - 0
src/views/operate/home/exclusive-image.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
+      <el-tab-pane label="专属广告" name="first" />
+      <el-tab-pane label="小广告位" name="second" />
+      <!-- 列表 -->
+      <template v-if="activeName === 'first'">
+        <exclusive-img />
+      </template>
+      <template v-if="activeName === 'second'">
+        <exclusive-small-img />
+      </template>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import ExclusiveImg from './components/exclusive-img'
+import ExclusiveSmallImg from './components/exclusive-small-img'
+export default {
+  name: 'ExclusiveImage',
+  components: {
+    ExclusiveImg,
+    ExclusiveSmallImg
+  },
+  filters: {},
+  data() {
+    return {
+      activeName: 'first',
+      isLoading: true,
+      list: [],
+      total: 0
+    }
+  },
+  computed: {},
+  created() {
+    if (this.$route.query.activeName === 'second') {
+      this.activeName = 'second'
+    } else {
+      this.activeName = 'first'
+    }
+  },
+  mounted() {},
+  methods: {
+    // tab切换
+    handleClick(tab, event) {}
+  }
+}
+</script>
+
+<style></style>

+ 279 - 0
src/views/operate/home/exclusive-img-edit.vue

@@ -0,0 +1,279 @@
+<template>
+  <div class="app-container" style="width: 800px; margin: 0 auto">
+    <el-form ref="bannerForm" :model="form" label-width="130px">
+      <el-form-item label="广告图标题:" prop="title" :rules="rules.title">
+        <el-input v-model="form.title" placeholder="请输入广告图标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="PC端图片:" prop="image" :rules="rules.image" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 264px; height: 120px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessPcImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadPcImageLoading" class="avatar" style="width: 264px; height: 120px; display: block">
+              <img
+                v-if="form.image"
+                :src="form.image"
+                style="width: 264px; height: 120px; display: block"
+                @error="reloadImage"
+                @load="loadPcImageSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 264px; height: 120x; line-height: 120px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请上传尺寸1080*540(px)的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="PC端链接:" prop="link" :rules="rules.link">
+        <el-input v-model="form.link" placeholder="请输入PC端链接" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="小程序端标题:" prop="crmTitle">
+        <el-input v-model="form.crmTitle" placeholder="请输入小程序端标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="小程序端图片:" prop="crmImage" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 264px; height: 120px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessAppImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadImgLoading" class="avatar" style="width: 264px; height: 120px; display: block">
+              <img
+                v-if="form.crmImage"
+                :src="form.crmImage"
+                style="width: 264px; height: 120px; display: block"
+                @error="reloadImage"
+                @load="loadSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 264px; height: 120px; line-height: 120px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请上传尺寸528*240(px)的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="小程序端链接:" prop="crmLink">
+        <el-input v-model="form.crmLink" placeholder="请输入小程序端链接" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="PC端状态" prop="wwwEnabledStatus">
+        <el-select v-model="form.wwwEnabledStatus" placeholder="请选择网站状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="小程序状态" prop="crmEnabledStatus">
+        <el-select v-model="form.crmEnabledStatus" placeholder="请选择小程序状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <div class="el-dialog__footer" style="text-align: center">
+      <el-button type="primary" @click="onSubmit('bannerForm')"> 保存 </el-button>
+      <el-button plain @click="backToList"> 返回 </el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getTopAdvertisementForm, saveTopAdvertisement } from '@/api/activity/home/home'
+
+export default {
+  name: 'ExclusiveImgEdit',
+  data() {
+    const defaultForm = () => {
+      return {
+        id: '',
+        title: '', // PC端标题
+        crmTitle: '', // 小程序标题
+        image: '', // PC广告图
+        crmImage: '', // 小程序广告图
+        link: '', // PC链接链接
+        crmLink: '', // 小程序链接
+        wwwEnabledStatus: 1, // 停启用状态 1 启用 0 停用
+        crmEnabledStatus: 0 // 停启用状态 1 启用 0 停用
+      }
+    }
+    return {
+      form: defaultForm(),
+      editType: 'add',
+      loadImgLoading: false,
+      loadPcImageLoading: false,
+      rules: {
+        title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
+        image: [{ required: true, message: '请上传PC广告图', trigger: 'blur' }],
+        crmImage: [{ required: true, message: '请上传小程序广告图', trigger: 'blur' }],
+        link: [{ required: true, message: '请输入PC端链接', trigger: 'blur' }],
+        crmLink: [{ required: true, message: '请输入小程序链接', trigger: 'blur' }],
+        wwwEnabledStatus: [{ required: true, message: '请选择PC端状态', trigger: 'blur' }],
+        crmEnabledStatus: [{ required: true, message: '请选择小程序状态', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    getToken() {
+      return {
+        token: this.$store.getters.token
+      }
+    },
+    actionUrl() {
+      return process.env.VUE_APP_BASE_API + '/formData/MultiPictareaddData'
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type || 'edit'
+    if (this.editType === 'edit') {
+      console.log('edit')
+      this.getTopAdvertisementForm(this.$route.query.id)
+    }
+  },
+  methods: {
+    async getTopAdvertisementForm(id) {
+      // 获取轮播详情
+      try {
+        const res = await getTopAdvertisementForm({ id: id })
+        this.form = { ...this.form, ...res.data }
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    onSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$confirm('是否提交保存数据?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log('form', this.form)
+            this.saveTopAdvertisement(this.form)
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    async saveTopAdvertisement(params) {
+      // 保存
+      await saveTopAdvertisement(params)
+      this.$notify.success({ title: '保存成功~', message: '' })
+      this.$router.back()
+    },
+    // 取消选择商品
+    handleCancel() {
+      this.shopDialogVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 上传PC广告图事件
+    handleSuccessPcImage(response, file) {
+      this.loadPcImageLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.image = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 上传小程序广告图事件
+    handleSuccessAppImage(response, file) {
+      this.loadImgLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.crmImage = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 对上传图片的大小、格式进行限制
+    beforeUpload(file) {
+      const isJPG = file.type === 'image/jpeg'
+      const isJPG2 = file.type === 'image/jpg'
+      const isPNG = file.type === 'image/png'
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!isJPG && !isJPG2 && !isPNG) {
+        this.$message.error('只支持jpg或png格式图片')
+      }
+      if (!isLt5M) {
+        this.$message.error('请上传5MB以内的图片!')
+      }
+      return (isJPG || isJPG2 || isPNG) && isLt5M
+    },
+    reloadImage() {
+      this.loadImgLoading = true
+      setTimeout(() => {
+        this.temp.classifyImage = this.temp.classifyImage.split('?')[0] + '?r=' + Math.floor(Math.random() * 1000)
+      }, 1000 * 2)
+    },
+    loadPcImageSucess() {
+      this.loadPcImageLoading = false
+    },
+    loadSucess() {
+      this.loadImgLoading = false
+    },
+    backToList() {
+      this.$store.dispatch('tagsView/delView', this.$route).then(() => {
+        this.$nextTick(() => {
+          this.$router.replace({
+            path: '/operate/zones/exclusive-image',
+            query: { activeName: 'first' }
+          })
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+.avatar-uploader-icon {
+  font-size: 30px;
+  color: #999999;
+}
+.el-form-item__label {
+  text-align: right !important;
+}
+.el-upload__tip {
+  line-height: 20px;
+  color: red;
+  text-align: left;
+}
+.span_tip {
+  font-size: 12px;
+  color: red;
+  margin-left: 5px;
+}
+.filter-item-temp {
+  width: 100px;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 280px;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 285 - 0
src/views/operate/home/exclusive-small-edit.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="app-container" style="width: 800px; margin: 0 auto">
+    <el-form ref="bannerForm" :model="form" label-width="130px">
+      <el-form-item label="标题:" prop="title" :rules="rules.title">
+        <el-input v-model="form.title" placeholder="请输入标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="广告图片:" prop="image" :rules="rules.image" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 236px; height: 117px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessPcImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadPcImageLoading" class="avatar" style="width: 236px; height: 117px; display: block">
+              <img
+                v-if="form.image"
+                :src="form.image"
+                style="width: 236px; height: 117px; display: block"
+                @error="reloadImage"
+                @load="loadPcImageSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 236px; height: 117px; line-height: 117px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请上传尺寸232*117(px)的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="广告链接:" prop="link" :rules="rules.link">
+        <el-input v-model="form.link" placeholder="请输入广告链接" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <!--<el-form-item label="小程序端标题:" prop="crmTitle">
+        <el-input v-model="form.crmTitle" placeholder="请输入小程序端标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="小程序端图片:" prop="crmImage" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 264px; height: 120px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessAppImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadImgLoading" class="avatar" style="width: 264px; height: 120px; display: block">
+              <img
+                v-if="form.crmImage"
+                :src="form.crmImage"
+                style="width: 264px; height: 120px; display: block"
+                @error="reloadImage"
+                @load="loadSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 264px; height: 120px; line-height: 120px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请尽量上传270*135(px)尺寸的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="小程序端链接:" prop="crmLink">
+        <el-input v-model="form.crmLink" placeholder="请输入小程序端链接" maxlength="200" style="width: 600px" />
+      </el-form-item>-->
+      <el-form-item label="广告排序:" prop="sort">
+        <el-input v-model="form.sort" type="number" placeholder="请设置广告排序" maxlength="3" style="width: 218px" />
+      </el-form-item>
+      <!--<el-form-item label="广告状态" prop="wwwEnabledStatus">
+        <el-select v-model="form.wwwEnabledStatus" placeholder="请选择广告状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>-->
+      <!--<el-form-item label="小程序状态" prop="crmEnabledStatus">
+        <el-select v-model="form.crmEnabledStatus" placeholder="请选择小程序状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>-->
+    </el-form>
+    <div class="el-dialog__footer" style="text-align: center">
+      <el-button type="primary" @click="onSubmit('bannerForm')"> 保存 </el-button>
+      <el-button plain @click="backToList"> 返回 </el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getAdvertisementForm, saveAdvertisement } from '@/api/activity/home/home'
+
+export default {
+  name: 'ExclusiveSmallEdit',
+  data() {
+    const defaultForm = () => {
+      return {
+        id: '',
+        title: '', // PC端标题
+        // crmTitle: '', // 小程序标题
+        image: '', // PC广告图
+        // crmImage: '', // 小程序广告图
+        link: '', // PC链接链接
+        sort: 0,
+        // crmLink: '', // 小程序链接
+        wwwEnabledStatus: 1 // 停启用状态 1 启用 0 停用
+        // crmEnabledStatus: 0// 停启用状态 1 启用 0 停用
+      }
+    }
+    return {
+      form: defaultForm(),
+      editType: 'add',
+      loadImgLoading: false,
+      loadPcImageLoading: false,
+      rules: {
+        title: [{ required: true, message: '请输入轮播标题', trigger: 'blur' }],
+        image: [{ required: true, message: '请上传PC广告图', trigger: 'blur' }],
+        crmImage: [{ required: true, message: '请上传小程序广告图', trigger: 'blur' }],
+        shops: [{ required: true, type: 'array', message: '请添加供应商', trigger: ['change'] }],
+        link: [{ required: true, message: '请输入广告链接', trigger: 'blur' }],
+        crmLink: [{ required: true, message: '请输入小程序链接', trigger: 'blur' }],
+        wwwEnabledStatus: [{ required: true, message: '请选择PC端状态', trigger: 'blur' }],
+        crmEnabledStatus: [{ required: true, message: '请选择小程序状态', trigger: 'blur' }],
+        sort: [{ required: true, message: '排序值不能为空', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    getToken() {
+      return {
+        token: this.$store.getters.token
+      }
+    },
+    actionUrl() {
+      return process.env.VUE_APP_BASE_API + '/formData/MultiPictareaddData'
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type || 'edit'
+    if (this.editType === 'edit') {
+      console.log('edit')
+      this.getAdvertisementForm(this.$route.query.id)
+    }
+  },
+  methods: {
+    async getAdvertisementForm(id) {
+      // 获取轮播详情
+      try {
+        const res = await getAdvertisementForm({ id: id })
+        this.form = { ...this.form, ...res.data }
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    onSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$confirm('是否提交保存数据?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log('form', this.form)
+            this.saveAdvertisement(this.form)
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    async saveAdvertisement(params) {
+      // 保存
+      await saveAdvertisement(params)
+      this.$notify.success({ title: '保存成功~', message: '' })
+      this.$router.back()
+    },
+    // 取消选择商品
+    handleCancel() {
+      this.shopDialogVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 上传PC广告图事件
+    handleSuccessPcImage(response, file) {
+      this.loadPcImageLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.image = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 上传小程序广告图事件
+    handleSuccessAppImage(response, file) {
+      this.loadImgLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.crmImage = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 对上传图片的大小、格式进行限制
+    beforeUpload(file) {
+      const isJPG = file.type === 'image/jpeg'
+      const isJPG2 = file.type === 'image/jpg'
+      const isPNG = file.type === 'image/png'
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!isJPG && !isJPG2 && !isPNG) {
+        this.$message.error('只支持jpg或png格式图片')
+      }
+      if (!isLt5M) {
+        this.$message.error('请上传5MB以内的图片!')
+      }
+      return (isJPG || isJPG2 || isPNG) && isLt5M
+    },
+    reloadImage() {
+      this.loadImgLoading = true
+      setTimeout(() => {
+        this.temp.classifyImage = this.temp.classifyImage.split('?')[0] + '?r=' + Math.floor(Math.random() * 1000)
+      }, 1000 * 2)
+    },
+    loadPcImageSucess() {
+      this.loadPcImageLoading = false
+    },
+    loadSucess() {
+      this.loadImgLoading = false
+    },
+    backToList() {
+      this.$store.dispatch('tagsView/delView', this.$route).then(() => {
+        this.$nextTick(() => {
+          this.$router.replace({
+            path: '/operate/zones/exclusive-image',
+            query: { activeName: 'second' }
+          })
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+.avatar-uploader-icon {
+  font-size: 30px;
+  color: #999999;
+}
+.el-form-item__label {
+  text-align: right !important;
+}
+.el-upload__tip {
+  line-height: 20px;
+  color: red;
+  text-align: left;
+}
+.span_tip {
+  font-size: 12px;
+  color: red;
+  margin-left: 5px;
+}
+.filter-item-temp {
+  width: 100px;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 250px;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 207 - 0
src/views/operate/home/recom-goods.vue

@@ -0,0 +1,207 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container" style="padding-bottom: 0;">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+        <el-button type="primary" @click="goodsDialogVisible = true"> 添加商品 </el-button>
+        <el-button v-permission="'tag:list:del'" type="danger" :disabled="disabled" @click="handleDeletePros">
+          批量删除
+        </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" />
+      <el-table-column prop="productId" label="商品ID" align="center" width="80" />
+      <el-table-column prop="mainImage" label="商品图片" align="center" width="100">
+        <template slot-scope="{ row }">
+          <img :src="row.mainImage" alt="" style="width: 50px; height: 50px" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" label="商品名称" align="center" />
+      <el-table-column prop="shopName" label="供应商名称" align="center" />
+      <el-table-column prop="sort" label="排序" width="70" align="center">
+        <template slot-scope="{ row }">
+          <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="updateRecommendSort(row)" />
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDeletePros(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10,20]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getRecommendList"
+    />
+    <!--  选择商品弹窗 -->
+    <goods-dialog v-if="goodsDialogVisible" ref="goodsDialog" @confirm="handleAddShopConfirm" @cancel="handleCancel" />
+  </div>
+</template>
+
+<script>
+import { getRecommendList, addRecommendProduct, delRecommendProduct, updateRecommendSort } from '@/api/activity/home/home'
+import GoodsDialog from './components/goods-recom-dialog'
+export default {
+  name: 'RecomGoods',
+  components: { GoodsDialog },
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      floorTitle: this.$route.query.floorTitle,
+      listQuery: {
+        shopName: '',
+        productId: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      goodsDialogVisible: false,
+      dialogFormVisible: false,
+      logoFormVisible: false,
+      loadImgLoading: false,
+      renewCustome: {
+        id: '',
+        status: ''
+      },
+      currentList: []
+    }
+  },
+  computed: {
+    disabled() {
+      return this.currentList.length === 0
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取专区商品列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getRecommendList()
+    },
+    // 获取专区商品列表
+    async getRecommendList() {
+      try {
+        this.isLoading = true
+        const res = await getRecommendList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 确认选择商品
+    handleAddShopConfirm(data) {
+      console.log('data', data)
+      const productIds = []
+      data.forEach((ele) => {
+        productIds.push(ele.productId)
+      })
+      this.addRecommendProduct({ ids: productIds.join(',') })
+    },
+    // 取消选择商品
+    handleCancel() {
+      this.goodsDialogVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 选择列表项
+    handleSelectionChange(current) {
+      this.currentList = current
+      console.log('currentList', current)
+    },
+    // 专区商品排序
+    async updateRecommendSort(row) {
+      try {
+        await updateRecommendSort({ productId: row.productId, sort: row.sort })
+        this.$notify.success({ title: '排序更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 保存添加商品
+    async addRecommendProduct(params) {
+      try {
+        await addRecommendProduct(params)
+        this.goodsDialogVisible = false
+        this.$notify.success({ title: '保存成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作删除商品
+    async handleDeletePros(row) {
+      try {
+        let confirmText = ''
+        if (this.currentList.length > 0) {
+          confirmText = '确定删除所选商品吗?'
+        } else {
+          confirmText = '确定删除该商品吗?'
+        }
+        await this.$confirm(confirmText, {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delRecommendProduct(row)
+      } catch (error) {
+        this.$notify.info({ title: '用户取消操作~', message: '' })
+      }
+    },
+    // 调用删除推荐商品
+    async delRecommendProduct(row) {
+      try {
+        const productIds = row instanceof Event ? this.currentList : [].concat(row)
+        const ids = productIds.map((item) => item.productId).join(',')
+        await delRecommendProduct({ ids: ids })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.tags-sms-span{
+  font-weight: bold;
+  font-size: 16px !important;
+}
+</style>

+ 211 - 0
src/views/operate/home/zones-goods.vue

@@ -0,0 +1,211 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container" style="padding-bottom: 0;">
+      <div class="filter-control">
+        <span class="tags-sms-span">【{{ floorTitle }}】</span>
+      </div>
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+        <el-button type="primary" @click="goodsDialogVisible = true"> 添加商品 </el-button>
+        <el-button v-permission="'tag:list:del'" type="danger" :disabled="disabled" @click="handleDeletePros">
+          批量删除
+        </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" />
+      <el-table-column prop="productId" label="商品ID" align="center" width="80" />
+      <el-table-column prop="mainImage" label="商品图片" align="center" width="100">
+        <template slot-scope="{ row }">
+          <img :src="row.mainImage" alt="" style="width: 50px; height: 50px" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" label="商品名称" align="center" />
+      <el-table-column prop="shopName" label="供应商名称" align="center" />
+      <el-table-column prop="sort" label="排序" width="70" align="center">
+        <template slot-scope="{ row }">
+          <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="updateProductSort(row)" />
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDeletePros(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10,20]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getZoneProductList"
+    />
+    <!--  选择商品弹窗 -->
+    <goods-dialog v-if="goodsDialogVisible" ref="shopDialog" @confirm="handleAddShopConfirm" @cancel="handleCancel" />
+  </div>
+</template>
+
+<script>
+import { getZoneProductList, addZoneProduct, delZoneProduct, updateProductSort } from '@/api/activity/home/home'
+import GoodsDialog from './components/goods-dialog'
+export default {
+  name: 'RecordList',
+  components: { GoodsDialog },
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      floorTitle: this.$route.query.floorTitle,
+      listQuery: {
+        id: this.$route.query.id,
+        shopName: '',
+        productId: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      goodsDialogVisible: false,
+      dialogFormVisible: false,
+      logoFormVisible: false,
+      loadImgLoading: false,
+      renewCustome: {
+        id: '',
+        status: ''
+      },
+      currentList: []
+    }
+  },
+  computed: {
+    disabled() {
+      return this.currentList.length === 0
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取专区商品列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getZoneProductList()
+    },
+    // 获取专区商品列表
+    async getZoneProductList() {
+      try {
+        this.isLoading = true
+        const res = await getZoneProductList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 确认选择商品
+    handleAddShopConfirm(data) {
+      console.log('data', data)
+      const productIds = []
+      data.forEach((ele) => {
+        productIds.push(ele.productId)
+      })
+      this.addZoneProduct({ id: this.listQuery.id, ids: productIds.join(',') })
+    },
+    // 取消选择商品
+    handleCancel() {
+      this.goodsDialogVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 选择列表项
+    handleSelectionChange(current) {
+      this.currentList = current
+      console.log('currentList', current)
+    },
+    // 专区商品排序
+    async updateProductSort(row) {
+      try {
+        await updateProductSort({ id: this.listQuery.id, productId: row.productId, sort: row.sort })
+        this.$notify.success({ title: '排序更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 保存添加商品
+    async addZoneProduct(params) {
+      try {
+        await addZoneProduct(params)
+        this.goodsDialogVisible = false
+        this.$notify.success({ title: '保存成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作删除商品
+    async handleDeletePros(row) {
+      try {
+        let confirmText = ''
+        if (this.currentList.length > 0) {
+          confirmText = '确定删除所选商品吗?'
+        } else {
+          confirmText = '确定删除该商品吗?'
+        }
+        await this.$confirm(confirmText, {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delZoneProduct(row)
+      } catch (error) {
+        this.$notify.info({ title: '用户取消操作~', message: '' })
+      }
+    },
+    // 调用删除商品
+    async delZoneProduct(row) {
+      try {
+        const productIds = row instanceof Event ? this.currentList : [].concat(row)
+        const ids = productIds.map((item) => item.productId).join(',')
+        await delZoneProduct({ id: this.listQuery.id, ids: ids })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.tags-sms-span{
+  font-weight: bold;
+  font-size: 16px !important;
+}
+</style>

+ 285 - 0
src/views/operate/home/zones-image-edit.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="app-container" style="width: 800px; margin: 0 auto">
+    <el-form ref="bannerForm" :model="form" label-width="130px">
+      <el-form-item label="轮播标题:" prop="title" :rules="rules.title">
+        <el-input v-model="form.title" placeholder="请输入轮播标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="PC端图片:" prop="image" :rules="rules.image" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 264px; height: 120px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessPcImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadPcImageLoading" class="avatar" style="width: 264px; height: 120px; display: block">
+              <img
+                v-if="form.image"
+                :src="form.image"
+                style="width: 264px; height: 120px; display: block"
+                @error="reloadImage"
+                @load="loadPcImageSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 264px; height: 120x; line-height: 120px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请上传尺寸1184*400(px)的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="PC端链接:" prop="link" :rules="rules.link">
+        <el-input v-model="form.link" placeholder="请输入PC端链接" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="小程序端标题:" prop="crmTitle" :rules="rules.crmTitle">
+        <el-input v-model="form.crmTitle" placeholder="请输入小程序端标题" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="小程序端图片:" prop="crmImage" :rules="rules.crmImage" style="margin-bottom: 40px">
+        <div class="form-el-upload" style="width: 264px; height: 120px">
+          <el-upload
+            class="avatar-uploader"
+            :action="actionUrl"
+            :headers="getToken"
+            :show-file-list="false"
+            :on-success="handleSuccessAppImage"
+            :before-upload="beforeUpload"
+          >
+            <div v-loading="loadImgLoading" class="avatar" style="width: 264px; height: 120px; display: block">
+              <img
+                v-if="form.crmImage"
+                :src="form.crmImage"
+                style="width: 264px; height: 120px; display: block"
+                @error="reloadImage"
+                @load="loadSucess"
+              />
+              <i
+                v-else
+                class="el-icon-plus avatar-uploader-icon"
+                style="width: 264px; height: 120px; line-height: 120px"
+              ></i>
+            </div>
+          </el-upload>
+          <p class="uploader-tips">注:请上传尺寸702*240(px)的图片。</p>
+        </div>
+      </el-form-item>
+      <el-form-item label="小程序端链接:" prop="crmLink" :rules="rules.crmLink">
+        <el-input v-model="form.crmLink" placeholder="请输入小程序端链接" maxlength="200" style="width: 600px" />
+      </el-form-item>
+      <el-form-item label="轮播排序:" prop="sort">
+        <el-input v-model="form.sort" type="number" placeholder="请设置专区排序" maxlength="3" style="width: 218px" />
+      </el-form-item>
+      <el-form-item label="PC端状态" prop="wwwEnabledStatus">
+        <el-select v-model="form.wwwEnabledStatus" placeholder="请选择网站状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="小程序状态" prop="crmEnabledStatus">
+        <el-select v-model="form.crmEnabledStatus" placeholder="请选择小程序状态">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <div class="el-dialog__footer" style="text-align: center">
+      <el-button type="primary" @click="onSubmit('bannerForm')"> 保存 </el-button>
+      <el-button plain @click="backToList"> 返回 </el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getZoneImageById, saveZoneImage } from '@/api/activity/home/home'
+
+export default {
+  name: 'ZonesImageEdit',
+  data() {
+    const defaultForm = () => {
+      return {
+        imageId: '',
+        zoneId: this.$route.query.zoneId,
+        title: '', // PC端标题
+        crmTitle: '', // 小程序标题
+        image: '', // PC广告图
+        crmImage: '', // 小程序广告图
+        link: '', // PC链接链接
+        crmLink: '', // 小程序链接
+        wwwEnabledStatus: 1, // 停启用状态 1 启用 0 停用
+        crmEnabledStatus: 1, // 停启用状态 1 启用 0 停用
+        sort: 0
+      }
+    }
+    return {
+      form: defaultForm(),
+      editType: 'add',
+      loadImgLoading: false,
+      loadPcImageLoading: false,
+      rules: {
+        title: [{ required: true, message: '请输入轮播标题', trigger: 'blur' }],
+        image: [{ required: true, message: '请上传PC广告图', trigger: 'blur' }],
+        crmImage: [{ required: true, message: '请上传小程序广告图', trigger: 'blur' }],
+        link: [{ required: true, message: '请输入PC端链接', trigger: 'blur' }],
+        crmLink: [{ required: true, message: '请输入小程序链接', trigger: 'blur' }],
+        sort: [{ required: true, message: '排序值不能为空', trigger: 'blur' }],
+        wwwEnabledStatus: [{ required: true, message: '请选择PC端状态', trigger: 'blur' }],
+        crmEnabledStatus: [{ required: true, message: '请选择小程序状态', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    getToken() {
+      return {
+        token: this.$store.getters.token
+      }
+    },
+    actionUrl() {
+      return process.env.VUE_APP_BASE_API + '/formData/MultiPictareaddData'
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type || 'edit'
+    if (this.editType === 'edit') {
+      console.log('edit')
+      this.getZoneImageById(this.$route.query.imageId)
+    }
+  },
+  methods: {
+    async getZoneImageById(imageId) {
+      // 获取轮播详情
+      try {
+        const res = await getZoneImageById({ imageId: imageId })
+        this.form = { ...this.form, ...res.data }
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    onSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.$confirm('是否提交保存数据?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log('form', this.form)
+            this.saveZoneImage(this.form)
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    async saveZoneImage(params) {
+      // 保存
+      await saveZoneImage(params)
+      this.$notify.success({ title: '保存成功~', message: '' })
+      this.$router.back()
+    },
+    // 取消选择商品
+    handleCancel() {
+      this.shopDialogVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 上传PC广告图事件
+    handleSuccessPcImage(response, file) {
+      this.loadPcImageLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.image = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 上传小程序广告图事件
+    handleSuccessAppImage(response, file) {
+      this.loadImgLoading = true
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.form.crmImage = response.data
+        }, 1000 * 2)
+      })
+    },
+    // 对上传图片的大小、格式进行限制
+    beforeUpload(file) {
+      const isJPG = file.type === 'image/jpeg'
+      const isJPG2 = file.type === 'image/jpg'
+      const isPNG = file.type === 'image/png'
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!isJPG && !isJPG2 && !isPNG) {
+        this.$message.error('只支持jpg或png格式图片')
+      }
+      if (!isLt5M) {
+        this.$message.error('请上传5MB以内的图片!')
+      }
+      return (isJPG || isJPG2 || isPNG) && isLt5M
+    },
+    reloadImage() {
+      this.loadImgLoading = true
+      setTimeout(() => {
+        this.temp.classifyImage = this.temp.classifyImage.split('?')[0] + '?r=' + Math.floor(Math.random() * 1000)
+      }, 1000 * 2)
+    },
+    loadPcImageSucess() {
+      this.loadPcImageLoading = false
+    },
+    loadSucess() {
+      this.loadImgLoading = false
+    },
+    backToList() {
+      this.$store.dispatch('tagsView/delView', this.$route).then(() => {
+        this.$nextTick(() => {
+          this.$router.replace({
+            path: '/operate/zones/zones-image',
+            query: { id: this.$route.query.zoneId, floorTitle: this.$route.query.floorTitle }
+          })
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+.avatar-uploader-icon {
+  font-size: 30px;
+  color: #999999;
+}
+.el-form-item__label {
+  text-align: right !important;
+}
+.el-upload__tip {
+  line-height: 20px;
+  color: red;
+  text-align: left;
+}
+.span_tip {
+  font-size: 12px;
+  color: red;
+  margin-left: 5px;
+}
+.filter-item-temp {
+  width: 100px;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 280px !important;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 250 - 0
src/views/operate/home/zones-image.vue

@@ -0,0 +1,250 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+
+    <div class="filter-container" style="padding-bottom: 0;">
+      <div class="filter-control">
+        <span class="tags-sms-span">【{{ floorTitle }}】</span>
+      </div>
+      <div class="filter-control">
+        <span>轮播标题:</span>
+        <el-input
+          v-model="listQuery.title"
+          placeholder="轮播标题"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>网站状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>小程序状态:</span>
+        <el-select v-model="listQuery.status" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="0" label="已启用" />
+          <el-option :value="1" label="已停用" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+        <el-button type="primary" @click="handleoOerate('add')"> 添加轮播 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660">
+      <el-table-column prop="imageId" label="ID" align="center" width="50" />
+      <el-table-column prop="title" label="轮播标题" align="center" width="200" />
+      <el-table-column prop="image" label="网站广告图" align="center">
+        <template slot-scope="{ row }">
+          <img :src="row.image" alt="" style="width: 132px; height: 60px;" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="crmImage" label="小程序广告图" align="center">
+        <template slot-scope="{ row }">
+          <img :src="row.crmImage" alt="" style="width: 132px; height: 60px;" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="wwwEnabledStatus" label="网站状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.wwwEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.wwwEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.imageId, row.wwwEnabledStatus, 0)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.imageId, row.wwwEnabledStatus, 0)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column prop="crmEnabledStatus" label="小程序状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.crmEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.crmEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.imageId, row.crmEnabledStatus, 1)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.imageId, row.crmEnabledStatus, 1)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" width="70" align="center">
+        <template slot-scope="{ row }">
+          <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="handleOnInputBlur(row)" />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="220">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handleoOerate('edit', row)">
+            编辑
+          </el-button>
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDelete(row)"> 删除 </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[20]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getZoneImageList"
+    />
+  </div>
+</template>
+
+<script>
+
+import { getZoneImageList, delZoneImage, updateImageSort, updateImageStatus } from '@/api/activity/home/home'
+export default {
+  name: 'ZonesImage',
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      floorTitle: this.$route.query.floorTitle,
+      listQuery: {
+        id: this.$route.query.id,
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      timesValue: []
+    }
+  },
+  computed: {},
+  watch: {
+    timesValue: {
+      handler() {
+        this.getList()
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取行为记录列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.list = []
+      this.getZoneImageList()
+    },
+
+    // 获取关键词列表
+    async getZoneImageList() {
+      try {
+        this.isLoading = true
+        const res = await getZoneImageList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 添加专区广告图
+    handleoOerate(type, row) {
+      if (type === 'add') {
+        this.$router.push({
+          path: '/operate/zones/zones-image-edit',
+          query: { zoneId: this.listQuery.id, type: type, floorTitle: this.floorTitle }
+        })
+      } else {
+        this.$router.push({
+          path: '/operate/zones/zones-image-edit',
+          query: { zoneId: this.listQuery.id, imageId: row.imageId, type: type, floorTitle: this.floorTitle }
+        })
+      }
+    },
+    // 操作启用停用广告图
+    handleShangeStatus(imageId, status, type) {
+      let confirmTxt = ''
+      let paramsStatus
+      if (status === 1) {
+        confirmTxt = '确定停用该广告图?'
+        paramsStatus = 0
+      } else {
+        confirmTxt = '确定启用该广告图?'
+        paramsStatus = 1
+      }
+      this.$confirm(confirmTxt)
+        .then((_) => {
+          this.updateImageStatus(imageId, paramsStatus, type)
+        })
+        .catch(() => {
+          this.$notify.info({ title: '用户取消操作~', message: '' })
+        })
+    },
+    // 停用启用广告图
+    async updateImageStatus(imageId, paramsStatus, type) {
+      try {
+        await updateImageStatus({ imageId: imageId, status: paramsStatus, type: type })
+        this.$notify.success({ title: '更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    // 操作删除广告图
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该广告图吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delZoneImage(row)
+      } catch (error) {
+        this.$notify.info('用户取消操作~')
+      }
+    },
+    // 调用删除广告图
+    async delZoneImage(row) {
+      try {
+        await delZoneImage({ imageId: row.imageId })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 广告图排序
+    async handleOnInputBlur(row) {
+      try {
+        await updateImageSort({ imageId: row.imageId, sort: row.sort })
+        this.$notify.success({ title: '排序更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 机构跳转
+    handleClubHrefLink(row) {
+      return (
+        process.env.VUE_APP_ADMIN_URL +
+        `/a/user/jumpLink/toOldAdmin?type=1&clubId=${row.clubId}&clubName=${row.corporateName}`
+      )
+    }
+  }
+}
+</script>
+
+<style>
+.tags-sms-span{
+  font-weight: bold;
+  font-size: 16px !important;
+}
+</style>

+ 294 - 0
src/views/operate/home/zones-list.vue

@@ -0,0 +1,294 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <!--<div class="filter-control">
+        <span>网站状态:</span>
+        <el-select v-model="listQuery.wwwEnabledStatus" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="1" label="启用" />
+          <el-option :value="0" label="停用" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>小程序状态:</span>
+        <el-select v-model="listQuery.crmEnabledStatus" style="width: 120px" clearable @change="getList">
+          <el-option value="" label="请选择" />
+          <el-option :value="1" label="启用" />
+          <el-option :value="0" label="停用" />
+        </el-select>
+      </div>-->
+      <div class="filter-control">
+        <el-button type="primary" @click="dialogFormVisible = true"> 添加专区 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%">
+      <el-table-column label="序号" align="center" width="50">
+        <template slot-scope="scope">
+          {{ scope.$index + 1 }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="floorTitle" label="专区标题" align="center" width="200" />
+      <el-table-column prop="floorDetail" label="专区描述" align="center" />
+      <el-table-column prop="wwwEnabledStatus" label="网站状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.wwwEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.wwwEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.wwwEnabledStatus, 0)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column prop="crmEnabledStatus" label="小程序状态" align="center" width="150">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.crmEnabledStatus === 1" type="success" size="small">已启用</el-tag>
+          <el-tag v-else type="danger" size="small">已停用</el-tag>
+          <el-button v-if="row.crmEnabledStatus === 1" type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            停用
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleShangeStatus(row.id, row.crmEnabledStatus, 1)">
+            启用
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" width="70" align="center">
+        <template slot-scope="{ row }">
+          <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="updateZoneSort(row)" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="createDate" label="创建时间" align="center" width="180">
+        <template slot-scope="{ row }">
+          {{ row.createDate }}
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" align="center">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handleEdit(row)"> 编辑 </el-button>
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handlePath(1,row)"> 专区商品 </el-button>
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handlePath(2,row)"> 专区轮播 </el-button>
+          <el-button type="danger" size="mini" style="margin: 2px" @click="handleDelete(row)"> 删除 </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20, 30, 100]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getPageZoneList"
+    />
+    <!-- 专区添加 -->
+    <el-dialog title="专区添加" :visible.sync="dialogFormVisible" width="500px">
+      <el-form ref="dataForm" :rules="rules" :model="form" label-position="right" label-width="100px">
+        <el-form-item label="专区标题:" prop="floorTitle">
+          <el-input v-model="form.floorTitle" type="text" placeholder="请输入专区标题" maxlength="10" />
+        </el-form-item>
+        <el-form-item label="专区描述:" prop="floorDetail">
+          <el-input v-model="form.floorDetail" type="text" placeholder="请输入专区描述" maxlength="50" />
+        </el-form-item>
+        <el-form-item label="标题背景色:" prop="backColor">
+          <el-input v-model="form.backColor" type="text" placeholder="请输入标题背景色(如:#FF5B00)" maxlength="10" />
+        </el-form-item>
+        <el-form-item label="专区排序:" prop="sort">
+          <el-input v-model="form.sort" type="number" placeholder="请设置专区排序" maxlength="3" />
+        </el-form-item>
+        <el-form-item label="网站状态" prop="wwwEnabledStatus">
+          <el-select v-model="form.wwwEnabledStatus" placeholder="请选择网站状态">
+            <el-option label="启用" :value="1" />
+            <el-option label="停用" :value="0" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="小程序状态" prop="crmEnabledStatus">
+          <el-select v-model="form.crmEnabledStatus" placeholder="请选择小程序状态">
+            <el-option label="启用" :value="1" />
+            <el-option label="停用" :value="0" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取消</el-button>
+        <el-button type="primary" @click="handleSavePageZone">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getPageZoneList, savePageZone, delPageZone, updateZoneSort, updateZoneStatus } from '@/api/activity/home/home'
+import { mapGetters } from 'vuex'
+export default {
+  name: 'ZonesList',
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      listQuery: {
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      dialogFormVisible: false,
+      form: {
+        id: '',
+        floorTitle: '', // 专区标题
+        floorDetail: '', // 专区描述
+        backColor: '', // 标题背景色
+        sort: 0, // 专区排序
+        crmEnabledStatus: 1, // 小程序状态
+        wwwEnabledStatus: 1, // WWW状态
+        createBy: ''
+      },
+      rules: {
+        floorTitle: [{ required: true, message: '请输入专区标题', trigger: 'blur' }],
+        floorDetail: [{ required: true, message: '请输入专区描述', trigger: 'blur' }],
+        backColor: [{ required: true, message: '请输入标题背景色', trigger: 'blur' }],
+        sort: [{ required: true, message: '请设置专区排序', trigger: 'blur' }],
+        wwwEnabledStatus: [{ required: true, message: '请选择网站状态', trigger: 'blur' }],
+        crmEnabledStatus: [{ required: true, message: '请选择小程序状态', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    ...mapGetters(['fullName'])
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取专区列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.getPageZoneList()
+    },
+
+    // 获取专区列表
+    async getPageZoneList() {
+      try {
+        this.isLoading = true
+        const res = await getPageZoneList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作启用停用
+    handleShangeStatus(id, status, type) {
+      let confirmTxt = ''
+      let paramsStatus
+      if (status === 1) {
+        confirmTxt = '确定停用该专区?'
+        paramsStatus = 0
+      } else {
+        confirmTxt = '确定启用该专区?'
+        paramsStatus = 1
+      }
+      this.$confirm(confirmTxt)
+        .then((_) => {
+          this.updateZoneStatus(id, paramsStatus, type)
+        })
+        .catch(() => {
+          this.$notify.info({ title: '用户取消操作~', message: '' })
+        })
+    },
+    // 停用启用专区
+    async updateZoneStatus(id, paramsStatus, type) {
+      try {
+        await updateZoneStatus({ id: id, status: paramsStatus, type: type })
+        this.$notify.success({ title: '更新成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log('error', error)
+      }
+    },
+    // 确认保存专区
+    async handleSavePageZone() {
+      try {
+        await this.$refs.dataForm.validate()
+        this.form.createBy = this.fullName
+        this.savePageZone(this.form)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 保存专区
+    async savePageZone(params) {
+      await savePageZone(params)
+      this.$notify.success({ title: '保存成功~', message: '' })
+      this.closeDialog()
+      this.getList()
+    },
+    // 添加取消
+    closeDialog() {
+      this.$refs.dataForm.resetFields()
+      this.dialogFormVisible = false
+    },
+    // 编辑专区
+    handleEdit(row) {
+      this.form = { ...this.form, ...row }
+      this.dialogFormVisible = true
+    },
+    // 操作删除专区
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该专区吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delPageZone(row)
+      } catch (error) {
+        this.$notify.info({ title: '用户取消操作~', message: '' })
+      }
+    },
+    // 调用删除专区
+    async delPageZone(row) {
+      try {
+        await delPageZone({ id: row.id })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 专区排序
+    async updateZoneSort(row) {
+      try {
+        await updateZoneSort({ id: row.id, sort: row.sort })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 跳转
+    handlePath(type, row) {
+      switch (type) {
+        case 1: // 专区商品
+          this.$router.push({
+            path: '/operate/zones/zones-goods',
+            query: { id: row.id, floorTitle: row.floorTitle }
+          })
+          break
+        case 2: // 专区轮播
+          this.$router.push({
+            path: '/operate/zones/zones-image',
+            query: { id: row.id, floorTitle: row.floorTitle }
+          })
+          break
+      }
+    }
+  }
+}
+</script>
+
+<style></style>

+ 206 - 0
src/views/serviceSettlement/club/index.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>机构ID:</span>
+        <el-input
+          v-model="listQuery.clubId"
+          style="width: 120px"
+          placeholder="机构ID"
+          clearable
+          maxlength="10"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>机构名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="机构名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.bindMobile"
+          placeholder="手机号"
+          maxlength="11"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>联系人:</span>
+        <el-input
+          v-model="listQuery.linkMan"
+          placeholder="联系人名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660">
+      <el-table-column prop="clubId" fixed label="机构ID" align="center" width="80" />
+      <el-table-column prop="name" fixed label="机构名称" align="center" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+      <el-table-column prop="spName" label="服务商名称" align="center" />
+      <el-table-column prop="contractMobile" label="手机号" align="center">
+        <template slot-scope="{ row }">
+          {{ row.contractMobile ? row.contractMobile : '---' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="status" label="机构状态" align="center" width="100">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.status === 1" type="warning" size="small">待审核</el-tag>
+          <el-tag v-if="row.status === 90" type="success" size="small">已上线</el-tag>
+          <el-tag v-if="row.status === 91" type="info" size="small">已下线</el-tag>
+          <el-tag v-if="row.status === 92" type="danger" size="small">审核未通过</el-tag>
+          <el-tag v-if="row.status === 93" type="warning" size="small">已确认</el-tag>
+          <el-tag v-if="row.status === 94" type="danger" size="small">已冻结</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="userIdentity" label="机构级别" align="center">
+        <template slot-scope="{ row }">
+          <template v-if="row.userIdentity === '4'">
+            <el-tag v-if="row.userIdentity === '4' && row.svipUserFlag === 1" type="success" size="small">个人机构(超级会员)</el-tag>
+            <el-tag v-else type="info" size="small">个人机构(普通会员)</el-tag>
+          </template>
+          <template v-if="row.userIdentity === '2'">
+            <el-tag v-if="row.userIdentity === '2' && row.svipUserFlag ===1" type="success" size="small">资质机构(超级会员)</el-tag>
+            <el-tag v-if="row.userIdentity === '2' && row.svipUserFlag !==1 && !row.medicalPracticeLicenseImg" type="warning" size="small">资质机构(高级会员)</el-tag>
+            <el-tag v-if="row.userIdentity === '2' && row.svipUserFlag !==1 && row.medicalPracticeLicenseImg" type="danger" size="small">资质机构(医美会员)</el-tag>
+          </template>
+        </template>
+      </el-table-column>
+      <el-table-column prop="addTime" label="注册时间" align="center">
+        <template slot-scope="{ row }">
+          {{ row.addTime ? row.addTime : '---' }}
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20, 30, 100]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="providersClubList"
+    />
+  </div>
+</template>
+
+<script>
+import { providersClubList } from '@/api/serviceSettlement/service'
+import pickerOptions from '@/utils/time-picker.js'
+export default {
+  name: 'CustomerList',
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      pickerOptions,
+      time: [],
+      time1: [],
+      listQuery: {
+        spId: this.$route.query.serviceProviderId,
+        clubId: '',
+        name: '',
+        bindMobile: '',
+        linkMan: '',
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      shopDialogVisible: false,
+      dialogFormVisible: false,
+      renewCustome: {
+        id: '',
+        status: ''
+      },
+      rules: {
+        status: [{ required: true, message: '请设置统计状态', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {},
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取行为记录列表
+    getList() {
+      this.list = []
+      this.isLoading = true
+      this.listQuery.pageNum = 1
+      this.providersClubList()
+    },
+    // 获取机构列表
+    async providersClubList() {
+      try {
+        const res = await providersClubList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作
+    handleRecordDetail(type, row) {
+      switch (type) {
+        case 1: // 咨询记录
+          this.$router.push({
+            path: '/user/consult/list',
+            query: { clubName: row.name, clubId: row.clubId }
+          })
+          break
+        case 2: // 行为记录
+          this.$router.push({
+            path: '/user/record-list',
+            query: { type: 'first', corporateName: row.name, clubId: row.clubId }
+          })
+          break
+        case 3: // 机构画像
+          this.$router.push({
+            path: '/user/club-portrait',
+            query: { clubName: row.name, clubId: row.clubId }
+          })
+          break
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 160px;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 1 - 1
src/views/serviceSettlement/components/CmQrcode/index.vue

@@ -74,7 +74,7 @@ export default {
       }).then(async() => {
         this.isLoading = true
         // 使用a链接下载
-        const downUrl = `${process.env.VUE_APP_BASE_API}/providers/download/image?ids=${this.itemObj.id}&type=2`
+        const downUrl = `${process.env.VUE_APP_BASE_API}/providers/download/image?ids=${this.itemObj.serviceProviderId}&type=2`
         this.downloadWithUrl(downUrl, this.itemObj.name)
           .catch((err) => {
             console.log(err)

+ 1 - 1
src/views/serviceSettlement/components/goods-dialog.vue

@@ -93,7 +93,7 @@ export default {
     return {
       visible: true,
       listQuery: {
-        providerId: this.$route.query.providersId,
+        serviceProviderId: this.$route.query.serviceProviderId,
         shopId: '',
         productId: '',
         shopName: '',

+ 139 - 0
src/views/serviceSettlement/components/group-dialog.vue

@@ -0,0 +1,139 @@
+<template>
+  <el-dialog title="添加成员" :visible.sync="visible" width="1200px" :close-on-click-modal="false" :show-close="false">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>服务商名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="服务商名称"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="手机号"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="400px"
+      border
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="服务商ID" prop="serviceProviderId" align="center" />
+      <el-table-column label="服务商名称" prop="name" align="center" />
+      <el-table-column label="手机号" prop="mobile" align="center" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getServiceList"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle"> 取 消 </el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleConfirm"> 确 定 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getServiceList } from '@/api/serviceSettlement/group'
+
+export default {
+  name: 'GoodsDialog',
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        pageNum: 1,
+        pageSize: 100
+      },
+      list: [],
+      total: 0,
+      groupRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.groupRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取所有供应商列表
+    async getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getServiceList()
+    },
+    // 获取所有服务商列表
+    async getServiceList() {
+      try {
+        const res = await getServiceList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 选择服务商
+    handleSelectionChange(row) {
+      this.groupRadio = row
+      console.log('row', row)
+    },
+    // 确认选择服务商
+    handleConfirm() {
+      this.$emit('confirm', this.groupRadio)
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    },
+    // 已选择的禁用勾选框
+    selectable(row) {
+      if (row.flag) {
+        return true
+      } else {
+        return false
+      }
+    },
+    checkedInput(event, type) {
+      let pattern = ''
+      switch (type) {
+        case 1:
+          pattern = /[^\d]/g
+          break
+        case 2:
+          pattern = /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!,。?!…—&$=()-+/*{}[]]|s/g
+          break
+      }
+      return event.replace(pattern, '')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 54 - 0
src/views/serviceSettlement/components/task-Item.vue

@@ -0,0 +1,54 @@
+<template>
+  <div class="store-item">
+    <el-image :src="selectStore.mainImage" />
+    <div class="store-name">{{ selectStore.productName }}</div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    selectStore: {
+      type: Object,
+      default: null
+    }
+  },
+  data() {
+    return {
+    }
+  },
+  watch: {
+    selectStore: {
+      handler(val) {
+        console.log(val)
+        this.selectStore = val
+      },
+      deep: true
+    }
+  },
+  created() {
+    console.log('selectStore', this.selectStore)
+    console.log('mainImage', this.selectStore.mainImage)
+    console.log('productName', this.selectStore.productName)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.store-item {
+  padding: 10px;
+  margin: 10px 0;
+  display: flex;
+  align-items: center;
+  background: #66666636;
+  margin-bottom: 10px;
+  .el-image {
+    width: 80px;
+    height: 80px;
+    margin-right: 10px;
+  }
+  .store-name {
+    width: calc(100% - 80px);
+  }
+}
+</style>

+ 159 - 0
src/views/serviceSettlement/components/task-goods-dialog.vue

@@ -0,0 +1,159 @@
+<template>
+  <el-dialog title="添加商品" :visible.sync="visible" width="1200px" :close-on-click-modal="false" :show-close="false">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>商品名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="商品名称"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="400px"
+      border
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="商品ID" prop="productId" align="center" width="100" />
+      <el-table-column prop="mainImage" label="商品图片" align="center" width="120">
+        <template slot-scope="{ row }">
+          <img v-if="row.mainImage" :src="row.mainImage" alt="" style="width: 50px; height: 50px" />
+          <span v-else>---</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" prop="productName" align="center" />
+      <el-table-column label="供应商名称" prop="shopName" align="center" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getTaskProducts"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle"> 取 消 </el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleConfirm"> 确 定 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getTaskProducts } from '@/api/serviceSettlement/task'
+
+export default {
+  name: 'GoodsDialog',
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        name: '',
+        shopName: '',
+        productId: '',
+        pageNum: 1, // 页码
+        pageSize: 10 // 页面数据数
+      },
+      list: [],
+      total: 0,
+      shopsRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.shopsRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取所有供应商列表
+    async getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getTaskProducts()
+    },
+    // 获取所有供应商列表
+    async getTaskProducts() {
+      try {
+        const res = await getTaskProducts(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 选择供应商
+    handleSelectionChange(row) {
+      this.shopsRadio = row
+      console.log('row', row)
+    },
+    // 确认选择供应商
+    handleConfirm() {
+      this.$emit('confirm', this.shopsRadio)
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    },
+    // 已选择的禁用勾选框
+    selectable(row) {
+      if (row.flag) {
+        return true
+      } else {
+        return false
+      }
+    },
+    checkedInput(event, type) {
+      let pattern = ''
+      switch (type) {
+        case 1:
+          pattern = /[^\d]/g
+          break
+        case 2:
+          pattern = /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!,。?!…—&$=()-+/*{}[]]|s/g
+          break
+      }
+      return event.replace(pattern, '')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 140 - 0
src/views/serviceSettlement/components/task-service-dialog.vue

@@ -0,0 +1,140 @@
+<template>
+  <el-dialog title="选择服务商" :visible.sync="visible" width="1200px" :close-on-click-modal="false" :show-close="false">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>服务商名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="服务商名称"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.mobile"
+          placeholder="手机号"
+          clearable
+          style="width: 160px"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="400px"
+      border
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="服务商ID" prop="serviceProviderId" align="center" />
+      <el-table-column label="服务商名称" prop="name" align="center" />
+      <el-table-column label="手机号" prop="mobile" align="center" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getReceiveList"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle"> 取 消 </el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleConfirm"> 确 定 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getReceiveList } from '@/api/serviceSettlement/task'
+
+export default {
+  name: 'TaskServiceDialog',
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        taskId: this.$route.query.taskId,
+        pageNum: 1,
+        pageSize: 100
+      },
+      list: [],
+      total: 0,
+      groupRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.groupRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取任务服务商列表
+    async getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getReceiveList()
+    },
+    // 获取任务服务商列表
+    async getReceiveList() {
+      try {
+        const res = await getReceiveList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 选择服务商
+    handleSelectionChange(row) {
+      this.groupRadio = row
+      console.log('row', row)
+    },
+    // 确认选择服务商
+    handleConfirm() {
+      this.$emit('confirm', this.groupRadio)
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    },
+    // 已选择的禁用勾选框
+    selectable(row) {
+      if (row.flag) {
+        return true
+      } else {
+        return false
+      }
+    },
+    checkedInput(event, type) {
+      let pattern = ''
+      switch (type) {
+        case 1:
+          pattern = /[^\d]/g
+          break
+        case 2:
+          pattern = /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!,。?!…—&$=()-+/*{}[]]|s/g
+          break
+      }
+      return event.replace(pattern, '')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 3 - 3
src/views/serviceSettlement/contract/edit.vue

@@ -78,8 +78,8 @@ export default {
     id() {
       return this.$route.query.id || false
     },
-    providersId() {
-      return Number(this.$route.query.providersId) || false
+    serviceProviderId() {
+      return Number(this.$route.query.serviceProviderId) || false
     },
     isCheck() {
       return !!Number(this.$route.query.isCheck)
@@ -99,7 +99,7 @@ export default {
     submitForm(form) {
       this.$refs[form].validate(async valid => {
         if (valid) {
-          const form = Object.assign(this.formLabelAlign, { providersId: this.providersId, createBy: this.fullName })
+          const form = Object.assign(this.formLabelAlign, { serviceProviderId: this.serviceProviderId, createBy: this.fullName })
           await addContract(form)
           this.$router.back()
         }

+ 7 - 7
src/views/serviceSettlement/contract/index.vue

@@ -27,7 +27,7 @@
       </div>
       <div class="filter-control">
         <el-button type="primary" @click="getList">查询</el-button>
-        <el-button type="primary" @click="$router.push('/service/settlement/contract/edit?providersId=' + providersId)">添加</el-button>
+        <el-button type="primary" @click="$router.push('/service/settlement/contract/edit?serviceProviderId=' + serviceProviderId)">添加</el-button>
       </div>
     </div>
     <el-table
@@ -62,7 +62,7 @@
             v-else
             type="primary"
             size="mini"
-            @click="$router.push('/service/settlement/contract/edit?id=' + scope.row.id + '&providersId=' + providersId + '&isCheck=1')"
+            @click="$router.push('/service/settlement/contract/edit?id=' + scope.row.id + '&serviceProviderId=' + serviceProviderId + '&isCheck=1')"
           >查看</el-button>
         </template>
       </el-table-column>
@@ -96,12 +96,12 @@ export default {
     }
   },
   computed: {
-    providersId() {
-      return this.$route.query.providersId || false
+    serviceProviderId() {
+      return this.$route.query.serviceProviderId || false
     }
   },
   mounted() {
-    if (this.providersId) {
+    if (this.serviceProviderId) {
       this.getList()
     }
   },
@@ -110,7 +110,7 @@ export default {
       const form = Object.assign(this.listQuery, {
         contractStartDate: obj ? obj[0] : '',
         contractEndDate: obj ? obj[1] : '',
-        providersId: this.providersId || ''
+        serviceProviderId: this.serviceProviderId || ''
       })
       const { data } = await getContractList(form)
       this.list = data.results
@@ -118,7 +118,7 @@ export default {
     handleSelectionChange() {},
     checkout(row) {
       console.log(row)
-      this.$router.push('/service/settlement/contract/edit?id=' + row.row.id + '&providersId=' + this.providersId)
+      this.$router.push('/service/settlement/contract/edit?id=' + row.row.id + '&serviceProviderId=' + this.serviceProviderId)
     }
   }
 }

+ 10 - 10
src/views/serviceSettlement/goods/index.vue

@@ -54,7 +54,7 @@
       @pagination="getShopProduct"
     />
     <!--  选择商品弹窗 -->
-    <goods-dialog v-if="goodsDialogVisible" ref="shopDialog" @confirm="handleAddGoodsConfirm" @cancel="handleCancel" />
+    <goods-dialog v-if="goodsDialogVisible" ref="goodsDialog" @confirm="handleAddGoodsConfirm" @cancel="handleCancel" />
   </div>
 </template>
 
@@ -69,7 +69,7 @@ export default {
     return {
       isLoading: true,
       listQuery: {
-        providerId: this.$route.query.providersId,
+        serviceProviderId: this.$route.query.serviceProviderId,
         productName: '',
         productId: '',
         pageNum: 1,
@@ -81,8 +81,8 @@ export default {
     }
   },
   computed: {
-    providersId() {
-      return this.$route.query.providersId || false
+    serviceProviderId() {
+      return this.$route.query.serviceProviderId || false
     }
   },
   created() {
@@ -103,12 +103,12 @@ export default {
       data.forEach((ele) => {
         productIds.push(ele.productId)
       })
-      this.addProducts({ providerId: this.providersId, productIds: productIds.join(',') })
+      this.addProducts({ serviceProviderId: this.serviceProviderId, productIds: productIds.join(',') })
     },
     // 取消选择供商品
     handleCancel() {
       this.goodsDialogVisible = false
-      this.$refs.shopDialog.visible = false
+      this.$refs.goodsDialog.visible = false
     },
     // 获取服务商商品列表
     async getProvidersProducts() {
@@ -131,7 +131,7 @@ export default {
           title: '',
           message: '添加成功',
           type: 'success'
-        });
+        })
         this.getList()
       } catch (error) {
         console.log(error)
@@ -150,15 +150,15 @@ export default {
         this.$message.info('已取消删除操作')
       }
     },
-    // 调用删除广告图
+    // 调用删除商品
     async delProduct(row) {
       try {
-        await delProduct({ providerId: this.providersId, productId: row.productId })
+        await delProduct({ serviceProviderId: this.serviceProviderId, productId: row.productId })
         this.$notify({
           title: '',
           message: '删除成功',
           type: 'success'
-        });
+        })
         this.getList()
       } catch (error) {
         console.log(error)

+ 204 - 0
src/views/serviceSettlement/group/group-team.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary" @click="dialogFormVisible = true"> 添加成员 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660">
+      <el-table-column prop="serviceProviderId" label="成员ID" align="center" width="120" />
+      <el-table-column prop="name" label="成员名称" align="center">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.serviceProviderId === row.leaderId" type="primary" size="mini" style="margin:5px;">管理员</el-tag>
+          <span>{{ row.name }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="mobile" label="联系电话" align="center" />
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 5px;" :disabled="row.serviceProviderId === row.leaderId ? true : false" @click="handleUpdateLeader(row)">设为管理员</el-button>
+          <el-button type="danger" size="mini" style="margin: 2px" :disabled="row.serviceProviderId === row.leaderId ? true : false" @click="handleDelete(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20, 30, 100]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="groupList"
+    />
+    <!--  选择成员弹窗 -->
+    <group-dialog v-if="dialogFormVisible" ref="groupDialog" @confirm="handleAddGroupConfirm" @cancel="handleCancel" />
+  </div>
+</template>
+
+<script>
+import { groupList, addGroup, delGroup, updateLeader } from '@/api/serviceSettlement/group'
+import GroupDialog from '../components/group-dialog'
+export default {
+  name: 'GroupTeam',
+  components: { GroupDialog },
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      listQuery: {
+        id: this.$route.query.teamId,
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      dialogFormVisible: false
+    }
+  },
+  computed: {
+    leaderId() {
+      return this.$route.query.leaderId * 1 || 0
+    },
+    teamId() {
+      return this.$route.query.teamId * 1 || 0
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取行为记录列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.groupList()
+    },
+    // 确认选择成员
+    handleAddGroupConfirm(data) {
+      console.log('data', data)
+      const serviceProviderIds = []
+      data.forEach((ele) => {
+        serviceProviderIds.push(ele.serviceProviderId)
+      })
+      this.addGroup({ teamId: this.teamId, spId: serviceProviderIds.join(',') })
+    },
+    // 取消选择供成员
+    handleCancel() {
+      this.dialogFormVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 获取团队成员列表
+    async groupList() {
+      try {
+        this.isLoading = true
+        const res = await groupList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 保存添加成员
+    async addGroup(params) {
+      try {
+        await addGroup(params)
+        this.dialogFormVisible = false
+        this.$notify({
+          title: '',
+          message: '添加成功',
+          type: 'success'
+        })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作设置管理员
+    async handleUpdateLeader(row) {
+      try {
+        await this.$confirm('确定设置该成员为管理员吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.updateLeader(row)
+      } catch (error) {
+        this.$message.info('已取消删除操作')
+      }
+    },
+    // 调用设置管理员
+    async updateLeader(row) {
+      try {
+        await updateLeader({ leaderId: row.serviceProviderId, teamId: this.teamId })
+        this.$notify({
+          title: '',
+          message: '设置成功~',
+          type: 'success'
+        })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作删除成员
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该成员吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delGroup(row)
+      } catch (error) {
+        this.$message.info('已取消删除操作')
+      }
+    },
+    // 调用删除成员
+    async delGroup(row) {
+      try {
+        await delGroup({ spId: row.serviceProviderId, teamId: this.teamId })
+        this.$notify({
+          title: '',
+          message: '删除成功',
+          type: 'success'
+        })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.tags-sms {
+  width: 100%;
+  height: auto;
+  font-size: 16px;
+  color: #333333;
+  line-height: 28px;
+  box-sizing: border-box;
+  padding: 5px;
+}
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 160px;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 204 - 0
src/views/serviceSettlement/group/index.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary" @click="handleAdd">添加团队</el-button>
+      </div>
+    </div>
+
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      border
+      :default-sort="{ prop: 'frequency', order: 'descending' }"
+    >
+      <!--<el-table-column type="selection" width="55" align="center" />-->
+      <el-table-column
+        label="序号"
+        type="index"
+        sortable="custom"
+        align="center"
+        width="50"
+      />
+      <el-table-column prop="name" label="团队名称" align="center" />
+      <el-table-column prop="leaderName" label="团队管理员" align="center" />
+      <el-table-column prop="groupCount" label="成员数量" align="center" />
+      <el-table-column prop="createdTime" label="添加时间" align="center" />
+      <el-table-column label="操作" align="center" width="300">
+        <template slot-scope="{ row }">
+          <div class="labelCenter">
+            <el-button type="primary" size="mini" @click="handleEdit(row)">编辑</el-button>
+            <el-button
+              type="primary"
+              size="mini"
+              @click="$router.push(`/service/group/group-team?teamId=${row.teamId}`)"
+            >团队成员</el-button>
+            <el-button type="danger" size="mini" @click="handleDele(row)">删除</el-button>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 添加团队 -->
+    <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible" width="500px">
+      <el-form ref="dataForm" :rules="rules" :model="form" label-position="right" label-width="120px">
+        <el-form-item label="团队名称:" prop="name">
+          <el-input v-model="form.name" type="text" placeholder="请输入团队名称" maxlength="20" style="width:300px;" />
+        </el-form-item>
+        <el-form-item v-if="!isEdit" label="团队管理员:" prop="leaderId">
+          <el-select v-model="form.leaderId" placeholder="请选择团队管理员" style="width:300px;">
+            <el-option value="" label="请选择" />
+            <el-option
+              v-for="item in sellerList"
+              :key="item.serviceProviderId"
+              :label="item.name"
+              :value="item.serviceProviderId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取消</el-button>
+        <el-button type="primary" @click="handleAddGroup">确定</el-button>
+      </div>
+    </el-dialog>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { getTeamList, addTeam, delTeam, getServiceList } from '@/api/serviceSettlement/group'
+import serviceMixin from '../mixin/index'
+
+export default {
+  mixins: [serviceMixin],
+  data() {
+    return {
+      listQuery: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      time: '',
+      showQrImag: false,
+      isLoading: false,
+      exportDialogVisible: false,
+      list: [],
+      indexMethod: 1,
+      total: 0,
+      selectType: 0,
+      providerItem: {},
+      dialogFormVisible: false,
+      form: {
+        name: '', // 小组名称
+        leaderId: '' // 小组管理员ID
+      },
+      rules: {
+        name: [{ required: true, message: '请输入小组名称', trigger: 'blur' }],
+        leaderId: [{ required: true, message: '请选择小组管理员', trigger: 'blur' }]
+      },
+      sellerList: [],
+      dialogTitle: '添加团队',
+      isEdit: false
+    }
+  },
+  mounted() {
+    this.getServiceList()
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      const { data } = await getTeamList(this.listQuery)
+      this.list = data.results
+      this.total = data.totalRecord
+    },
+    // 获取协销列表选项
+    async getServiceList() {
+      try {
+        const res = await getServiceList({ pageNum: 1, pageSize: 100 })
+        this.sellerList = res.data.results
+      } catch (error) {
+        console.warn(error)
+      }
+    },
+    // 添加团队
+    handleAdd() {
+      this.isEdit = false
+      this.dialogTitle = '添加团队'
+      this.form = { name: '', leaderId: '' }
+      this.dialogFormVisible = true
+    },
+    // 添加取消
+    closeDialog() {
+      this.$refs.dataForm.resetFields()
+      this.dialogFormVisible = false
+    },
+    // 编辑团队
+    handleEdit(row) {
+      this.isEdit = true
+      this.dialogTitle = '编辑团队'
+      this.form = { ...this.form, ...row }
+      this.dialogFormVisible = true
+    },
+    // 保存重置新密码
+    async handleAddGroup() {
+      try {
+        await this.$refs.dataForm.validate()
+        this.addTeam(this.form)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 保存团队
+    async addTeam(params) {
+      await addTeam(params)
+      this.$notify.success({ title: '添加团队成功~', message: '' })
+      this.closeDialog()
+      this.getList()
+    },
+    // 删除团队
+    async handleDele(row) {
+      try {
+        console.log('row', row)
+        await this.$confirm('确定删除该团队吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.delTeam(row)
+      } catch (error) {
+        this.$notify.info({ title: '用户取消操作~', message: '' })
+      }
+    },
+    // 调用删除专区
+    async delTeam(row) {
+      try {
+        await delTeam({ id: row.teamId })
+        this.$notify.success({ title: '删除成功~', message: '' })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.labelCenter {
+  display: grid;
+  grid-template-rows: repeat(1, 1fr);
+  grid-template-columns: repeat(3, 1fr);
+  grid-gap: 5px;
+  .el-button {
+    width: 80px;
+    margin-left: 0;
+  }
+}
+</style>

+ 75 - 24
src/views/serviceSettlement/list/edit.vue

@@ -19,9 +19,19 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="服务商品牌:" prop="brandName" v-if="formLabelAlign.serviceLevel === 4 || formLabelAlign.serviceLevel === 5">
+      <el-form-item v-if="formLabelAlign.serviceLevel === 4 || formLabelAlign.serviceLevel === 5" label="服务商品牌:" prop="brandName">
         <el-input v-model="formLabelAlign.brandName" placeholder="服务商品牌" />
       </el-form-item>
+      <el-form-item label="服务商类型:" prop="serviceCategory">
+        <el-select v-model="formLabelAlign.serviceCategory" placeholder="服务商类型">
+          <el-option
+            v-for="i in serviceCategoryList"
+            :key="i.id"
+            :label="i.value"
+            :value="i.id"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="服务商地区:" prop="address">
         <!--<el-cascader
           ref="cascader"
@@ -34,12 +44,12 @@
           :placeholder="cascaderPlaceholder"
           @change="handleChange"
         />-->
-        <el-input v-model="formLabelAlign.address" placeholder="请服务商地区" />
+        <el-input v-model="formLabelAlign.address" placeholder="请输入服务商地区" />
       </el-form-item>
-      <el-form-item label="服务商类型:" prop="serviceCategory">
-        <el-select v-model="formLabelAlign.serviceCategory" placeholder="服务商类型">
+      <el-form-item label="服务商分类:" prop="insiderFlag">
+        <el-select v-model="formLabelAlign.insiderFlag" placeholder="请选择服务商分类">
           <el-option
-            v-for="i in serviceCategoryList"
+            v-for="i in insiderFlagList"
             :key="i.id"
             :label="i.value"
             :value="i.id"
@@ -60,6 +70,14 @@
           oninput="value=value.replace(/[^\d]/g, '')"
         />
       </el-form-item>
+      <template v-if="editType === 'add'">
+        <el-form-item label="登录密码:" prop="password">
+          <el-input v-model="formLabelAlign.password" placeholder="请输入登录密码" />
+        </el-form-item>
+        <el-form-item label="确认密码:" prop="confirmPassword">
+          <el-input v-model="formLabelAlign.confirmPassword" placeholder="请确认登录密码" />
+        </el-form-item>
+      </template>
       <el-form-item label="简介图:" prop="textRelateds">
         <image-upload
           :limit="6"
@@ -76,7 +94,7 @@
           placeholder="请输入内容"
         />
       </el-form-item>
-      <el-form-item v-if="id" label="资格证书:">
+      <el-form-item v-if="serviceProvidersId" label="资格证书:">
         <el-image style="width: 200px;" :src="qualificationImage" :preview-src-list="[qualificationImage]" />
       </el-form-item>
       <el-form-item label="资料上传:" prop="infoRelateds">
@@ -91,7 +109,7 @@
           @remove="handleRemove($event, 'infoRelateds')"
         />
       </el-form-item>
-      <div v-if="!id">
+      <template v-if="!serviceProvidersId">
         <el-form-item label="合同:">
           (由于是添加新服务商,必须添加合同,后续可去合同列表编辑及添加)
         </el-form-item>
@@ -124,7 +142,7 @@
             @remove="contractHandleRemove($event)"
           />
         </el-form-item>
-      </div>
+      </template>
       <el-form-item>
         <el-button type="primary" @click="submitForm('formLabelAlign')">保存</el-button>
         <el-button @click="$router.back()">返回</el-button>
@@ -151,9 +169,21 @@ export default {
   },
   mixins: [serviceMixin],
   data() {
+    // 自定义密码一致性验证规则
+    const validateConfirmPassword = (rule, value, callback) => {
+      if (value !== this.formLabelAlign.password) {
+        callback(new Error('两次输入的密码不一致!'))
+      } else {
+        callback()
+      }
+    }
     return {
+      editType: 'add',
       formLabelAlign: {
         address: '',
+        serviceLevel: '',
+        insiderFlag: '',
+        serviceCategory: '',
         brandName: '',
         infoRelateds: [],
         area: [],
@@ -174,15 +204,23 @@ export default {
         ],
         brandName: [{ required: true, message: '请输入服务商品牌', trigger: 'blur' }],
         address: [{ required: true, message: '请输入地址', trigger: 'blur' }],
+        password: [{ required: true, message: '请输入登录密码', trigger: 'blur' }],
+        confirmPassword: [
+          { required: true, message: '请再次输入密码', trigger: 'blur' },
+          { validator: validateConfirmPassword, trigger: 'blur' } // 使用自定义校验器
+        ],
         serviceLevel: [
           { required: true, message: '请选择服务商级别', trigger: 'change' }
         ],
-        //splitCode: [{ required: true, message: '请输入联系服务商分账号', trigger: 'blur' }],
+        // splitCode: [{ required: true, message: '请输入联系服务商分账号', trigger: 'blur' }],
         mobile: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
         linkMan: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
         serviceCategory: [
           { required: true, message: '请选择服务商类型', trigger: 'change' }
         ],
+        insiderFlag: [
+          { required: true, message: '请选择服务商分类', trigger: 'change' }
+        ],
         textRelateds: [{ required: true, message: '请上传简介图', trigger: 'change' }],
         contract: {
           contractId: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
@@ -201,8 +239,8 @@ export default {
   },
   computed: {
     ...mapGetters(['userId', 'username', 'fullName', 'phone']),
-    id() {
-      return this.$route.query.id || false
+    serviceProvidersId() {
+      return this.$route.query.serviceProviderId || false
     },
     cascaderPlaceholder() {
       return this.cascaderDisplay ? this.formLabelAlign.address : '请选择所在区域'
@@ -230,18 +268,19 @@ export default {
     }
   },
   mounted() {
-    if (this.id) {
+    if (this.serviceProvidersId) {
+      this.editType = this.$route.query.type || 'edit'
       this.getInfo()
     }
   },
   methods: {
     async getInfo() {
-      const { data } = await getProviderDetail({ providersId: this.id })
+      const { data } = await getProviderDetail({ serviceProvidersId: this.serviceProvidersId })
       this.formLabelAlign = data
       this.infoList = data.infoRelateds.map((e, i) => ({ name: e.fileName, response: { data: e.image }}))
       this.textRelateds = data.textRelateds.map((e, i) => ({ uid: i, url: e.image }))
-      this.formLabelAlign.area = data.address.split('/').map(e => e.trim())
       this.qualificationImage = data.qualificationImage
+      this.formLabelAlign.area = data.address.split('/').map(e => e.trim())
     },
     // 地区选择
     handleChange($event) {
@@ -255,22 +294,34 @@ export default {
     contractHandleRemove($event) {
       this.formLabelAlign.contract.contractRelateds = $event.fileList.map(e => ({ image: e.response?.data || '', fileName: e.name }))
     },
+    // 提交保存
     submitForm(form) {
-      console.log(this.formLabelAlign)
       this.$refs[form].validate(async(valid) => {
         if (valid) {
-          try {
-            delete this.formLabelAlign.area
-            const form = Object.assign(this.formLabelAlign, { createBy: this.fullName })
-            await addProvider(form)
-            this.$message({ type: 'success', message: '添加成功' })
-            this.$router.back()
-          } catch (e) {
-            console.warn(e)
-          }
+          this.$confirm('是否提交保存数据?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log('formLabelAlign', this.formLabelAlign)
+            this.addProvider(this.formLabelAlign)
+          })
         }
       })
     },
+    // 保存
+    async addProvider(params) {
+      try {
+        delete params.area
+        delete params.confirmPassword
+        const form = Object.assign(params, { createBy: this.fullName })
+        await addProvider(form)
+        this.$notify.success({ title: '保存成功~', message: '' })
+        this.$router.back()
+      } catch (e) {
+        console.warn(e)
+      }
+    },
     beforeUpload(file) {
       console.log(file)
       if (file.size / 1024 / 1024 < 50) {

+ 122 - 58
src/views/serviceSettlement/list/index.vue

@@ -6,7 +6,7 @@
         <span>服务商名称:</span>
         <el-input
           v-model="listQuery.name"
-          placeholder="关键词"
+          placeholder="服务商名称"
           clearable
           @keyup.enter.native="getList"
           @clear="getList"
@@ -39,7 +39,7 @@
         <span>资格证书编号:</span>
         <el-input
           v-model="listQuery.qualificationId"
-          placeholder="关键词"
+          placeholder="资格证书编号"
           clearable
           @keyup.enter.native="getList"
           @clear="getList"
@@ -61,7 +61,6 @@
       <div class="filter-control">
         <el-button type="primary" @click="getList">查询</el-button>
         <el-button type="primary" @click="$router.push('/service/settlement/edit')">添加</el-button>
-        <el-button type="primary" @click="batchOffline(3)">下线</el-button>
         <el-button type="primary" @click="batchOffline(1)">下载资格证书</el-button>
         <el-button type="primary" @click="batchOffline(2)">下载二维码</el-button>
       </div>
@@ -73,79 +72,86 @@
       :data="list"
       border
       :default-sort="{ prop: 'frequency', order: 'descending' }"
-      @selection-change="handleSelectionChange"
     >
-      <!--<el-table-column type="selection" width="55" align="center" />-->
-      <el-table-column
-        label="序号"
-        type="index"
-        sortable="custom"
-        align="center"
-        width="50"
-      />
+      <el-table-column prop="serviceProviderId" label="ID" align="center" width="60" />
       <el-table-column prop="name" label="服务商名称" align="center" />
-      <el-table-column prop="serviceLevel" label="服务商级别" align="center">
+      <el-table-column prop="mobile" label="手机号" align="center" width="120" />
+      <el-table-column prop="insiderFlag" label="服务商分类" align="center" width="120">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.insiderFlag === 1" type="info" size="mini">外部服务商</el-tag>
+          <el-tag v-else type="primary" size="mini">内部服务商</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="serviceLevel" label="服务商级别" align="center" width="120">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.serviceLevel === 1" type="success" effect="dark" size="mini">一级</el-tag>
-          <el-tag v-if="row.serviceLevel === 2" type="success" effect="dark" size="mini">二级</el-tag>
-          <el-tag v-if="row.serviceLevel === 3" type="success" effect="dark" size="mini">三级</el-tag>
-          <el-tag v-if="row.serviceLevel === 4" type="success" effect="dark" size="mini">品牌特约</el-tag>
-          <el-tag v-if="row.serviceLevel === 5" type="success" effect="dark" size="mini">品牌指定</el-tag>
+          <el-tag v-if="row.serviceLevel === 1" type="success" size="mini">一级</el-tag>
+          <el-tag v-if="row.serviceLevel === 2" type="success" size="mini">二级</el-tag>
+          <el-tag v-if="row.serviceLevel === 3" type="success" size="mini">三级</el-tag>
+          <el-tag v-if="row.serviceLevel === 4" type="success" size="mini">品牌特约</el-tag>
+          <el-tag v-if="row.serviceLevel === 5" type="success" size="mini">品牌指定</el-tag>
         </template>
       </el-table-column>
-      <el-table-column prop="serviceCategory" label="服务商类型" align="center">
+      <el-table-column prop="serviceCategory" label="服务商类型" align="center" width="120">
         <template slot-scope="scope">
           <div>
             {{ scope.row.serviceCategory == "1" ? "个人" : "企业" }}
           </div>
         </template>
       </el-table-column>
-      <el-table-column prop="serviceCategory" label="服务商分账号" align="center">
+      <el-table-column prop="serviceCategory" label="服务商分账号" align="center" width="120">
         <template slot-scope="{ row }">
           <div>
             {{ row.splitCode ? row.splitCode : "--" }}
           </div>
         </template>
       </el-table-column>
-      <el-table-column prop="contractStartDate" label="授权起始日期" align="center" />
-      <el-table-column prop="contractEndDate" label="授权截止日期" align="center" />
-      <el-table-column prop="status" label="状态" align="center" width="100">
-        <template slot-scope="scope">
-          <div>
-            已{{ scope.row.status === 90 ? "上线" : "下线" }}
-          </div>
+      <el-table-column prop="contractStartDate" label="授权起始日期" align="center" width="120" />
+      <el-table-column prop="contractEndDate" label="授权截止日期" align="center" width="120" />
+      <el-table-column prop="status" label="状态" align="center" width="140">
+        <template slot-scope="{ row }">
+          <el-tag v-if="row.status === 90" type="success" size="small">已上线</el-tag>
+          <el-tag v-else type="danger" size="small">已下线</el-tag>
+          <el-button v-if="row.status === 91" type="primary" size="mini" @click="handleStatus({ serviceProviderId: row.serviceProviderId, status: row.status })">
+            上线
+          </el-button>
+          <el-button v-else type="primary" size="mini" @click="handleStatus({ serviceProviderId: row.serviceProviderId, status: row.status })">
+            下线
+          </el-button>
         </template>
       </el-table-column>
-      <el-table-column prop="updateTime" label="添加时间" align="center" />
-      <el-table-column prop="createBy" label="创建人" align="center" />
-      <el-table-column label="操作" align="center" width="200">
+      <el-table-column prop="addTime" label="添加时间" align="center" width="100" />
+      <el-table-column prop="createBy" label="创建人" align="center" width="100" />
+      <el-table-column label="操作" align="center" width="300">
         <template slot-scope="{ row }">
           <div class="labelCenter">
             <el-button
-              type="primary"
+              type="success"
               size="mini"
-              @click="handleStatus({ userIds: row.userId, status: row.status })"
-            >{{ row.status === 91 ? "上线" : "下线" }}</el-button>
+              @click="$router.push('/service/settlement/edit?type=edit&serviceProviderId=' + row.serviceProviderId)"
+            >编辑</el-button>
+            <el-button type="success" size="mini" @click="showQrCode(row)">二维码</el-button>
             <el-button
-              type="primary"
+              type="success"
               size="mini"
-              @click="$router.push('/service/settlement/edit?id=' + row.id)"
-            >编辑</el-button>
-            <el-button type="primary" size="mini" @click="showQrCode(row)">二维码</el-button>
+              @click="$router.push('/service/settlement/club/list?serviceProviderId=' + row.serviceProviderId)"
+            >
+              机构详情
+            </el-button>
             <el-button
               type="primary"
               size="mini"
-              @click="
-                $router.push('/service/settlement/contract/list?providersId=' + row.id)
-              "
-            >合同管理</el-button>
+              @click="$router.push('/service/settlement/contract/list?serviceProviderId=' + row.serviceProviderId)"
+            >
+              合同管理
+            </el-button>
             <el-button
               type="primary"
               size="mini"
-              @click="
-                $router.push('/service/settlement/goods/list?providersId=' + row.id)
-              "
-            >商品管理</el-button>
+              @click="$router.push('/service/settlement/goods/list?serviceProviderId=' + row.serviceProviderId)"
+            >
+              商品管理
+            </el-button>
+            <el-button type="danger" size="mini" @click="handleChangePassword(row)">重置密码</el-button>
           </div>
         </template>
       </el-table-column>
@@ -158,14 +164,28 @@
       @showQrCode="showQrCode"
     />
 
-    <el-dialog title="选择服务商" :visible.sync="exportDialogVisible" width="70%">
+    <el-dialog title="选择服务商" :visible.sync="exportDialogVisible" width="70%" top="8vh">
       <service-list-selector
         v-if="exportDialogVisible"
         @cancel="onSelectorCancel"
         @confirm="onSelectorConfirm"
       />
     </el-dialog>
-
+    <!-- 重置密码 -->
+    <el-dialog title="重置密码" :visible.sync="dialogFormVisible" width="440px">
+      <el-form ref="dataForm" :rules="rules" :model="form" label-position="right" label-width="100px">
+        <el-form-item label="新密码:" prop="password">
+          <el-input v-model="form.password" type="text" placeholder="请输入新密码" maxlength="20" />
+        </el-form-item>
+        <el-form-item label="确认新密码:" prop="confirmPassword">
+          <el-input v-model="form.confirmPassword" type="text" placeholder="请再次确认新密码" maxlength="20" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取消</el-button>
+        <el-button type="primary" @click="handleSavePassword">确定</el-button>
+      </div>
+    </el-dialog>
     <!-- 页码 -->
     <pagination
       :total="total"
@@ -179,7 +199,7 @@
 <script>
 import QrCode from '../components/CmQrcode/index.vue'
 import ServiceListSelector from '../components/ServiceListSelector.vue'
-import { getProviderList, updatedStatus } from '@/api/serviceSettlement/service'
+import { getProviderList, updatedStatus, updatePassword } from '@/api/serviceSettlement/service'
 import serviceMixin from '../mixin/index'
 
 export default {
@@ -189,10 +209,20 @@ export default {
   },
   mixins: [serviceMixin],
   data() {
+    // 自定义密码一致性验证规则
+    const validateConfirmPassword = (rule, value, callback) => {
+      if (value !== this.form.password) {
+        callback(new Error('两次输入的密码不一致!'))
+      } else {
+        callback()
+      }
+    }
     return {
       listQuery: {
         pageNum: 1,
         pageSize: 10,
+        name: '',
+        qualificationId: '',
         serviceCategory: '',
         serviceLevel: ''
       },
@@ -204,7 +234,20 @@ export default {
       indexMethod: 1,
       total: 0,
       selectType: 0,
-      providerItem: {}
+      providerItem: {},
+      dialogFormVisible: false,
+      form: {
+        id: '',
+        password: '', // 新密码
+        confirmPassword: '' // 确认新密码
+      },
+      rules: {
+        password: [{ required: true, message: '请输入新密码', trigger: 'blur' }],
+        confirmPassword: [
+          { required: true, message: '请再次输入新密码', trigger: 'blur' },
+          { validator: validateConfirmPassword, trigger: 'blur' } // 使用自定义校验器
+        ]
+      }
     }
   },
   mounted() {
@@ -215,7 +258,7 @@ export default {
       const form = Object.assign(this.listQuery, {
         contractStartDate: obj ? obj[0] : '',
         contractEndDate: obj ? obj[1] : '',
-        providersId: this.providersId || ''
+        serviceProviderId: this.serviceProviderId || ''
       })
       const { data } = await getProviderList(form)
       this.list = data.results
@@ -232,7 +275,6 @@ export default {
       this.selectType = type
       this.exportDialogVisible = true
     },
-    handleSelectionChange() {},
     async handleStatus($event) {
       this.$confirm(`是否${$event.status === 91 ? '上线' : '下线'}该服务商?`, '提示', {
         confirmButtonText: '确定',
@@ -241,14 +283,11 @@ export default {
       }).then(async() => {
         try {
           const data = await updatedStatus({
-            userIds: $event.userIds,
+            serviceProviderId: $event.serviceProviderId,
             status: $event.status === 91 ? 90 : 91
           })
           if (data.code === 0) {
-            this.$message({
-              message: '更新成功',
-              type: 'success'
-            })
+            this.$notify.success({ title: '操作成功~', message: '' })
             this.getList()
           }
         } catch (error) {
@@ -256,6 +295,31 @@ export default {
         }
       })
     },
+    // 重置密码
+    handleChangePassword(row) {
+      this.form = { ...this.form, ...row }
+      this.dialogFormVisible = true
+    },
+    // 保存重置新密码
+    async handleSavePassword() {
+      try {
+        await this.$refs.dataForm.validate()
+        this.updatePassword(this.form)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 重置密码
+    async updatePassword(params) {
+      await updatePassword(params)
+      this.$notify.success({ title: '重置密码成功~', message: '' })
+      this.closeDialog()
+    },
+    // 添加取消
+    closeDialog() {
+      this.$refs.dataForm.resetFields()
+      this.dialogFormVisible = false
+    },
     onSelectorCancel() {
       this.exportDialogVisible = false
     },
@@ -288,7 +352,7 @@ export default {
       const toSelect = {
         3: () =>
           this.handleStatus({
-            userIds: $event.map((e) => e.userId).join(','),
+            serviceProviderId: $event.map((e) => e.userId).join(','),
             status: 90
           }),
         1: () =>
@@ -312,7 +376,7 @@ export default {
 .labelCenter {
   display: grid;
   grid-template-rows: repeat(2, 1fr);
-  grid-template-columns: repeat(2, 1fr);
+  grid-template-columns: repeat(3, 1fr);
   grid-gap: 10px;
   .el-button {
     width: 80px;

+ 1 - 0
src/views/serviceSettlement/mixin/index.js

@@ -11,6 +11,7 @@ export default {
         { id: 4, value: '品牌特约' },
         { id: 5, value: '品牌指定' }
       ],
+      insiderFlagList: [{ id: '', value: '请选择' }, { id: 0, value: '内部服务商' }, { id: 1, value: '外部服务商' }],
       serviceCategoryList: [{ id: '', value: '请选择' }, { id: 1, value: '个人' }, { id: 2, value: '企业' }]
     }
   },

+ 185 - 0
src/views/serviceSettlement/task/edit.vue

@@ -0,0 +1,185 @@
+<template>
+  <div class="app-container">
+    <el-form
+      ref="form"
+      label-width="120px"
+      :model="form"
+      :rules="rules"
+    >
+      <el-form-item label="推广任务标题:" prop="title">
+        <el-input v-model="form.title" placeholder="请输入推广标题" maxlength="50" style="width: 630px;" />
+      </el-form-item>
+      <el-form-item label="推广关联商品:" prop="productId">
+        <store-item v-if="selectStore" :select-store="selectStore" />
+        <el-button type="primary" @click="handleAddPros">{{ selectStore ? '选择商品' : '关联商品' }}</el-button>
+      </el-form-item>
+      <el-form-item label="推广任务赏金:" prop="reward">
+        <el-input v-model="form.reward" placeholder="请输入推广任务赏金" maxlength="5" style="width: 220px;">
+          <template slot="append">元</template>
+        </el-input>
+      </el-form-item>
+      <el-form-item label="推广起始日期:" prop="startTime">
+        <el-date-picker
+          v-model="form.startTime"
+          type="datetime"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          placeholder="选择日期"
+        />
+      </el-form-item>
+      <el-form-item label="推广截止日期:" prop="endTime">
+        <el-date-picker
+          v-model="form.endTime"
+          type="datetime"
+          placeholder="选择日期"
+          value-format="yyyy-MM-dd HH:mm:ss"
+        />
+      </el-form-item>
+      <el-form-item label="推广任务封面:" prop="topPic">
+        <image-upload
+          :limit="1"
+          :image-list="fileList"
+          @success="handleImageSuccess($event, 'textRelateds')"
+          @remove="handleImageRemove($event, 'textRelateds')"
+        />
+      </el-form-item>
+      <el-form-item label="推广任务内容:" prop="content">
+        <editor-input v-model="form.content" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="submitForm('form')">保存</el-button>
+        <el-button @click="$router.back()">返回</el-button>
+      </el-form-item>
+    </el-form>
+    <!--  选择商品弹窗 -->
+    <goods-dialog v-if="goodsDialogVisible" ref="goodsDialog" @confirm="handleAddGoodsConfirm" @cancel="handleCancel" />
+  </div>
+</template>
+
+<script>
+import ImageUpload from '@/components/UploadImage/index.vue'
+import GoodsDialog from '../components/task-goods-dialog.vue'
+import StoreItem from '../components/task-Item.vue'
+import EditorInput from '@/components/Editor/index.vue'
+import { addTask, getTaskDetail } from '@/api/serviceSettlement/task'
+import { mapGetters } from 'vuex'
+
+export default {
+  components: {
+    ImageUpload,
+    GoodsDialog,
+    StoreItem,
+    EditorInput
+  },
+  data() {
+    return {
+      editType: 'add',
+      selectStore: null,
+      goodsDialogVisible: false,
+      fileList: [],
+      form: {
+        title: '', // 推广标题
+        reward: '', // 推广赏金
+        productId: '', // 关联商品Id
+        shopId: '', // 供应商Id
+        topPic: '', // 宣传封面
+        startTime: '', // 开始时间
+        endTime: '', // 结束时间
+        content: '' // 文本内容
+      },
+      rules: {
+        title: [{ required: true, message: '请输入推广标题', trigger: 'blur' }],
+        reward: [{ required: true, message: '请设置推广赏金', trigger: 'blur' }],
+        topPic: [{ required: true, message: '请上传封面图', trigger: 'blur' }],
+        productId: [{ required: true, message: '请选择商品', trigger: 'blur' }],
+        startTime: [
+          { required: true, message: '请选择推广起始时间', trigger: 'change' }
+        ],
+        endTime: [
+          { required: true, message: '请选择推广结束时间', trigger: 'change' }
+        ],
+        content: [{ required: true, message: '请添加推广内容', trigger: 'blur' }]
+      }
+    }
+  },
+  computed: {
+    ...mapGetters(['userId', 'username', 'fullName', 'phone']),
+    taskId() {
+      return this.$route.query.taskId || false
+    }
+  },
+  mounted() {
+    this.editType = this.$route.query.type || 'edit'
+    if (this.taskId) {
+      this.getInfo()
+    }
+  },
+  methods: {
+    async getInfo() {
+      const { data } = await getTaskDetail({ taskId: this.taskId })
+      this.form = data
+      const file = { uid: data.id, url: data.topPic }
+      this.fileList.push(file)
+    },
+    // 确认选择商品
+    handleAddGoodsConfirm(data) {
+      console.log('data', data[0])
+      const vForm = {
+        productId: data[0].productId,
+        shopId: data[0].shopId
+      }
+      this.form = Object.assign(this.form, vForm)
+      this.selectStore = data[0]
+      this.goodsDialogVisible = false
+    },
+    // 添加商品
+    handleAddPros() {
+      this.goodsDialogVisible = true
+    },
+    // 取消选择供商品
+    handleCancel() {
+      this.goodsDialogVisible = false
+      this.$refs.goodsDialog.visible = false
+    },
+    // 提交保存
+    submitForm(form) {
+      this.$refs[form].validate(async(valid) => {
+        if (valid) {
+          this.$confirm('是否提交保存数据?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            console.log('form', this.form)
+            this.addTask(this.form)
+          })
+        }
+      })
+    },
+    // 保存推广
+    async addTask(params) {
+      this.btnLoading = true
+      await addTask(params)
+      this.$notify.success({ title: '添加推广成功~', message: '' })
+      this.$router.back()
+    },
+    handleImageSuccess(file) {
+      console.log(file)
+      this.form.topPic = file.response.data
+    },
+    handleImageRemove(file) {
+      console.log(file)
+      this.form.topPic = ''
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+::v-deep .el-textarea__inner {
+  width: 500px;
+}
+::v-deep .el-form {
+  width: 750px;
+  margin: 0 auto;
+}
+</style>

+ 129 - 0
src/views/serviceSettlement/task/index.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>服务商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商商名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList">查询</el-button>
+        <el-button type="primary" @click="$router.push('/service/task/edit')">添加推广任务</el-button>
+      </div>
+    </div>
+
+    <el-table
+      ref="table"
+      v-loading="isLoading"
+      :data="list"
+      height="660"
+      border
+      :default-sort="{ prop: 'frequency', order: 'descending' }"
+    >
+      <el-table-column label="序号" align="center" width="50">
+        <template slot-scope="scope">{{ scope.$index + 1 }}</template>
+      </el-table-column>
+      <el-table-column prop="title" label="推广标题" align="center" />
+      <el-table-column prop="reward" label="推广赏金" align="center">
+        <template slot-scope="{ row }">
+          {{ row.reward }}元
+        </template>
+      </el-table-column>
+      <el-table-column prop="topPic" label="推广封面" align="center" width="120">
+        <template slot-scope="{ row }">
+          <img v-if="row.topPic" :src="row.topPic" alt="" style="width: 50px; height: 50px" />
+          <span v-else>---</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="shopName" label="关联供应商" align="center" />
+      <el-table-column prop="startTime" label="任务起始日期" align="center" />
+      <el-table-column prop="endTime" label="任务截止日期" align="center" />
+      <el-table-column prop="addTime" label="添加时间" align="center" />
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <div class="labelCenter">
+            <el-button
+              type="success"
+              size="mini"
+              @click="$router.push('/service/task/edit?type=edit&taskId=' + row.id)"
+            >编辑</el-button>
+            <el-button
+              type="primary"
+              size="mini"
+              @click="$router.push('/service/task/task-details?taskId=' + row.id)"
+            >
+              下发服务商
+            </el-button>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getTaskList"
+    />
+  </div>
+</template>
+
+<script>
+import { getTaskList } from '@/api/serviceSettlement/task'
+
+export default {
+  data() {
+    return {
+      listQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        shopName: ''
+      },
+      isLoading: false,
+      list: [],
+      total: 0
+    }
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    // 获取行为记录列表
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.getTaskList()
+    },
+    // 获取服务商商品列表
+    async getTaskList() {
+      try {
+        this.isLoading = true
+        const res = await getTaskList(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.labelCenter {
+  display: grid;
+  grid-template-rows: repeat(1, 1fr);
+  grid-template-columns: repeat(2, 1fr);
+  grid-gap: 10px;
+  .el-button {
+    margin: 0px;
+  }
+}
+</style>

+ 257 - 0
src/views/serviceSettlement/task/task-details.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>服务商名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="服务商名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.bindMobile"
+          placeholder="手机号"
+          maxlength="11"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+        <el-button type="primary" @click="dialogFormVisible = true"> 分配服务商 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%" height="660">
+      <el-table-column prop="serviceProviderId" fixed label="服务商ID" align="center" width="80" />
+      <el-table-column prop="name" fixed label="服务商名称" align="center" />
+      <el-table-column prop="mobile" label="手机号" align="center">
+        <template slot-scope="{ row }">
+          {{ row.mobile ? row.mobile : '---' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="auditStatus" label="任务状态" align="center" width="120">
+        <template slot-scope="{ row }">
+          <template v-if="row.receiveFlag === 1">
+            <el-tag v-if="row.auditStatus === 0" type="info" size="small">已领取</el-tag>
+            <el-tag v-if="row.auditStatus === 1" type="warning" size="small">待审核</el-tag>
+            <el-tag v-if="row.auditStatus === 2" type="success" size="small">审核通过</el-tag>
+            <el-tag v-if="row.auditStatus === 3" type="danger" size="small">审核未通过</el-tag>
+          </template>
+          <template v-else>
+            <el-tag type="info" size="small">未领取</el-tag>
+          </template>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button v-if="row.auditStatus === 1" v-permission="'task:list:examine'" type="primary" size="mini" @click="handleExamine(row)">审核</el-button>
+          <el-button type="danger" size="mini" @click="handleDelete(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20, 30, 100]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getTaskProvider"
+    />
+    <!--  选择成员弹窗 -->
+    <task-service-dialog v-if="dialogFormVisible" ref="taskServiceDdialog" @confirm="handleConfirm" @cancel="handleCancel" />
+    <!-- 审核任务完成情况 -->
+    <el-dialog title="审核任务" :visible.sync="dialogVisible" width="700px" top="8vh">
+      <el-form ref="dataForm" label-position="top" label-width="120px" style="height: 600px;overflow-y: scroll;">
+        <el-form-item label="推广截图:">
+          <div class="block">
+            <el-image v-for="(item, index) in taskInfo.images" :key="index" :src="item" />
+          </div>
+        </el-form-item>
+        <el-form-item v-if="taskInfo.taskDesc" label="备注:">
+          <p v-text="taskInfo.taskDesc"></p>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="danger" @click="handleAudit(3)"> 审核不通过 </el-button>
+        <el-button type="primary" @click="handleAudit(2)"> 审核通过 </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getTaskProvider, assignTask, taskProviderDel, getTaskaAudit } from '@/api/serviceSettlement/task'
+import TaskServiceDialog from '../components/task-service-dialog'
+export default {
+  name: 'TaskDetails',
+  components: { TaskServiceDialog },
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      time: [],
+      time1: [],
+      listQuery: {
+        taskId: this.$route.query.taskId,
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0,
+      dialogFormVisible: false,
+      renewCustome: {
+        id: '',
+        status: ''
+      },
+      rules: {
+        status: [{ required: true, message: '请设置统计状态', trigger: 'blur' }]
+      },
+      dialogVisible: false,
+      taskInfo: {}
+    }
+  },
+  computed: {
+    taskId() {
+      return this.$route.query.taskId * 1 || 0
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取行为记录列表
+    getList() {
+      this.list = []
+      this.isLoading = true
+      this.listQuery.pageNum = 1
+      this.getTaskProvider()
+    },
+    // 获取分配服务商列表
+    async getTaskProvider() {
+      try {
+        const res = await getTaskProvider(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 确认选择分配的服务商
+    handleConfirm(data) {
+      console.log('data', data)
+      const serviceProviderIds = []
+      data.forEach((ele) => {
+        serviceProviderIds.push(ele.serviceProviderId)
+      })
+      this.assignTask({ id: this.taskId, serviceProviderIds: serviceProviderIds.join(',') })
+    },
+    // 取消选择选择分配服务商
+    handleCancel() {
+      this.dialogFormVisible = false
+      this.$refs.shopDialog.visible = false
+    },
+    // 确认分配服务商
+    async assignTask(params) {
+      try {
+        await assignTask(params)
+        this.dialogFormVisible = false
+        this.$notify({
+          title: '',
+          message: '分配成功',
+          type: 'success'
+        })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作审核任务
+    handleExamine(row) {
+      this.taskInfo = row
+      this.dialogVisible = true
+    },
+    // 操作审核
+    handleAudit(status) {
+      const params = {
+        auditStatus: status,
+        taskId: this.taskId,
+        serviceProviderId: this.taskInfo.serviceProviderId
+      }
+      this.getTaskaAudit(params)
+    },
+    // 调用审核
+    async getTaskaAudit(params) {
+      try {
+        await getTaskaAudit(params)
+        this.$notify({
+          title: '',
+          message: '操作成功',
+          type: 'success'
+        })
+        this.getList()
+        this.dialogVisible = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 操作删除服务商
+    async handleDelete(row) {
+      try {
+        await this.$confirm('确定删除该服务商吗?', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        this.taskProviderDel(row)
+      } catch (error) {
+        this.$message.info('已取消删除操作')
+      }
+    },
+    // 调用删除成员
+    async taskProviderDel(row) {
+      try {
+        await taskProviderDel({ serviceProviderId: row.serviceProviderId, taskId: this.taskId })
+        this.$notify({
+          title: '',
+          message: '删除成功',
+          type: 'success'
+        })
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  float: left;
+}
+.uploader-tips {
+  position: absolute;
+  bottom: 0;
+  left: 160px;
+  line-height: 28px;
+  color: red;
+  margin: 0;
+}
+</style>

+ 4 - 4
src/views/sys/error/404.vue

@@ -2,10 +2,10 @@
   <div class="wscn-http404-container">
     <div class="wscn-http404">
       <div class="pic-404">
-        <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
-        <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
-        <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
-        <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
+        <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" />
+        <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" />
+        <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" />
+        <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" />
       </div>
       <div class="bullshit">
         <div class="bullshit__oops">OOPS!</div>

+ 1 - 1
src/views/sys/icons/index.vue

@@ -28,7 +28,7 @@
                 {{ generateElementIconCode(item) }}
               </div>
               <div class="icon-item">
-                <i :class="'el-icon-' + item" />
+                <i :class="'el-icon-' + item"></i>
                 <span>{{ item }}</span>
               </div>
             </el-tooltip>

+ 2 - 2
src/views/sys/menus/form.vue

@@ -5,7 +5,7 @@
       <el-form ref="menuFrom" :model="menu" :rules="rules" label-width="150px">
         <el-form-item label="上级菜单:" prop="parentId">
           <el-input v-model="parentTitle" readonly />
-          <input v-model="menu.parentId" type="hidden">
+          <input v-model="menu.parentId" type="hidden" />
         </el-form-item>
         <el-form-item label="菜单名称:" prop="title">
           <el-input v-model="menu.title" />
@@ -22,7 +22,7 @@
         <el-form-item label="前端图标:" prop="icon">
           <el-input v-model="menu.icon" style="width: 80%" placeholder="系统图标里拷贝Class" />
           <template>
-            <i v-if="isElementIcon(menu.icon)" :class="menu.icon" />
+            <i v-if="isElementIcon(menu.icon)" :class="menu.icon"></i>
             <svg-icon v-else-if="menu.icon" :icon-class="menu.icon" />
           </template>
         </el-form-item>

+ 66 - 66
src/views/user/club-portrait/components/bar-echarts.vue

@@ -5,160 +5,160 @@
 </template>
 
 <script>
-import echarts from "echarts";
+import echarts from 'echarts'
 export default {
   props: {
     title: {
       type: String,
-      default: () => "myEcharts",
+      default: () => 'myEcharts'
     },
     optionData: {
       type: Object,
-      default: () => ({}),
-    },
+      default: () => ({})
+    }
   },
   data() {
     return {
       timeTicket: null,
       chart: null,
-      optionData1: {},
-    };
+      optionData1: {}
+    }
   },
   watch: {
     optionData: {
       handler(val) {
         if (val) {
-          clearInterval(this.timeTicket);
-          this.timeTicket = null;
-          this.optionData1 = val;
-          console.log("option-data888888888", this.optionData1);
+          clearInterval(this.timeTicket)
+          this.timeTicket = null
+          this.optionData1 = val
+          console.log('option-data888888888', this.optionData1)
           this.initChart()
         }
       },
       deep: true,
-      immediate: true,
-    },
+      immediate: true
+    }
   },
   mounted() {
     // 初始化图表
-    this.chart = echarts.init(this.$refs["echarts"]);
+    this.chart = echarts.init(this.$refs['echarts'])
     // 初始设置和配置...
-    this.initChart(); // 调用函数设置初始图表
+    this.initChart() // 调用函数设置初始图表
+  },
+  beforeDestroy() {
+    // 组件销毁前,销毁图表实例
+    if (this.chart) {
+      this.chart.dispose()
+    }
   },
   methods: {
     initChart() {
       // 如果图表实例存在,先清空数据和配置项(可选)
       if (this.chart) {
-        this.chart.clear(); // 清空当前图表
+        this.chart.clear() // 清空当前图表
       }
       const option = {
         title: {
-          text: this.optionData1.name,
+          text: this.optionData1.name
         },
         tooltip: {
-          trigger: "axis",
+          trigger: 'axis',
           axisPointer: {
-            type: "shadow",
-          },
+            type: 'shadow'
+          }
         },
         legend: {
-          show: false,
+          show: false
         },
         grid: {
-          left: "3%",
-          right: "4%",
-          bottom: "3%",
-          containLabel: true,
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
         },
         xAxis: {
-          type: "value",
+          type: 'value',
           splitLine: {
             show: true,
             lineStyle: {
               opacity: 0.2,
-              color: "#DCDCDC",
-            },
+              color: '#DCDCDC'
+            }
           },
           boundaryGap: [0, 0.01],
           axisLabel: {
             show: true,
             textStyle: {
-              color: "#DCDCDC", //更改坐标轴文字颜色
-              fontSize: 12, //更改坐标轴文字大小
-            },
+              color: '#DCDCDC', // 更改坐标轴文字颜色
+              fontSize: 12 // 更改坐标轴文字大小
+            }
           },
           axisTick: {
-            //轴网格,在xAxis或yAxis根下
+            // 轴网格,在xAxis或yAxis根下
             lineStyle: {
               width: 1,
-              color: "#3333333",
-              type: "solid",
-            },
-          },
+              color: '#3333333',
+              type: 'solid'
+            }
+          }
         },
         yAxis: {
-          type: "category",
+          type: 'category',
           splitLine: {
-            show: false,
+            show: false
           },
           axisLabel: {
             show: true,
             textStyle: {
-              color: "#333333", //更改坐标轴文字颜色
-              fontSize: 12, //更改坐标轴文字大小
+              color: '#333333', // 更改坐标轴文字颜色
+              fontSize: 12 // 更改坐标轴文字大小
             },
             margin: 8,
-            formatter: function (params) {
-              var val = "";
+            formatter: function(params) {
+              var val = ''
               if (params.length > 6) {
-                val = params.substr(0, 6) + "...";
-                return val;
+                val = params.substr(0, 6) + '...'
+                return val
               } else {
-                return params;
+                return params
               }
-            },
+            }
           },
           axisTick: {
-            //轴网格,在xAxis或yAxis根下
+            // 轴网格,在xAxis或yAxis根下
             show: false,
             lineStyle: {
               width: 1,
-              color: "#333333",
-              type: "solid",
-            },
+              color: '#333333',
+              type: 'solid'
+            }
           },
-          data: this.optionData1.yAxisData,
+          data: this.optionData1.yAxisData
         },
         series: [
           {
-            type: "bar",
+            type: 'bar',
             name: this.optionData1.name,
             data: this.optionData1.xAxisData,
             barBorderRadius: [10, 0, 0, 0],
             itemStyle: {
               fontSize: 14,
               color: this.optionData1.color,
-              barBorderRadius: 20, // 鼠标悬停时的圆角大小
-            },
-          },
-        ],
-      };
+              barBorderRadius: 20 // 鼠标悬停时的圆角大小
+            }
+          }
+        ]
+      }
       // 使用刚指定的配置项和数据显示图表。
       if (this.chart) {
-        this.chart.setOption(option);
+        this.chart.setOption(option)
       }
-    },
-  },
-  beforeDestroy() {
-    // 组件销毁前,销毁图表实例
-    if (this.chart) {
-      this.chart.dispose();
     }
-  },
-};
+  }
+}
 </script>
 
-<style lang="scss" scoped>
+<style lang='scss' scoped>
 .echarts-content {
   width: 100%;
   height: 400px;

+ 15 - 15
src/views/user/club-portrait/components/club-dialog.vue

@@ -116,7 +116,7 @@
           <div class="main-row">
             <span>门头照:</span>
             <a href="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" target="_blank">
-              <img src="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" alt="">
+              <img src="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" alt="" />
             </a>
           </div>
         </div>
@@ -149,7 +149,7 @@
           <div class="main-row">
             <span>营业执照:</span>
             <a href="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" target="_blank">
-              <img src="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" alt="">
+              <img src="https://img.caimei365.com/group1/M00/00/42/rB-lGGHEEDCAHRaLAAL6r7YS4OA918.jpg" alt="" />
             </a>
           </div>
         </div>
@@ -173,28 +173,28 @@ export default {
     }
   },
   props: {
-    dialogType:{
-        type:Number,
-        default:1
+    dialogType: {
+      type: Number,
+      default: 1
     }
   },
   data() {
     return {
       visible: true,
-      title:'机构活跃信息',
-      form:{
-        name:'测试的热季卡',
-        linkMan:'ASDASD',
-        contractMobile:'13565444444',
-        address:'吉林省延边朝鲜族自治州延吉市',
-        businessLicenseImage:'https://img.caimei365.com/group1/M00/00/C9/rB-lF2YfnY2AImFYAAWYX3X0D6Q546.jpg',
-        medicalPracticeLicenseImg:'https://img.caimei365.com/group1/M00/00/C9/rB-lF2YfnY2AImFYAAWYX3X0D6Q546.jpg',
+      title: '机构活跃信息',
+      form: {
+        name: '测试的热季卡',
+        linkMan: 'ASDASD',
+        contractMobile: '13565444444',
+        address: '吉林省延边朝鲜族自治州延吉市',
+        businessLicenseImage: 'https://img.caimei365.com/group1/M00/00/C9/rB-lF2YfnY2AImFYAAWYX3X0D6Q546.jpg',
+        medicalPracticeLicenseImg: 'https://img.caimei365.com/group1/M00/00/C9/rB-lF2YfnY2AImFYAAWYX3X0D6Q546.jpg'
       }
     }
   },
   computed: {},
   created() {
-    if(this.dialogType === 2){
+    if (this.dialogType === 2) {
       this.title = '机构资料'
     }
   },
@@ -213,7 +213,7 @@ export default {
     handleCanle() {
       // 取消弹窗
       this.$emit('cancel')
-    },
+    }
   }
 }
 </script>

+ 18 - 19
src/views/user/club-portrait/components/hot-tips.vue

@@ -15,37 +15,36 @@ export default {
       type: Array,
       default: () => [
         {
-          logo: "https://baidu.jpg",
-          bandName:
-            "百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度百度",
-          top: 1,
-        },
-      ],
-    },
+          logo: 'https://baidu.jpg',
+          bandName: '百度百度百度百度百度百度百度百度百度',
+          top: 1
+        }
+      ]
+    }
   },
   computed: {
     reloadData() {
-      const d = this.keywordData;
+      const d = this.keywordData
       return d.map((e) => {
         if (e) {
-          return e;
-        } else return {};
-      });
-    },
+          return e
+        } else return {}
+      })
+    }
   },
   methods: {
     isObj(str) {
-      return typeof str === "object";
+      return typeof str === 'object'
     },
     is_picture(str) {
-      const r = new RegExp(/\.(png|jpe?g|gif|svg|JPEG)(\?.*)?$/);
-      return r.test(str);
-    },
-  },
-};
+      const r = new RegExp(/\.(png|jpe?g|gif|svg|JPEG)(\?.*)?$/)
+      return r.test(str)
+    }
+  }
+}
 </script>
 
-<style scoped lang="scss">
+<style scoped lang='scss'>
 .hot-container {
   border-radius: 12px;
   overflow: hidden;

+ 35 - 35
src/views/user/club-portrait/components/pei-echarts.vue

@@ -5,24 +5,24 @@
 </template>
 
 <script>
-import echarts from "echarts";
+import echarts from 'echarts'
 export default {
   props: {
     title: {
       type: String,
-      default: () => "myEcharts",
+      default: () => 'myEcharts'
     },
     optionData: {
       type: Object,
-      default: () => ({}),
-    },
+      default: () => ({})
+    }
   },
   data() {
     return {
       timeTicket: null,
       chart: null,
-      optionData1: {},
-    };
+      optionData1: {}
+    }
   },
   watch: {
     optionData: {
@@ -31,20 +31,26 @@ export default {
           clearInterval(this.timeTicket)
           this.timeTicket = null
           this.optionData1 = val
-          console.log("option-data111111111", this.optionData1)
+          console.log('option-data111111111', this.optionData1)
           this.initChart()
         }
       },
       deep: true,
-      immediate: true,
-    },
+      immediate: true
+    }
   },
   mounted() {
     // 初始化图表
-    this.chart = echarts.init(this.$refs["echarts"])
+    this.chart = echarts.init(this.$refs['echarts'])
     // 初始设置和配置...
     this.initChart() // 调用函数设置初始图表
   },
+  beforeDestroy() {
+    // 组件销毁前,销毁图表实例
+    if (this.chart) {
+      this.chart.dispose()
+    }
+  },
   methods: {
     initChart() {
       // 如果图表实例存在,先清空数据和配置项(可选)
@@ -53,59 +59,53 @@ export default {
       }
       const option = {
         title: {
-          text: this.optionData1.name,
+          text: this.optionData1.name
         },
         tooltip: {
-          trigger: "item",
+          trigger: 'item'
         },
         legend: {
-          orient: "vertical",
-          right: "2%",
-          top: "20%",
+          orient: 'vertical',
+          right: '2%',
+          top: '20%',
           textStyle: {
             fontSize: 14,
-            color: "#333333",
-          },
+            color: '#333333'
+          }
         },
         color: this.optionData1.color,
         series: [
           {
             name: this.optionData1.name,
-            type: "pie",
-            radius: "55%",
-            center: ["25%", "50%"],
+            type: 'pie',
+            radius: '55%',
+            center: ['25%', '50%'],
             avoidLabelOverlap: false,
             emphasis: {
               itemStyle: {
                 shadowBlur: 10,
                 shadowOffsetX: 0,
-                shadowColor: "rgba(0, 0, 0, 0.5)",
-              },
+                shadowColor: 'rgba(0, 0, 0, 0.5)'
+              }
             },
             label: {
               show: false,
-              position: "center",
+              position: 'center'
             },
-            data: this.optionData1.seriesData,
-          },
-        ],
-      };
+            data: this.optionData1.seriesData
+          }
+        ]
+      }
       // 使用刚指定的配置项和数据显示图表。
       if (this.chart) {
         this.chart.setOption(option)
       }
-    },
-  },
-  beforeDestroy() {
-    // 组件销毁前,销毁图表实例
-    if (this.chart) {
-      this.chart.dispose()
     }
   }
-};
+}
 </script>
 
-<style lang="scss" scoped>
+<style lang='scss' scoped>
 .echarts-content {
   width: 100%;
   height: 400px;

+ 128 - 129
src/views/user/club-portrait/index.vue

@@ -87,16 +87,16 @@
 </template>
 
 <script>
-import SelectTime from "./components/select-time";
-import PieEcharts from "./components/pei-echarts.vue";
-import BarEcharts from "./components/bar-echarts.vue";
-import HotTips from "./components/hot-tips.vue";
-import ClubDialog from "./components/club-dialog.vue";
+import SelectTime from './components/select-time'
+import PieEcharts from './components/pei-echarts.vue'
+import BarEcharts from './components/bar-echarts.vue'
+import HotTips from './components/hot-tips.vue'
+import ClubDialog from './components/club-dialog.vue'
 import {
   getIns_statistics,
   getIns_orderTrends,
-  getIns_accessStatistics,
-} from "@/api/mallPortrait/disitrib";
+  getIns_accessStatistics
+} from '@/api/mallPortrait/disitrib'
 
 export default {
   components: {
@@ -104,121 +104,121 @@ export default {
     SelectTime,
     PieEcharts,
     BarEcharts,
-    HotTips,
+    HotTips
   },
   data() {
     return {
-      clubId:'',
-      clubName:'',
+      clubId: '',
+      clubName: '',
       dialogVisible: false,
       dialogType: 1,
       keywordData: [
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌logo", label: 1 },
-        { text: "品牌名称", label: 1 },
-        { text: "品牌名称", label: 1 },
-        { text: "品牌名称", label: 1 },
-        { text: "TOP", label: 0 },
-        { text: "TOP", label: 0 },
-        { text: "TOP", label: 0 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌logo', label: 1 },
+        { text: '品牌名称', label: 1 },
+        { text: '品牌名称', label: 1 },
+        { text: '品牌名称', label: 1 },
+        { text: 'TOP', label: 0 },
+        { text: 'TOP', label: 0 },
+        { text: 'TOP', label: 0 }
       ],
       storeColumns: [
-        { text: "商品图片", label: "image", labelWidth: 80 },
-        { text: "商品名称", label: "name" },
-        { text: "TOP", label: "top", labelWidth: 80 },
+        { text: '商品图片', label: 'image', labelWidth: 80 },
+        { text: '商品名称', label: 'name' },
+        { text: 'TOP', label: 'TOP', labelWidth: 80 }
       ],
       keyColumns: [
-        { text: "搜索词", labelWidth: 120 },
-        { text: "TOP", label: "top" },
+        { text: '搜索词', labelWidth: 120 },
+        { text: 'TOP', label: 'TOP' }
       ],
       dataValue: {
         // 机构活跃度统计
         clubActivityCount: {
           data: {
             不活跃机构: 0,
-            活跃机构: 0,
-          },
+            活跃机构: 0
+          }
         },
         // 订单统计
         orderData: {
           orderTotalNum: 1,
-          name: "订单总量",
-          color: ["#3aa0ff", "#36cbcb", "#fad337", "#4dcb73", "#f2637b", "#975fe4"],
+          name: '订单总量',
+          color: ['#3aa0ff', '#36cbcb', '#fad337', '#4dcb73', '#f2637b', '#975fe4'],
           seriesData: [
             {
-              name: "普通订单 【100%】 【1个】",
-              value: 1,
+              name: '普通订单 【100%】 【1个】',
+              value: 1
             },
             {
-              name: "二手订单 【 0 %】 【0个】",
-              value: 0,
-            },
-          ],
+              name: '二手订单 【 0 %】 【0个】',
+              value: 0
+            }
+          ]
         },
         // 咨询记录
         consultData: {
           data: {
-            name: "咨询记录",
+            name: '咨询记录',
             yAxisData: [
-              "撒肯德基阿拉基",
-              "水阿斯达四大光",
-              "士大夫撒多发生的",
-              "asdas阿瑟的",
-              "奥术大师大所多",
-              "第三方士大夫",
-              "从VB餐补v",
-              "水电费",
+              '撒肯德基阿拉基',
+              '水阿斯达四大光',
+              '士大夫撒多发生的',
+              'asdas阿瑟的',
+              '奥术大师大所多',
+              '第三方士大夫',
+              '从VB餐补v',
+              '水电费'
             ],
             xAxisData: [1, 1, 2, 2, 2, 3, 5, 6],
-            color: "#FF5B00",
+            color: '#FF5B00'
           },
-          count: 11,
+          count: 11
         },
         keyWordsData: {
           data: {
-            name: "搜索关键词",
+            name: '搜索关键词',
             yAxisData: [
-              "热玛吉",
-              "水光",
-              "超清秀",
-              "黄金微针",
-              "LDM",
-              "皮秒",
-              "检测",
-              "水光仪",
+              '热玛吉',
+              '水光',
+              '超清秀',
+              '黄金微针',
+              'LDM',
+              '皮秒',
+              '检测',
+              '水光仪'
             ],
             xAxisData: [1, 1, 2, 2, 2, 3, 5, 6],
-            color: "#07c160",
+            color: '#07c160'
           },
-          count: 11,
+          count: 11
         },
         // 访问记录
         accessData: {
           data: {
-            name: "访问记录",
+            name: '访问记录',
             yAxisData: [
-              "玩儿玩儿",
-              "让他也让他也让他",
-              "日也同样",
-              "水电费",
-              "发挂号费",
-              "CVBS",
-              "不你们部门",
-              "电饭锅电饭锅",
+              '玩儿玩儿',
+              '让他也让他也让他',
+              '日也同样',
+              '水电费',
+              '发挂号费',
+              'CVBS',
+              '不你们部门',
+              '电饭锅电饭锅'
             ],
             xAxisData: [1, 1, 2, 2, 2, 3, 5, 6],
-            color: "#6585fa",
+            color: '#6585fa'
           },
-          count: 11,
+          count: 11
         },
         // 机构新增趋势
         addClubCount: {},
@@ -230,75 +230,74 @@ export default {
         remarks: {
           data: {
             游客咨询: 0,
-            机构咨询: 0,
-          },
+            机构咨询: 0
+          }
         },
         // 热门品牌
         brandProductSalesRecords: [],
         // 热门商品
         productSalesRecords: [],
         // 热搜词
-        keywords: [],
+        keywords: []
       },
       timeList: [
         {
           id: 5,
-          content: "近一周",
+          content: '近一周'
         },
         {
           id: 2,
-          content: "近1月",
+          content: '近1月'
         },
         {
           id: 3,
-          content: "近6月",
+          content: '近6月'
         },
         {
           id: 4,
-          content: "近1年",
-        },
-      ],
-    };
+          content: '近1年'
+        }
+      ]
+    }
   },
   created() {
     this.clubId = this.$route.query.clubId
     this.clubName = this.$route.query.clubName
-
   },
   methods: {
-    handleRouter(type){
+    handleRouter(type) {
       switch (type) {
         case 1: // 咨询记录
           this.$router.push({
             path: '/user/consult/list',
-            query: { clubName:this.clubName,clubId: this.clubId }
+            query: { clubName: this.clubName, clubId: this.clubId }
           })
           break
         case 2: // 行为记录
           this.$router.push({
             path: '/user/record-list',
-            query: { type:'first',corporateName:this.clubName,clubId: this.clubId }
+            query: { type: 'first', corporateName: this.clubName, clubId: this.clubId }
           })
           break
       }
     },
     handleClubDialog(type) {
-      this.dialogType = type;
-      this.dialogVisible = true;
+      this.dialogType = type
+      this.dialogVisible = true
     },
     handleCancel() {
-      this.dialogVisible = false;
+      this.dialogVisible = false
     },
     /**
      * 获取机构需求
      */
     async getCulbDemand(e) {
-      const { data } = await getCulbDemand({
+      const { data } = await getIns_orderTrends({
         startCreateTime: e[0],
-        endCreateTime: e[1],
-      });
-      this.dataValue.clubActivityCount = data.clubActivityCount;
-      this.dataValue.clubCount = data.clubCount;
+        endCreateTime: e[1]
+      })
+      this.dataValue.clubActivityCount = data.clubActivityCount
+      this.dataValue.clubCount = data.clubCount
     },
     /**
      * 机构订单数据
@@ -306,49 +305,49 @@ export default {
     async getIns_statistics(e) {
       const { data } = await getIns_statistics({
         startCreateTime: e[0],
-        endCreateTime: e[1],
-      });
-      this.dataValue.clubActivityCount = data.clubActivityCount;
-      this.dataValue.clubCount = data.clubCount;
+        endCreateTime: e[1]
+      })
+      this.dataValue.clubActivityCount = data.clubActivityCount
+      this.dataValue.clubCount = data.clubCount
     },
-     /**
+    /**
      * 获取机构搜索词
      */
     async getIns_orderTrends(e) {
       const { data } = await getIns_orderTrends({
         startCreateTime: e[0],
-        endCreateTime: e[1],
-      });
-      this.dataValue.addClubCount = data.clubCount;
-      this.dataValue.clubOrder = data.clubOrder;
+        endCreateTime: e[1]
+      })
+      this.dataValue.addClubCount = data.clubCount
+      this.dataValue.clubOrder = data.clubOrder
     },
-     /**
+    /**
      * 获取机构咨询数据
      */
-    async getIns_accessStatistics(e) {
+    async getIns_accessS(e) {
       const { data } = await getIns_accessStatistics({
         startCreateTime: e[0],
-        endCreateTime: e[1],
-      });
-      this.dataValue.record = data.record;
-      this.dataValue.remarks = data.remarks;
-      this.dataValue.brandProductSalesRecords = data.brandProductSalesRecords;
-      this.dataValue.productSalesRecords = data.productSalesRecords;
-      this.dataValue.keywords = data.keywords;
+        endCreateTime: e[1]
+      })
+      this.dataValue.record = data.record
+      this.dataValue.remarks = data.remarks
+      this.dataValue.brandProductSalesRecords = data.brandProductSalesRecords
+      this.dataValue.productSalesRecords = data.productSalesRecords
+      this.dataValue.keywords = data.keywords
     },
-     /**
+    /**
      * 获取机构访问记录数据
      */
     async getIns_accessStatistics(e) {
       const { data } = await getIns_accessStatistics({
         startCreateTime: e[0],
-        endCreateTime: e[1],
-      });
-      this.dataValue.record = data.record;
-      this.dataValue.remarks = data.remarks;
-      this.dataValue.brandProductSalesRecords = data.brandProductSalesRecords;
-      this.dataValue.productSalesRecords = data.productSalesRecords;
-      this.dataValue.keywords = data.keywords;
+        endCreateTime: e[1]
+      })
+      this.dataValue.record = data.record
+      this.dataValue.remarks = data.remarks
+      this.dataValue.brandProductSalesRecords = data.brandProductSalesRecords
+      this.dataValue.productSalesRecords = data.productSalesRecords
+      this.dataValue.keywords = data.keywords
     },
     handleSelectTime(e, num) {
       const obj = {
@@ -356,12 +355,12 @@ export default {
         1: () => this.getIns_statistics(e),
         2: () => this.getIns_orderTrends(e),
         3: () => this.getIns_accessStatistics(e),
-        4: () => this.getIns_accessStatistics(e),
-      };
-      obj[num]();
-    },
-  },
-};
+        4: () => this.getIns_accessStatistics(e)
+      }
+      obj[num]()
+    }
+  }
+}
 </script>
 
 <style lang="scss" scoped>

+ 0 - 1
src/views/user/consult/detail.vue

@@ -450,7 +450,6 @@ export default {
 <style>
 .filter-container {
   padding: 10px;
-  background: #f7f7f7;
   margin: 10px 0;
 }
 .span-labels {

+ 0 - 1
src/views/user/consult/list.vue

@@ -587,7 +587,6 @@ export default {
 <style>
 .filter-container {
   padding: 10px;
-  background: #f7f7f7;
   margin: 10px 0;
 }
 .span-labels {

+ 0 - 1
src/views/user/consult/unreg-detail.vue

@@ -403,7 +403,6 @@ export default {
 <style>
 .filter-container {
   padding: 10px;
-  background: #f7f7f7;
   margin: 10px 0;
 }
 .span-labels {

+ 1 - 1
src/views/user/record/components/detail-dialog.vue

@@ -119,7 +119,7 @@ export default {
       listQuery: {
         ip: '',
         accessDate: '',
-        userId: 0,
+        userId: '',
         pageNum: 1,
         pageSize: 100
       },

+ 137 - 0
src/views/user/record/components/product-detail-dialog.vue

@@ -0,0 +1,137 @@
+<template>
+  <el-dialog
+    title="商品用户详情"
+    :visible.sync="visible"
+    width="1300px"
+    :close-on-click-modal="false"
+    :show-close="false"
+  >
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border height="500px">
+      <el-table-column prop="region" label="地区" align="center">
+        <template slot-scope="{ row }">
+          {{ row.region ? row.region : "---" }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="accessClient" label="访问客户端" align="center" />
+      <el-table-column prop="companyType" label="公司类型" align="center" />
+      <el-table-column prop="corporateName" label="机构名称" align="center">
+        <template slot-scope="{ row }">
+          {{ row.corporateName ? row.corporateName : "---" }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="contacts" label="联系人" align="center">
+        <template slot-scope="{ row }">
+          {{ row.contacts ? row.contacts : "---" }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="phoneNumber" label="手机号" align="center">
+        <template slot-scope="{ row }">
+          {{ row.phoneNumber ? row.phoneNumber : "---" }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="spName" label="所属协销" align="center" width="100">
+        <template slot-scope="{ row }">
+          {{ row.spName ? row.spName : "---" }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="lastAccessTime" label="最后访问时间" align="center" width="150" />
+      <el-table-column prop="accessDuration" label="访问时长" align="center" width="150" />
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10]"
+      :page-size="10"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="fetchBehaviorProductDetail"
+    />
+    <div slot="footer">
+      <el-button type="primary" @click="handleCanle"> 关闭 </el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { fetchBehaviorProductDetail } from '@/api/user/record/record'
+
+export default {
+  name: 'ProductDetailDialog',
+  filters: { },
+  props: {
+    detailQuery: {
+      type: Object,
+      // eslint-disable-next-line vue/require-valid-default-prop
+      default: {}
+    }
+  },
+  data() {
+    return {
+      visible: true,
+      isLoading: true,
+      listQuery: {
+        productId: '', // 商品ID
+        pageNum: 1,
+        pageSize: 10
+      },
+      list: [],
+      total: 0
+    }
+  },
+  computed: {
+
+  },
+  created() {
+    this.listQuery = { ...this.listQuery, ...this.detailQuery }
+    console.log('listQuery', this.listQuery)
+    this.getList()
+  },
+  methods: {
+    // 获取详情列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.fetchBehaviorProductDetail()
+    },
+    // 获取商品用户详情
+    async fetchBehaviorProductDetail() {
+      try {
+        this.isLoading = true
+        const res = await fetchBehaviorProductDetail(this.listQuery)
+        const data = res.data
+        this.list = data.results
+        this.total = data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    handleRelevanceShop(value) {
+      console.log('va', value.split(','))
+      return value.split(',')
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.tags-sms {
+  width: 100%;
+  height: auto;
+  font-size: 14px;
+  color: #666666;
+  line-height: 40px;
+  border-radius: 4px;
+  box-sizing: border-box;
+  padding: 5px;
+  border: 1px solid #e1e1e1;
+}
+.tags-sms .tags-sms-span {
+  font-size: 18px;
+  font-weight: bold;
+  color: #333333;
+}
+</style>

+ 3 - 3
src/views/user/record/list.vue

@@ -115,7 +115,7 @@
             />
           </el-select>
         </div>
-        <div class="filter-control">
+        <!--<div class="filter-control">
           <span>页面类型:</span>
           <el-select v-model="listQuery.pageTypes" filterable @change="getList">
             <el-option value="" label="请选择" />
@@ -123,10 +123,10 @@
               v-for="item in typesOptions"
               :key="item.id"
               :label="item.pageType"
-              :value="item.pageType"
+              :value="item.id"
             />
           </el-select>
-        </div>
+        </div>-->
         <div v-if="tabsCurrent === 1" class="filter-control">
           <span>访问日期:</span>
           <el-date-picker

+ 145 - 0
src/views/user/record/record-product-list.vue

@@ -0,0 +1,145 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部操作区域 -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>统计时间:</span>
+        <el-date-picker
+          v-model="time"
+          type="daterange"
+          unlink-panels
+          value-format="yyyy-MM-dd"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :picker-options="pickerOptions"
+          @change="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList"> 查询 </el-button>
+      </div>
+    </div>
+    <!-- 列表 -->
+    <el-table v-loading="isLoading" :data="list" border style="width: 100%">
+      <el-table-column prop="productId" label="商品ID" align="center" width="200" />
+      <el-table-column prop="productImage" label="商品图片" align="center">
+        <template slot-scope="{ row }">
+          <el-popover v-if="row.productImage" placement="top-start" title="" width="100" trigger="hover">
+            <img :src="row.productImage" alt="" style="width: 80px; height: 80px" />
+            <img slot="reference" :src="row.productImage" alt="" style="width: 80px; height: 80px" />
+          </el-popover>
+          <span v-else>---</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="productName" label="商品名称" align="center" />
+      <el-table-column prop="productCount" label="商城总浏览次数" align="center">
+        <template slot-scope="{ row }">
+          <el-link type="primary" :underline="false">【{{ row.productCount }}】次</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" style="margin: 2px" @click="handleOperate(row)"> 查看用户详情 </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[10, 20, 30, 100]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getRecordProductCount"
+    />
+    <!--  详情弹窗 -->
+    <product-detail-dialog
+      v-if="dialogVisible"
+      ref="detailDialog"
+      :detail-query="detailQuery"
+      @cancel="handleCancel"
+    />
+  </div>
+</template>
+
+<script>
+import pickerOptions from '@/utils/time-picker.js'
+import { getRecordProductCount } from '@/api/user/record/record'
+import ProductDetailDialog from './components/product-detail-dialog'
+const defaultListQuery = {
+  productId: '', // 商品ID
+  beginTime: '', // 开始日期
+  endTime: '', // 结束日期
+  pageNum: 1,
+  pageSize: 20
+}
+export default {
+  name: 'RecordProductList',
+  components: {
+    ProductDetailDialog
+  },
+  filters: {},
+  data() {
+    return {
+      isLoading: true,
+      listQuery: Object.assign({}, defaultListQuery),
+      pickerOptions,
+      time: [],
+      list: [],
+      total: 0,
+      dialogVisible: false,
+      detailQuery: {}
+    }
+  },
+  computed: {},
+  created() {
+    this.getList()
+  },
+  mounted() {},
+  methods: {
+    // 获取列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.listQuery.beginTime = this.time[0]
+      this.listQuery.endTime = this.time[1]
+      this.getRecordProductCount()
+    },
+
+    // 获取商品列表
+    async getRecordProductCount() {
+      try {
+        this.isLoading = true
+        const res = await getRecordProductCount(this.listQuery)
+        this.list = res.data.results
+        this.total = res.data.totalRecord
+        this.isLoading = false
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // 查看详情
+    handleOperate(row) {
+      this.detailQuery = { productId: row.productId }
+      this.dialogVisible = true
+    },
+    // 关闭详情弹窗
+    handleCancel() {
+      this.dialogVisible = false
+    }
+  }
+}
+</script>
+
+<style></style>