From d0b06ccc74fcbe1c113eb3fc4cd52f935655f4e1 Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期二, 11 十一月 2025 14:08:00 +0800
Subject: [PATCH] Merge branch 'dev-1.3.0.1' into dev-1.3.0.2

---
 apps/underTakeMiniApp/src/pages/publish/publish.config.ts |    3 
 apps/underTakeMiniApp/src/custom-tab-bar/index.tsx        |   15 
 apps/underTakeMiniApp/src/pages/publish/publish.vue       |   14 
 apps/underTakeMiniApp/src/pages/publish/InnerPage.vue     |  807 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/underTakeMiniApp/src/app.config.ts                   |    8 
 apps/underTakeMiniApp/src/constants/tabBar.ts             |    7 
 6 files changed, 850 insertions(+), 4 deletions(-)

diff --git a/apps/underTakeMiniApp/src/app.config.ts b/apps/underTakeMiniApp/src/app.config.ts
index a301864..bd8b870 100644
--- a/apps/underTakeMiniApp/src/app.config.ts
+++ b/apps/underTakeMiniApp/src/app.config.ts
@@ -1,6 +1,6 @@
 export default defineAppConfig({
   entryPagePath: 'pages/workbenches/workbenches',
-  pages: ['pages/workbenches/workbenches', 'pages/mine/index'],
+  pages: ['pages/workbenches/workbenches', 'pages/publish/publish', 'pages/mine/index'],
   requiredPrivateInfos: ['getLocation', 'chooseLocation'],
   permission: {
     'scope.userLocation': {
@@ -26,6 +26,12 @@
         text: '宸ヤ綔鍙�',
       },
       {
+        pagePath: 'pages/publish/publish',
+        iconPath: 'assets/tabbar/icon-publish.png',
+        selectedIconPath: 'assets/tabbar/icon-publish.png',
+        text: '鍙戝竷',
+      },
+      {
         pagePath: 'pages/mine/index',
         iconPath: 'assets/tabbar/icon-mine.png',
         selectedIconPath: 'assets/tabbar/icon-mine-active.png',
diff --git a/apps/underTakeMiniApp/src/constants/tabBar.ts b/apps/underTakeMiniApp/src/constants/tabBar.ts
index 7cbb417..244c94c 100644
--- a/apps/underTakeMiniApp/src/constants/tabBar.ts
+++ b/apps/underTakeMiniApp/src/constants/tabBar.ts
@@ -1,6 +1,11 @@
 export const TabBarPageRouter = {
   Workbenches: '/pages/workbenches/workbenches',
+  Publish: '/pages/publish/publish',
   Mine: '/pages/mine/index',
 };
 
-export const TabBarPageRouterList = [TabBarPageRouter.Workbenches, TabBarPageRouter.Mine];
+export const TabBarPageRouterList = [
+  TabBarPageRouter.Workbenches,
+  TabBarPageRouter.Publish,
+  TabBarPageRouter.Mine,
+];
diff --git a/apps/underTakeMiniApp/src/custom-tab-bar/index.tsx b/apps/underTakeMiniApp/src/custom-tab-bar/index.tsx
index b9fc9ed..6d484b0 100644
--- a/apps/underTakeMiniApp/src/custom-tab-bar/index.tsx
+++ b/apps/underTakeMiniApp/src/custom-tab-bar/index.tsx
@@ -140,15 +140,26 @@
             index={0}
           ></TarBarItem>
           <TarBarItem
+            text="鍙戝竷"
+            icon="../assets/tabbar/icon-publish.png"
+            activeIcon="../assets/tabbar/icon-publish.png"
+            pagePath={TabBarPageRouter.Publish}
+            currentPath={_router.path}
+            active={system.activeTab === 1}
+            className="task"
+            onClick={switchTab}
+            index={1}
+          ></TarBarItem>
+          <TarBarItem
             text="鎴戠殑"
             icon="../assets/tabbar/icon-mine.png"
             activeIcon="../assets/tabbar/icon-mine-active.png"
             pagePath={TabBarPageRouter.Mine}
             currentPath={_router.path}
-            active={system.activeTab === 1}
+            active={system.activeTab === 2}
             className="mine"
             onClick={switchTab}
-            index={1}
+            index={2}
           ></TarBarItem>
         </View>
       );
diff --git a/apps/underTakeMiniApp/src/pages/publish/InnerPage.vue b/apps/underTakeMiniApp/src/pages/publish/InnerPage.vue
new file mode 100644
index 0000000..ad8484f
--- /dev/null
+++ b/apps/underTakeMiniApp/src/pages/publish/InnerPage.vue
@@ -0,0 +1,807 @@
+<template>
+  <ContentScrollView :paddingH="false">
+    <nut-form :model-value="form" ref="formRef" :rules="rules">
+      <nut-form-item
+        label="渚涘簲鍟�:"
+        class="bole-form-item"
+        prop="supplierEnterpriseId"
+        label-width="90px"
+        required
+      >
+        <ChooseInputWithPicker
+          v-model="form.supplierEnterpriseId"
+          placeholder="璇烽�夋嫨渚涘簲鍟�"
+          :value-enum="supplierEnterpriseSelect"
+          :disabled="isEdit"
+        />
+      </nut-form-item>
+      <nut-form-item label="浠诲姟鍚嶇О:" class="bole-form-item" prop="name" label-width="90px">
+        <nut-input v-model="form.name" placeholder="璇疯緭鍏ヤ换鍔″悕绉�"> </nut-input>
+      </nut-form-item>
+      <nut-form-item
+        label="闇�姹備汉鏁�:"
+        class="bole-form-item"
+        prop="needPeopleNumber"
+        label-width="90px"
+      >
+        <div class="bole-form-input-wrapper">
+          <NumberInput
+            v-model.trim="form.needPeopleNumber"
+            class="nut-input-text bole-input-text"
+            placeholder="璇疯緭鍏ラ渶姹備汉鏁�"
+            :min="0"
+            :max="999999999999"
+            :precision="0"
+            @change="calcTaskTotalServiceFee"
+          />
+          <div class="form-input-unit">浜�</div>
+        </div>
+      </nut-form-item>
+      <nut-form-item
+        label="鏈嶅姟璐�:"
+        class="bole-form-item alignTop"
+        prop="billingMethod"
+        required
+        label-width="90px"
+        label-position="top"
+      >
+        <nut-radio-group
+          v-model="form.billingMethod"
+          direction="horizontal"
+          @change="calcTaskTotalServiceFee"
+        >
+          <BlRadio
+            :label="Number(key)"
+            v-for="(val, key) in EnumBillingMethodText"
+            :key="key"
+            :disabled="feeCannotEdit"
+            >{{ val }}</BlRadio
+          >
+        </nut-radio-group>
+      </nut-form-item>
+      <nut-form-item
+        label=" "
+        class="bole-form-item"
+        prop="serviceFee"
+        label-width="0"
+        v-if="form.billingMethod !== EnumBillingMethod.Face"
+      >
+        <div class="bole-form-input-wrapper">
+          <NumberInput
+            v-model.trim="form.serviceFee"
+            class="nut-input-text bole-input-text"
+            placeholder="璇疯緭鍏ユ湇鍔¤垂"
+            :min="0"
+            :max="999999999999"
+            :precision="2"
+            type="text"
+            :disabled="feeCannotEdit"
+            @change="calcTaskTotalServiceFee"
+          />
+          <div class="form-input-unit">{{ BillingMethodEnumUnit[form.billingMethod] }}</div>
+        </div>
+      </nut-form-item>
+      <template v-if="form.billingMethod === EnumBillingMethod.Hour">
+        <nut-form-item
+          label="鏍稿畾宸ユ椂:"
+          class="bole-form-item"
+          prop="verifyWorkHours"
+          label-width="90"
+        >
+          <div class="bole-form-input-wrapper">
+            <NumberInput
+              v-model.trim="form.verifyWorkHours"
+              class="nut-input-text bole-input-text"
+              placeholder="璇疯緭鍏ユ牳瀹氬伐鏃�"
+              :min="0"
+              :max="999999999999"
+              :precision="2"
+              type="text"
+              :disabled="feeCannotEdit"
+              @change="calcTaskTotalServiceFee"
+            />
+            <div class="form-input-unit">{{ '灏忔椂/澶�' }}</div>
+          </div>
+        </nut-form-item>
+        <nut-form-item
+          label="瓒呮椂鏈嶅姟璐�:"
+          class="bole-form-item"
+          prop="timeoutServiceFee"
+          label-width="90"
+        >
+          <div class="bole-form-input-wrapper">
+            <NumberInput
+              v-model.trim="form.timeoutServiceFee"
+              class="nut-input-text bole-input-text"
+              placeholder="璇疯緭鍏ヨ秴鏃舵湇鍔¤垂"
+              :min="0"
+              :max="999999999999"
+              :precision="2"
+              type="text"
+              :disabled="feeCannotEdit"
+            />
+            <div class="form-input-unit">{{ '鍏�/灏忔椂' }}</div>
+          </div>
+        </nut-form-item>
+      </template>
+      <nut-form-item
+        v-if="form.billingMethod === EnumBillingMethod.Piece"
+        label="鎬讳欢鏁�:"
+        class="bole-form-item"
+        prop="totalPieceQuantity"
+        label-width="90"
+      >
+        <div class="bole-form-input-wrapper">
+          <NumberInput
+            v-model.trim="form.totalPieceQuantity"
+            class="nut-input-text bole-input-text"
+            placeholder="璇疯緭鍏ヤ换鍔℃�讳欢鏁�"
+            :min="0"
+            :max="999999999999"
+            :precision="2"
+            type="text"
+            :disabled="feeCannotEdit"
+            @change="calcTaskTotalServiceFee"
+          />
+          <div class="form-input-unit">{{ '浠�' }}</div>
+        </div>
+      </nut-form-item>
+      <nut-form-item
+        label="缁撶畻鏂瑰紡:"
+        class="bole-form-item"
+        prop="settleType"
+        required
+        label-width="90px"
+      >
+        <nut-radio-group
+          v-model="form.settlementCycle"
+          direction="horizontal"
+          @change="settleTypeChange"
+        >
+          <BlRadio
+            :label="Number(key)"
+            v-for="(val, key) in EnumSettlementCycleText"
+            :key="key"
+            :disabled="feeCannotEdit"
+            >{{ val }}</BlRadio
+          >
+        </nut-radio-group>
+      </nut-form-item>
+      <nut-form-item
+        label="缁撶畻鏃ユ湡:"
+        class="bole-form-item"
+        prop="settlementDate"
+        label-width="90px"
+        required
+        v-if="form.settlementCycle !== EnumSettlementCycle.Day"
+      >
+        <ChooseInputWithPicker
+          v-model="form.settlementDate"
+          placeholder="璇疯缃粨绠楁棩鏈�"
+          :value-enum="settlementDateList"
+        />
+      </nut-form-item>
+      <nut-form-item label="绂忓埄:" class="bole-form-item" prop="benefits" label-width="90px">
+        <ChooseInputWithCheckbox
+          v-model="form.benefits"
+          title="璇烽�夋嫨绂忓埄"
+          :columns="WelfareTypeList"
+          placeholder="璇烽�夋嫨绂忓埄"
+        />
+      </nut-form-item>
+      <nut-form-item
+        label="骞撮緞鑼冨洿:"
+        class="bole-form-item"
+        prop="ageMinLimit"
+        required
+        label-width="90px"
+      >
+        <div class="bole-form-input-wrapper">
+          <NumberInput
+            v-model.trim="form.ageMinLimit"
+            class="nut-input-text bole-input-text"
+            placeholder="璇烽�夋嫨骞撮緞鑼冨洿"
+            :min="16"
+          />
+          <div class="form-input-separator">鑷�</div>
+          <NumberInput
+            v-model.trim="form.ageMaxLimit"
+            class="nut-input-text bole-input-text"
+            placeholder="璇烽�夋嫨骞撮緞鑼冨洿"
+            :min="16"
+          />
+        </div>
+      </nut-form-item>
+      <nut-form-item
+        label="鎬у埆瑕佹眰:"
+        class="bole-form-item"
+        prop="genderLimit"
+        label-width="90px"
+        required
+      >
+        <ChooseInputWithPicker
+          v-model="form.genderLimit"
+          placeholder="璇烽�夋嫨鎬у埆瑕佹眰"
+          :value-enum="EnumUserGenderTextOptions"
+        />
+      </nut-form-item>
+      <nut-form-item
+        label="璧勬牸璇佷功:"
+        class="bole-form-item"
+        prop="credentialLimits"
+        label-width="90px"
+      >
+        <ChooseInputWithCheckbox
+          v-model="form.credentialLimits"
+          title="璇烽�夋嫨璧勬牸璇佷功"
+          :columns="CertificateTypeList"
+          placeholder="璇烽�夋嫨璧勬牸璇佷功"
+        />
+      </nut-form-item>
+      <nut-form-item
+        label="浠诲姟鍦扮偣"
+        label-width="90px"
+        class="bole-form-item"
+        prop="weMapInfo"
+        required
+      >
+        <ChooseLocationInput
+          inputAlign="left"
+          placeholder="璇烽�夋嫨浠诲姟鍦扮偣"
+          v-model="form.weMapInfo"
+        />
+      </nut-form-item>
+      <nut-form-item
+        label="鍦扮偣璇存槑:"
+        class="bole-form-item"
+        prop="addressDetail"
+        label-width="90px"
+      >
+        <nut-input v-model="form.addressDetail" placeholder="璇疯緭鍏ュ湴鐐硅鏄�"> </nut-input>
+      </nut-form-item>
+      <nut-form-item label="浠诲姟璇存槑:" class="bole-form-item" prop="description" label-width="90px">
+        <nut-textarea v-model="form.description" placeholder="璇疯緭鍏ヤ换鍔¤鏄�"> </nut-textarea>
+      </nut-form-item>
+      <nut-form-item
+        label="浠诲姟寮�濮嬫棩鏈�:"
+        class="bole-form-item"
+        prop="beginTime"
+        label-width="90px"
+      >
+        <ChooseInputWithDatePicker
+          v-model="form.beginTime"
+          :minDate="nowDate"
+          placeholder="璇烽�夋嫨浠诲姟寮�濮嬫棩鏈�"
+          @change="timeChange"
+        ></ChooseInputWithDatePicker>
+      </nut-form-item>
+      <nut-form-item label="浠诲姟缁撴潫鏃ユ湡:" class="bole-form-item" prop="endTime" label-width="90px">
+        <ChooseInputWithDatePicker
+          v-model="form.endTime"
+          :minDate="nowDate"
+          placeholder="璇烽�夋嫨浠诲姟缁撴潫鏃ユ湡"
+          @change="calcTaskTotalServiceFee()"
+        ></ChooseInputWithDatePicker>
+      </nut-form-item>
+      <nut-form-item
+        label="鎶ュ悕寮�濮嬫棩鏈�:"
+        class="bole-form-item"
+        prop="applyBeginTime"
+        label-width="90px"
+      >
+        <ChooseInputWithDatePicker
+          v-model="form.applyBeginTime"
+          :minDate="nowDate"
+          placeholder="璇烽�夋嫨鎶ュ悕寮�濮嬫棩鏈�"
+        ></ChooseInputWithDatePicker>
+      </nut-form-item>
+      <nut-form-item
+        label="鎶ュ悕缁撴潫鏃ユ湡:"
+        class="bole-form-item"
+        prop="applyEndTime"
+        label-width="90px"
+      >
+        <ChooseInputWithDatePicker
+          v-model="form.applyEndTime"
+          :minDate="form.applyBeginTime ? dayjs(form.applyBeginTime).toDate() : nowDate"
+          placeholder="璇烽�夋嫨鎶ュ悕缁撴潫鏃ユ湡"
+        ></ChooseInputWithDatePicker>
+      </nut-form-item>
+      <nut-form-item
+        label="楠屾敹鏂瑰紡:"
+        class="bole-form-item"
+        prop="checkReceiveMethods"
+        label-width="90px"
+      >
+        <!-- <nut-radio-group v-model="form.checkReceiveMethod" direction="horizontal">
+          <BlRadio
+            :label="Number(key)"
+            v-for="(val, key) in EnumTaskCheckReceiveMethodText"
+            :key="key"
+            >{{ val }}</BlRadio
+          >
+        </nut-radio-group> -->
+        <nut-checkbox-group v-model="form.checkReceiveMethods">
+          <nut-checkbox
+            :disabled="isEdit"
+            v-for="(val, key) in EnumTaskCheckReceiveMethodText"
+            :key="key"
+            :label="Number(key) as any"
+          >
+            {{ val }}
+          </nut-checkbox>
+        </nut-checkbox-group>
+      </nut-form-item>
+      <nut-form-item
+        label="缁撶畻鏂瑰紡:"
+        class="bole-form-item"
+        prop="settlementAccess"
+        label-width="90px"
+        required
+      >
+        <ChooseInputWithPicker
+          v-model="form.settlementAccess"
+          placeholder="璇烽�夋嫨缁撶畻鏂瑰紡"
+          :value-enum="settlementAccessList"
+          :disabled="isEdit"
+        />
+      </nut-form-item>
+      <nut-form-item
+        label="棰勮鏈嶅姟璐规�婚:"
+        class="bole-form-item"
+        prop="totalServiceFee"
+        label-width="110px"
+      >
+        {{ `${toThousand(totalServiceFee)}鍏僠 }}
+      </nut-form-item>
+    </nut-form>
+  </ContentScrollView>
+  <PageFooter>
+    <PageFooterBtn type="primary" plain @click="handleCancel">鍙栨秷</PageFooterBtn>
+    <PageFooterBtn type="primary" @click="handleConfirm">鍙戝竷</PageFooterBtn>
+  </PageFooter>
+</template>
+
+<script setup lang="ts">
+import { useUser } from '@/hooks';
+import {
+  CategoryCode,
+  EnumBillingMethod,
+  EnumSettlementCycle,
+  EnumUserGender,
+  EnumBillingMethodText,
+  EnumUserGenderText,
+  EnumSettlementCycleText,
+  BillingMethodEnumUnit,
+  EnumUserGenderTextOptions,
+  EnumSettlementCycleDateWeekArray,
+  EnumSettlementCycleDateMonthArray,
+  EnumTaskCheckReceiveMethod,
+  EnumTaskCheckReceiveMethodText,
+  EnumEnterpriseWalletAccess,
+  EnumEnterpriseWalletAccessText,
+} from '@12333/constants';
+import {
+  ChooseInputWithPicker,
+  ChooseInputWithDatePicker,
+  NumberInput,
+  ChooseLocationInput,
+  Radio as BlRadio,
+  ChooseInputWithAreaPicker,
+  ChooseInputWithCheckbox,
+} from '@12333/components';
+import { FormValidator, Message, toThousand } from '@12333/utils';
+import * as taskServices from '@12333/services/apiV2/task';
+import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
+import Taro from '@tarojs/taro';
+import { goBack } from '@/utils';
+import {
+  useAllAreaList,
+  useDictionaryDataSelect,
+  useEnterpriseWalletAccessSelect,
+  useGetSupplierEnterpriseSelect,
+} from '@12333/hooks';
+import { useQuery } from '@tanstack/vue-query';
+import dayjs from 'dayjs';
+
+defineOptions({
+  name: 'InnerPage',
+});
+
+const { userDetail } = useUser();
+const { findAreaNameFromCode } = useAllAreaList();
+
+const { supplierEnterpriseSelect } = useGetSupplierEnterpriseSelect();
+const router = Taro.useRouter();
+const taskId = router.params?.id ?? '';
+const isEdit = !!taskId;
+const isCopy = router.params?.isCopy === 'true';
+
+const nowDate = dayjs().toDate();
+const applyBeginTimeMinDate = computed(() => {
+  return form.applyBeginTime
+    ? dayjs(form.applyBeginTime).toDate()
+    : form.beginTime
+    ? dayjs(form.beginTime).toDate()
+    : nowDate;
+});
+
+const feeCannotEdit = computed(() => {
+  return dayjs().isAfter(form.beginTime, 'second') && isEdit;
+});
+
+const { dictionaryDataList: WelfareTypeList } = useDictionaryDataSelect({
+  categoryCode: CategoryCode.Welfare,
+});
+const { dictionaryDataList: CertificateTypeList } = useDictionaryDataSelect({
+  categoryCode: CategoryCode.CertificateType,
+});
+
+const settlementDateList = computed(() => {
+  if (form.settlementCycle === EnumSettlementCycle.Month) {
+    return EnumSettlementCycleDateMonthArray;
+  }
+  if (form.settlementCycle === EnumSettlementCycle.Week) {
+    return EnumSettlementCycleDateWeekArray;
+  }
+  return [];
+});
+
+const form = reactive({
+  supplierEnterpriseId: '',
+  name: '',
+  needPeopleNumber: '' as any as number,
+  billingMethod: EnumBillingMethod.Day,
+  serviceFee: '' as any as number,
+  settlementCycle: EnumSettlementCycle.Day,
+  benefits: [] as string[],
+  ageMinLimit: '' as any as number,
+  ageMaxLimit: '' as any as number,
+  genderLimit: 0 as any as EnumUserGender,
+  credentialLimits: [] as string[],
+  beginTime: '',
+  endTime: '',
+  settlementDate: null as number,
+
+  weMapInfo: {} as WeMapModel,
+  addressDetail: '',
+
+  verifyWorkHours: null as number,
+  timeoutServiceFee: null as number,
+  description: '',
+  checkReceiveMethods: [] as EnumTaskCheckReceiveMethod[],
+  applyBeginTime: '',
+  applyEndTime: '',
+  settlementAccess: '' as any as EnumEnterpriseWalletAccess,
+  totalPieceQuantity: '' as any as number,
+
+  totalServiceFee: null as number,
+});
+
+const rules = reactive<FormRules>({
+  supplierEnterpriseId: [{ required: true, message: '璇烽�夋嫨渚涘簲鍟�' }],
+  name: [{ required: true, message: '璇疯緭鍏ヤ换鍔″悕绉�' }],
+  needPeopleNumber: [{ required: true, message: '璇疯緭鍏ラ渶姹備汉鏁�' }],
+  totalPieceQuantity: [{ required: true, message: '璇疯緭鍏ヤ换鍔℃�讳欢鏁�' }],
+  verifyWorkHours: [{ required: true, message: '璇疯緭鍏ユ牳瀹氬伐鏃�' }],
+  timeoutServiceFee: [{ required: true, message: '璇疯緭鍏ヨ秴鏃舵湇鍔¤垂' }],
+  genderLimit: [{ required: true, message: '璇烽�夋嫨鎬у埆瑕佹眰' }],
+  settlementCycleDate: [{ required: true, message: '璇疯缃粨绠楁棩鏈�' }],
+  settlementAccess: [{ required: true, message: '璇烽�夋嫨缁撶畻鏂瑰紡' }],
+  // addressDetail: [{ required: true, message: '璇疯緭鍏ヨ缁嗗湴鍧�' }],
+  billingMethod: [
+    {
+      required: true,
+      message: '璇烽�夋嫨鏀惰垂鏂瑰紡',
+      validator: () => {
+        if (!form.billingMethod) {
+          return Promise.reject('璇烽�夋嫨鏈嶅姟璐圭被鍨�');
+        }
+        if (!form.serviceFee && form.billingMethod !== EnumBillingMethod.Face) {
+          return Promise.reject('璇疯緭鍏ユ湇鍔¤垂');
+        }
+        return Promise.resolve(true);
+      },
+    },
+  ],
+  weMapInfo: [
+    { required: true, message: '璇疯缃伐浣滃湴鐐�', validator: FormValidator.validatorWeMap },
+  ],
+
+  ageMinLimit: [
+    {
+      required: true,
+      message: '璇疯緭鍏ュ勾榫勮姹�',
+      validator: () => {
+        if (!form.ageMinLimit && form.ageMinLimit > 0) {
+          return Promise.reject('璇疯緭鍏ュ勾榫勮姹�');
+        }
+        if (!form.ageMaxLimit && form.ageMaxLimit > 0) {
+          return Promise.reject('璇疯緭鍏ュ勾榫勮姹�');
+        }
+        if (Number(form.ageMaxLimit) <= Number(form.ageMinLimit)) {
+          return Promise.reject('鏈�澶у勾榫勪笉鑳藉皬浜庢渶灏忓勾榫�');
+        }
+        return Promise.resolve(true);
+      },
+    },
+  ],
+
+  beginTime: [
+    {
+      required: true,
+      message: '璇烽�夋嫨寮�濮嬫棩鏈�',
+    },
+  ],
+  endTime: [
+    {
+      required: true,
+      message: '璇烽�夋嫨缁撴潫鏃ユ湡',
+      validator(value) {
+        if (!value) return Promise.reject('璇烽�夋嫨缁撴潫鏃ユ湡');
+        if (form.billingMethod === EnumBillingMethod.Month) {
+          if (dayjs(form.endTime).isBefore(dayjs(form.beginTime).add(1, 'month'))) {
+            return Promise.reject('鎸夋湀鏈嶅姟璐癸紝浠诲姟鏃堕暱闇�澶т簬涓�涓湀');
+          }
+          return Promise.resolve(true);
+        }
+        if (dayjs(value).isBefore(dayjs(form.beginTime)))
+          return Promise.reject('缁撴潫鏃ユ湡闇�澶т簬寮�濮嬫棩鏈�');
+        return Promise.resolve(true);
+      },
+    },
+  ],
+  applyBeginTime: [
+    {
+      required: true,
+      message: '璇烽�夋嫨鎶ュ悕寮�濮嬫棩鏈�',
+      validator(value) {
+        if (!value) return Promise.reject('璇烽�夋嫨鎶ュ悕寮�濮嬫棩鏈�');
+        if (dayjs(value).isAfter(dayjs(form.endTime)))
+          return Promise.reject('鎶ュ悕寮�濮嬫棩鏈熼渶灏忎簬浠诲姟缁撴潫鏃ユ湡');
+        return Promise.resolve(true);
+      },
+    },
+  ],
+  applyEndTime: [
+    {
+      required: true,
+      message: '璇烽�夋嫨鎶ュ悕缁撴潫鏃ユ湡',
+      validator(value) {
+        if (!value) return Promise.reject('璇烽�夋嫨鎶ュ悕缁撴潫鏃ユ湡');
+        if (dayjs(value).isBefore(dayjs(form.applyBeginTime)))
+          return Promise.reject('鎶ュ悕缁撴潫鏃ユ湡闇�澶т簬鎶ュ悕寮�濮嬫棩鏈�');
+        if (dayjs(value).isAfter(dayjs(form.endTime)))
+          return Promise.reject('鎶ュ悕缁撴潫鏃ユ湡闇�灏忎簬浠诲姟缁撴潫鏃ユ湡');
+        return Promise.resolve(true);
+      },
+    },
+  ],
+  checkReceiveMethods: [
+    {
+      required: true,
+      message: '璇烽�夋嫨楠屾敹鏂瑰紡',
+      validator(value) {
+        if (!value?.length) return Promise.reject('璇烽�夋嫨楠屾敹鏂瑰紡');
+        return Promise.resolve(true);
+      },
+    },
+  ],
+});
+
+const { settlementAccessList } = useEnterpriseWalletAccessSelect({
+  supplierEnterpriseId: computed(() => form.supplierEnterpriseId),
+});
+
+const {
+  isLoading,
+  isError,
+  data: detail,
+  refetch,
+} = useQuery({
+  queryKey: ['taskServices/getTaskInfo', taskId],
+  queryFn: async () => {
+    return await taskServices.getTaskInfo(
+      { id: taskId },
+      {
+        showLoading: false,
+      }
+    );
+  },
+  placeholderData: () => ({} as API.GetTaskInfoQueryResult),
+  enabled: isEdit,
+  onSuccess(data) {
+    form.supplierEnterpriseId = data.supplierEnterpriseId;
+    form.name = data.name;
+    form.needPeopleNumber = data.needPeopleNumber;
+    form.billingMethod = data.billingMethod;
+    form.serviceFee = data.serviceFee;
+    form.totalPieceQuantity = data.totalPieceQuantity;
+    form.settlementCycle = data.settlementCycle;
+    form.settlementDate = data.settlementDate;
+    form.benefits = (data.benefits ?? []).map((item) => item.benefitCode);
+    form.ageMinLimit = data.ageMinLimit;
+    form.ageMaxLimit = data.ageMaxLimit;
+    form.genderLimit = data.genderLimit;
+    form.credentialLimits = (data.credentialLimits ?? []).map((item) => item.typeCode);
+    form.beginTime = dayjs(data.beginTime).format('YYYY-MM-DD');
+    form.endTime = dayjs(data.endTime).format('YYYY-MM-DD');
+    form.addressDetail = data.addressDetail;
+    form.weMapInfo = {
+      provinceName: data.provinceContent,
+      cityName: data.cityContent,
+      provinceCode: data.provinceCode,
+      cityCode: data.cityCode,
+      latitude: data.latitude,
+      longitude: data.longitude,
+      addressName: data.addressName,
+      address: data.addressName,
+    };
+    form.description = data.description;
+    form.verifyWorkHours = data.verifyWorkHours;
+    form.timeoutServiceFee = data.timeoutServiceFee;
+    form.checkReceiveMethods = data.checkReceiveMethods;
+    form.applyBeginTime = dayjs(data.applyBeginTime).format('YYYY-MM-DD');
+    form.applyEndTime = dayjs(data.applyEndTime).format('YYYY-MM-DD');
+    form.settlementAccess = data.settlementAccess;
+
+    if (!!data.timeoutServiceFee) {
+      calcTaskTotalServiceFee();
+    }
+  },
+});
+
+async function calcTaskTotalServiceFee() {
+  try {
+    if (!form.beginTime || !form.endTime) {
+      return;
+    }
+    if (form.billingMethod !== EnumBillingMethod.Piece && !form.needPeopleNumber) {
+      return;
+    }
+    let params: API.CalcTaskTotalServiceFeeCommand = {
+      billingMethod: form.billingMethod,
+      serviceFee: form.serviceFee,
+      verifyWorkHours: form.verifyWorkHours,
+      totalPieceQuantity: form.totalPieceQuantity,
+      needPeopleNumber: form.needPeopleNumber,
+      beginTime: dayjs(form.beginTime).format('YYYY-MM-DD 00:00:00'),
+      endTime: dayjs(form.endTime).format('YYYY-MM-DD 23:59:59'),
+    };
+    let res = await taskServices.calcTaskTotalServiceFee(params, { showLoading: false });
+    if (res) {
+      form.totalServiceFee = res.totalServiceFee;
+    }
+  } catch (error) {}
+}
+
+const totalServiceFee = computed(() => {
+  if (!form.beginTime || !form.endTime) {
+    return 0;
+  }
+  var days = dayjs(form.endTime).diff(dayjs(form.beginTime), 'day') + 1;
+  const serviceFee = form.serviceFee || 0;
+  const needPeopleNumber = form.needPeopleNumber || 0;
+  switch (form.billingMethod) {
+    case EnumBillingMethod.Month:
+      return serviceFee * Math.round(days / 30) * needPeopleNumber;
+    case EnumBillingMethod.Day:
+      return serviceFee * days * needPeopleNumber;
+    case EnumBillingMethod.Hour:
+      return serviceFee * (form.verifyWorkHours || 0) * days * needPeopleNumber;
+    case EnumBillingMethod.Piece:
+      return serviceFee * (form.totalPieceQuantity || 0);
+    default:
+      return 0;
+  }
+});
+
+const formRef = ref<any>(null);
+function handleConfirm() {
+  if (!formRef.value) return;
+  formRef.value.validate().then(({ valid, errors }: any) => {
+    if (valid) {
+      confirm();
+    }
+  });
+}
+
+async function confirm() {
+  try {
+    await calcTaskTotalServiceFee();
+
+    let params: API.SaveTaskInfoCommand = {
+      supplierEnterpriseId: form.supplierEnterpriseId,
+      name: form.name,
+      needPeopleNumber: form.needPeopleNumber,
+      billingMethod: form.billingMethod,
+      serviceFee: form.serviceFee,
+      totalPieceQuantity: form.totalPieceQuantity,
+      settlementCycle: form.settlementCycle,
+      settlementDate: form.settlementDate ? form.settlementDate : 0,
+      benefits: form.benefits,
+      ageMinLimit: form.ageMinLimit,
+      ageMaxLimit: form.ageMaxLimit,
+      genderLimit: form.genderLimit,
+      credentialLimits: form.credentialLimits,
+      provinceCode: form.weMapInfo.provinceCode,
+      cityCode: form.weMapInfo.cityCode,
+      addressName: form.weMapInfo.addressName,
+      addressDetail: form.addressDetail,
+      longitude: form.weMapInfo.longitude,
+      latitude: form.weMapInfo.latitude,
+      beginTime: dayjs(form.beginTime).format('YYYY-MM-DD 00:00:00'),
+      endTime: dayjs(form.endTime).format('YYYY-MM-DD 23:59:59'),
+      description: form.description,
+      verifyWorkHours: form.verifyWorkHours,
+      timeoutServiceFee: form.timeoutServiceFee,
+      checkReceiveMethods: form.checkReceiveMethods,
+      applyBeginTime: dayjs(form.applyBeginTime).format('YYYY-MM-DD 00:00:00'),
+      applyEndTime: dayjs(form.applyEndTime).format('YYYY-MM-DD 23:59:59'),
+      settlementAccess: form.settlementAccess,
+    };
+    if (isEdit) {
+      params.id = taskId;
+    }
+    if (isCopy) {
+      params.id = '';
+    }
+    let res = await taskServices.saveTaskInfo(params, { skipErrorHandler: true });
+    if (res) {
+      Message.success(isEdit && !isCopy ? '缂栬緫鎴愬姛' : '鍙戝竷鎴愬姛', {
+        onClosed() {
+          goBack();
+        },
+      });
+    }
+  } catch (error) {
+    if (error?.info?.errorCode == 'BalanceNotEnough') {
+      await Message.confirm({
+        message: `鎮ㄥ綋鍓嶈处鎴蜂綑棰濅笉瓒筹紝鏆傛椂鏃犳硶鍙戝竷浠诲姟锛岃鐧诲綍瀹㈡埛绔悗鍙板厖鍊煎悗鎿嶄綔`,
+        showCancelBtn: false,
+      });
+    } else {
+      Message.error(error);
+    }
+  }
+}
+
+function timeChange() {
+  form.applyBeginTime = '';
+  form.applyEndTime = '';
+  calcTaskTotalServiceFee();
+}
+
+function applyTimeChange() {
+  form.applyEndTime = '';
+}
+
+function settleTypeChange() {
+  form.settlementDate = null as number;
+}
+
+function handleCancel() {
+  goBack();
+}
+</script>
+
+<style lang="scss">
+@import '@/styles/common.scss';
+
+.publish-page-wrapper {
+  .bole-form-input-wrapper {
+    display: flex;
+    align-items: center;
+  }
+
+  .form-input-unit {
+    margin-left: 10px;
+    color: boleGetCssVar('text-color', 'primary');
+    flex-shrink: 0;
+  }
+
+  .form-input-separator {
+    margin-right: 10px;
+  }
+}
+</style>
diff --git a/apps/underTakeMiniApp/src/pages/publish/publish.config.ts b/apps/underTakeMiniApp/src/pages/publish/publish.config.ts
new file mode 100644
index 0000000..305fdb1
--- /dev/null
+++ b/apps/underTakeMiniApp/src/pages/publish/publish.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+  disableScroll: true,
+});
diff --git a/apps/underTakeMiniApp/src/pages/publish/publish.vue b/apps/underTakeMiniApp/src/pages/publish/publish.vue
new file mode 100644
index 0000000..4999343
--- /dev/null
+++ b/apps/underTakeMiniApp/src/pages/publish/publish.vue
@@ -0,0 +1,14 @@
+<template>
+  <PageLayoutWithBg class="publish-page-wrapper" title="鍙戝竷" needAuth>
+    <InnerPage />
+  </PageLayoutWithBg>
+</template>
+
+<script setup lang="ts">
+import PageLayoutWithBg from '@/components/Layout/PageLayoutWithBg.vue';
+import InnerPage from './InnerPage.vue';
+
+defineOptions({
+  name: 'publish',
+});
+</script>

--
Gitblit v1.9.1