first commit
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
<script setup lang="ts">
|
||||
import ChooseImage from "@/components/choose-image/choose-image.vue";
|
||||
import {appFeedbackAddPost} from "@/service";
|
||||
import { z } from 'zod';
|
||||
const {t} = useI18n()
|
||||
|
||||
const form = ref({
|
||||
content: '',
|
||||
contactPhone: '',
|
||||
images: '',
|
||||
})
|
||||
|
||||
// 创建zod校验schema
|
||||
const createValidationSchema = () => {
|
||||
return z.object({
|
||||
content: z.string()
|
||||
.min(1, t('pages-user.complaints.validation.content-required'))
|
||||
.min(10, t('pages-user.complaints.validation.content-min-length'))
|
||||
.max(500, t('pages-user.complaints.validation.content-max-length')),
|
||||
contactPhone: z.string()
|
||||
.min(1, t('pages-user.complaints.validation.contact-phone-required'))
|
||||
.regex(/^[\d\s\-\+\(\)]+$/, t('pages-user.complaints.validation.contact-phone-invalid'))
|
||||
})
|
||||
}
|
||||
|
||||
const chooseImageRef = ref()
|
||||
|
||||
// 校验单个字段
|
||||
const validateField = (field: keyof typeof form.value) => {
|
||||
try {
|
||||
const schema = createValidationSchema()
|
||||
const fieldSchema = schema.shape[field]
|
||||
fieldSchema.parse(form.value[field])
|
||||
return true
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
uni.showToast({
|
||||
title: error.errors[0].message,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 校验整个表单
|
||||
const validateForm = () => {
|
||||
try {
|
||||
const schema = createValidationSchema()
|
||||
schema.parse(form.value)
|
||||
return true
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
uni.showToast({
|
||||
title: error.errors[0].message,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!validateForm()) {
|
||||
return
|
||||
}
|
||||
|
||||
appFeedbackAddPost({
|
||||
body: {
|
||||
...form.value
|
||||
}
|
||||
}).then(res=> {
|
||||
uni.showToast({
|
||||
title: t('toast.submitSuccess'),
|
||||
icon: 'none'
|
||||
})
|
||||
form.value = {
|
||||
content: '',
|
||||
contactPhone: '',
|
||||
images: '',
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleChooseImage = () => {
|
||||
chooseImageRef.value.init()
|
||||
}
|
||||
function onImageChange(files: string[]) {
|
||||
form.value.images = files[0]
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<navbar :title="t('pages-user.complaints.title')" />
|
||||
<view class="px-18rpx">
|
||||
<view class="mb-27rpx mt-32rpx text-28rpx text-#333">
|
||||
{{ t('pages-user.complaints.description') }}
|
||||
</view>
|
||||
<view class="bg-white rounded-14rpx px-18rpx pt-30rpx pb-24rpx">
|
||||
<view class="text-28rpx text-#333 mb-28rpx">{{ t('pages-user.complaints.feedback-content') }}:</view>
|
||||
<view
|
||||
class="min-h-234rpx box-border bg-#F6F6F6 rounded-14rpx overflow-hidden px-18rpx py-10rpx"
|
||||
>
|
||||
<wd-textarea
|
||||
v-model="form.content"
|
||||
:maxlength="500"
|
||||
custom-class="!bg-#F6F6F6"
|
||||
custom-textarea-container-class="!bg-#F6F6F6"
|
||||
no-border
|
||||
auto-height
|
||||
:placeholder="t('pages-user.complaints.feedback-content-placeholder')"
|
||||
@blur="validateField('content')"
|
||||
/>
|
||||
</view>
|
||||
|
||||
|
||||
<view>
|
||||
<view class="text-28rpx text-#333 mt-32rpx mb-24rpx">{{ t('pages-user.complaints.image') }}:</view>
|
||||
<view @click="handleChooseImage" class="relative w-210rpx h-210rpx">
|
||||
<image
|
||||
v-if="form.images"
|
||||
src="@img/chef/113.png"
|
||||
class="absolute top--10rpx right--10rpx z-10 w-36rpx h-36rpx"
|
||||
></image>
|
||||
<image
|
||||
v-if="!form.images"
|
||||
src="@img/chef/112.png"
|
||||
class="w-210rpx h-210rpx"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
:src="form.images"
|
||||
class="w-210rpx h-210rpx rounded-16rpx"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-14rpx flex-center-sb bg-white h-86rpx rounded-14rpx px-18rpx">
|
||||
<view class="text-28rpx text-#333 ">{{ t('pages-user.complaints.contact-information') }}:</view>
|
||||
<wd-input
|
||||
no-border
|
||||
custom-class="!p-[12rpx+20rpx] rounded-10rpx"
|
||||
v-model.trim="form.contactPhone"
|
||||
placeholderStyle="font-size: 28rpx;line-height: 40rpx;color: #B1B1B1; text-align: right;"
|
||||
:placeholder="t('common.enter')"
|
||||
:maxlength="50"
|
||||
custom-input-class="text-right"
|
||||
@blur="validateField('contactPhone')"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="mt-38rpx text-28rpx text-#999">
|
||||
{{ t('pages-user.complaints.contact-information-tip') }}
|
||||
</view>
|
||||
<fixed-bottom-large-btn
|
||||
class="z-100"
|
||||
fixed
|
||||
:text="`${t('common.submit')}`"
|
||||
@click="handleSubmit"
|
||||
/>
|
||||
<ChooseImage ref="chooseImageRef" @change="onImageChange" />
|
||||
</view>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user