Przeglądaj źródła

feat: 添加设计师基本信息接口;更新相关页面和组件以支持新功能

EvilDragon 1 miesiąc temu
rodzic
commit
4eda4edbe9

+ 1 - 1
packages/app/src/components/section-heading.vue

@@ -38,7 +38,7 @@ const props = defineProps({
   dark: {
     type: Boolean,
     default: false,
-  },
+  }
 })
 const handleMore = async () => {
   props.path && (await uni.navigateTo({ url: props.path }))

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

@@ -741,6 +741,36 @@ export interface Designer {
   focus: boolean
   brokerId: number
 }
+export interface DesignerBasicInfo {
+  id: number
+  userId: number
+  avatar: string
+  name: string
+  sex: number
+  birthday: string
+  mobile: string
+  referrer: string
+  brokerName: string
+  employer: string
+  companyAddress: string
+  idCardNumber: string
+  passportNumber: string
+  householdAddress: string
+  cooperationTime: string
+  joinTime: string
+  circle: string
+  hobbies: string
+  sharingIntent: number
+  createTime: string
+  imageNumber: number
+  imageUrl: string
+  maritalStatus: number
+  maritalStatusStr: string
+}
+export interface DesignerEvent {
+  name: string
+  applyTime: string
+}
 export interface Broker {
   createTime: string
   updateTime: string

+ 1 - 1
packages/merchant/env/.env.development

@@ -7,4 +7,4 @@ VITE_SHOW_SOURCEMAP = true
 
 VITE_SERVER_BASEURL='https://www.zhuchaohui.com'
 # VITE_SERVER_BASEURL = 'http://39.106.91.179:48080'
-# VITE_SERVER_BASEURL = 'http://192.168.2.45:48080'
+# VITE_SERVER_BASEURL = 'http://192.168.2.58:48080'

+ 3 - 3
packages/merchant/src/components/data-form.ts

@@ -1,13 +1,13 @@
 export interface DataFormProps {
   defaultValue?: Date
   placeholder?: string
-  columns?: { label: string; value: string }[]
+  columns?: { label: string; value: string | number }[]
   disabled?: boolean
   'onUpdate:modelValue'?: (value: string) => void
   type?: 'nickname'
 }
-export interface DataFormSchema {
-  [key: symbol | string]: {
+export type DataFormSchema<T = any> = {
+  [key in keyof T]: {
     type:
       | 'TextField'
       | 'Select'

+ 21 - 0
packages/merchant/src/components/data-render.vue

@@ -0,0 +1,21 @@
+<script setup lang="ts">
+import dayjs from 'dayjs'
+
+withDefaults(
+  defineProps<{
+    type: 'Original' | 'Date' | 'Avatar' | 'Select'
+    value: number | string | Date
+    customClass?: string
+    options?: { label: string; value: string | number }[]
+  }>(),
+  { type: 'Original', value: '' },
+)
+</script>
+<template>
+  <div>
+    <span v-if="type === 'Original'">{{ value }}</span>
+    <span v-if="type === 'Date'">{{ dayjs(value).format('YYYY-MM-DD') }}</span>
+    <img v-if="type === 'Avatar'" :src="value" class="w-10 h-10 rounded-full" />
+    <span v-if="type === 'Select'">{{ options?.find((it) => it.value === value)?.label }}</span>
+  </div>
+</template>

+ 23 - 2
packages/merchant/src/core/libs/agent-requests.ts

@@ -8,6 +8,8 @@ import {
   AgentTask,
   ReportInfo,
   FollowUp,
+  DesignerBasicInfo,
+  DesignerEvent,
 } from '@designer-hub/app/src/core/libs/models'
 /**
  * 通过ID获取用户信息
@@ -49,8 +51,27 @@ export const getUserInfoById = (id) =>
 /**
  * 获取设计师基本信息
  */
-export const getStylistBasicInfo = (userId: number) =>
-  httpGet<Designer>('/app-api/member/stylist-basic-info/get', { userId })
+export const getDesignerBasicInfo = (userId: number) =>
+  httpGet<DesignerBasicInfo>('/app-api/member/stylist-basic-info/get', { userId })
+/**
+ * 更新设计师基本信息
+ */
+export const updateDesignerBasicInfo = (data: Partial<DesignerBasicInfo>) =>
+  httpPut('/app-api/member/stylist-basic-info/update', data)
+/**
+ * 获取设计师额外事件
+ */
+export const getDesignerExtraEvents = (query = {}) =>
+  httpGet<ResPageData<DesignerEvent>>('/app-api/member/stylist-extra-events/pageInfo', query)
+/**
+ * /app-api/member/stylist-extra-events/getStudyAndActivity 获取设计师学习和活动
+ */
+export const getDesignerActivityEvents = (userId: number) =>
+  httpGet<{
+    [key in 'study' | 'activity' | 'extraEventsQuantity']:
+      | { type: number; quantity: number }[]
+      | number
+  }>('/app-api/member/stylist-extra-events/getStudyAndActivity', { userId })
 /**
  * 设计师列表
  */

+ 45 - 0
packages/merchant/src/core/libs/messages.ts

@@ -0,0 +1,45 @@
+import { designer } from './pngs'
+
+export const messages = {
+  home: { shareTitle: '筑巢荟' },
+  moment: { imageNotExist: '请上传图片' },
+  mine: {
+    authentication: {
+      channelSourceErrorText: '请选择来源',
+      referrerErrorText: '请输入推荐人编号',
+      designerNameErrorText: '请输入姓名',
+      employerErrorText: '请输入公司',
+      spatialExpertiseTypeErrorText: '请选择擅长空间类型',
+      attachmentErrorText: '请上传附件',
+    },
+  },
+  objects: {
+    designerBasiceInfo: {
+      id: 'ID',
+      userId: '用户ID',
+      avatar: '头像',
+      name: '姓名',
+      sex: '性别',
+      birthday: '生日',
+      mobile: '手机',
+      referrer: '推荐人',
+      brokerName: '经纪人姓名',
+      employer: '公司',
+      companyAddress: '公司地址',
+      idCardNumber: '身份证号',
+      passportNumber: '护照号',
+      householdAddress: '家庭地址',
+      cooperationTime: '合作时间',
+      joinTime: '加入时间',
+      circle: '圈子',
+      hobbies: '爱好',
+      sharingIntent: '分享意图',
+      createTime: '创建时间',
+      imageNumber: '图片数量',
+      imageUrl: '图片URL',
+      maritalStatus: '婚姻状况',
+      maritalStatusStr: '婚姻状况描述',
+    },
+  },
+  // 写出上面对象的显示文案 如:designerBasiceInfo: { id: 'ID', userId: '用户ID', avatar: '头像'}
+}

+ 38 - 0
packages/merchant/src/core/libs/renders.ts

@@ -0,0 +1,38 @@
+import { designer } from './pngs'
+import { h } from 'vue'
+
+export const renders = {
+  designerBasiceInfo: {
+    id: (value) => ({ type: 'Original', value }),
+    userId: (value) => ({ type: 'Original', value }),
+    avatar: (value) => ({ type: 'Avatar', value }),
+    name: (value) => ({ type: 'Original', value }),
+    sex: (value) => ({
+      type: 'Select',
+      options: [
+        { label: '男', value: 0 },
+        { label: '女', value: 1 },
+      ],
+      value,
+    }),
+    birthday: (value) => ({ type: 'Date', value }),
+    mobile: (value) => ({ type: 'Original', value }),
+    referrer: (value) => ({ type: 'Original', value }),
+    brokerName: (value) => ({ type: 'Original', value }),
+    employer: (value) => ({ type: 'Original', value }),
+    companyAddress: (value) => ({ type: 'Original', value }),
+    idCardNumber: (value) => ({ type: 'Original', value }),
+    passportNumber: (value) => ({ type: 'Original', value }),
+    householdAddress: (value) => ({ type: 'Original', value }),
+    cooperationTime: (value) => ({ type: 'Date', value }),
+    joinTime: (value) => ({ type: 'Date', value }),
+    circle: (value) => ({ type: 'Original', value }),
+    hobbies: (value) => ({ type: 'Original', value }),
+    sharingIntent: (value) => ({ type: 'Original', value }),
+    createTime: (value) => ({ type: 'Date', value }),
+    imageNumber: (value) => ({ type: 'Original', value }),
+    imageUrl: (value) => ({ type: 'Original', value }),
+    maritalStatus: (value) => ({ type: 'Original', value }),
+    maritalStatusStr: (value) => ({ type: 'Original', value }),
+  },
+}

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

@@ -95,6 +95,14 @@
       }
     },
     {
+      "path": "pages/designer/archives/index",
+      "type": "page",
+      "style": {
+        "navigationBarTitleText": "个人信息",
+        "navigationBarBackgroundColor": "#ffffff"
+      }
+    },
+    {
       "path": "pages/designer/points_details/index",
       "type": "page",
       "style": {
@@ -144,6 +152,14 @@
       }
     },
     {
+      "path": "pages/designer/archives/basic-info/index",
+      "type": "page",
+      "style": {
+        "navigationBarTitleText": "编辑基本信息",
+        "navigationBarBackgroundColor": "#ffffff"
+      }
+    },
+    {
       "path": "pages/home/agent/report-infos/index",
       "type": "page",
       "style": {

+ 125 - 0
packages/merchant/src/pages/designer/archives/basic-info/index.vue

@@ -0,0 +1,125 @@
+<route lang="json">
+{
+  "style": {
+    "navigationBarTitleText": "编辑基本信息",
+    "navigationBarBackgroundColor": "#ffffff"
+  }
+}
+</route>
+<script setup lang="ts">
+import { getDesignerBasicInfo, updateDesignerBasicInfo } from '../../../../core/libs/agent-requests'
+import { messages } from '../../../../core/libs/messages'
+import BottomAppBar from '@/components/bottom-app-bar.vue'
+import DataForm from '@/components/data-form.vue'
+import { DataFormSchema } from '../../../../components/data-form'
+import { DesignerBasicInfo } from '@designer-hub/app/src/core/libs/models'
+import { requestToast } from '@designer-hub/app/src/core/utils/common'
+import { omit } from 'radash'
+
+const tab = ref('basic')
+// 基础信息 家庭信息 奖项信息 销售信息 游学/活动信息
+const tabs = [
+  { label: '基础信息', value: 'basic' },
+  { label: '家庭信息', value: 'family' },
+  { label: '奖项信息', value: 'award' },
+  { label: '销售信息', value: 'sale' },
+  { label: '游学/活动信息', value: 'activity' },
+  { label: '其他活动信息', value: 'events' },
+]
+const id = ref()
+const { data: basicData, run: setBasicData } = useRequest(() => getDesignerBasicInfo(id.value))
+const formData = ref({})
+const schema = ref<
+  DataFormSchema<
+    Pick<
+      DesignerBasicInfo,
+      | 'companyAddress'
+      | 'idCardNumber'
+      | 'passportNumber'
+      | 'householdAddress'
+      | 'cooperationTime'
+      | 'circle'
+      | 'hobbies'
+      | 'sharingIntent'
+      | 'imageUrl'
+      | 'maritalStatus'
+    >
+  >
+>({
+  companyAddress: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.companyAddress,
+    labelWidth: 0,
+    props: undefined,
+  },
+  idCardNumber: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.idCardNumber,
+  },
+  passportNumber: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.passportNumber,
+  },
+  householdAddress: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.householdAddress,
+  },
+  cooperationTime: {
+    type: 'TimePick',
+    label: messages.objects.designerBasiceInfo.cooperationTime,
+  },
+  circle: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.circle,
+  },
+  hobbies: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.hobbies,
+  },
+  sharingIntent: {
+    type: 'TextField',
+    label: messages.objects.designerBasiceInfo.sharingIntent,
+  },
+  imageUrl: {
+    type: 'ImageUploader',
+    label: messages.objects.designerBasiceInfo.imageUrl,
+  },
+  maritalStatus: {
+    type: 'Radio',
+    label: messages.objects.designerBasiceInfo.maritalStatus,
+    props: {
+      columns: [
+        { label: '未婚', value: 0 },
+        { label: '已婚', value: 1 },
+      ],
+    },
+  },
+})
+const eventsQuery = computed(() => ({ type: '3' }))
+// const {} = useRequest()
+const handleSubmit = async () => {
+  const { code } = await requestToast(() => updateDesignerBasicInfo(formData.value), {
+    success: true,
+    successTitle: '保存成功',
+  })
+  if (code === 0) {
+    await setBasicData()
+    uni.navigateBack()
+  }
+}
+onLoad(async (query: { id: string }) => {
+  id.value = query.id
+  await setBasicData()
+  formData.value = {
+    ...omit(basicData.value, ['sex']),
+  }
+})
+</script>
+<template>
+  <div class="flex-grow bg-white p-4">
+    <DataForm :schema="schema" v-model="formData" :direction="'horizontal'"></DataForm>
+    <BottomAppBar fixed placeholder>
+      <wd-button block :round="false" @click="handleSubmit">保存</wd-button>
+    </BottomAppBar>
+  </div>
+</template>

