Files
rent/apps/miniapp/src/pages/seller/shop-edit.vue
T
2026-05-10 23:32:27 +08:00

1063 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page-shop-edit">
<!-- 基本信息 -->
<view class="form-section">
<view class="section-title">基本信息</view>
<!-- 店铺名称 -->
<view class="form-item">
<text class="label required">店铺名称</text>
<input
class="input"
type="text"
v-model="form.shopName"
placeholder="请输入店铺名称"
maxlength="100"
/>
</view>
<!-- 联系电话 -->
<view class="form-item">
<text class="label required">联系电话</text>
<input
class="input"
type="number"
v-model="form.phone"
placeholder="请输入联系电话"
maxlength="20"
/>
</view>
<!-- 地区选择 -->
<view class="form-item">
<text class="label">所在地区</text>
<RegionSelector
:province="form.province"
:city="form.city"
:district="form.district"
@change="onRegionChange"
/>
</view>
<!-- 详细地址 -->
<view class="form-item">
<text class="label">详细地址</text>
<input
class="input"
type="text"
v-model="form.address"
placeholder="请输入详细地址"
maxlength="255"
/>
</view>
<!-- 店铺描述 -->
<view class="form-item">
<text class="label">店铺描述</text>
<textarea
class="textarea"
v-model="form.description"
placeholder="请输入店铺描述(选填)"
maxlength="500"
/>
</view>
<!-- 门店营业执照 -->
<view class="form-item">
<text class="label required">门店营业执照</text>
<view class="upload-section">
<view v-if="form.storeLicense" class="image-preview">
<image class="preview-img" :src="form.storeLicense" mode="aspectFit" />
<view class="delete-btn" @tap="form.storeLicense = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadStoreLicense">
<text class="upload-icon">+</text>
<text class="upload-text">上传门店营业执照</text>
</view>
</view>
</view>
</view>
<!-- 酒店照片 -->
<view class="form-section">
<view class="section-title">酒店照片</view>
<view class="section-desc">用于店铺首页轮播图展示最多上传9张</view>
<view class="form-item">
<view class="upload-grid">
<view
v-for="(img, index) in form.hotelImages"
:key="index"
class="image-preview"
>
<image class="preview-img" :src="img" mode="aspectFill" />
<view class="delete-btn" @tap="deleteHotelImage(index)">×</view>
</view>
<view
v-if="form.hotelImages.length < 9"
class="upload-btn"
@tap="uploadHotelImages"
>
<text class="upload-icon">+</text>
<text class="upload-text">上传照片</text>
</view>
</view>
</view>
</view>
<!-- 签约资料 -->
<view class="form-section">
<view class="section-title">签约资料</view>
<!-- 签约类型 -->
<view class="form-item">
<text class="label required">签约类型</text>
<view class="radio-group">
<view
class="radio-item"
:class="{ active: form.contractType === 'personal' }"
@tap="form.contractType = 'personal'"
>
<view class="radio-icon">
<view v-if="form.contractType === 'personal'" class="radio-dot"></view>
</view>
<text>个人签约</text>
</view>
<view
class="radio-item"
:class="{ active: form.contractType === 'company' }"
@tap="form.contractType = 'company'"
>
<view class="radio-icon">
<view v-if="form.contractType === 'company'" class="radio-dot"></view>
</view>
<text>公司/法人签约</text>
</view>
</view>
</view>
<!-- 个人签约 -->
<template v-if="form.contractType === 'personal'">
<view class="form-item">
<text class="label required">身份证正面</text>
<view class="upload-section">
<view v-if="form.idCardFront" class="image-preview">
<image class="preview-img" :src="form.idCardFront" mode="aspectFit" />
<view class="delete-btn" @tap="form.idCardFront = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadIdCardFront">
<text class="upload-icon">+</text>
<text class="upload-text">上传身份证正面</text>
</view>
</view>
</view>
<view class="form-item">
<text class="label required">身份证反面</text>
<view class="upload-section">
<view v-if="form.idCardBack" class="image-preview">
<image class="preview-img" :src="form.idCardBack" mode="aspectFit" />
<view class="delete-btn" @tap="form.idCardBack = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadIdCardBack">
<text class="upload-icon">+</text>
<text class="upload-text">上传身份证反面</text>
</view>
</view>
</view>
</template>
<!-- 公司/法人签约 -->
<template v-if="form.contractType === 'company'">
<view class="form-item">
<text class="label required">法人身份证正面</text>
<view class="upload-section">
<view v-if="form.legalIdCardFront" class="image-preview">
<image class="preview-img" :src="form.legalIdCardFront" mode="aspectFit" />
<view class="delete-btn" @tap="form.legalIdCardFront = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadLegalIdCardFront">
<text class="upload-icon">+</text>
<text class="upload-text">上传法人身份证正面</text>
</view>
</view>
</view>
<view class="form-item">
<text class="label required">法人身份证反面</text>
<view class="upload-section">
<view v-if="form.legalIdCardBack" class="image-preview">
<image class="preview-img" :src="form.legalIdCardBack" mode="aspectFit" />
<view class="delete-btn" @tap="form.legalIdCardBack = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadLegalIdCardBack">
<text class="upload-icon">+</text>
<text class="upload-text">上传法人身份证反面</text>
</view>
</view>
</view>
<view class="form-item">
<text class="label required">营业执照</text>
<view class="upload-section">
<view v-if="form.businessLicense" class="image-preview">
<image class="preview-img" :src="form.businessLicense" mode="aspectFit" />
<view class="delete-btn" @tap="form.businessLicense = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadLicense">
<text class="upload-icon">+</text>
<text class="upload-text">上传营业执照</text>
</view>
</view>
</view>
<!-- 营业执照编号 -->
<view class="form-item">
<text class="label">营业执照编号</text>
<input
class="input"
type="text"
v-model="form.licenseNo"
placeholder="请输入营业执照编号"
maxlength="50"
/>
</view>
<!-- 法人姓名 -->
<view class="form-item">
<text class="label">法人姓名</text>
<input
class="input"
type="text"
v-model="form.legalPerson"
placeholder="请输入法人姓名"
maxlength="50"
/>
</view>
</template>
</view>
<!-- 财务信息 -->
<view class="form-section">
<view class="section-title">财务信息</view>
<!-- 账户类型 -->
<view class="form-item">
<text class="label required">账户类型</text>
<view class="radio-group">
<view
class="radio-item"
:class="{ active: form.accountType === 'company' }"
@tap="form.accountType = 'company'"
>
<view class="radio-icon">
<view v-if="form.accountType === 'company'" class="radio-dot"></view>
</view>
<text>对公账户</text>
</view>
<view
class="radio-item"
:class="{ active: form.accountType === 'personal' }"
@tap="form.accountType = 'personal'"
>
<view class="radio-icon">
<view v-if="form.accountType === 'personal'" class="radio-dot"></view>
</view>
<text>对私账户</text>
</view>
</view>
</view>
<!-- 对公账户 -->
<template v-if="form.accountType === 'company'">
<view class="form-item">
<text class="label required">收款银行</text>
<input
class="input"
type="text"
v-model="form.bankName"
placeholder="请输入收款银行名称"
maxlength="100"
/>
</view>
<view class="form-item">
<text class="label required">银行账号</text>
<input
class="input"
type="text"
v-model="form.bankAccount"
placeholder="请输入银行账号"
maxlength="50"
/>
</view>
<view class="form-item">
<text class="label required">开户营业执照</text>
<view class="upload-section">
<view v-if="form.bankLicense" class="image-preview">
<image class="preview-img" :src="form.bankLicense" mode="aspectFit" />
<view class="delete-btn" @tap="form.bankLicense = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadBankLicense">
<text class="upload-icon">+</text>
<text class="upload-text">上传开户营业执照</text>
</view>
</view>
</view>
</template>
<!-- 对私账户 -->
<template v-if="form.accountType === 'personal'">
<view class="form-item">
<text class="label required">开户名</text>
<input
class="input"
type="text"
v-model="form.accountName"
placeholder="请输入开户名"
maxlength="50"
/>
</view>
<view class="form-item">
<text class="label required">开户账号</text>
<input
class="input"
type="text"
v-model="form.bankAccount"
placeholder="请输入开户账号"
maxlength="50"
/>
</view>
<view class="form-item">
<text class="label required">开户银行</text>
<input
class="input"
type="text"
v-model="form.bankName"
placeholder="请输入开户银行"
maxlength="100"
/>
</view>
<view class="form-item">
<text class="label required">支行信息</text>
<input
class="input"
type="text"
v-model="form.bankBranch"
placeholder="请输入支行名称"
maxlength="100"
/>
</view>
<view class="form-item">
<text class="label required">开户身份证正面</text>
<view class="upload-section">
<view v-if="form.accountIdCardFront" class="image-preview">
<image class="preview-img" :src="form.accountIdCardFront" mode="aspectFit" />
<view class="delete-btn" @tap="form.accountIdCardFront = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadAccountIdCardFront">
<text class="upload-icon">+</text>
<text class="upload-text">上传身份证正面</text>
</view>
</view>
</view>
<view class="form-item">
<text class="label required">开户身份证反面</text>
<view class="upload-section">
<view v-if="form.accountIdCardBack" class="image-preview">
<image class="preview-img" :src="form.accountIdCardBack" mode="aspectFit" />
<view class="delete-btn" @tap="form.accountIdCardBack = ''">×</view>
</view>
<view v-else class="upload-btn" @tap="uploadAccountIdCardBack">
<text class="upload-icon">+</text>
<text class="upload-text">上传身份证反面</text>
</view>
</view>
</view>
</template>
</view>
<button class="submit-btn" :disabled="loading" @tap="handleSubmit">
{{ loading ? '提交中...' : '保存修改' }}
</button>
<view class="tips">
<view class="tips-title">温馨提示</view>
<text class="tips-text">1. 修改店铺信息后需要重新等待平台审核</text>
<text class="tips-text">2. 所有证件照片需清晰可见确保信息真实有效</text>
<text class="tips-text">3. 审核通过后即可继续营业</text>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { updateMerchant, getMyMerchant } from '@/api/seller/merchant';
import { useSellerStore } from '@/store/seller';
import RegionSelector from '@/components/RegionSelector.vue';
import { chooseAndUpload } from '@/utils/upload';
const sellerStore = useSellerStore();
const loading = ref(false);
const form = ref({
// 基本信息
shopName: '',
phone: '',
province: '',
city: '',
district: '',
address: '',
description: '',
storeLicense: '', // 门店营业执照
// 酒店照片
hotelImages: [] as string[],
// 签约资料
contractType: 'personal' as 'personal' | 'company',
idCardFront: '', // 个人身份证正面
idCardBack: '', // 个人身份证反面
legalIdCardFront: '', // 法人身份证正面
legalIdCardBack: '', // 法人身份证反面
businessLicense: '', // 营业执照
licenseNo: '',
legalPerson: '',
// 财务信息
accountType: 'company' as 'company' | 'personal',
accountName: '', // 开户名(对私)
bankAccount: '', // 银行账号
bankName: '', // 银行名称
bankBranch: '', // 支行信息(对私)
bankLicense: '', // 开户营业执照(对公)
accountIdCardFront: '', // 开户身份证正面(对私)
accountIdCardBack: '', // 开户身份证反面(对私)
});
onMounted(async () => {
try {
const res = await getMyMerchant();
const merchant = res.data;
form.value = {
// 基本信息
shopName: merchant.shopName || '',
phone: merchant.phone || '',
province: merchant.province || '',
city: merchant.city || '',
district: merchant.district || '',
address: merchant.address || '',
description: merchant.description || '',
storeLicense: merchant.storeLicense || '',
// 酒店照片
hotelImages: merchant.hotelImages ? merchant.hotelImages.split(',').filter((img: string) => img) : [],
// 签约资料
contractType: merchant.contractType || 'personal',
idCardFront: merchant.idCardFront || '',
idCardBack: merchant.idCardBack || '',
legalIdCardFront: merchant.legalIdCardFront || '',
legalIdCardBack: merchant.legalIdCardBack || '',
businessLicense: merchant.businessLicense || '',
licenseNo: merchant.licenseNo || '',
legalPerson: merchant.legalPerson || '',
// 财务信息
accountType: merchant.accountType || 'company',
accountName: merchant.accountName || '',
bankAccount: merchant.bankAccount || '',
bankName: merchant.bankName || '',
bankBranch: merchant.bankBranch || '',
bankLicense: merchant.bankLicense || '',
accountIdCardFront: merchant.accountIdCardFront || '',
accountIdCardBack: merchant.accountIdCardBack || '',
};
} catch (error) {
uni.showToast({ title: '获取店铺信息失败', icon: 'none' });
}
});
function onRegionChange(value: { province: string; city: string; district: string }) {
form.value.province = value.province;
form.value.city = value.city;
form.value.district = value.district;
}
// 上传酒店照片
async function uploadHotelImages() {
try {
uni.showLoading({ title: '上传中...' });
const remainCount = 9 - form.value.hotelImages.length;
const urls = await chooseAndUpload({ count: remainCount, useSellerToken: true });
form.value.hotelImages.push(...urls);
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
function deleteHotelImage(index: number) {
form.value.hotelImages.splice(index, 1);
}
// 上传门店营业执照
async function uploadStoreLicense() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.storeLicense = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传身份证正面(个人)
async function uploadIdCardFront() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.idCardFront = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传身份证反面(个人)
async function uploadIdCardBack() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.idCardBack = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传法人身份证正面
async function uploadLegalIdCardFront() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.legalIdCardFront = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传法人身份证反面
async function uploadLegalIdCardBack() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.legalIdCardBack = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传营业执照
async function uploadLicense() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.businessLicense = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传开户营业执照
async function uploadBankLicense() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.bankLicense = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传开户身份证正面
async function uploadAccountIdCardFront() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.accountIdCardFront = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
// 上传开户身份证反面
async function uploadAccountIdCardBack() {
try {
uni.showLoading({ title: '上传中...' });
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
form.value.accountIdCardBack = urls[0];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (err: any) {
uni.showToast({ title: err.message || '上传失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
function validateForm(): boolean {
const { shopName, phone, contractType, accountType } = form.value;
// 基本信息验证
if (!shopName || shopName.length < 2) {
uni.showToast({ title: '店铺名称至少2个字', icon: 'none' });
return false;
}
if (!phone) {
uni.showToast({ title: '请填写联系电话', icon: 'none' });
return false;
}
if (!form.value.storeLicense) {
uni.showToast({ title: '请上传门店营业执照', icon: 'none' });
return false;
}
// 签约资料验证
if (contractType === 'personal') {
if (!form.value.idCardFront) {
uni.showToast({ title: '请上传身份证正面', icon: 'none' });
return false;
}
if (!form.value.idCardBack) {
uni.showToast({ title: '请上传身份证反面', icon: 'none' });
return false;
}
} else if (contractType === 'company') {
if (!form.value.legalIdCardFront) {
uni.showToast({ title: '请上传法人身份证正面', icon: 'none' });
return false;
}
if (!form.value.legalIdCardBack) {
uni.showToast({ title: '请上传法人身份证反面', icon: 'none' });
return false;
}
if (!form.value.businessLicense) {
uni.showToast({ title: '请上传营业执照', icon: 'none' });
return false;
}
}
// 财务信息验证
if (accountType === 'company') {
if (!form.value.bankName) {
uni.showToast({ title: '请填写收款银行', icon: 'none' });
return false;
}
if (!form.value.bankAccount) {
uni.showToast({ title: '请填写银行账号', icon: 'none' });
return false;
}
if (!form.value.bankLicense) {
uni.showToast({ title: '请上传开户营业执照', icon: 'none' });
return false;
}
} else if (accountType === 'personal') {
if (!form.value.accountName) {
uni.showToast({ title: '请填写开户名', icon: 'none' });
return false;
}
if (!form.value.bankAccount) {
uni.showToast({ title: '请填写开户账号', icon: 'none' });
return false;
}
if (!form.value.bankName) {
uni.showToast({ title: '请填写开户银行', icon: 'none' });
return false;
}
if (!form.value.bankBranch) {
uni.showToast({ title: '请填写支行信息', icon: 'none' });
return false;
}
if (!form.value.accountIdCardFront) {
uni.showToast({ title: '请上传开户身份证正面', icon: 'none' });
return false;
}
if (!form.value.accountIdCardBack) {
uni.showToast({ title: '请上传开户身份证反面', icon: 'none' });
return false;
}
}
return true;
}
async function handleSubmit() {
if (!validateForm()) return;
loading.value = true;
try {
const res = await updateMerchant({
// 基本信息
shopName: form.value.shopName,
phone: form.value.phone,
province: form.value.province,
city: form.value.city,
district: form.value.district,
address: form.value.address,
description: form.value.description,
storeLicense: form.value.storeLicense,
// 酒店照片
hotelImages: form.value.hotelImages.join(','),
// 签约资料
contractType: form.value.contractType,
idCardFront: form.value.idCardFront,
idCardBack: form.value.idCardBack,
legalIdCardFront: form.value.legalIdCardFront,
legalIdCardBack: form.value.legalIdCardBack,
businessLicense: form.value.businessLicense,
licenseNo: form.value.licenseNo,
legalPerson: form.value.legalPerson,
// 财务信息
accountType: form.value.accountType,
accountName: form.value.accountName,
bankAccount: form.value.bankAccount,
bankName: form.value.bankName,
bankBranch: form.value.bankBranch,
bankLicense: form.value.bankLicense,
accountIdCardFront: form.value.accountIdCardFront,
accountIdCardBack: form.value.accountIdCardBack,
});
uni.showToast({ title: '修改成功', icon: 'success' });
// 更新 sellerInfo 中的 merchantStatus 为 pending
if (sellerStore.sellerInfo && res.data.status === 'pending') {
sellerStore.sellerInfo.merchantStatus = 'pending';
uni.setStorageSync('sellerInfo', sellerStore.sellerInfo);
}
setTimeout(() => {
uni.redirectTo({ url: '/pages/seller/home' });
}, 1500);
} catch (error: any) {
uni.showToast({ title: error.message || '修改失败', icon: 'none' });
} finally {
loading.value = false;
}
}
</script>
<style lang="scss" scoped>
@import '@/static/styles/common.scss';
.page-shop-edit {
min-height: 100vh;
background: $bg-page;
padding: $spacing-xl;
padding-bottom: 200rpx;
}
.form-section {
background: $bg-card;
border-radius: $radius-lg;
padding: $spacing-2xl;
margin-bottom: $spacing-xl;
border: 1rpx solid $border-light;
}
.section-title {
font-size: $font-lg;
font-weight: $font-semibold;
color: $text-primary;
margin-bottom: $spacing-xs;
}
.section-desc {
font-size: $font-xs;
color: $text-secondary;
margin-bottom: $spacing-xl;
}
.form-item {
margin-bottom: $spacing-2xl;
&:last-child {
margin-bottom: 0;
}
}
.label {
font-size: $font-base;
color: $text-primary;
margin-bottom: $spacing-md;
display: block;
font-weight: $font-medium;
&.required::before {
content: '*';
color: $primary-color;
margin-right: $spacing-xs;
}
}
.input {
width: 100%;
height: 88rpx;
background: $bg-page;
border-radius: $radius-base;
padding: 0 $spacing-xl;
font-size: $font-base;
color: $text-primary;
box-sizing: border-box;
border: 2rpx solid $border-light;
transition: all 0.2s ease;
&:focus {
border-color: $primary-color;
background: $bg-card;
}
}
.textarea {
width: 100%;
min-height: 160rpx;
background: $bg-page;
border-radius: $radius-base;
padding: $spacing-xl;
font-size: $font-base;
color: $text-primary;
box-sizing: border-box;
border: 2rpx solid $border-light;
transition: all 0.2s ease;
&:focus {
border-color: $primary-color;
background: $bg-card;
}
}
/* 单选组 */
.radio-group {
display: flex;
gap: $spacing-xl;
}
.radio-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: $spacing-sm;
height: 88rpx;
background: $bg-page;
border-radius: $radius-base;
font-size: $font-base;
color: $text-secondary;
border: 2rpx solid $border-light;
transition: all 0.2s ease;
&.active {
background: $primary-bg;
color: $primary-color;
border-color: $primary-color;
}
}
.radio-icon {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid $border-base;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
.radio-item.active & {
border-color: $primary-color;
}
}
.radio-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: $primary-color;
}
/* 上传区域 */
.upload-section {
display: flex;
}
.upload-grid {
display: flex;
flex-wrap: wrap;
gap: $spacing-md;
}
.upload-btn {
width: 200rpx;
height: 200rpx;
background: $bg-page;
border-radius: $radius-base;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 2rpx dashed $border-base;
transition: all 0.2s ease;
&:active {
background: $bg-hover;
}
}
.upload-icon {
font-size: 48rpx;
color: $text-tertiary;
margin-bottom: $spacing-xs;
}
.upload-text {
font-size: $font-xs;
color: $text-tertiary;
}
.image-preview {
width: 200rpx;
height: 200rpx;
background: $bg-page;
border-radius: $radius-base;
position: relative;
overflow: hidden;
border: 1rpx solid $border-light;
}
.preview-img {
width: 100%;
height: 100%;
border-radius: $radius-base;
}
.delete-btn {
position: absolute;
top: -12rpx;
right: -12rpx;
width: 48rpx;
height: 48rpx;
background: $error-color;
border-radius: 50%;
color: #fff;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
/* 提交按钮 */
.submit-btn {
width: 100%;
height: 96rpx;
background: $primary-color;
color: #fff;
font-size: $font-lg;
font-weight: $font-semibold;
border-radius: $radius-base;
border: none;
margin-top: $spacing-3xl;
transition: all 0.2s ease;
&::after {
border: none;
}
&:active:not([disabled]) {
background: $primary-dark;
}
&[disabled] {
background: $bg-disabled;
color: $text-disabled;
}
}
/* 提示信息 */
.tips {
margin-top: $spacing-2xl;
padding: $spacing-2xl;
background: $bg-card;
border-radius: $radius-lg;
border: 2rpx solid $warning-color;
}
.tips-title {
font-size: $font-base;
font-weight: $font-semibold;
color: $warning-color;
margin-bottom: $spacing-md;
display: flex;
align-items: center;
gap: $spacing-xs;
&::before {
content: '!';
width: 32rpx;
height: 32rpx;
background: $warning-color;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: $font-lg;
font-weight: $font-bold;
}
}
.tips-text {
font-size: $font-sm;
color: $text-secondary;
display: block;
margin-top: $spacing-sm;
line-height: 1.6;
}
</style>