Ver código fonte

feat(app): 材料商列表页面并添加新功能

EvilDragon 5 meses atrás
pai
commit
40983f0d9b

+ 2 - 0
packages/app/src/components/card.vue

@@ -5,11 +5,13 @@ defineProps({
     default: () => '',
   },
 })
+const emits = defineEmits(['click'])
 </script>
 <template>
   <view
     class="rounded-2xl bg-white shadow-[0_16rpx_20rpx_-10rpx_rgba(0,0,0,0.05)] p-3.5 overflow-hidden box-border"
     :class="customClass"
+    @click="emits('click')"
   >
     <slot></slot>
   </view>

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

@@ -1,7 +1,8 @@
 import { http, httpGet, httpPost } from '../../utils/http'
 import { Schedule } from '../models/schedule'
-import { DictType, Moment } from '../models/moment'
+import { DictType, MaterialDealer, materialDealer, Moment } from '../models/moment'
 import dayjs from 'dayjs'
+import { getMaterialDealers } from './requests'
 
 export const getUserInfo = () =>
   httpGetMock<any>({
@@ -288,6 +289,16 @@ export const getSetIndexConfigs = (query = {}) =>
       createTime: string
     }[]
   }>('/app-api/basicsetting/set-index-config/page', query)
+
+/**
+ * 获取材料商列表
+ * @param query {{brandLevel: '1'|'2'}}
+ * @returns {Promise<*>}
+ */
+export const getMaterials = (query = {}) =>
+  httpGet<{
+    list: MaterialDealer[]
+  }>('/app-api/member/materials/page', query)
 export const refreshToken = (refreshToken: string) =>
   httpPost<any>('/app-api/member/auth/refresh-token', {}, { refreshToken })
 export const httpGetMock = <T>(data: T) =>

+ 33 - 0
packages/app/src/core/models/moment.ts

@@ -51,6 +51,31 @@ export interface Task {
   sort: number
   status: number
 }