+ 85 - 0
packages/merchant/src/pages/designer/archives/index.vue

@@ -0,0 +1,85 @@
+<route lang="json">
+{
+  "style": {
+    "navigationBarTitleText": "个人信息",
+    "navigationBarBackgroundColor": "#ffffff"
+  }
+}
+</route>
+<script setup lang="ts">
+import SectionHeading from '@designer-hub/app/src/components/section-heading.vue'
+import { getDesignerBasicInfo, getDesignerExtraEvents } from '../../../core/libs/agent-requests'
+import { messages } from '../../../core/libs/messages'
+import { omit } from 'radash'
+import BottomAppBar from '@/components/bottom-app-bar.vue'
+import { renders } from '../../../core/libs/renders'
+import DataRender from '@/components/data-render.vue'
+import PageHelperEvo from '@/components/page-helper-evo.vue'
+
+const tab = ref('basic')
+// 基础信息 家庭信息 奖项信息 销售信息 游学/活动信息
+const tabs = [
+  { label: '基础信息', value: 'basic' },
+  { label: '家庭信息', value: 'family' },
+  { label: '奖项信息', value: 'award' },
+  { label: '销售信息', value: 'sale' },
+  { label: '游学/活动信息', value: 'activity' },
+  { label: '其他活动信息', value: 'events' },
+]
+const id = ref()
+const { data: basicData, run: setBasicData } = useRequest(() => getDesignerBasicInfo(id.value))
+const eventsQuery = computed(() => ({ type: '3' }))
+// const {} = useRequest()
+const handleEditBasicInfo = async () => {
+  await uni.navigateTo({ url: `/pages/designer/archives/basic-info/index?id=${id.value}` })
+}
+onLoad(async (query: { id: string }) => {
+  id.value = query.id
+  await setBasicData()
+})
+</script>
+<template>
+  <div class="flex-grow bg-white">
+    <wd-tabs v-model="tab">
+      <template v-for="(it, index) in tabs" :key="index">
+        <wd-tab :title="it.label" :name="it.value"></wd-tab>
+      </template>
+    </wd-tabs>
+    <div class="flex flex-col px-5 gap-5">
+      <template v-if="tab === 'basic'">
+        <template
+          v-for="([key, value], index) in Object.entries(omit(basicData, ['id', 'userId']))"
+          :key="index"
+        >
+          <div class="flex items-center justify-between">
+            <div class="text-black/40 text-base font-normal font-['PingFang SC'] leading-none">
+              {{ messages.objects.designerBasiceInfo[key] }}
+            </div>
+            <DataRender v-bind="renders.designerBasiceInfo[key](value)"></DataRender>
+          </div>
+          <!-- <SectionHeading size="base" :title="messages.objects.designerBasiceInfo[key]">
+          <template #append>
+            <DataRender v-bind="renders.designerBasiceInfo[key](value)"></DataRender>
+          </template>
+        </SectionHeading> -->
+          <div class="w-full h-.25 bg-[#f4f4f4]"></div>
+        </template>
+      </template>
+      <template v-if="tab === 'family'">
+        <template></template>
+      </template>
+      <template v-if="tab === 'events'">
+        <PageHelperEvo :request="getDesignerExtraEvents" :query="eventsQuery">
+          <template #default="{ source }">
+            <template v-for="(it, index) in source.list" :key="index">
+              <div>{{ it }}</div>
+            </template>
+          </template>
+        </PageHelperEvo>
+      </template>
+    </div>
+    <BottomAppBar fixed placeholder>
+      <wd-button block :round="false" @click="handleEditBasicInfo">编辑</wd-button>
+    </BottomAppBar>
+  </div>
+</template>

