Browse Source

feat(merchant): 添加设计师浏览记录统计功能

- 新增设计师浏览记录统计接口和相关数据模型- 在设计师详情页面添加浏览记录统计卡片
- 优化活动详情页面的报名人数显示逻辑
- 调整列表助手组件,支持自定义样式
EvilDragon 3 months ago
parent
commit
c53dcdf9c2

+ 83 - 0
packages/app/src/core/libs/models.ts

@@ -1007,6 +1007,89 @@ export interface AgentPoint {
   remark: string
   createTime: string
 }
+export interface BrowseRecord {
+  /* */
+  createTime: Record<string, unknown>
+
+  /* */
+  updateTime: Record<string, unknown>
+
+  /* */
+  creator: string
+
+  /* */
+  updater: string
+
+  /* */
+  deleted: boolean
+
+  /* id */
+  id: number
+
+  /* 设计师id */
+  stylistId: number
+
+  /* 设计师名称 */
+  stylistName: string
+
+  /* 业务id */
+  bizId: string
+
+  /* 业务类型:分享-1,获客-2,浏览-3等具体查看BrowseTypeEnum类,可用值:1,2,3,4,5 */
+  bizType: string
+
+  /* 分享类型,可用值:1,2 */
+  shareType: string
+
+  /* 时长:单位-秒 */
+  duration: string
+
+  /* 创建人 */
+  creatorName: string
+
+  /* 备注 */
+  remark: string
+}
+/**
+ * 设计师动态统计
+ */
+export interface BrowseRecordCountRes {
+  /* 打开次数 */
+  openNumber: number
+
+  /* 最近打开时间 */
+  openTime: string
+
+  /* 浏览时间 */
+  duration: number
+
+  /* 本年浏览时间 */
+  durationYear: number
+
+  /* 发圈次数 */
+  circleNumber: number
+
+  /* 本年发圈次数 */
+  circleNumberYear: number
+
+  /* 主页分享 */
+  homeShareNumber: number
+
+  /* 本年分享 */
+  homeShareNumberYear: number
+
+  /* 分享浏览数 */
+  shareViewNumber: number
+
+  /* 本年分享浏览数 */
+  shareViewNumberYear: number
+
+  /* 分享获客数 */
+  customersAcquired: number
+
+  /* 本年分享获客数 */
+  customersAcquiredYear: number
+}
 
 export enum DictType {
   /**

+ 1 - 3
packages/app/src/pages/home/activity/detail/index.vue

@@ -142,9 +142,7 @@ const infos = computed(() => [
     icon: user,
     title: `${activityTypes.value[type.value]}名额`,
     content: [
-      places.value === '不限制'
-        ? `不限制`
-        : `${data.value.signUpNumber}人/剩余${data.value.surplus}人`,
+      places.value === '不限制' ? `不限制` : `${places.value}人/剩余${data.value.surplus}人`,
     ],
     visable: true,
   },

+ 10 - 1
packages/merchant/src/components/list-helper-evo.vue

@@ -9,6 +9,7 @@ const props = withDefaults(
     automatic?: boolean
     mockList?: Partial<T>[]
     contentClass?: string
+    customClass?: string
   }>(),
   {
     automatic: true,
@@ -56,9 +57,17 @@ defineExpose({
   },
 })
 </script>
+<script lang="ts">
+export default {
+  options: {
+    virtualHost: true,
+    styleIsolation: 'shared',
+  },
+}
+</script>
 
 <template>
-  <div class="flex-grow relative flex flex-col">
+  <div class="flex-grow relative flex flex-col" :class="customClass">
     <div :class="contentClass">
       <template v-for="(it, index) in data" :key="index">
         <slot

+ 15 - 1
packages/merchant/src/core/libs/agent-requests.ts

@@ -13,6 +13,7 @@ import {
   DesignerPointsStatistics,
   PointsOrder,
   DesignerOrderSaleOther,
+  BrowseRecordCountRes, BrowseRecord,
 } from '@designer-hub/app/src/core/libs/models'
 import dayjs from 'dayjs'
 /**
@@ -279,6 +280,19 @@ export const getDesignerEvents = (query = {}) =>
  */
 export const updateDesignerEvent = (query: Partial<DesignerEvent>) =>
   httpPost('/app-api/member/stylist-extra-events/update', query)
+/**
+ * 获取设计师浏览记录统计
+ */
+export const getBrowseRecordCount = (stylistId: number) =>
+  httpGet<BrowseRecordCountRes>(
+    `/app-api/member/browse-record/browseRecordCount?stylistId=${stylistId}`,
+  )
+/**
+ * /app-api/member/browse-record/page 浏览记录
+ * @param query
+ */
+export const getBrowseRecords = (query = {}) =>
+  httpGet<ResPageData<BrowseRecord>>('/app-api/member/browse-record/page', query)
 
 export const getSalesOrdersCounts = (query = {}) =>
   getSalesOrdersCount(query).then((res) => ({
@@ -303,7 +317,7 @@ export const getPointsCounts = (query = {}) =>
         title: '当前剩余积分',
         value: res.data.points ?? 0,
         subTitle: '最近',
-        subValue: dayjs(res.data.pointsTime).format('YYYY/MM/DD'),
+        subValue: dayjs(res.data.pointsTime).format('YY/MM/DD'),
       },
       {
         userId: '',

+ 86 - 35
packages/merchant/src/pages/agent/designer/detail.vue

@@ -12,6 +12,8 @@ import {
   getPointsCounts,
   getUserInfoById,
   getPointsOrders,
+  getBrowseRecordCount,
+  getBrowseRecords,
 } from '@/core/libs/agent-requests'
 import {
   desinTopBg,
@@ -26,7 +28,6 @@ import {
 import PageHelperEvo from '@/components/page-helper-evo.vue'
 import { dayjs } from 'wot-design-uni'
 import { toHomePage } from '@/core/libs/actions'
-import arcBottom from '@designer-hub/assets/src/libs/assets/arcBottom'
 import arcBottomBlue from '@designer-hub/assets/src/libs/assets/arcBottomBlue'
 import { useMemberLevelsStore } from '@/store/member-levles'
 import { getDesignerPointsActivities } from '@/core/libs/requests'
@@ -50,6 +51,55 @@ const tabs = ref([
 ])
 const status = ref({ '0': '已报名', '1': '已完成', '2': '未核销', '3': '已取消', '4': '待交付' })
 const followUpQuery = ref({})
+const { data: browseRecordCount, run: setBrowseRecordCount } = useRequest(() =>
+  getBrowseRecordCount(id.value),
+)
+const browseRecordCountItems = computed(() => [
+  {
+    title: '打开次数',
+    subTitle: '最近',
+    value: browseRecordCount.value?.openNumber ?? 0,
+    subValue: browseRecordCount.value?.openTime
+      ? dayjs(browseRecordCount.value.openTime).format('YY/MM/DD')
+      : '暂无',
+  },
+  {
+    title: '浏览时长',
+    subTitle: '本年',
+    value: browseRecordCount.value?.duration ?? 0,
+    subValue: browseRecordCount.value?.durationYear ?? 0,
+  },
+  {
+    title: '发圈次数',
+    subTitle: '本年',
+    value: browseRecordCount.value?.circleNumber ?? 0,
+    subValue: browseRecordCount.value?.circleNumberYear ?? 0,
+  },
+  {
+    title: '主页分享数',
+    subTitle: '本年',
+    value: browseRecordCount.value?.homeShareNumber ?? 0,
+    subValue: browseRecordCount.value?.homeShareNumberYear ?? 0,
+  },
+  {
+    title: '分享浏览数',
+    subTitle: '本年',
+    value: browseRecordCount.value?.shareViewNumber ?? 0,
+    subValue: browseRecordCount.value?.shareViewNumberYear ?? 0,
+  },
+  {
+    title: '分享获客数',
+    subTitle: '本年',
+    value: browseRecordCount.value?.customersAcquired ?? 0,
+    subValue: browseRecordCount.value?.customersAcquiredYear ?? 0,
+  },
+])
+const recentActivities = computed(() => [
+  { label: '最近浏览品牌', value: '' },
+  { label: '最近到店品牌', value: '' },
+  { label: '最近浏览游学', value: '' },
+  { label: '最近浏览活动', value: '' },
+])
 const pointsActivitiesQuery = computed(() => ({ stylistId: id.value }))
 const toPointsDetails = () => {
   uni.navigateTo({ url: `/pages/agent/designer/points/index?id=${id.value}` })
@@ -60,9 +110,10 @@ const toOrderDetails = (it: any) => {
 const toArchives = () => {
   uni.navigateTo({ url: '/pages/agent/designer/archives/index?id=' + id.value })
 }
-onLoad((query) => {
+onLoad(async (query) => {
   id.value = query?.id
-  setData()
+  await setData()
+  await Promise.all([setBrowseRecordCount()])
 })
 </script>
 
@@ -185,37 +236,37 @@ onLoad((query) => {
                 使用动态
               </div>
             </div>
-            <div class="mt-3 grid grid-cols-3 gap-2.5">
-              <template
-                v-for="{ name, value } of [
-                  { name: '打开次数', des: '最近', value: 220 },
-                  { name: '浏览时长', des: '本年', value: 220 },
-                  { name: '发圈次数', des: '本年', value: 220 },
-                  { name: '主页分享数', des: '本年', value: 220 },
-                  { name: '分享浏览数', des: '本年', value: 220 },
-                  { name: '分享获客数', des: '本年', value: 220 },
-                ]"
-                :key="name"
+            <div class="mt-3">
+              <ListHelperEvo
+                :content-class="`grid grid-cols-3 gap-2.5`"
+                :items="browseRecordCountItems"
+                custom-class="grid grid-cols-3 gap-2.5"
               >
-                <div class="rounded-lg aspect-[1/1] flex flex-col justify-around p-2.5">
-                  <div class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-none">
-                    {{ name }}
-                  </div>
-                  <div class="text-black/90 text-lg font-bold font-['D-DIN Exp'] leading-normal">
-                    {{ value }}
-                  </div>
-                  <div class="flex items-center gap-1">
+                <template #default="{ item }">
+                  <div class="rounded-lg aspect-[1/1] flex flex-col justify-around p-2.5">
                     <div
-                      class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-none"
+                      class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-none"
                     >
-                      年新增
+                      {{ item.title }}
                     </div>
-                    <div class="text-black/90 text-xs font-normal font-['D-DIN Exp'] leading-norma">
-                      20
+                    <div class="text-black/90 text-lg font-bold font-['D-DIN Exp'] leading-normal">
+                      {{ item.value }}
+                    </div>
+                    <div class="flex items-center gap-1">
+                      <div
+                        class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-none"
+                      >
+                        {{ item.subTitle }}
+                      </div>
+                      <div
+                        class="text-black/90 text-xs font-normal font-['D-DIN Exp'] leading-norma"
+                      >
+                        {{ item.subValue }}
+                      </div>
                     </div>
                   </div>
-                </div>
-              </template>
+                </template>
+              </ListHelperEvo>
             </div>
           </Card>
 
@@ -229,18 +280,18 @@ onLoad((query) => {
                 </div>
               </div>
               <div class="w-full h-.25 bg-[#f9f9f9]"></div>
-              <div class="flex flex-col gap-6 py-5">
-                <template v-for="(it, index) in [1, 2, 3]" :key="index">
-                  <div class="h-4 relative">
+              <ListHelperEvo :items="recentActivities" custom-class="flex flex-col gap-6">
+                <template #default="{ item }">
+                  <div class="mx-2 flex items-center gap-1 my-6">
+                    <div class="w-1 h-1 bg-[#2357e9] rounded-full"></div>
                     <div
-                      class="left-[11px] top-0 absolute text-black/60 text-sm font-normal font-['PingFang_SC'] leading-none"
+                      class="text-black/60 text-sm font-normal font-['PingFang_SC'] leading-none"
                     >
-                      最近浏览品牌:Imola
+                      {{ item.label + ':' + item.value }}
                     </div>
-                    <div class="w-1 h-1 left-0 top-[6px] absolute bg-[#2357e9] rounded-full"></div>
                   </div>
                 </template>
-              </div>
+              </ListHelperEvo>
             </Card>
           </div>