初始化参股

This commit is contained in:
2026-01-27 18:06:04 +08:00
commit 2774a539bf
254 changed files with 33255 additions and 0 deletions

View File

@@ -0,0 +1,489 @@
<template>
<view class="page">
<scroll-view class="page-scroll" scroll-y>
<!-- 表单头部 -->
<view class="header-section">
<text class="header-title">预约翻新服务</text>
<text class="header-desc">填写以下信息,我们会尽快与您联系</text>
</view>
<!-- 表单内容 -->
<view class="form-section">
<!-- 姓名 -->
<view class="form-item">
<text class="form-label">
<text class="required">*</text>
您的姓名
</text>
<input
class="form-input"
type="text"
v-model="formData.userName"
placeholder="请输入您的姓名"
placeholder-class="placeholder"
/>
</view>
<!-- 电话 -->
<view class="form-item">
<text class="form-label">
<text class="required">*</text>
联系电话
</text>
<input
class="form-input"
type="number"
v-model="formData.phone"
placeholder="请输入您的手机号"
placeholder-class="placeholder"
maxlength="11"
/>
</view>
<!-- 地址 -->
<view class="form-item">
<text class="form-label">
<text class="required">*</text>
您的地址
</text>
<input
class="form-input"
type="text"
v-model="formData.address"
placeholder="请输入详细地址"
placeholder-class="placeholder"
/>
</view>
<!-- 沙发类型 -->
<view class="form-item">
<text class="form-label">沙发类型</text>
<view class="type-grid">
<view
class="type-item"
:class="{ 'type-active': formData.sofaType == item.id }"
v-for="item in sofaTypes"
:key="item.id"
@click="selectSofaType(item.id)"
>
<text
class="type-text"
:class="{ 'type-text-active': formData.sofaType == item.id }"
>{{ item.name }}</text>
</view>
</view>
</view>
<!-- 问题描述 -->
<view class="form-item">
<text class="form-label">问题描述</text>
<textarea
class="form-textarea"
v-model="formData.problem"
placeholder="请描述沙发的问题(如:皮面开裂、褪色、塌陷等)"
placeholder-class="placeholder"
maxlength="500"
></textarea>
<text class="textarea-count">{{ formData.problem.length }}/500</text>
</view>
<!-- 上传图片 -->
<view class="form-item">
<text class="form-label">上传图片(可选)</text>
<view class="upload-grid">
<view
class="upload-item"
v-for="(item, index) in imageList"
:key="index"
>
<image class="upload-image" :src="item" mode="aspectFill"></image>
<view class="upload-delete" @click="deleteImage(index)">
<text class="delete-icon">×</text>
</view>
</view>
<view class="upload-add" v-if="imageList.length < 9" @click="chooseImage">
<text class="add-icon">+</text>
<text class="add-text">添加图片</text>
</view>
</view>
<text class="upload-tip">最多可上传9张图片</text>
</view>
</view>
<!-- 底部间距 -->
<view class="bottom-space"></view>
</scroll-view>
<!-- 提交按钮 -->
<view class="submit-bar">
<view class="submit-btn" @click="handleSubmit">
<text class="submit-text">提交预约</text>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { submitBooking } from '@/api/index.uts'
import { SOFA_CATEGORIES } from '@/utils/config.uts'
// 表单类型
type FormData = {
userName : string
phone : string
address : string
sofaType : string
problem : string
}
// 沙发类型
type SofaType = {
id : string
name : string
}
// 表单数据
const formData = ref<FormData>({
userName: '',
phone: '',
address: '',
sofaType: '',
problem: ''
})
// 图片列表
const imageList = ref<string[]>([])
// 沙发类型列表
const sofaTypes = ref<SofaType[]>([])
// 提交中
const submitting = ref(false)
// 初始化沙发类型
const initSofaTypes = () => {
sofaTypes.value = SOFA_CATEGORIES.filter((item) : boolean => item.id != 'all').map((item) : SofaType => {
return {
id: item.id,
name: item.name
} as SofaType
})
}
// 选择沙发类型
const selectSofaType = (id : string) => {
formData.value.sofaType = id
}
// 选择图片
const chooseImage = () => {
uni.chooseImage({
count: 9 - imageList.value.length,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
imageList.value = [...imageList.value, ...res.tempFilePaths]
}
})
}
// 删除图片
const deleteImage = (index : number) => {
imageList.value.splice(index, 1)
}
// 验证表单
const validateForm = () : boolean => {
if (formData.value.userName.trim() == '') {
uni.showToast({
title: '请输入您的姓名',
icon: 'none'
})
return false
}
const phone = formData.value.phone.trim()
if (phone == '') {
uni.showToast({
title: '请输入联系电话',
icon: 'none'
})
return false
}
// 简单验证手机号
if (phone.length != 11) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none'
})
return false
}
if (formData.value.address.trim() == '') {
uni.showToast({
title: '请输入您的地址',
icon: 'none'
})
return false
}
return true
}
// 提交预约
const handleSubmit = async () => {
if (!validateForm()) return
if (submitting.value) return
submitting.value = true
try {
const data = {
userName: formData.value.userName,
phone: formData.value.phone,
address: formData.value.address,
sofaType: formData.value.sofaType,
problem: formData.value.problem,
images: imageList.value
} as UTSJSONObject
const res = await submitBooking(data)
const result = res.data as UTSJSONObject
uni.showModal({
title: '预约成功',
content: result['message'] as string,
showCancel: false,
success: () => {
// 返回上一页或首页
uni.navigateBack({
fail: () => {
uni.switchTab({
url: '/pages/index/index'
})
}
})
}
})
} catch (e) {
console.error('提交预约失败', e)
uni.showToast({
title: '提交失败,请重试',
icon: 'none'
})
}
submitting.value = false
}
onLoad(() => {
initSofaTypes()
})
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f5f5f5;
}
.page-scroll {
flex: 1;
}
/* 头部 */
.header-section {
background: linear-gradient(135deg, #D4A574 0%, #B8895A 100%);
padding: 48rpx 32rpx;
align-items: center;
}
.header-title {
font-size: 40rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 12rpx;
}
.header-desc {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 表单区域 */
.form-section {
background-color: #ffffff;
margin: 24rpx;
border-radius: 16rpx;
padding: 32rpx;
}
.form-item {
margin-bottom: 32rpx;
}
.form-label {
font-size: 28rpx;
font-weight: 600;
color: #333333;
margin-bottom: 16rpx;
}
.required {
color: #F56C6C;
margin-right: 4rpx;
}
.form-input {
background-color: #f5f5f5;
border-radius: 12rpx;
padding: 24rpx;
font-size: 28rpx;
height:40px;
}
.placeholder {
color: #C0C4CC;
}
/* 沙发类型选择 */
.type-grid {
flex-direction: row;
flex-wrap: wrap;
}
.type-item {
padding: 16rpx 32rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
}
.type-active {
background-color: #D4A574;
}
.type-text {
font-size: 26rpx;
color: #606266;
}
.type-text-active {
color: #ffffff;
}
/* 文本域 */
.form-textarea {
background-color: #f5f5f5;
border-radius: 12rpx;
padding: 24rpx;
font-size: 28rpx;
height: 200rpx;
width: 100%;
}
.textarea-count {
font-size: 24rpx;
color: #909399;
text-align: right;
margin-top: 8rpx;
}
/* 图片上传 */
.upload-grid {
flex-direction: row;
flex-wrap: wrap;
}
.upload-item {
width: 200rpx;
height: 200rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
position: relative;
}
.upload-image {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
.upload-delete {
position: absolute;
top: -16rpx;
right: -16rpx;
width: 40rpx;
height: 40rpx;
background-color: #F56C6C;
border-radius: 50%;
align-items: center;
justify-content: center;
}
.delete-icon {
font-size: 28rpx;
color: #ffffff;
}
.upload-add {
width: 200rpx;
height: 200rpx;
background-color: #f5f5f5;
border-radius: 12rpx;
align-items: center;
justify-content: center;
border-width: 2rpx;
border-style: dashed;
border-color: #DCDFE6;
}
.add-icon {
font-size: 48rpx;
color: #909399;
}
.add-text {
font-size: 24rpx;
color: #909399;
margin-top: 8rpx;
}
.upload-tip {
font-size: 24rpx;
color: #909399;
margin-top: 16rpx;
}
/* 底部间距 */
.bottom-space {
height: 160rpx;
}
/* 提交按钮 */
.submit-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
padding: 24rpx 32rpx;
padding-bottom: 48rpx;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.submit-btn {
background-color: #D4A574;
border-radius: 999rpx;
padding: 28rpx 0;
align-items: center;
}
.submit-text {
font-size: 32rpx;
font-weight: 600;
color: #ffffff;
}
</style>