detail.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. <route lang="yaml">
  2. style:
  3. navigationBarTitleText: 设计师详情
  4. navigationBarBackgroundColor: '#fff'
  5. navigationStyle: custom
  6. </route>
  7. <script setup lang="ts">
  8. import NavbarEvo from '@/components/navbar-evo.vue'
  9. import {
  10. getFollowUpPage,
  11. getPointsCounts,
  12. getUserInfoById,
  13. getPointsOrders,
  14. getBrowseRecordCount,
  15. getBrowseRecords,
  16. getBrowseRecordRemarks,
  17. } from '@/core/libs/agent-requests'
  18. import {
  19. desinTopBg,
  20. rightArrowIcon,
  21. vipIcon,
  22. locationIcon,
  23. shareIcon,
  24. praiseIcon,
  25. messageIcon,
  26. yinyongIcon,
  27. } from '@designer-hub/assets/src/svgs'
  28. import PageHelperEvo from '@/components/page-helper-evo.vue'
  29. import { dayjs } from 'wot-design-uni'
  30. import { toHomePage } from '@/core/libs/actions'
  31. import arcBottomBlue from '@designer-hub/assets/src/libs/assets/arcBottomBlue'
  32. import link from '@designer-hub/assets/src/libs/assets/link'
  33. import { useMemberLevelsStore } from '@/store/member-levles'
  34. import { getDesignerPointsActivities } from '@/core/libs/requests'
  35. import { useUserStore } from '@/store'
  36. import { storeToRefs } from 'pinia'
  37. import Card from '@designer-hub/app/src/components/card.vue'
  38. import ListHelperEvo from '@/components/list-helper-evo.vue'
  39. // import { formatDuration } from '@designer-hub/app/src/core/utils/common'
  40. const userStore = useUserStore()
  41. const { userInfo } = storeToRefs(userStore)
  42. const memberLevelsStore = useMemberLevelsStore()
  43. const { getMemberLevelLogo } = memberLevelsStore
  44. const id = ref()
  45. const { data, run: setData } = useRequest(() => getUserInfoById(id.value))
  46. console.log('getUserInfoById', data)
  47. const active = ref('integral')
  48. const tabs = ref([
  49. { label: '数据动态', value: 'integral' },
  50. { label: '跟进记录', value: 'followUp' },
  51. // { label: '圈子动态', value: 'interact' },
  52. { label: '兑换记录', value: 'product' },
  53. ])
  54. const status = ref({ '0': '已报名', '1': '已完成', '2': '未核销', '3': '已取消', '4': '待交付' })
  55. const followUpQuery = computed(() => ({
  56. stylistId: id.value,
  57. }))
  58. const { data: browseRecordCount, run: setBrowseRecordCount } = useRequest(() =>
  59. getBrowseRecordCount(id.value),
  60. )
  61. console.log('browseRecordCount data', data)
  62. const browseRecordCountItems = computed(() => [
  63. {
  64. title: '打开次数',
  65. subTitle: '最近',
  66. value: browseRecordCount.value?.openNumber ?? 0,
  67. subValue: browseRecordCount.value?.openTime
  68. ? dayjs(browseRecordCount.value.openTime).format('YY/MM/DD')
  69. : '暂无',
  70. },
  71. {
  72. title: '浏览时长',
  73. subTitle: '本年',
  74. // 浏览时长 小于60秒,显示秒 大于60秒小于1小时,显示分钟 大于1小时小于1天,显示x小时x分钟 大于1天,显示x天x小时x分钟
  75. value: formatDuration1(browseRecordCount.value?.duration ?? 0),
  76. subValue: formatDuration1(browseRecordCount.value?.durationYear ?? 0),
  77. },
  78. {
  79. title: '发圈次数',
  80. subTitle: '本年',
  81. value: browseRecordCount.value?.circleNumber ?? 0,
  82. subValue: browseRecordCount.value?.circleNumberYear ?? 0,
  83. },
  84. {
  85. title: '主页分享数',
  86. subTitle: '本年',
  87. value: browseRecordCount.value?.homeShareNumber ?? 0,
  88. subValue: browseRecordCount.value?.homeShareNumberYear ?? 0,
  89. },
  90. {
  91. title: '主页浏览数',
  92. subTitle: '本年',
  93. value: browseRecordCount.value?.shareViewNumber ?? 0,
  94. subValue: browseRecordCount.value?.shareViewNumberYear ?? 0,
  95. },
  96. {
  97. title: '分享获客数',
  98. subTitle: '本年',
  99. value: browseRecordCount.value?.customersAcquired ?? 0,
  100. subValue: browseRecordCount.value?.customersAcquiredYear ?? 0,
  101. },
  102. ])
  103. const recentActivities = computed(() => [
  104. { label: '最近浏览品牌', value: '' },
  105. { label: '最近到店品牌', value: '' },
  106. { label: '最近浏览游学', value: '' },
  107. { label: '最近浏览活动', value: '' },
  108. ])
  109. const pointsActivitiesQuery = computed(() => ({ stylistId: id.value }))
  110. const toPointsDetails = () => {
  111. uni.navigateTo({ url: `/pages/agent/designer/points/index?id=${id.value}` })
  112. }
  113. const toOrderDetails = (it: any) => {
  114. uni.navigateTo({ url: `/pages/common/orders/detail/index?id=${it.id}` })
  115. }
  116. const toArchives = () => {
  117. uni.navigateTo({ url: '/pages/agent/designer/archives/index?id=' + id.value })
  118. }
  119. const formatDuration = (duration: number) => {
  120. if (duration < 60) {
  121. return `${duration}秒`
  122. } else if (duration < 3600) {
  123. return `${Math.floor(duration / 60)}分钟`
  124. } else if (duration < 86400) {
  125. return `${Math.floor(duration / 3600)}小时${Math.floor((duration % 3600) / 60)}分钟`
  126. } else {
  127. return `${Math.floor(duration / 86400)}天${Math.floor((duration % 86400) / 3600)}小时${Math.floor(
  128. (duration % 3600) / 60,
  129. )}分钟`
  130. }
  131. }
  132. function formatDuration1(seconds) {
  133. if (seconds < 60) {
  134. return `${seconds}秒`;
  135. } else if (seconds < 3600) {
  136. const minutes = Math.floor(seconds / 60);
  137. return `${minutes}分钟`;
  138. } else if (seconds < 86400) {
  139. const hours = Math.floor(seconds / 3600);
  140. return `${hours}小时`;
  141. } else {
  142. const days = Math.floor(seconds / 86400);
  143. return `${days}天`;
  144. }
  145. }
  146. onLoad(async (query) => {
  147. id.value = query?.id
  148. await setData()
  149. await Promise.all([setBrowseRecordCount()])
  150. console.log(browseRecordCount.value)
  151. })
  152. </script>
  153. <template>
  154. <view>
  155. <NavbarEvo placeholder transparent dark></NavbarEvo>
  156. <div class="aspect-[1.575/1] absolute left-0 right-0 top-0">
  157. <wd-img width="100%" height="100%" :src="desinTopBg" custom-class="vertical-top"></wd-img>
  158. </div>
  159. <div class="p-4 flex flex-col gap-4 relative">
  160. <div class="bg-white rounded-2xl shadow flex items-center p-4">
  161. <div class="relative">
  162. <wd-img width="64" height="64" round :src="data?.avatar"></wd-img>
  163. <div v-if="data?.retryStatus === 1" class="absolute right-0 bottom-1">
  164. <wd-img width="14" height="14" :src="link" round></wd-img>
  165. </div>
  166. </div>
  167. <div class="flex-1 ml-[11px]">
  168. <div class="flex flex-col w-[100%]">
  169. <div class="flex-row flex items-center justify-between w-full">
  170. <div class="flex-row flex items-center">
  171. <div
  172. class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[10.18px]"
  173. >
  174. <!-- 苏小萌 -->
  175. {{ data?.name }}
  176. </div>
  177. <wd-img
  178. v-if="data?.levelId"
  179. width="63"
  180. height="18.6"
  181. :src="getMemberLevelLogo(data?.levelId)"
  182. ></wd-img>
  183. </div>
  184. <div
  185. class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-snug flex items-center"
  186. @click="toHomePage(id)"
  187. >
  188. <div>个人主页</div>
  189. <wd-img width="13" height="13" :src="rightArrowIcon"></wd-img>
  190. </div>
  191. </div>
  192. </div>
  193. <div
  194. class="mt-4 px-1.5 py-1 bg-[#f0f3ff] rounded justify-center items-center gap-px inline-flex"
  195. @click="toArchives"
  196. >
  197. <div class="text-[#2357e9] text-xs font-normal font-['PingFang_SC'] leading-3">
  198. 个人档案
  199. </div>
  200. <wd-icon name="arrow-right" size="13" color="#2357e9"></wd-icon>
  201. </div>
  202. </div>
  203. </div>
  204. <div>
  205. <div class="flex items-center justify-around">
  206. <template v-for="(it, i) in tabs" :key="i">
  207. <div class="flex flex-col items-center gap-0" @click="active = it.value">
  208. <div
  209. class="text-center font-normal font-['PingFang_SC'] visible"
  210. :class="`${it.value === active ? 'text-black text-lg leading-relaxed ' : 'text-black/60 text-base leading-normal'}`"
  211. >
  212. {{ it.label }}
  213. </div>
  214. <wd-img
  215. :style="{ visibility: it.value === active ? 'visible' : 'hidden' }"
  216. width="17"
  217. height="5.6"
  218. :src="arcBottomBlue"
  219. ></wd-img>
  220. </div>
  221. </template>
  222. </div>
  223. <view class="content mt-[20px]" v-if="active === 'integral'">
  224. <Card>
  225. <div class="flex items-center justify-between">
  226. <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-relaxed">
  227. 积分动态
  228. </div>
  229. <div
  230. class="text-black/30 text-xs font-normal font-['PingFang_SC'] leading-none"
  231. @click="toPointsDetails"
  232. >
  233. 积分明细
  234. <wd-icon size="12" name="arrow-right" color="rgba(0,0,0,.3)"></wd-icon>
  235. </div>
  236. </div>
  237. <div class="mt-2 w-full h-.25 bg-[#f9f9f9]"></div>
  238. <ListHelperEvo
  239. :request="getPointsCounts"
  240. :query="{ userId: id }"
  241. content-class="grid grid-cols-3 gap-7 py-4"
  242. >
  243. <template #default="{ item }">
  244. <div class="rounded-lg aspect-[1/1] flex flex-col justify-around">
  245. <div class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-none">
  246. {{ item.title }}
  247. </div>
  248. <div class="text-black/90 text-lg font-bold font-['D-DIN_Exp'] leading-normal">
  249. {{ item.value }}
  250. </div>
  251. <div class="flex items-center gap-1">
  252. <div
  253. class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-none"
  254. >
  255. {{ item.subTitle }}
  256. </div>
  257. <div class="text-black/90 text-xs font-normal font-['D-DIN_Exp'] leading-norma">
  258. {{ item.subValue }}
  259. </div>
  260. </div>
  261. </div>
  262. </template>
  263. </ListHelperEvo>
  264. </Card>
  265. <Card custom-class="my-4">
  266. <div class="flex items-center justify-between">
  267. <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-relaxed">
  268. 使用动态
  269. </div>
  270. </div>
  271. <div class="mt-3">
  272. <ListHelperEvo
  273. :content-class="`grid grid-cols-3 gap-2.5`"
  274. :items="browseRecordCountItems"
  275. custom-class="grid grid-cols-3 gap-2.5"
  276. >
  277. <template #default="{ item }">
  278. <div class="rounded-lg aspect-[1/1] flex flex-col justify-around p-2.5">
  279. <div
  280. class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-none"
  281. >
  282. {{ item.title }}
  283. </div>
  284. <div class="text-black/90 text-lg font-bold font-['D-DIN_Exp'] leading-normal">
  285. {{ item.value }}
  286. </div>
  287. <div class="flex items-center gap-1 whitespace-nowrap">
  288. <div
  289. class="text-black/40 text-xs font-normal font-['PingFang_SC'] leading-none"
  290. >
  291. {{ item.subTitle }}
  292. </div>
  293. <div
  294. class="text-black/90 text-xs font-normal font-['D-DIN_Exp'] leading-norma"
  295. >
  296. {{ item.subValue }}
  297. </div>
  298. </div>
  299. </div>
  300. </template>
  301. </ListHelperEvo>
  302. </div>
  303. </Card>
  304. <div class="my-4">
  305. <Card>
  306. <div class="flex items-center justify-between mb-2">
  307. <div
  308. class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-relaxed"
  309. >
  310. 最近动态
  311. </div>
  312. </div>
  313. <div class="w-full h-.25 bg-[#f9f9f9]"></div>
  314. <ListHelperEvo
  315. :request="getBrowseRecordRemarks"
  316. :query="{ userId: id }"
  317. custom-class="flex flex-col gap-6"
  318. >
  319. <template #default="{ item }">
  320. <div class="mx-2 flex items-center gap-1 my-6">
  321. <div class="w-1 h-1 bg-[#2357e9] rounded-full"></div>
  322. <div
  323. class="text-black/60 text-sm font-normal font-['PingFang_SC'] leading-none"
  324. >
  325. {{ item }}
  326. </div>
  327. </div>
  328. </template>
  329. </ListHelperEvo>
  330. </Card>
  331. </div>
  332. <PageHelperEvo :request="getDesignerPointsActivities" :query="pointsActivitiesQuery">
  333. <template #default="{ source }">
  334. <div class="flex flex-col gap-4">
  335. <template v-for="(it, index) in source?.list" :key="index">
  336. <Card>
  337. <div class="">
  338. <div
  339. class="text-black/90 text-sm font-normal font-['PingFang_SC'] leading-none"
  340. >
  341. {{ it.content }}
  342. </div>
  343. <div
  344. class="text-black/30 text-xs font-normal font-['PingFang_SC'] leading-none mt-[10px]"
  345. >
  346. {{ dayjs(it.createTime).format('YYYY-MM-DD HH:mm') }}
  347. </div>
  348. </div>
  349. </Card>
  350. </template>
  351. </div>
  352. </template>
  353. </PageHelperEvo>
  354. </view>
  355. <view class="content mt-[20px]" v-if="active === 'followUp'">
  356. <PageHelperEvo :request="getFollowUpPage" :query="followUpQuery">
  357. <template #default="{ source }">
  358. <div class="flex flex-col gap-4">
  359. <template v-for="(it, index) in source?.list" :key="index">
  360. <div class="bg-white rounded-2xl shadow pl-[15px] py-[15px] flex-col gap-2 flex">
  361. <div class="flex items-center justify-between">
  362. <div
  363. class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-relaxed"
  364. >
  365. {{ dayjs(it.followTime).format('YYYY-MM-DD HH:mm') }}
  366. </div>
  367. <div
  368. class="text-white text-xs font-normal font-['PingFang_SC'] leading-none pa-[8px]"
  369. :class="`${{ 1: 'bg-[#2357E9]', 2: 'bg-[#f8b344]' }[it.followType]}`"
  370. style="border-top-left-radius: 15px; border-bottom-left-radius: 5px"
  371. >
  372. <div class="flex items-center gap-1">
  373. <div class="w-1 h-1 bg-white rounded-full border"></div>
  374. <!-- 线下拜访 -->
  375. {{ it.followTypeName }}
  376. </div>
  377. </div>
  378. </div>
  379. <div
  380. class="text-black/60 text-sm font-normal font-['PingFang_SC'] leading-normal mr-[15px] mt-[29px]"
  381. >
  382. <!-- 和周老师在工作碰了环球项目,选了瓷砖款式,后天客户交定金,订单金额初步为
  383. 304958 -->
  384. {{ it.remark }}
  385. </div>
  386. <div class="mt-[15px] flex gap-2.5">
  387. <template v-for="(src, index) in it?.imgUrl?.split(',')" :key="index">
  388. <wd-img
  389. custom-class="rounded-lg overflow-hidden"
  390. width="70"
  391. height="70"
  392. :src="src"
  393. :enable-preview="true"
  394. />
  395. </template>
  396. </div>
  397. <div class="flex items-center justify-between mt-[19px] relative">
  398. <div
  399. class="h-[25px] px-1.5 bg-[#f4f4f4] rounded-md justify-center items-center gap-1 inline-flex"
  400. v-if="it?.followType == 1"
  401. >
  402. <wd-img width="15px" height="15px" :src="locationIcon"></wd-img>
  403. <div
  404. class="text-black/40 text-[10px] font-normal font-['PingFang_SC'] leading-[25px]"
  405. >
  406. {{ it?.address.address }}
  407. </div>
  408. </div>
  409. <!-- 渠道 div 固定在右侧 -->
  410. <div
  411. class="text-black/90 text-sm font-normal font-['PingFang_SC'] leading-relaxed mr-[15px] absolute right-0"
  412. v-if="it?.brokerName"
  413. >
  414. 渠道:{{ it?.brokerName }}
  415. </div>
  416. </div>
  417. </div>
  418. </template>
  419. </div>
  420. </template>
  421. </PageHelperEvo>
  422. </view>
  423. <view class="content mt-[20px]" v-if="active === ''">
  424. <div class="bg-white rounded-2xl shadow pa-[15px] mt-[20px] flex-col gap-2 flex">
  425. <div class="flex-row flex items-center justify-between w-full">
  426. <div class="flex-row flex items-center">
  427. <div
  428. class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[10.18px]"
  429. >
  430. 苏小萌
  431. </div>
  432. <div
  433. class="h-4 bg-neutral-100 rounded-[20px] justify-start items-center inline-flex flex-row ml-[9px]"
  434. >
  435. <wd-img width="17" height="17" :src="vipIcon"></wd-img>
  436. <div
  437. class="text-black/40 text-[10px] font-normal font-['PingFang_SC'] px-[7px] leading-none"
  438. >
  439. 白银会员
  440. </div>
  441. </div>
  442. </div>
  443. <div class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[10.18px]">
  444. 4小时前
  445. </div>
  446. </div>
  447. <div class="mt-[26px]">
  448. <img
  449. class="w-[165px] h-[220px] rounded-lg"
  450. src="https://via.placeholder.com/165x220"
  451. />
  452. </div>
  453. <div
  454. class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[10.18px] mt-[29px]"
  455. >
  456. 用心做好设计,为客户创造美好家居环境
  457. </div>
  458. <div
  459. class="h-7 py-1.5 rounded-[50px] border border-black/20 justify-start items-center gap-[5px] inline-flex mt-[29px]"
  460. >
  461. <wd-img width="17" height="17" :src="yinyongIcon"></wd-img>
  462. <div class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-none">
  463. 意大利游学设计班
  464. </div>
  465. </div>
  466. <div class="flex items-center justify-between mt-[19px]">
  467. <div class="flex items-center gap-[8px]">
  468. <wd-img width="17" height="17" :src="shareIcon"></wd-img>
  469. <div class="text-black/90 text-sm font-normal font-['D-DIN_Exp'] leading-snug">
  470. 232
  471. </div>
  472. </div>
  473. <div class="flex items-center gap-[8px]">
  474. <wd-img width="17" height="17" :src="messageIcon"></wd-img>
  475. <div class="text-black/90 text-sm font-normal font-['D-DIN_Exp'] leading-snug">
  476. 232
  477. </div>
  478. </div>
  479. <div class="flex items-center gap-[8px]">
  480. <wd-img width="17" height="17" :src="praiseIcon"></wd-img>
  481. <div class="text-black/90 text-sm font-normal font-['D-DIN_Exp'] leading-snug">
  482. 232
  483. </div>
  484. </div>
  485. </div>
  486. </div>
  487. </view>
  488. <view class="content mt-[20px]" v-if="active === 'product'">
  489. <div class="flex-grow flex flex-col gap-4">
  490. <PageHelperEvo
  491. ref="pageHelperRef"
  492. :request="getPointsOrders"
  493. :query="{ orderType: 2, stylistId: id }"
  494. class="flex-grow flex flex-col"
  495. >
  496. <template #default="{ source }">
  497. <div class="flex-grow flex flex-col gap-4">
  498. <template v-for="(it, i) in source?.list" :key="i">
  499. <div @click="toOrderDetails(it)">
  500. <Card>
  501. <div class="flex gap-4">
  502. <wd-img
  503. width="94"
  504. height="94"
  505. custom-class="rounded-2xl overflow-hidden"
  506. :src="it.orderImgUrl"
  507. />
  508. <div class="flex flex-col flex-1">
  509. <div
  510. class="text-black text-base font-normal font-['PingFang_SC'] leading-normal"
  511. >
  512. {{ it.projectName }}
  513. </div>
  514. <div
  515. class="text-start text-black/40 text-sm font-normal font-['PingFang_SC'] leading-normal"
  516. >
  517. x{{ it.orderQuantity || 1 }}
  518. </div>
  519. <div class="flex-1"></div>
  520. <div
  521. class="text-start text-black/60 text-sm font-normal font-['PingFang_SC'] leading-normal"
  522. >
  523. {{ it.points }}积分
  524. </div>
  525. </div>
  526. <div>
  527. <div
  528. class="text-black/40 text-sm font-normal font-['PingFang_SC'] leading-normal"
  529. >
  530. <!-- 已完成 -->
  531. {{ status[it.orderStatus] }}
  532. </div>
  533. </div>
  534. </div>
  535. </Card>
  536. </div>
  537. </template>
  538. </div>
  539. </template>
  540. </PageHelperEvo>
  541. </div>
  542. </view>
  543. </div>
  544. </div>
  545. </view>
  546. </template>
  547. <style scoped lang="scss"></style>