first commit
This commit is contained in:
@@ -0,0 +1,604 @@
|
||||
<script lang="ts" setup>
|
||||
import {z} from "zod";
|
||||
import * as R from 'ramda'
|
||||
import {debounce} from "throttle-debounce";
|
||||
import Config from "@/config";
|
||||
import ChooseImage from "@/components/choose-image/choose-image.vue";
|
||||
import {
|
||||
appMerchantCategoryListGet,
|
||||
appMerchantGetFirstShopSettledGet,
|
||||
appShopSettlementApplyPost,
|
||||
appShopSettlementDetailGet
|
||||
} from "@/service";
|
||||
import useEventEmit from "@/hooks/useEventEmit";
|
||||
import {EventEnum} from "@/constant/enums";
|
||||
import {useUserStore} from "@/store";
|
||||
|
||||
const userStore = useUserStore()
|
||||
const {t} = useI18n();
|
||||
|
||||
// 审核状态 null 未提交 1审核中 2审核通过 3审核驳回
|
||||
const auditStatus = ref(null);
|
||||
|
||||
const type = ref('')
|
||||
const rejectReason = ref('')
|
||||
const id = ref('')
|
||||
const shopInfo = ref({})
|
||||
onLoad((options) => {
|
||||
appMerchantGetFirstShopSettledGet({}).then(res=> {
|
||||
console.log(res)
|
||||
if(res.data) {
|
||||
shopInfo.value = res.data
|
||||
auditStatus.value = Number(res.data.auditStatus)
|
||||
rejectReason.value = res.data.rejectReason
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 点击了重新编辑
|
||||
function clickInitEdit() {
|
||||
auditStatus.value = null
|
||||
// appShopSettlementDetailGet({
|
||||
// params: {
|
||||
// id: id.value
|
||||
// }
|
||||
// }).then(res => {
|
||||
//
|
||||
// })
|
||||
|
||||
formData.value = shopInfo.value
|
||||
formData.value.idCardImage = shopInfo.value.idCardImage || ''
|
||||
formData.value.passportImage = shopInfo.value.passportImage || ''
|
||||
formData.value.foodOperationCertificateImage = shopInfo.value.foodOperationCertificateImage || ''
|
||||
handleShowTypePicker(false)
|
||||
}
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
shopName: "",
|
||||
shopTypeId: "", // 所属类型(关联店铺类型表)
|
||||
category: "",
|
||||
street: "", // 街道
|
||||
city: "", // 市
|
||||
state: "", // 州
|
||||
detailAddress: "",
|
||||
description: "",
|
||||
idCardImage: "",
|
||||
passportImage: "",
|
||||
foodOperationCertificateImage: "",
|
||||
});
|
||||
|
||||
// 表单验证schema
|
||||
const FormSchema = z.object({
|
||||
shopName: z.string().min(1, {message: t("pages-user.store-settle-in.schema.storeName")}),
|
||||
category: z.string().min(1, {message: t("pages-user.store-settle-in.schema.category")}),
|
||||
detailAddress: z.string().min(1, {message: t("pages-user.store-settle-in.schema.detailAddress")}),
|
||||
description: z.string().min(1, {message: t("pages-user.store-settle-in.schema.description")}),
|
||||
// idCardImage: z.string().min(1, {message: t("pages-user.store-settle-in.schema.idCardFront")}),
|
||||
// passportImage: z.string().min(1, {message: t("pages-user.store-settle-in.schema.idCardBack")}),
|
||||
// foodOperationCertificateImage: z.string().min(1, {message: t("pages-user.store-settle-in.schema.businessLicense")}),
|
||||
});
|
||||
|
||||
const currentImageType = ref("");
|
||||
const chooseImageRef = ref();
|
||||
|
||||
// 状态
|
||||
const isSubmitting = ref(false);
|
||||
|
||||
// 表单验证
|
||||
function validateForm(): boolean {
|
||||
const validateResult = FormSchema.safeParse(formData.value);
|
||||
|
||||
if (!validateResult.success) {
|
||||
const fieldErrors = validateResult.error.flatten().fieldErrors;
|
||||
const firstError = R.values(fieldErrors)[0]?.[0];
|
||||
|
||||
if (firstError) {
|
||||
uni.showToast({
|
||||
title: firstError,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
async function submitForm() {
|
||||
if (!validateForm()) return;
|
||||
|
||||
isSubmitting.value = true;
|
||||
|
||||
try {
|
||||
console.log("提交数据:", formData.value);
|
||||
appShopSettlementApplyPost({
|
||||
body: {
|
||||
...formData.value,
|
||||
}
|
||||
}).then(res => {
|
||||
uni.showToast({
|
||||
title: t("toast.submitSuccess"),
|
||||
icon: "none",
|
||||
});
|
||||
auditStatus.value = 1
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("提交失败:", error);
|
||||
uni.showToast({
|
||||
title: "提交失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
} finally {
|
||||
isSubmitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 防抖提交
|
||||
const handleSubmit = debounce(Config.debounceLongTime, submitForm, {
|
||||
atBegin: true,
|
||||
});
|
||||
|
||||
// 选择图片 - 添加安全检查
|
||||
function chooseImage(type: string) {
|
||||
currentImageType.value = type;
|
||||
if (chooseImageRef.value?.init) {
|
||||
chooseImageRef.value.init();
|
||||
}
|
||||
}
|
||||
|
||||
// 图片选择回调 - 修复类型问题
|
||||
function onImageChange(images: string[]) {
|
||||
if (images.length > 0 && currentImageType.value) {
|
||||
// 使用类型断言确保类型安全
|
||||
(formData.value as any)[currentImageType.value] = images[0];
|
||||
}
|
||||
}
|
||||
|
||||
const show = ref(false);
|
||||
|
||||
function handleClose() {
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
const columnsType = ref([])
|
||||
const typePickerValue = ref('')
|
||||
|
||||
function handleShowTypePicker(type: boolean) {
|
||||
appMerchantCategoryListGet({
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
columnsType.value = res.data
|
||||
show.value = type;
|
||||
typePickerValue.value = columnsType.value[0].id
|
||||
|
||||
if (!type) {
|
||||
const data = res.data.find(item => item.id === formData.value.shopTypeId)
|
||||
formData.value.category = data.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleSubmitPickType() {
|
||||
console.log(typePickerValue.value)
|
||||
const data = columnsType.value.find(item => item.id === typePickerValue.value)
|
||||
if (data) {
|
||||
formData.value.shopTypeId = data.id
|
||||
formData.value.category = data.name
|
||||
}
|
||||
handleClose()
|
||||
}
|
||||
|
||||
|
||||
function handleAddressPicker() {
|
||||
uni.navigateTo({
|
||||
url: '/pages-user/pages/search-address/index',
|
||||
})
|
||||
}
|
||||
|
||||
useEventEmit(EventEnum.CHOOSE_ADDRESS, (data) => {
|
||||
console.log('接收到的地址信息', data)
|
||||
|
||||
// 解析地址信息并填充表单
|
||||
if (data && data.addressComponents) {
|
||||
// 重置地址相关字段
|
||||
formData.value.street = ""
|
||||
formData.value.city = ""
|
||||
formData.value.state = ""
|
||||
|
||||
// 遍历地址组件,根据类型填充对应字段
|
||||
data.addressComponents.forEach((component: any) => {
|
||||
const types = component.types || []
|
||||
|
||||
// 街道号码 (street_number)
|
||||
if (types.includes('street_number')) {
|
||||
formData.value.street = component.longText + ' ' + formData.value.street
|
||||
}
|
||||
|
||||
// 街道名称 (route)
|
||||
if (types.includes('route')) {
|
||||
formData.value.street = (formData.value.street + ' ' + component.longText).trim()
|
||||
}
|
||||
|
||||
// 子区域 (sublocality_level_1) - 可作为街道的一部分
|
||||
if (types.includes('sublocality_level_1') && !formData.value.street) {
|
||||
formData.value.street = component.longText
|
||||
}
|
||||
|
||||
// 城市 (locality)
|
||||
if (types.includes('locality')) {
|
||||
formData.value.city = component.longText
|
||||
}
|
||||
|
||||
// 如果没有locality,使用administrative_area_level_3作为城市
|
||||
if (types.includes('administrative_area_level_3') && !formData.value.city) {
|
||||
formData.value.city = component.longText
|
||||
}
|
||||
|
||||
// 州/省 (administrative_area_level_1)
|
||||
if (types.includes('administrative_area_level_1')) {
|
||||
formData.value.state = component.shortText || component.longText
|
||||
}
|
||||
})
|
||||
|
||||
// 如果没有解析到街道信息,使用格式化地址的第一部分
|
||||
if (!formData.value.street && data.formattedAddress) {
|
||||
const addressParts = data.formattedAddress.split(', ')
|
||||
if (addressParts.length > 0) {
|
||||
formData.value.street = addressParts[0]
|
||||
}
|
||||
}
|
||||
|
||||
// 设置详细地址为完整的格式化地址
|
||||
if (data.formattedAddress) {
|
||||
formData.value.detailAddress = data.formattedAddress
|
||||
}
|
||||
|
||||
console.log('解析后的地址信息:', {
|
||||
street: formData.value.street,
|
||||
city: formData.value.city,
|
||||
state: formData.value.state,
|
||||
detailAddress: formData.value.detailAddress
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 删除图片
|
||||
function removeImage(type: string) {
|
||||
if (type && formData.value.hasOwnProperty(type)) {
|
||||
(formData.value as any)[type] = "";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view class="">
|
||||
<navbar customClass="!bg-transparent"/>
|
||||
<view class="px-30rpx mt-18rpx mb-44rpx">
|
||||
<view class="text-56rpx lh-56rpx text-#333 font-bold">{{ t("pages-user.store-settle-in.title") }}</view>
|
||||
<view class="text-28rpx text-#666 lh-28rpx mt-20rpx pr-240rpx"
|
||||
>{{ t("pages-user.store-settle-in.desc") }}
|
||||
</view
|
||||
>
|
||||
</view>
|
||||
<view class="px-30rpx relative mb-30rpx z-1">
|
||||
<image
|
||||
class="absolute top--200rpx right-20rpx z-9 w-256rpx h-213rpx"
|
||||
src="@img/chef/109.png"
|
||||
></image>
|
||||
<view class="bg-white rounded-16rpx px-30rpx pb-46rpx relative z-10">
|
||||
<template v-if="auditStatus === null">
|
||||
<view class="border-bottom py-32rpx flex-center-sb">
|
||||
<view class="text-28rpx text-#333 w-140rpx">{{ t("pages-user.store-settle-in.storeName") }}:</view>
|
||||
<wd-input
|
||||
v-model.trim="formData.shopName"
|
||||
:cursorSpacing="20"
|
||||
:focus-when-clear="false"
|
||||
:maxlength="20"
|
||||
:placeholder="t('common.enter')"
|
||||
clearable
|
||||
custom-class="flex-1"
|
||||
no-border
|
||||
placeholderStyle="font-size: 28rpx;color: #999;"
|
||||
>
|
||||
</wd-input>
|
||||
</view>
|
||||
|
||||
<view class="border-bottom py-32rpx flex-center-sb" @click="handleShowTypePicker(true)">
|
||||
<view class="flex text-28rpx">
|
||||
<view class="text-#333 w-140rpx">{{ t("pages-user.store-settle-in.category") }}:</view>
|
||||
<template v-if="formData.category">
|
||||
<text class="text-#333">
|
||||
{{ formData.category }}
|
||||
</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text class="text-#999">
|
||||
{{ t("common.select") }}
|
||||
</text>
|
||||
</template>
|
||||
</view>
|
||||
<image class="w-22rpx h-30rpx" src="@img/chef/100202.png"></image>
|
||||
</view>
|
||||
|
||||
<view class="border-bottom py-32rpx flex-center-sb" @click="handleAddressPicker">
|
||||
<view class="flex text-28rpx">
|
||||
<view class="text-#333 w-140rpx">{{ t("pages-user.store-settle-in.address") }}:</view>
|
||||
<template v-if="formData.street || formData.city || formData.state">
|
||||
<text class="text-#333 flex-1">
|
||||
{{ [formData.street, formData.city, formData.state].filter(Boolean).join(', ') }}
|
||||
</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text class="text-#999">{{ t("common.select") }}</text>
|
||||
</template>
|
||||
</view>
|
||||
<image class="w-22rpx h-30rpx" src="@img/chef/100202.png"></image>
|
||||
</view>
|
||||
|
||||
<view class="border-bottom py-32rpx flex-center-sb">
|
||||
<view class="text-28rpx text-#333 w-140rpx">{{ t("pages-user.store-settle-in.detailedAddress") }}:</view>
|
||||
<wd-input
|
||||
v-model.trim="formData.detailAddress"
|
||||
:cursorSpacing="20"
|
||||
:focus-when-clear="false"
|
||||
:maxlength="20"
|
||||
:placeholder="t('common.enter')"
|
||||
clearable
|
||||
custom-class="flex-1"
|
||||
no-border
|
||||
placeholderStyle="font-size: 28rpx;color: #999;"
|
||||
>
|
||||
</wd-input>
|
||||
</view>
|
||||
|
||||
<view class="border-bottom py-32rpx">
|
||||
<view class="text-28rpx text-#333 mb-24rpx">{{ t("pages-user.store-settle-in.introduction") }}:</view>
|
||||
<view
|
||||
class="min-h-226rpx box-border bg-#F6F6F6 rounded-36rpx overflow-hidden px-18rpx py-10rpx"
|
||||
>
|
||||
<wd-textarea
|
||||
v-model="formData.description"
|
||||
:maxlength="500"
|
||||
:placeholder="t('components.placeholder')"
|
||||
auto-height
|
||||
custom-class="!bg-#F6F6F6"
|
||||
custom-textarea-container-class="!bg-#F6F6F6"
|
||||
no-border
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="border-bottom py-30rpx">
|
||||
<view class="text-28rpx text-#333 mb-24rpx">{{ t("pages-user.store-settle-in.idCardFront") }}:</view>
|
||||
<view class="flex-center-sb">
|
||||
<view class="relative" @click="chooseImage('idCardImage')">
|
||||
<image
|
||||
v-if="formData.idCardImage"
|
||||
class="absolute top--10rpx right--10rpx z-10 w-36rpx h-36rpx"
|
||||
src="@img/chef/113.png"
|
||||
@click.stop="removeImage('idCardImage')"
|
||||
></image>
|
||||
<image
|
||||
v-if="!formData.idCardImage"
|
||||
class="w-276rpx h-188rpx"
|
||||
src="@img/chef/110.png"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
:src="formData.idCardImage"
|
||||
class="w-276rpx h-188rpx rounded-16rpx"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</view>
|
||||
<view class="relative" @click="chooseImage('passportImage')">
|
||||
<image
|
||||
v-if="formData.passportImage"
|
||||
class="absolute top--10rpx right--10rpx z-10 w-36rpx h-36rpx"
|
||||
src="@img/chef/113.png"
|
||||
@click.stop="removeImage('passportImage')"
|
||||
></image>
|
||||
<image
|
||||
v-if="!formData.passportImage"
|
||||
class="w-276rpx h-188rpx"
|
||||
src="@img/chef/111.png"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
:src="formData.passportImage"
|
||||
class="w-276rpx h-188rpx rounded-16rpx"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view>
|
||||
<view class="text-28rpx text-#333 mt-32rpx mb-24rpx">{{
|
||||
t("pages-user.store-settle-in.businessLicense")
|
||||
}}:
|
||||
</view>
|
||||
<view class="relative w-160rpx h-160rpx" @click="chooseImage('foodOperationCertificateImage')">
|
||||
<image
|
||||
v-if="formData.foodOperationCertificateImage"
|
||||
class="absolute top--10rpx right--10rpx z-10 w-36rpx h-36rpx"
|
||||
src="@img/chef/113.png"
|
||||
@click.stop="removeImage('foodOperationCertificateImage')"
|
||||
></image>
|
||||
<image
|
||||
v-if="!formData.foodOperationCertificateImage"
|
||||
class="w-160rpx h-160rpx"
|
||||
src="@img/chef/112.png"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
:src="formData.foodOperationCertificateImage"
|
||||
class="w-160rpx h-160rpx rounded-16rpx"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<view v-else class="center flex-col h-798rpx">
|
||||
<template v-if="auditStatus === 1">
|
||||
<image
|
||||
class="w-98rpx h-98rpx"
|
||||
src="@img/chef/1109.png"
|
||||
></image>
|
||||
<view class="text-42rpx lh-42rpx text-#333 font-500 mt-26rpx mb-18rpx">
|
||||
{{ t("pages-user.store-settle-in.audit.submitted") }}
|
||||
</view>
|
||||
<view class="text-28rpx lh-28rpx text-#868686 text-center">
|
||||
{{ t("pages-user.store-settle-in.audit.submittedDesc") }}
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="auditStatus === 2">
|
||||
<image
|
||||
class="w-98rpx h-98rpx"
|
||||
src="@img/chef/1108.png"
|
||||
></image>
|
||||
<view class="text-42rpx lh-42rpx text-#333 font-500 mt-26rpx mb-18rpx">
|
||||
{{ t("pages-user.store-settle-in.audit.pass") }}
|
||||
</view>
|
||||
<view class="text-28rpx lh-28rpx text-#868686 text-center">
|
||||
{{ t("pages-user.store-settle-in.audit.passDesc") }}
|
||||
<br>
|
||||
<text class="mt-22rpx block">{{ t("pages-user.store-settle-in.audit.passDesc1") }}~</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="auditStatus === 3">
|
||||
<image
|
||||
class="w-98rpx h-98rpx"
|
||||
src="@img/chef/1110.png"
|
||||
></image>
|
||||
<view class="text-42rpx lh-42rpx text-#333 font-500 mt-26rpx mb-18rpx">
|
||||
{{ t("pages-user.store-settle-in.audit.reject") }}
|
||||
</view>
|
||||
<view class="text-28rpx lh-28rpx text-#868686">{{
|
||||
t("pages-user.store-settle-in.audit.rejectDesc")
|
||||
}}:{{ rejectReason }}
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-if="auditStatus === null">
|
||||
<fixed-bottom-large-btn
|
||||
:text="`${t('common.submit')}`"
|
||||
class="z-100"
|
||||
fixed
|
||||
@click="handleSubmit"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="auditStatus === 3">
|
||||
<!--如果是走新增进来的且Id不存在-->
|
||||
<fixed-bottom-large-btn
|
||||
:text="`${t('common.reEdit')}`"
|
||||
class="z-100"
|
||||
fixed
|
||||
@click="clickInitEdit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<ChooseImage ref="chooseImageRef" @change="onImageChange"/>
|
||||
|
||||
|
||||
<wd-popup
|
||||
v-model="show"
|
||||
position="bottom"
|
||||
@close="handleClose"
|
||||
>
|
||||
<view>
|
||||
<view class="flex-center-sb h-102rpx bg-#F7F7F7 px-30rpx">
|
||||
<view @click="handleClose" class="text-30rpx text-#999">{{ t('common.cancel') }}</view>
|
||||
<view class="text-34rpx text-#333">{{ t('common.placeholder.pleaseSelect') }}</view>
|
||||
<view class="text-30rpx text-#FF6106" @click="handleSubmitPickType">{{ t('common.confirm') }}</view>
|
||||
</view>
|
||||
<view class="bg-#fff px-54rpx py-56rpx">
|
||||
<wd-picker-view v-model="typePickerValue" :columns="columnsType" label-key="name" value-key="id"/>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
</view>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.form-item {
|
||||
@apply flex items-start py-30rpx border-b border-#f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
@apply border-b-0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-label {
|
||||
@apply text-28rpx text-primary font-medium w-160rpx flex-shrink-0;
|
||||
}
|
||||
|
||||
.form-input-wrapper {
|
||||
@apply flex-1 flex items-center justify-between;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
@apply flex-1 text-28rpx text-primary;
|
||||
}
|
||||
|
||||
.form-textarea-wrapper {
|
||||
@apply flex-1;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
@apply w-full min-h-200rpx text-28rpx text-primary leading-40rpx p-20rpx bg-#f8f8f8 rounded-20rpx;
|
||||
}
|
||||
|
||||
.form-upload-wrapper {
|
||||
@apply flex-1 flex gap-20rpx;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
@apply w-160rpx h-120rpx border-2rpx border-dashed border-#ddd rounded-20rpx flex items-center justify-center bg-#f8f8f8;
|
||||
}
|
||||
|
||||
.upload-image {
|
||||
@apply w-full h-full rounded-20rpx;
|
||||
}
|
||||
|
||||
.upload-placeholder {
|
||||
@apply flex items-center justify-center w-full h-full;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
@apply w-full h-88rpx bg-#333 text-white text-32rpx font-medium rounded-44rpx;
|
||||
|
||||
&:disabled {
|
||||
@apply bg-#ccc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:deep(.uni-picker-view-wrapper) {
|
||||
& > uni-picker-view-column:first-of-type .uni-picker-view-group {
|
||||
.uni-picker-view-indicator {
|
||||
border-radius: 20rpx 0 0 20rpx !important;
|
||||
|
||||
&:after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:before {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.wd-picker-view-column__item) {
|
||||
line-height: 94rpx !important;
|
||||
}
|
||||
|
||||
:deep(.uni-picker-view-indicator) {
|
||||
height: 94rpx !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user