Browse Source

feat: 添加关系报备页面及相关接口;更新请求模型,支持标签 ID;优化任务卡片展示逻辑

EvilDragon 3 months ago
parent
commit
424e0afec8

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

@@ -775,6 +775,28 @@ export interface Report {
   remark: string
   num: number
 }
+export interface ReportInfo {
+  id: number
+  brokerName: string
+  stylistId: number
+  /**
+   * 设计师姓名
+   */
+  stylistName: string
+  arrivalTime: number
+  shopName: string
+  receptionist: string
+  contactNumber: string
+  customerName: string
+  customerPhoneNumbe: string
+  customerAddress: string
+  createTime: number
+  reviewStatus: number
+  auditId: number
+  auditName: string
+  auditTime: number
+  reason: string
+}
 export interface AgentTask {
   id: number
   bearerId: number

+ 1 - 0
packages/app/src/core/libs/requests.ts

@@ -1008,6 +1008,7 @@ export interface Circle {
   spaceAddr: string
   customerDemand: string
   bannerUrls: string[]
+  tagIds?: number[]
 }
 export interface CircleRes {
   id: number

+ 6 - 3
packages/app/src/pages/publish/moment/index.vue

@@ -82,6 +82,7 @@ const rules = {
 const formData = ref({})
 const formInited = ref(false)
 const tagName = ref('')
+const tagIds = ref([])
 const publishing = ref(false)
 const handleChange = ({ fileList: files }) => {
   fileList.value = files
@@ -108,6 +109,7 @@ const handleSubmit = async () => {
     headUrl: userInfo.value.avatar,
     circleDesc: content.value,
     circleType: circleType.value,
+    tagIds: tagIds.value,
     ...formData.value,
   })
   if (code !== 0) {
@@ -119,12 +121,13 @@ const handleSubmit = async () => {
   publishing.value = false
   router.back()
 }
-const updateTagName = (tagNames: string[]) => {
-  if (tagNames.length === 0) {
+const updateTagName = (options: { tagNames: string[]; tagIds: string[] }) => {
+  if (options.tagNames.length === 0) {
     tagName.value = ''
     return
   }
-  tagName.value = tagNames.join(',')
+  tagName.value = options.tagNames.join(',')
+  tagIds.value = options.tagIds
 }
 onMounted(() => {
   uni.$on('updateTagName', updateTagName)

+ 11 - 4
packages/app/src/pages/publish/tags/index.vue

@@ -38,17 +38,24 @@ const { data: memberTags, run: setMemberTags } = useRequest(
   },
 )
 const selected = ref<string[]>([])
+const tagIds = ref<string[]>([])
 
-const handleClick = (tagName: string) => {
+const handleClick = ({ tagName, tagId, isReport }) => {
   if (selected.value.includes(tagName)) {
     selected.value = selected.value.filter((it) => it !== tagName)
   } else {
     selected.value.push(tagName)
   }
+  if (!isReport) return
+  if (tagIds.value.includes(tagId)) {
+    tagIds.value = tagIds.value.filter((it) => it !== tagId)
+  } else {
+    tagIds.value.push(tagId)
+  }
 }
 const handleSubmit = async () => {
   await uni.navigateBack()
-  uni.$emit('updateTagName', selected.value)
+  uni.$emit('updateTagName', { tagNames: selected.value, tagIds: tagIds.value })
 }
 const handleAddTag = async () => {
   await confirm({
@@ -115,7 +122,7 @@ onLoad(async (query: { tagName: string }) => {
           :key="id"
         >
           <wd-tag
-            @click="handleClick(labelName)"
+            @click="handleClick({ tagName: labelName, tagId: id, isReport: true })"
             :type="selected.includes(labelName) ? 'primary' : 'default'"
           >
             {{ labelName }}
@@ -137,7 +144,7 @@ onLoad(async (query: { tagName: string }) => {
           </div>
           <wd-tag
             custom-class="m-1"
-            @click="handleClick(it.tagName)"
+            @click="handleClick({ tagName: it.tagName, tagId: it.id, isReport: false })"
             :type="selected.includes(it.tagName) ? 'primary' : 'default'"
           >
             {{ it.tagName }}

+ 26 - 8
packages/merchant/src/components/page-helper-evo.vue

@@ -75,7 +75,20 @@ defineExpose({
   },
   refresh: async () => {
     console.log('Page Helper Refresh')
+    console.log(items.value.length)
     await setData()
+    // 之前页的数据
+    const prevItems = items.value.slice(0, pageSize.value * (pageNo.value - 1))
+    console.log(prevItems.length)
+
+    // 之后页的数据
+    const nextItems = items.value.slice(pageSize.value * pageNo.value, items.value.length)
+    console.log(nextItems.length)
+
+    items.value = prevItems.concat(data.value?.list || [], nextItems)
+    console.log(items.value.length)
+
+    // console.log(items.value)
   },
 })
 </script>
@@ -94,13 +107,18 @@ defineExpose({
         <slot name="top"></slot>
       </div>
     </div>
-
-    <template v-if="!items?.length">
-      <wd-status-tip :image="NetImages.NotContent" tip="暂无内容"></wd-status-tip>
-    </template>
-    <slot :source="{ list: items }"></slot>
-    <template v-if="nomore">
-      <div class="my-4"><wd-divider>没有更多了</wd-divider></div>
-    </template>
+    <div class="flex-grow flex flex-col">
+      <template v-if="!items?.length">
+        <div class="flex-grow flex flex-col justify-center">
+          <wd-status-tip :image="NetImages.NotContent" tip="暂无内容"></wd-status-tip>
+        </div>
+      </template>
+      <div v-if="items.length" class="flex-grow flex flex-col">
+        <slot :source="{ list: items }"></slot>
+      </div>
+      <template v-if="nomore">
+        <div class="my-4"><wd-divider>没有更多了</wd-divider></div>
+      </template>
+    </div>
   </div>
 </template>

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

@@ -1,4 +1,4 @@
-import { httpGet } from '../../utils/http'
+import { httpDelete, httpGet } from '../../utils/http'
 import {
   PointsOrder,
   ResPageData,
@@ -6,6 +6,7 @@ import {
   Agent,
   Designer,
   AgentTask,
+  ReportInfo,
 } from '@designer-hub/app/src/core/libs/models'
 
 /**
@@ -18,3 +19,13 @@ export const getDesigners = (query = {}) =>
  */
 export const getTasks = (query = {}) =>
   httpGet<ResPageData<AgentTask>>('/app-api/member/task/page', query)
+/**
+ * 关系报备
+ */
+export const getReportInfoPage = (query = {}) =>
+  httpGet<ResPageData<ReportInfo>>('/app-api/member/report-info/page', query)
+/**
+ * 删除关系报备
+ */
+export const deleteReportInfo = (id: number) =>
+  httpDelete(`/app-api/member/report-info/delete`, { id })

+ 18 - 0
packages/merchant/src/core/libs/enums.ts

@@ -8,6 +8,24 @@ export enum QrCodeBusinessType {
    */
   InStoreWriteOff = 'ISWO',
 }
+// 审核状态(0,审核通过,1、待审核、2、驳回),示例值(1,2,3)
+export enum ReportInfoReviewStatus {
+  /**
+   * 待审核
+   */
+  PendingReview = 1,
+  /**
+   * 驳回
+   */
+  Rejected = 2,
+  /**
+   * 审核通过
+   */
+  Approved = 0,
+}
+/**
+ *
+ */
 export enum NetImages {
   'default' = 'https://cdn.jsdelivr.net/gh/yangyang-yangyang/yangyang-yangyang.github.io@master/images/default.png',
   'avatar' = 'https://cdn.jsdelivr.net/gh/yangyang-yangyang/yangyang-yangyang.github.io@master/images/avatar.png',

+ 8 - 0
packages/merchant/src/pages.json

@@ -143,6 +143,14 @@
       }
     },
     {
+      "path": "pages/home/agent/report-infos/index",
+      "type": "page",
+      "style": {
+        "navigationBarTitleText": "关系报备",
+        "navigationBarBackgroundColor": "#fff"
+      }
+    },
+    {
       "path": "pages/home/agent/todo/index",
       "type": "page",
       "style": {

+ 140 - 0
packages/merchant/src/pages/home/agent/report-infos/index.vue

@@ -0,0 +1,140 @@
+<route lang="json">
+{ "style": { "navigationBarTitleText": "关系报备", "navigationBarBackgroundColor": "#fff" } }
+</route>
+<script setup lang="ts">
+import BottomAppBar from '@/components/bottom-app-bar.vue'
+import PageHelperEvo from '@/components/page-helper-evo.vue'
+import { deleteReportInfo, getReportInfoPage } from '../../../../core/libs/agent-requests'
+import { ReportInfoReviewStatus } from '../../../../core/libs/enums'
+import Card from '@designer-hub/app/src/components/card.vue'
+import dayjs from 'dayjs'
+import { ReportInfo } from '@designer-hub/app/src/core/libs/models'
+import { requestToast } from '@designer-hub/app/src/core/utils/common'
+import { ComponentExposed } from 'vue-component-type-helpers'
+
+const tab = ref(0)
+const tabs = [
+  { label: '全部', value: '' },
+  { label: '审核中', value: ReportInfoReviewStatus.PendingReview.toString() },
+  { label: '未通过', value: ReportInfoReviewStatus.Rejected.toString() },
+  { label: '已通过', value: ReportInfoReviewStatus.Approved.toString() },
+]
+const pageHelperRef = ref<ComponentExposed<typeof PageHelperEvo>>()
+const query = computed(() => (tab.value ? { reviewStatus: tabs[tab.value].value } : {}))
+const handleAdd = () => {
+  uni.navigateTo({ url: '/pages/home/merchant/add-reporting-information' })
+}
+const handleDelete = async (reportInfo: ReportInfo) => {
+  await requestToast(() => deleteReportInfo(reportInfo.id), {
+    success: true,
+    successTitle: '删除成功',
+  })
+  pageHelperRef.value?.refresh()
+}
+</script>
+<template>
+  <div class="flex-grow flex flex-col">
+    <!-- <PageHelperEvo
+      :request="
+        async () => ({
+          code: 0,
+          msg: '',
+          data: { list: [{ title: '', a: 1, sss: 444 }], total: 0 },
+        })
+      "
+    >
+      <template #default="{ source }">
+        {{ source.list[0].title }}
+        {{ source.list[0].a }}
+        {{ source.list[0].sss }}
+      </template>
+    </PageHelperEvo> -->
+
+    <PageHelperEvo ref="pageHelperRef" :request="getReportInfoPage" :query="query">
+      <template #top>
+        <wd-tabs v-model="tab">
+          <template v-for="(it, i) in tabs" :key="i">
+            <wd-tab :title="it.label"></wd-tab>
+          </template>
+        </wd-tabs>
+      </template>
+      <template #default="{ source }">
+        <div class="flex flex-col gap-4 p-4">
+          <template v-for="(it, i) in source.list" :key="i">
+            <Card>
+              <!-- {{ it.stylistName }} -->
+              <div class="flex items-center justify-between">
+                <div
+                  class="text-center text-black text-sm font-normal font-['PingFang_SC'] leading-normal"
+                >
+                  报备时间:
+                  <!-- 2024-02-21 10:12 -->
+                  {{ dayjs(it.createTime).format('YYYY-MM-DD HH:mm') }}
+                </div>
+                <div
+                  class="right-0 top-[15px] text-center text-sm font-normal font-['PingFang_SC'] leading-normal"
+                  :class="`${{ [ReportInfoReviewStatus.PendingReview]: 'text-[#2357e9]', [ReportInfoReviewStatus.Approved]: 'text-[#16b032]', [ReportInfoReviewStatus.Rejected]: 'text-[#ff2d2d]' }[it.reviewStatus]}`"
+                >
+                  {{ it.reviewStatus === ReportInfoReviewStatus.PendingReview ? '审核中' : '' }}
+                  {{ it.reviewStatus === ReportInfoReviewStatus.Rejected ? '未通过' : '' }}
+                  {{ it.reviewStatus === ReportInfoReviewStatus.Approved ? '已通过' : '' }}
+                </div>
+              </div>
+              <div class="my-3 w-full h-.25 bg-[#f4f4f4]"></div>
+              <div class="grid grid-cols-[1fr_2fr] gap-y-2.5">
+                <template
+                  v-for="(item, index) in [
+                    { label: '店面名称', value: it.shopName },
+                    { value: it.arrivalTime, label: '到店时间' },
+                    { value: it.receptionist, label: '接待人员' },
+                    { value: it.contactNumber, label: '联系电话' },
+                    { value: it.customerName, label: '客户姓名' },
+                    { value: it.customerPhoneNumbe, label: '客户电话' },
+                    { value: it.customerAddress, label: '客户地址' },
+                    { value: it.stylistName, label: '设计师姓名' },
+                  ]"
+                  :key="index"
+                >
+                  <!-- <div class="flex items-center"> -->
+                  <div
+                    class="left-0 top-0 text-black/40 text-sm font-normal font-['PingFang_SC'] leading-none"
+                  >
+                    {{ item.label }}
+                  </div>
+                  <div
+                    class="left-[105px] top-0 text-[#3f4c64] text-sm font-normal font-['PingFang_SC'] leading-none"
+                  >
+                    {{ item.value }}
+                  </div>
+                  <!-- </div> -->
+                </template>
+              </div>
+              <template v-if="it.reviewStatus === ReportInfoReviewStatus.Rejected">
+                <div class="my-3 w-full h-.25 bg-[#f4f4f4]"></div>
+                <div class="text-[#ff2d2d] text-sm font-normal font-['PingFang SC'] leading-none">
+                  原因:{{ it.reason }}
+                </div>
+                <div class="flex justify-end">
+                  <div>
+                    <wd-button
+                      :round="false"
+                      icon="delete"
+                      size="small"
+                      plain
+                      @click="handleDelete(it)"
+                    >
+                      删除
+                    </wd-button>
+                  </div>
+                </div>
+              </template>
+            </Card>
+          </template>
+        </div>
+      </template>
+    </PageHelperEvo>
+    <BottomAppBar fixed placeholder>
+      <div><wd-button block :round="false" @click="handleAdd">添加报备信息</wd-button></div>
+    </BottomAppBar>
+  </div>
+</template>

+ 9 - 8
packages/merchant/src/pages/home/index.vue

@@ -149,7 +149,7 @@ onShareAppMessage(() => ({}))
             </Card>
             <template v-for="(it, i) in tasks.list" :key="i">
               <div class="inline-block">
-                <div class="w-[calc(100vw-64rpx)]"><TaskCard :options="it"></TaskCard></div>
+                <div class="w-[calc(75vw)]"><TaskCard :options="it"></TaskCard></div>
               </div>
             </template>
           </div>
@@ -158,7 +158,12 @@ onShareAppMessage(() => ({}))
           <SectionHeading title="设计师" path="" custom-class="mb-5"></SectionHeading>
           <div class="flex flex-col gap-4">
             <template
-              v-for="{ label, color } of [
+              v-for="{ label, color, ...it } of [
+                {
+                  label: '关系报备',
+                  color: 'white',
+                  path: '/pages/home/agent/report-infos/index',
+                },
                 { label: '重点跟进设计师', color: '#FF523F' },
                 { label: '全部设计师', color: '#7199FF' },
                 { label: '本月新增设计师', color: '#FFE786' },
@@ -171,18 +176,14 @@ onShareAppMessage(() => ({}))
             >
               <div
                 class="h-12 bg-white rounded-lg shadow flex items-center hover:bg-[#fff6f5]"
-                @click="toDesigner"
+                @click="it.path ? router.push(it.path) : toDesigner"
               >
                 <div
                   class="w-1.5 h-12 rounded-tl-lg rounded-bl-lg shadow"
                   :style="{ background: color }"
                 ></div>
                 <div class="flex-1 mx-3">
-                  <SectionHeading
-                    :title="label"
-                    path="/pages/designer/index"
-                    size="sm"
-                  ></SectionHeading>
+                  <SectionHeading :title="label" :end-arrow="true" size="sm"></SectionHeading>
                 </div>
               </div>
             </template>

+ 21 - 19
packages/merchant/src/pages/home/merchant/add-reporting-information.vue

@@ -2,6 +2,8 @@
 { "style": { "navigationBarTitleText": "添加关系报备", "navigationBarBackgroundColor": "#fff" } }
 </route>
 <script setup lang="ts">
+import dayjs from 'dayjs'
+import { DataFormSchema } from '../../../components/data-form'
 import DataForm from '../../../components/data-form.vue'
 import { createReportInfo, getDesignerList } from '../../../core/libs/requests'
 import { useUserStore } from '../../../store'
@@ -9,18 +11,20 @@ import { storeToRefs } from 'pinia'
 
 const userStore = useUserStore()
 const { userInfo } = storeToRefs(userStore)
-const formData = ref<any>({})
+const formData = ref<any>({
+  arrivalTime: dayjs().toDate(),
+})
 const designerList = ref([])
 const stylistIdName = ref('')
-const merchantSchema = ref({
+const merchantSchema = ref<DataFormSchema>({
   stylistId: {
     type: 'Select',
     label: '设计师:',
+    labelWidth: 84,
+    required: true,
     props: {
-      labelWidth: '150rpx',
       placeholder: '请选择设计师',
       columns: [],
-      required: true,
       // disabled: userAuthInfo.value != null,
       'onUpdate:modelValue': (value) => {
         // console.log(value),
@@ -34,67 +38,65 @@ const merchantSchema = ref({
     },
   },
   arrivalTime: {
-    type: 'timePick',
+    type: 'TimePick',
     label: '到店时间:',
+    labelWidth: 84,
+    required: true,
     props: {
-      required: true,
-      labelWidth: '150rpx',
       placeholder: '请选择到店时间',
-      // disabled: userAuthInfo.value != null,
     },
   },
   shopName: {
     type: 'TextField',
     label: '店面名称',
     existing: true,
+    required: true,
+    labelWidth: 84,
     props: {
-      required: true,
-      labelWidth: '150rpx',
       placeholder: '店面名称',
-      // disabled: userAuthInfo.value != null,
     },
   },
   receptionist: {
     type: 'TextField',
     label: '接待人员:',
+    required: true,
+    labelWidth: 84,
     props: {
-      required: true,
-      labelWidth: '150rpx',
       placeholder: '请输入接待人员',
     },
   },
   contactNumber: {
     type: 'TextField',
     label: '联系电话:',
+    required: true,
+    labelWidth: 84,
     props: {
-      required: true,
-      labelWidth: '150rpx',
       placeholder: '请输入联系电话',
     },
   },
 })
-const customerSchema = ref({
+const customerSchema = ref<DataFormSchema>({
   customerName: {
     type: 'TextField',
     label: '客户姓名:',
+    labelWidth: 84,
     props: {
-      labelWidth: '126rpx',
       placeholder: '请输入客户姓名',
     },
   },
   customerPhoneNumbe: {
     type: 'TextField',
     label: '客户电话:',
+    labelWidth: 84,
     props: {
-      labelWidth: '126rpx',
       placeholder: '请输入客户电话',
     },
   },
   customerAddress: {
     type: 'TextField',
     label: '客户地址:',
+    labelWidth: 84,
     props: {
-      labelWidth: '126rpx',
       placeholder: '请输入客户地址',
     },
   },

+ 1 - 0
packages/merchant/src/types/uni-pages.d.ts

@@ -15,6 +15,7 @@ interface NavigateToOptions {
        "/pages/home/merchant/settlement" |
        "/pages/home/tasks/index" |
        "/pages/mine/merchant/merchant_settings" |
+       "/pages/home/agent/report-infos/index" |
        "/pages/home/agent/todo/index" |
        "/pages/home/tasks/detail/index" |
        "/pages/mine/merchant/orders/detail/index";