+export interface MaterialDealer {
+  id: number
+  logoUrl: string
+  materialsName: string
+  materialsType: number
+  brandLevel: number
+  manageType: number
+  manageBrand: number
+  brandType: number
+  storeAddress: string
+  storeName: string
+  contactPerson: string
+  contactPhone: string
+  invoiceTitle: string
+  taxpayerNumber: string
+  invoiceAddr: string
+  bankDeposit: string
+  agreementFileUrl: string
+  virtualArrival: number
+  status: string
+  createTime: string
+  points: number
+  clockPoints: string
+  orderCount: number
+}
 export enum DictType {
   /**
    *  擅长空间类型
@@ -64,6 +89,14 @@ export enum DictType {
    * 圈子标签
    */
   circleTag = 'basic_set_label_type',
+  /**
+   * 材料商品牌等级
+   */
+  memberMaterialsBrandLevel = 'member_materials_brand_level',
+  /**
+   * 材料商运营类型
+   */
+  memberMaterialsOperationType = 'member_materials_operation_type',
 }
 export enum CircleType {
   moment = '1',

+ 66 - 36
packages/app/src/pages/material/index.vue

@@ -6,11 +6,22 @@
 import Card from '@/components/card.vue'
 import SectionHeading from '@/components/section-heading.vue'
 import { abc, calculator } from '../../core/libs/pngs'
-import { getMaterialDealers } from '../../core/libs/requests'
+import { getByDictType, getMaterials } from '../../core/libs/requests'
 import { materialDealers, close, phone } from '../../core/libs/svgs'
-import CardMenu from '@/components/card-menu.vue'
+import { DictType, MaterialDealer } from '../../core/models/moment'
 
-const { data, run } = useRequest(getMaterialDealers)
+const { data, run } = useRequest(() => getByDictType(DictType.memberMaterialsBrandLevel))
+const { data: materialOperationTypes, run: setMaterialOperationTypes } = useRequest(() =>
+  getByDictType(DictType.memberMaterialsOperationType),
+)
+const { data: selfOperateds, run: setSelfOperateds } = useRequest(
+  () => getMaterials({ brandLevel: 1 }),
+  { initialData: { list: [] } },
+)
+const { data: jointVenture, run: setJointVenture } = useRequest(
+  () => getMaterials({ brandLevel: 2 }),
+  { initialData: { list: [] } },
+)
 const dealerPanelState = ref(false)
 const pieces = ref([
   {
@@ -36,6 +47,7 @@ const pieces = ref([
     path: '/pages/material/recommend/index',
   },
 ])
+const materialsByBrandLevel = ref<{ list: MaterialDealer[] }[]>([])
 const handleMenuItemClick = ({ path }: any) => {
   uni.navigateTo({ url: path })
 }
@@ -44,8 +56,15 @@ const toDetail = () => {
     url: '/pages/material/detail/index',
   })
 }
-onMounted(() => {
-  run()
+onMounted(async () => {
+  await run()
+  console.log(data.value)
+  await setMaterialOperationTypes()
+  const reqs = data.value.map((it) =>
+    getMaterials({ brandLevel: it.value }).then(({ data }) => data),
+  )
+  materialsByBrandLevel.value = await Promise.all(reqs)
+  console.log(materialsByBrandLevel.value)
 })
 </script>
 <template>
@@ -94,37 +113,48 @@ onMounted(() => {
           </div>
         </template>
       </div>
-      <SectionHeading title="自营品牌" custom-class="mx-3.5"></SectionHeading>
-      <div class="my-6 flex px-1.75">
-        <template v-for="(it, i) in data" :key="i">
-          <Card custom-class="mx-1.75" :style="{ width: 'calc(50vw - 96rpx)' }" @click="toDetail">
-            <div class="flex flex-col items-center">
-              <wd-img
-                width="78"
-                height="78"
-                custom-class="border border-[#f2f2f2] rounded-full overflow-hidden"
-                :src="it.icon"
-              ></wd-img>
-              <div
-                class="my-4 text-black/90 text-base font-normal font-['PingFang SC'] leading-[10.18px]"
-              >
-                IMOLA瓷砖
-              </div>
-              <div
-                class="mb-4 text-black/60 text-sm font-normal font-['PingFang SC'] leading-[10.18px]"
-              >
-                进口品牌 | 瓷砖
-              </div>
-              <wd-button size="small" custom-class="my-4" @click="dealerPanelState = true">
-                联系商家
-              </wd-button>
-              <div class="text-black/30 text-xs font-normal font-['PingFang SC'] leading-[10.18px]">
-                {{ it.views }}次到店打卡
-              </div>
+
+      <template v-for="({ label }, i) in data" :key="i">
+        <SectionHeading :title="label" custom-class="mx-3.5"></SectionHeading>
+        <div class="my-6 flex px-3.5 gap-3">
+          <template v-for="(it, index) in materialsByBrandLevel[i]?.list" :key="index">
+            <div :style="{ width: '50%' }">
+              <Card @click="toDetail">
+                <div class="flex flex-col items-center">
+                  <wd-img
+                    width="78"
+                    height="78"
+                    custom-class="border border-[#f2f2f2] rounded-full overflow-hidden"
+                    :src="it.logoUrl"
+                  ></wd-img>
+                  <div
+                    class="my-4 text-black/90 text-base font-normal font-['PingFang SC'] leading-[10.18px]"
+                  >
+                    {{ it.materialsName }}
+                  </div>
+                  <div
+                    class="mb-4 text-black/60 text-sm font-normal font-['PingFang SC'] leading-[10.18px]"
+                  >
+                    进口品牌 {{ it.brandType }} |
+                    {{
+                      materialOperationTypes.find(({ value }) => value === String(it.manageType))
+                        ?.label
+                    }}
+                  </div>
+                  <wd-button size="small" custom-class="my-4" @click="dealerPanelState = true">
+                    联系商家
+                  </wd-button>
+                  <div
+                    class="text-black/30 text-xs font-normal font-['PingFang SC'] leading-[10.18px]"
+                  >
+                    {{ it.virtualArrival || 0 }}次到店打卡
+                  </div>
+                </div>
+              </Card>
             </div>
-          </Card>
-        </template>
-      </div>
+          </template>
+        </div>
+      </template>
     </view>
 
     <!-- <wd-action-sheet v-model="dealerPanelState">
@@ -134,7 +164,7 @@ onMounted(() => {
       <view style="padding: 15px 15px 150px 15px">内容</view>
     </wd-action-sheet> -->
     <wd-overlay :show="dealerPanelState" @click="dealerPanelState = false">
-      <view class="wrapper bg-amber/50 flex flex-col justify-end h-full">
+      <view class="wrapper flex flex-col justify-end h-full">
         <div class="w-full flex justify-end mb-4">
           <div class="mr-3.5">
             <wd-button type="text" custom-class="w-8! h-8! p-0!" size="small">