From 1d472eb06970c85b0edfb58871956bc2c8d69916 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期四, 25 十二月 2025 17:44:46 +0800
Subject: [PATCH] fix: 甲方小程序

---
 apps/housekeepingMiniApp/project.private.config.json                             |   11 +
 apps/housekeepingMiniApp/src/subpackages/mine/addressManange/InnerPage.vue       |    7 
 apps/housekeepingMiniApp/src/subpackages/sercice/addStandardOrder/InnerPage.vue  |  255 +++++++++++++++++++++++++++++++----
 packages/components/src/Input/ChooseInputWithDatePicker.vue                      |   10 +
 packages/components/src/Card/ServiceDetailAddressCard.vue                        |   31 +++
 apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue |   53 -------
 apps/cStandardMiniApp/src/styles/nut.scss                                        |    5 
 apps/housekeepingMiniApp/src/hooks/enterprise.ts                                 |    9 +
 apps/housekeepingMiniApp/src/styles/nut.scss                                     |    5 
 9 files changed, 288 insertions(+), 98 deletions(-)

diff --git a/apps/cStandardMiniApp/src/styles/nut.scss b/apps/cStandardMiniApp/src/styles/nut.scss
index ee5295d..9539f1a 100644
--- a/apps/cStandardMiniApp/src/styles/nut.scss
+++ b/apps/cStandardMiniApp/src/styles/nut.scss
@@ -127,6 +127,11 @@
   .bole-input-textarea:not(.nut-input--disabled) {
     color: boleGetCssVar('text-color', 'primary') !important;
     height: 100rpx;
+
+    .textarea-placeholder {
+      color: boleGetCssVar('text-color', 'placeholder') !important;
+      font-size: 26rpx;
+    }
   }
 
   .bole-input-text-placeholder {
diff --git a/apps/housekeepingMiniApp/project.private.config.json b/apps/housekeepingMiniApp/project.private.config.json
index b7b3260..ed955db 100644
--- a/apps/housekeepingMiniApp/project.private.config.json
+++ b/apps/housekeepingMiniApp/project.private.config.json
@@ -23,11 +23,18 @@
         "miniprogram": {
             "list": [
                 {
+                    "name": "閫夋嫨鍦板潃",
+                    "pathName": "subpackages/mine/addressManange/addressManange",
+                    "query": "type=select",
+                    "scene": null,
+                    "launchMode": "default"
+                },
+                {
                     "name": "棰勭害涓嬪崟",
                     "pathName": "subpackages/sercice/addStandardOrder/addStandardOrder",
                     "query": "specNumber=1&specId=72ec3beb-90dc-473b-d214-08de429af188&id=53208c5d-a823-40d3-e79e-08de429af17b",
-                    "scene": null,
-                    "launchMode": "default"
+                    "launchMode": "default",
+                    "scene": null
                 },
                 {
                     "name": "鏂板鍦板潃",
diff --git a/apps/housekeepingMiniApp/src/hooks/enterprise.ts b/apps/housekeepingMiniApp/src/hooks/enterprise.ts
index 1592700..b078d1f 100644
--- a/apps/housekeepingMiniApp/src/hooks/enterprise.ts
+++ b/apps/housekeepingMiniApp/src/hooks/enterprise.ts
@@ -1,13 +1,15 @@
-import { useInfiniteLoading } from '@12333/hooks';
+import { BaseData, useInfiniteLoading } from '@12333/hooks';
 import Taro from '@tarojs/taro';
 import * as enterpriseServices from '@12333/services/apiV2/enterprise';
+import { InfiniteData } from '@tanstack/vue-query';
 
 type UseEnterpriseAddressesOptions = {
   rows?: number;
+  onSuccess?: (data: InfiniteData<BaseData<API.GetEnterpriseAddressesQueryResultItem>>) => any;
 };
 
 export function useEnterpriseAddresses(options: UseEnterpriseAddressesOptions = {}) {
-  const { rows = 20 } = options;
+  const { rows = 20, onSuccess } = options;
 
   const { infiniteLoadingProps, invalidateQueries } = useInfiniteLoading(
     ({ pageParam }) => {
@@ -24,6 +26,9 @@
     },
     {
       queryKey: ['enterpriseServices/getEnterpriseAddresses', rows],
+      onSuccess(data) {
+        onSuccess?.(data);
+      },
     }
   );
 
diff --git a/apps/housekeepingMiniApp/src/styles/nut.scss b/apps/housekeepingMiniApp/src/styles/nut.scss
index ee5295d..9539f1a 100644
--- a/apps/housekeepingMiniApp/src/styles/nut.scss
+++ b/apps/housekeepingMiniApp/src/styles/nut.scss
@@ -127,6 +127,11 @@
   .bole-input-textarea:not(.nut-input--disabled) {
     color: boleGetCssVar('text-color', 'primary') !important;
     height: 100rpx;
+
+    .textarea-placeholder {
+      color: boleGetCssVar('text-color', 'placeholder') !important;
+      font-size: 26rpx;
+    }
   }
 
   .bole-input-text-placeholder {
diff --git a/apps/housekeepingMiniApp/src/subpackages/mine/addressManange/InnerPage.vue b/apps/housekeepingMiniApp/src/subpackages/mine/addressManange/InnerPage.vue
index 4cac17f..470a453 100644
--- a/apps/housekeepingMiniApp/src/subpackages/mine/addressManange/InnerPage.vue
+++ b/apps/housekeepingMiniApp/src/subpackages/mine/addressManange/InnerPage.vue
@@ -1,6 +1,6 @@
 <template>
   <InfiniteLoading
-    scrollViewClassName="common-infinite-scroll-list home-list"
+    scrollViewClassName="common-page-infinite-scroll-list"
     v-bind="infiniteLoadingProps"
   >
     <nut-address-list
@@ -28,6 +28,11 @@
   name: 'InnerPage',
 });
 
+const route = Taro.useRouter();
+const id = route.params?.id ?? '';
+const mode = route.params?.mode ?? '';
+const isSelectMode = mode === 'select';
+
 const dataOptions = reactive({
   id: 'id',
   addressDetail: 'addressDetail',
diff --git a/apps/housekeepingMiniApp/src/subpackages/sercice/addStandardOrder/InnerPage.vue b/apps/housekeepingMiniApp/src/subpackages/sercice/addStandardOrder/InnerPage.vue
index 53274b3..7855001 100644
--- a/apps/housekeepingMiniApp/src/subpackages/sercice/addStandardOrder/InnerPage.vue
+++ b/apps/housekeepingMiniApp/src/subpackages/sercice/addStandardOrder/InnerPage.vue
@@ -2,46 +2,108 @@
   <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
     <ContentScrollView hasPaddingTop>
       <ServiceDetailAddressCard
-        :name="defaultAddress?.name ?? ''"
-        :contactPhoneNumber="defaultAddress?.contactPhoneNumber ?? ''"
-        :addressDetail="defaultAddress?.addressDetail ?? ''"
+        :name="selectedAddress?.name ?? ''"
+        :contactPhoneNumber="selectedAddress?.contactPhoneNumber ?? ''"
+        :addressDetail="selectedAddress?.addressDetail ?? ''"
+        showArrow
+        @click="goSelectAddress"
       />
-      <div class="addStandardOrder-detail-card">
-        <nut-card
-          :img-url="'//img10.360buyimg.com/n2/s240x240_jfs/t1/210890/22/4728/163829/6163a590Eb7c6f4b5/6390526d49791cb9.jpg!q70.jpg'"
-          :title="detail?.name ?? ''"
-          :price="toThousand(spec?.price ?? 0)"
-          class="service-good-card"
+      <ServiceDetailGoodCard
+        :name="detail?.name"
+        :price="spec?.price"
+        :specName="spec?.name"
+        :specNumber="specNumber"
+        :imgUrl="detail?.files?.[0]"
+      />
+      <!-- <List>
+        <ListItem title="鏈嶅姟鏃堕棿">
+          <template #extra>
+            <div class="mine-service-detail-view-list-item">{{ '璇烽�夋嫨' }}</div>
+          </template>
+        </ListItem>
+        <ListItem title="鏈嶅姟鏈烘瀯">
+          <template #extra>
+            <div class="mine-service-detail-view-list-item">{{ '璇烽�夋嫨' }}</div>
+          </template>
+        </ListItem>
+      </List> -->
+      <nut-form :model-value="form" ref="formRef" :rules="rules" class="addStandardOrder-form">
+        <nut-form-item
+          label="鏈嶅姟寮�濮嬫椂闂�:"
+          class="bole-form-item"
+          prop="beginTime"
+          label-width="90px"
         >
-          <template #prolist>
-            <div class="card-tag-list">
-              <span class="tag">{{ spec?.name }}</span>
-            </div>
-          </template>
-          <template #origin>
-            <div></div>
-          </template>
-          <template #footer>
-            <div class="card-footer">x{{ specNumber }}</div>
-          </template>
-        </nut-card>
-      </div>
+          <ChooseInputWithDatePicker
+            v-model="form.beginTime"
+            :minDate="nowDate"
+            placeholder="璇烽�夋嫨"
+            type="datetime"
+            format="YYYY-MM-DD HH:mm:ss"
+          ></ChooseInputWithDatePicker>
+        </nut-form-item>
+        <nut-form-item
+          label="鏈嶅姟缁撴潫鏃堕棿:"
+          class="bole-form-item"
+          prop="endTime"
+          label-width="90px"
+        >
+          <ChooseInputWithDatePicker
+            v-model="form.endTime"
+            :minDate="endMinTime"
+            :maxDate="endMaxTime"
+            placeholder="璇烽�夋嫨"
+            type="datetime"
+            format="YYYY-MM-DD HH:mm:ss"
+          ></ChooseInputWithDatePicker>
+        </nut-form-item>
+        <nut-form-item
+          label="澶囨敞:"
+          class="bole-form-item alignTop"
+          prop="remark"
+          label-width="90px"
+        >
+          <nut-textarea
+            v-model="form.remark"
+            class="bole-input-textarea"
+            rows="4"
+            placeholder="璇峰~鍐欏娉ㄤ俊鎭�"
+          >
+          </nut-textarea>
+        </nut-form-item>
+      </nut-form>
     </ContentScrollView>
     <PageFooter>
       <PageFooterBtn type="primary" class="business-card-btn" @click="goConfirm"
         >绔嬪嵆涓嬪崟</PageFooterBtn
       >
     </PageFooter>
+    <nut-address
+      v-model:visible="form.selectAddressVisible"
+      v-model:value="form.addressId"
+      type="exist"
+      :exist-address="existAddress"
+      :is-show-custom-address="false"
+      @selected="selected"
+      exist-address-title="閫夋嫨鍦板潃"
+    ></nut-address>
   </LoadingLayout>
 </template>
 
 <script setup lang="ts">
-import { ServiceDetailAddressCard } from '@12333/components';
+import {
+  ServiceDetailAddressCard,
+  ServiceDetailGoodCard,
+  List,
+  ListItem,
+  ChooseInputWithDatePicker,
+} from '@12333/components';
 import Taro from '@tarojs/taro';
-import * as standardServiceServices from '@12333/services/apiV2/standardService';
 import { RouterPath } from '@/constants';
 import { useStandardServiceDetail } from '@12333/hooks';
-import { toThousand } from '@12333/utils';
+import * as standardOrderServices from '@12333/services/apiV2/standardOrder';
+import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
+import dayjs from 'dayjs';
 
 defineOptions({
   name: 'InnerPage',
@@ -52,6 +114,37 @@
 const specId = route.params?.specId ?? '';
 const specNumber = Number(route.params?.specNumber);
 
+const form = reactive({
+  addressId: '',
+  selectAddressVisible: false,
+  beginTime: '',
+  endTime: '',
+  supplierEnterpriseId: '',
+  enterpriseEmployeeIds: [] as string[],
+  remark: '',
+});
+
+const nowDate = dayjs().toDate();
+const endMinTime = computed(() => {
+  if (form.beginTime) {
+    return dayjs(form.beginTime).add(1, 'minute').toDate();
+  } else {
+    return dayjs().toDate();
+  }
+});
+const endMaxTime = computed(() => {
+  if (form.beginTime) {
+    return dayjs(dayjs(form.beginTime).format('YYYY-MM-DD 23:59:59')).toDate();
+  } else {
+    return undefined;
+  }
+});
+
+const rules = reactive<FormRules>({
+  beginTime: [{ required: true, message: '璇烽�夋嫨鏈嶅姟寮�濮嬫椂闂�' }],
+  endTime: [{ required: true, message: '璇烽�夋嫨鏈嶅姟缁撴潫鏃堕棿' }],
+});
+
 const { isLoading, isError, detail, refetch } = useStandardServiceDetail({
   id,
 });
@@ -65,26 +158,120 @@
 
 const { infiniteLoadingProps } = useEnterpriseAddresses({
   rows: 100,
+  onSuccess(res) {
+    const data = res.pages[0].data;
+    const address = data.find((item) => item.isDefault);
+    if (address) {
+      form.addressId = address.id;
+    } else {
+      form.addressId = data[0].id;
+    }
+  },
 });
 
-const defaultAddress = computed(() => {
-  const address = infiniteLoadingProps.value.flattenListData.find((item) => item.isDefault);
+const existAddress = computed(() => {
+  return infiniteLoadingProps.value.flattenListData.map((x) => ({
+    id: x.id,
+    addressDetail: x.addressDetail,
+    cityName: '',
+    countyName: '',
+    provinceName: '',
+    selectedAddress: x.id === form.addressId,
+    townName: '',
+    name: x.name,
+    phone: x.contactPhoneNumber,
+  }));
+});
+
+const selectedAddress = computed(() => {
+  const address = infiniteLoadingProps.value.flattenListData.find(
+    (item) => item.id === form.addressId
+  );
   return address || infiniteLoadingProps.value.flattenListData[0];
 });
 
-function goCancel() {
-  Taro.navigateTo({
-    url: `${RouterPath.mineReserveServiceCancel}?id=${id}`,
+function goSelectAddress() {
+  // Taro.navigateTo({
+  //   url: `${RouterPath.addressManange}?mode=select`,
+  // });
+  form.selectAddressVisible = true;
+}
+
+const selected = (prevExistAdd, nowExistAdd, arr) => {
+  form.addressId = nowExistAdd.id;
+};
+
+const formRef = ref<any>(null);
+function goConfirm() {
+  if (!formRef.value) return;
+  formRef.value.validate().then(({ valid, errors }: any) => {
+    if (valid) {
+      // addStandardOrder();
+    }
   });
 }
 
-function goConfirm() {
-  Taro.navigateTo({
-    url: `${RouterPath.mineReserveServiceConfirm}?id=${id}`,
-  });
+async function addStandardOrder() {
+  try {
+    let params: API.AddStandardOrderCommand = {
+      serviceId: detail.value.id,
+      serviceName: detail.value.name,
+      serviceCode: detail.value.code,
+      specId: spec.value.id,
+      specName: spec.value.name,
+      specPrice: spec.value.price ?? 0,
+      specNumber: specNumber,
+      addressId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
+      name: detail.value.name,
+      contactPhoneNumber: 'string',
+      provinceCode: 'string',
+      provinceContent: 'string',
+      cityCode: 'string',
+      cityContent: 'string',
+      areaCode: 'string',
+      areaContent: 'string',
+      addressName: 'string',
+      addressDetail: 'string',
+      longitude: 0,
+      latitude: 0,
+      beginTime: '2025-12-24T08:25:08.372Z',
+      endTime: '2025-12-24T08:25:08.372Z',
+      supplierEnterpriseId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
+      enterpriseEmployeeIds: ['3fa85f64-5717-4562-b3fc-2c963f66afa6'],
+      remark: 'string',
+      payAccess: 1,
+    };
+    let res = await standardOrderServices.addStandardOrder(params);
+  } catch (error) {}
+}
+
+async function pay() {
+  try {
+    let params: API.PayStandardOrderCommand = {
+      id: '9e919af2-3d33-4eac-f6dc-08de429676b3',
+    };
+    let res = await standardOrderServices.payStandardOrder(params);
+    if (res) {
+      Taro.requestPayment({
+        timeStamp: res.timestamp,
+        nonceStr: res.nonceStr,
+        package: res.package,
+        signType: res.signType as any,
+        paySign: res.paySign,
+      });
+    }
+  } catch (error) {}
 }
 </script>
 
 <style lang="scss">
 @import '@/styles/common.scss';
+
+.addStandardOrder-page-wrapper {
+  .addStandardOrder-form {
+    .nut-cell-group__wrap {
+      box-shadow: none;
+    }
+  }
+}
 </style>
diff --git a/apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue b/apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue
index 4c86db3..6911877 100644
--- a/apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue
+++ b/apps/housekeepingMiniApp/src/subpackages/sercice/serciceDetail/serciceDetail.vue
@@ -166,59 +166,6 @@
   });
 });
 
-async function addStandardOrder(specNumber: number) {
-  try {
-    const spec = SkuUtils.getCurrentActiveSpec(skuState.sku);
-    let params: API.AddStandardOrderCommand = {
-      serviceId: detail.value.id,
-      serviceName: detail.value.name,
-      serviceCode: detail.value.code,
-      specId: spec.id,
-      specName: spec.name,
-      specPrice: detail.value.specs.find((x) => x.id === spec.id)?.price ?? 0,
-      specNumber: specNumber,
-      addressId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
-      name: detail.value.name,
-      contactPhoneNumber: 'string',
-      provinceCode: 'string',
-      provinceContent: 'string',
-      cityCode: 'string',
-      cityContent: 'string',
-      areaCode: 'string',
-      areaContent: 'string',
-      addressName: 'string',
-      addressDetail: 'string',
-      longitude: 0,
-      latitude: 0,
-      beginTime: '2025-12-24T08:25:08.372Z',
-      endTime: '2025-12-24T08:25:08.372Z',
-      supplierEnterpriseId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
-      enterpriseEmployeeIds: ['3fa85f64-5717-4562-b3fc-2c963f66afa6'],
-      remark: 'string',
-      payAccess: 1,
-    };
-    let res = await standardOrderServices.addStandardOrder(params);
-  } catch (error) {}
-}
-
-async function pay() {
-  try {
-    let params: API.PayStandardOrderCommand = {
-      id: '9e919af2-3d33-4eac-f6dc-08de429676b3',
-    };
-    let res = await standardOrderServices.payStandardOrder(params);
-    if (res) {
-      Taro.requestPayment({
-        timeStamp: res.timestamp,
-        nonceStr: res.nonceStr,
-        package: res.package,
-        signType: res.signType as any,
-        paySign: res.paySign,
-      });
-    }
-  } catch (error) {}
-}
-
 async function handleAttention() {
   try {
     let params: API.CollectionStandardServiceCommand = {
diff --git a/packages/components/src/Card/ServiceDetailAddressCard.vue b/packages/components/src/Card/ServiceDetailAddressCard.vue
index 733d4e2..80ddcc0 100644
--- a/packages/components/src/Card/ServiceDetailAddressCard.vue
+++ b/packages/components/src/Card/ServiceDetailAddressCard.vue
@@ -1,14 +1,19 @@
 <template>
   <div class="mine-service-detail-view-address">
-    <div class="mine-service-detail-view-title-wrapper">
-      <div class="mine-service-detail-view-title">鏈嶅姟鍦板潃</div>
+    <div class="mine-service-detail-view-address-inner">
+      <div class="mine-service-detail-view-title-wrapper">
+        <div class="mine-service-detail-view-title">鏈嶅姟鍦板潃</div>
+      </div>
+      <div class="mine-service-detail-view-item">{{ addressDetail }}</div>
+      <div class="mine-service-detail-view-item">{{ name }} {{ contactPhoneNumber }}</div>
     </div>
-    <div class="mine-service-detail-view-item">{{ addressDetail }}</div>
-    <div class="mine-service-detail-view-item">{{ name }} {{ contactPhoneNumber }}</div>
+    <img v-if="showArrow" :src="IconArrow" class="mine-service-detail-view-arrow" />
   </div>
 </template>
 
 <script setup lang="ts">
+import IconArrow from '@/assets/setting/icon-arrow.png';
+
 defineOptions({
   name: 'ServiceDetailAddressCard',
 });
@@ -19,9 +24,12 @@
   contactPhoneNumber?: string;
   /** 鐪佸競鍖�+璇︾粏鍦板潃+闂ㄧ墝鍙� */
   addressDetail?: string;
+  showArrow?: boolean;
 };
 
-const props = withDefaults(defineProps<Props>(), {});
+const props = withDefaults(defineProps<Props>(), {
+  showArrow: false,
+});
 </script>
 
 <style lang="scss">
@@ -32,6 +40,13 @@
   margin-bottom: 24px;
   background-color: #fff;
   border-radius: 12px;
+  display: flex;
+  align-items: center;
+
+  .mine-service-detail-view-address-inner {
+    flex: 1;
+    min-width: 0;
+  }
 
   .mine-service-detail-view-title-wrapper {
     display: flex;
@@ -59,5 +74,11 @@
       margin-top: 14px;
     }
   }
+
+  .mine-service-detail-view-arrow {
+    width: 32px;
+    height: 32px;
+    margin-left: 12px;
+  }
 }
 </style>
diff --git a/packages/components/src/Input/ChooseInputWithDatePicker.vue b/packages/components/src/Input/ChooseInputWithDatePicker.vue
index a68a71f..f5b69c2 100644
--- a/packages/components/src/Input/ChooseInputWithDatePicker.vue
+++ b/packages/components/src/Input/ChooseInputWithDatePicker.vue
@@ -53,7 +53,15 @@
                   type: props.type,
                   maxDate: props.maxDate,
                   onConfirm: ({ selectedValue }) => {
-                    emit('update:modelValue', dayjs(selectedValue.join('-')).format(props.format));
+                    let _selectedVale = '';
+                    if (selectedValue.length > 3) {
+                      _selectedVale = `${selectedValue.slice(0, 3).join('-')} ${selectedValue
+                        .slice(3)
+                        .join(':')}`;
+                    } else {
+                      _selectedVale = selectedValue.join('-');
+                    }
+                    emit('update:modelValue', dayjs(_selectedVale).format(props.format));
                     onClose();
                   },
                   onChange: () => {

--
Gitblit v1.10.0