+ 4 - 0
packages/merchant/src/pages/designer/detail.vue

@@ -37,6 +37,9 @@ const toPointsDetails = () => {
 const toOrderDetails = () => {
   uni.navigateTo({ url: '/pages/mine/merchant/orders/detail/index' })
 }
+const toArchives = () => {
+  uni.navigateTo({ url: '/pages/designer/archives/index?id=' + id.value })
+}
 onLoad(async (query: { id: string }) => {
   id.value = query.id
   await setData()
@@ -88,6 +91,7 @@ onLoad(async (query: { id: string }) => {
           </div>
           <div
             class="mt-4 px-1.5 py-1 bg-[#f0f3ff] rounded justify-center items-center gap-px inline-flex"
+            @click="toArchives"
           >
             <div class="text-[#2357e9] text-xs font-normal font-['PingFang_SC'] leading-3">
               个人档案

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

@@ -9,12 +9,14 @@ interface NavigateToOptions {
        "/pages/designer/index" |
        "/pages/home/index" |
        "/pages/mine/index" |
+       "/pages/designer/archives/index" |
        "/pages/designer/points_details/index" |
        "/pages/home/merchant/add-reporting-information" |
        "/pages/home/merchant/mine" |
        "/pages/home/merchant/settlement" |
        "/pages/home/tasks/index" |
        "/pages/mine/merchant/merchant_settings" |
+       "/pages/designer/archives/basic-info/index" |
        "/pages/home/agent/report-infos/index" |
        "/pages/home/agent/todo/index" |
        "/pages/home/tasks/detail/index" |