index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <route lang="json">
  2. {
  3. "style": {
  4. "navigationBarTitleText": "全部设计师",
  5. "navigationBarBackgroundColor": "#fff"
  6. }
  7. }
  8. </route>
  9. <script setup lang="ts">
  10. import Card from '@/components/card.vue'
  11. import DataForm from '@/components/data-form.vue'
  12. import PageHelperEvo from '@/components/page-helper-evo.vue'
  13. import { focusOrCancel, getDesigners, updateFollowUp } from '../../core/libs/agent-requests'
  14. import { vipIcon, rightArrowIcon, filterIcon } from '@designer-hub/assets/src/svgs'
  15. import { toHomePage } from '../../core/libs/actions'
  16. import { Designer, FollowUp } from '@designer-hub/app/src/core/libs/models'
  17. import { requestToast } from '@designer-hub/app/src/core/utils/common'
  18. import { ComponentExposed } from 'vue-component-type-helpers'
  19. import { pick } from 'radash'
  20. import { useFollowUp } from '../../composables/followUp'
  21. import SectionHeading from '@designer-hub/app/src/components/section-heading.vue'
  22. import { useMemberLevelsStore } from '../../store/member-levles'
  23. import { storeToRefs } from 'pinia'
  24. import { useUserStore } from '../../store'
  25. const userStore = useUserStore()
  26. const { userInfo, isAgent, isMerchant } = storeToRefs(userStore)
  27. const searchText = ref('')
  28. const publishState = ref(false)
  29. const filterState = ref(false)
  30. const pageHelperRef = ref<ComponentExposed<typeof PageHelperEvo>>()
  31. const { schema, rules } = useFollowUp()
  32. const memberLevelsStore = useMemberLevelsStore()
  33. const { memberLevels } = storeToRefs(memberLevelsStore)
  34. const filterQuery = ref<{
  35. tags: any[]
  36. levels: any[]
  37. minPoints?: string
  38. maxPoints?: string
  39. brokerId?: string
  40. }>({
  41. tags: [],
  42. levels: [],
  43. brokerId: userInfo.value.userId.toString(),
  44. })
  45. const query = ref({})
  46. const searchFocus = () => {
  47. console.log('focus')
  48. }
  49. const searchBlur = () => {
  50. console.log('focus')
  51. }
  52. const search = () => {
  53. console.log('search')
  54. }
  55. const cancelSearch = () => {
  56. console.log('cancel')
  57. }
  58. const searchChange = (e: any) => {
  59. console.log(e)
  60. }
  61. const toDetail = async (designer: any) => {
  62. await uni.navigateTo({ url: '/pages/designer/detail' + '?id=' + designer.id })
  63. }
  64. const callPhone = (phoneNumber) => {
  65. uni.makePhoneCall({
  66. phoneNumber,
  67. })
  68. }
  69. const filterData = () => {
  70. filterState.value = true
  71. }
  72. const handleImportant = async (designer: Designer) => {
  73. const { code } = await requestToast(
  74. () =>
  75. focusOrCancel({
  76. brokerId: userInfo.value.userId,
  77. userId: Number(designer.id),
  78. }),
  79. {
  80. success: true,
  81. successTitle: '操作成功',
  82. },
  83. )
  84. if (code === 0) {
  85. await pageHelperRef.value?.refresh()
  86. }
  87. }
  88. const handleSubmit = () => {
  89. query.value = {
  90. ...filterQuery.value,
  91. tags: filterQuery.value.tags.join(','),
  92. levels: filterQuery.value.levels.join(','),
  93. }
  94. filterState.value = false
  95. }
  96. const handleReset = () => {
  97. filterQuery.value = { tags: [], levels: [], brokerId: userInfo.value.userId.toString() }
  98. query.value = {}
  99. }
  100. </script>
  101. <template>
  102. <view class="flex-grow">
  103. <PageHelperEvo ref="pageHelperRef" :request="getDesigners" :query="query">
  104. <template #top>
  105. <div class="flex items-center justify-between bg-white pr-3.5">
  106. <div class="flex-1">
  107. <wd-search
  108. v-model="searchText"
  109. @focus="searchFocus"
  110. @blur="searchBlur"
  111. @search="search"
  112. @cancel="cancelSearch"
  113. @change="searchChange"
  114. hide-cancel
  115. />
  116. </div>
  117. <wd-img :src="filterIcon" width="22px" height="22px" @click="filterData"></wd-img>
  118. </div>
  119. </template>
  120. <template #default="{ source }">
  121. <div class="p-3.5 gap-3.5 flex flex-col">
  122. <template v-for="(it, i) in source.list" :key="i">
  123. <Card>
  124. <div class="items-center" @click="toDetail(it)">
  125. <div class="">
  126. <div class="flex items-center">
  127. <div
  128. class="w-[55px] h-[55px] bg-neutral-100 rounded-full mr-2 flex items-center justify-center"
  129. >
  130. <wd-img width="100%" height="100%" round :src="it.avatar"></wd-img>
  131. </div>
  132. <div class="flex flex-col flex-1">
  133. <div class="flex-row flex items-center justify-between w-full">
  134. <div class="flex-row flex items-center">
  135. <div class="text-black/90 text-base font-normal font-['PingFang_SC']">
  136. <!-- 苏小萌 -->
  137. {{ it.name }}
  138. </div>
  139. <div
  140. class="h-4 bg-neutral-100 rounded-[20px] justify-start items-center inline-flex flex-row ml-[9px]"
  141. >
  142. <wd-img width="17" height="17" :src="vipIcon"></wd-img>
  143. <div
  144. class="text-black/40 text-[10px] font-normal font-['PingFang_SC'] px-[7px] leading-none"
  145. >
  146. <!-- 白银会员 -->
  147. {{ it.levelName }}
  148. </div>
  149. </div>
  150. </div>
  151. <div
  152. class="text-black/60 text-xs font-normal font-['PingFang_SC'] leading-snug flex items-center"
  153. @click.stop="toHomePage(it.id)"
  154. >
  155. <div>个人主页</div>
  156. <wd-img width="13" height="13" :src="rightArrowIcon"></wd-img>
  157. </div>
  158. </div>
  159. <div class="flex items-center gap-2 mt-[18px]">
  160. <div
  161. class="text-black/30 text-xs font-normal font-['PingFang_SC'] leading-none"
  162. >
  163. 2天前访问
  164. </div>
  165. <div class="bg-[#eeeeee] w-[2px] h-[10px]"></div>
  166. <div
  167. class="text-black/30 text-xs font-normal font-['PingFang_SC'] leading-none"
  168. >
  169. 积分:{{ it.points || 0 }}
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. </div>
  175. <div class="row-start-2 col-start-2 col-end-4">
  176. <div class="flex items-center justify-between w-full mt-[20px]">
  177. <div v-if="!it.followUp30Days" class="flex items-center">
  178. <div class="w-2 h-2 bg-[#89f4e2] rounded-full mr-[7px]"></div>
  179. <div
  180. class="text-black/90 text-xs font-normal font-['PingFang_SC'] leading-snug"
  181. >
  182. 30天未跟进
  183. </div>
  184. </div>
  185. <div class="flex items-center">
  186. <div class="w-2 h-2 bg-[#ffb96a] rounded-full mr-[7px]"></div>
  187. <div
  188. class="text-black/90 text-xs font-normal font-['PingFang_SC'] leading-snug"
  189. >
  190. 60天未产生积分
  191. </div>
  192. </div>
  193. <div class="flex items-center">
  194. <div class="w-2 h-2 bg-[#c493ff] rounded-full mr-[7px]"></div>
  195. <div
  196. class="text-black/90 text-xs font-normal font-['PingFang_SC'] leading-snug"
  197. >
  198. 60天未消耗积分
  199. </div>
  200. </div>
  201. </div>
  202. </div>
  203. <div
  204. class="row-start-5 col-start-2 col-end-4 flex items-center mt-[26px] justify-around"
  205. >
  206. <div
  207. v-if="!it.focus"
  208. class="px-3 py-1.5 rounded-[30px] border border-solid border-[#ff2d2d] justify-center items-center gap-1 flex"
  209. @click.stop="handleImportant(it)"
  210. >
  211. <!-- <span style="color: #ff2d2d" class="flex items-center">+</span> -->
  212. <wd-icon name="add" color="#ff2d2d" size="10"></wd-icon>
  213. <div
  214. class="text-[#ff2d2d] text-xs font-normal font-['PingFang_SC'] leading-none"
  215. >
  216. 重点跟进
  217. </div>
  218. </div>
  219. <div
  220. v-else
  221. class="px-3 py-1.5 rounded-[30px] border border-solid border-[#dcdcdc] justify-center items-center gap-1 inline-flex"
  222. @click.stop="handleImportant(it)"
  223. >
  224. <!-- 对号图标 -->
  225. <wd-icon name="check-bold" color="#8b8b8b" size="14"></wd-icon>
  226. <div
  227. class="text-[#8b8b8b] text-xs font-normal font-['PingFang_SC'] leading-none"
  228. >
  229. 已重点跟进
  230. </div>
  231. </div>
  232. <div
  233. class="px-5 py-1 bg-[#e1ecff] rounded-[30px] border border-[#2357e9] justify-center items-center gap-1 inline-flex"
  234. @click.stop="callPhone(it.mobile)"
  235. >
  236. <div
  237. class="text-center text-[#2357e9] text-sm font-normal font-['PingFang_SC'] leading-normal"
  238. >
  239. 打电话
  240. </div>
  241. </div>
  242. <div
  243. class="px-5 py-1 bg-[#0052d9] rounded-[30px] justify-center items-center gap-1 inline-flex"
  244. >
  245. <div
  246. class="text-center text-white text-sm font-normal font-['PingFang_SC'] leading-normal"
  247. @click.stop="publishState = true"
  248. >
  249. 写跟进
  250. </div>
  251. </div>
  252. </div>
  253. </div>
  254. </Card>
  255. </template>
  256. </div>
  257. </template>
  258. </PageHelperEvo>
  259. </view>
  260. <wd-action-sheet v-model="publishState" title="创建跟进" @close="publishState = false">
  261. <view class="flex flex-col p-4">
  262. <div><DataForm :schema="schema" :rules="rules" direction="horizontal"></DataForm></div>
  263. <div><wd-button block :round="false">提交</wd-button></div>
  264. </view>
  265. </wd-action-sheet>
  266. <!-- 筛选action-sheet -->
  267. <wd-action-sheet v-model="filterState" title="筛选" @close="filterState = false">
  268. <view class="flex flex-col p-4">
  269. <SectionHeading title="标签"></SectionHeading>
  270. <wd-checkbox-group shape="button" v-model="filterQuery.tags">
  271. <template
  272. v-for="(tag, index) in [
  273. // { label: '全部', value: '' },
  274. { label: '重点跟进', value: '1' },
  275. { label: '本月新增', value: '2' },
  276. { label: '超过30天未跟进', value: '3' },
  277. { label: '超过60天未产生积分', value: '4' },
  278. { label: '超过60天未消耗积分', value: '5' },
  279. { label: '未成交过', value: '6' },
  280. ]"
  281. :key="index"
  282. >
  283. <wd-checkbox custom-class="w-50%!" :model-value="tag.value">
  284. {{ tag.label }}
  285. </wd-checkbox>
  286. </template>
  287. </wd-checkbox-group>
  288. <SectionHeading title="会员等级"></SectionHeading>
  289. <wd-checkbox-group shape="button" v-model="filterQuery.levels">
  290. <template
  291. v-for="(tag, index) in memberLevels.map((it) => ({
  292. label: it.memberLevelName,
  293. value: it.id,
  294. }))"
  295. :key="index"
  296. >
  297. <wd-checkbox custom-class="w-50%!" :model-value="tag.value">{{ tag.label }}</wd-checkbox>
  298. </template>
  299. </wd-checkbox-group>
  300. <!-- <div class="flex items-center justify-between py-4">
  301. <template>
  302. <div class="w-[168px] h-10 bg-[#f5f7f9] rounded-lg flex items-center justify-center">
  303. <div class="w-7 text-black/90 text-sm font-normal font-['PingFang_SC'] leading-none">
  304. 全部
  305. </div>
  306. </div>
  307. </template>
  308. </div> -->
  309. <SectionHeading title="积分区间"></SectionHeading>
  310. <div class="flex items-center justify-between py-4">
  311. <wd-input
  312. v-model="filterQuery.minPoints"
  313. custom-class="h-10 bg-[#f5f7f9]!"
  314. no-border
  315. ></wd-input>
  316. <div class="w-4 h-.25 bg-black/35"></div>
  317. <wd-input
  318. v-model="filterQuery.maxPoints"
  319. custom-class="h-10 bg-[#f5f7f9]!"
  320. no-border
  321. ></wd-input>
  322. </div>
  323. <div class="flex gap-4">
  324. <div class="flex-1">
  325. <wd-button block :round="false" @click="handleReset">重置</wd-button>
  326. </div>
  327. <div class="flex-1">
  328. <wd-button block :round="false" @click="handleSubmit">提交</wd-button>
  329. </div>
  330. </div>
  331. </view>
  332. </wd-action-sheet>
  333. </template>
  334. <style scoped lang="scss">
  335. .filter-item {
  336. @apply w-[168px] h-10 bg-[#f5f7f9] rounded-lg flex items-center justify-center;
  337. &-text {
  338. @apply text-black/90 text-sm font-normal font-['PingFang_SC'] leading-none;
  339. }
  340. }
  341. </style>