Files
shop-toy/src/pages/me/loan-application.vue
2025-12-20 12:43:50 +08:00

1131 lines
29 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.

<script lang="ts" setup>
definePage({
style: {
navigationBarTitleText: '贷款申请',
navigationBarBackgroundColor: '#fff',
navigationBarTextStyle: 'black',
},
})
// 表单数据
const formData = ref({
// 个人信息
personalInfo: {
name: '',
phone: '',
idCard: '',
region: ['', '', ''], // 省、市、区
detailAddress: '',
},
// 经营信息
businessInfo: {
businessProject: '',
businessTime: '',
annualIncome: '',
hasDebt: 'no', // 'no' 或 'yes'
debtAmount: '',
loanDemand: '',
assets: [] as string[], // 家庭主要资产
},
// 证件信息
documentInfo: {
businessLicense: '', // 营业执照或租赁合同
otherMaterials: [] as string[], // 其他辅助材料
},
})
// 表单验证错误
const formErrors = ref({
personalInfo: {
name: '',
phone: '',
idCard: '',
region: '',
detailAddress: '',
},
businessInfo: {
businessProject: '',
businessTime: '',
annualIncome: '',
debtAmount: '',
loanDemand: '',
assets: '',
},
documentInfo: {
businessLicense: '',
},
})
// 省市区选项(模拟数据)
const regionOptions = ref([
{
value: '110000',
label: '北京市',
children: [
{
value: '110100',
label: '北京市',
children: [
{ value: '110101', label: '东城区' },
{ value: '110102', label: '西城区' },
{ value: '110105', label: '朝阳区' },
{ value: '110106', label: '丰台区' },
{ value: '110107', label: '石景山区' },
{ value: '110108', label: '海淀区' },
]
}
]
},
{
value: '310000',
label: '上海市',
children: [
{
value: '310100',
label: '上海市',
children: [
{ value: '310101', label: '黄浦区' },
{ value: '310104', label: '徐汇区' },
{ value: '310105', label: '长宁区' },
{ value: '310106', label: '静安区' },
{ value: '310107', label: '普陀区' },
{ value: '310109', label: '虹口区' },
]
}
]
},
{
value: '440000',
label: '广东省',
children: [
{
value: '440100',
label: '广州市',
children: [
{ value: '440103', label: '荔湾区' },
{ value: '440104', label: '越秀区' },
{ value: '440105', label: '海珠区' },
{ value: '440106', label: '天河区' },
{ value: '440111', label: '白云区' },
{ value: '440112', label: '黄埔区' },
]
},
{
value: '440300',
label: '深圳市',
children: [
{ value: '440303', label: '罗湖区' },
{ value: '440304', label: '福田区' },
{ value: '440305', label: '南山区' },
{ value: '440306', label: '宝安区' },
{ value: '440307', label: '龙岗区' },
{ value: '440308', label: '龙华区' },
]
}
]
}
])
// 家庭主要资产选项
const assetOptions = [
{ value: 'house', label: '商品房' },
{ value: 'selfBuiltState', label: '自建房 (国有)' },
{ value: 'selfBuiltCollective', label: '自建房 (集体)' },
{ value: 'shop', label: '商铺' },
{ value: 'land', label: '土地' },
{ value: 'car', label: '车辆' },
{ value: 'other', label: '其他' },
{ value: 'none', label: '无' },
]
// 选择省市区
function handleRegionPicker() {
// 简化的省市区选择器,使用 uni.showActionSheet
const provinces = regionOptions.value.map(item => item.label)
uni.showActionSheet({
itemList: provinces,
success: (res) => {
if (res.tapIndex !== undefined) {
const selectedProvince = regionOptions.value[res.tapIndex]
formData.value.personalInfo.region[0] = selectedProvince.value
// 选择市
const cities = selectedProvince.children.map((item: any) => item.label)
uni.showActionSheet({
itemList: cities,
success: (cityRes) => {
if (cityRes.tapIndex !== undefined) {
const selectedCity = selectedProvince.children[cityRes.tapIndex]
formData.value.personalInfo.region[1] = selectedCity.value
// 选择区
const districts = selectedCity.children.map((item: any) => item.label)
uni.showActionSheet({
itemList: districts,
success: (districtRes) => {
if (districtRes.tapIndex !== undefined) {
const selectedDistrict = selectedCity.children[districtRes.tapIndex]
formData.value.personalInfo.region[2] = selectedDistrict.value
}
}
})
}
}
})
}
}
})
}
// 处理资产选择
function handleAssetChange(value: string) {
const { assets } = formData.value.businessInfo
// 如果选择"无",则取消其他所有选项
if (value === 'none') {
formData.value.businessInfo.assets = ['none']
return
}
// 如果选择了其他选项,则取消"无"选项
if (assets.includes('none')) {
const index = assets.indexOf('none')
assets.splice(index, 1)
}
// 切换选项
const index = assets.indexOf(value)
if (index > -1) {
assets.splice(index, 1)
} else {
assets.push(value)
}
}
// 上传营业执照
function handleUploadBusinessLicense() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
formData.value.documentInfo.businessLicense = res.tempFilePaths[0]
formErrors.value.documentInfo.businessLicense = ''
}
})
}
// 上传其他材料
function handleUploadOtherMaterials() {
const currentCount = formData.value.documentInfo.otherMaterials.length
const maxCount = 5
if (currentCount >= maxCount) {
uni.showToast({
title: `最多上传${maxCount}张图片`,
icon: 'none'
})
return
}
uni.chooseImage({
count: maxCount - currentCount,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
if (Array.isArray(res.tempFilePaths)) {
formData.value.documentInfo.otherMaterials.push(...res.tempFilePaths)
}
}
})
}
// 删除其他材料
function handleRemoveOtherMaterial(index: number) {
formData.value.documentInfo.otherMaterials.splice(index, 1)
}
// 预览图片
function handlePreviewImage(url: string) {
uni.previewImage({
urls: [url]
})
}
// 表单验证
function validateForm() {
let isValid = true
const errors = formErrors.value
// 重置错误信息
Object.keys(errors.personalInfo).forEach(key => {
errors.personalInfo[key as keyof typeof errors.personalInfo] = ''
})
Object.keys(errors.businessInfo).forEach(key => {
errors.businessInfo[key as keyof typeof errors.businessInfo] = ''
})
errors.documentInfo.businessLicense = ''
// 验证个人信息
if (!formData.value.personalInfo.name.trim()) {
errors.personalInfo.name = '请输入姓名'
isValid = false
}
if (!formData.value.personalInfo.phone.trim()) {
errors.personalInfo.phone = '请输入联系方式'
isValid = false
} else if (!/^1[3-9]\d{9}$/.test(formData.value.personalInfo.phone)) {
errors.personalInfo.phone = '请输入正确的手机号'
isValid = false
}
if (!formData.value.personalInfo.idCard.trim()) {
errors.personalInfo.idCard = '请输入身份证号码'
isValid = false
} else if (!/^\d{17}[\dXx]$/.test(formData.value.personalInfo.idCard)) {
errors.personalInfo.idCard = '请输入正确的身份证号码'
isValid = false
}
if (formData.value.personalInfo.region.some(item => !item)) {
errors.personalInfo.region = '请选择省市区'
isValid = false
}
if (!formData.value.personalInfo.detailAddress.trim()) {
errors.personalInfo.detailAddress = '请输入详细地址'
isValid = false
} else if (formData.value.personalInfo.detailAddress.trim().length < 5 || formData.value.personalInfo.detailAddress.trim().length > 100) {
errors.personalInfo.detailAddress = '详细地址长度应在5-100字之间'
isValid = false
}
// 验证经营信息
if (!formData.value.businessInfo.businessProject.trim()) {
errors.businessInfo.businessProject = '请输入经营项目'
isValid = false
}
if (!formData.value.businessInfo.businessTime.trim()) {
errors.businessInfo.businessTime = '请输入经营时间'
isValid = false
}
if (!formData.value.businessInfo.annualIncome.trim()) {
errors.businessInfo.annualIncome = '请输入最近1年经营收入'
isValid = false
} else if (isNaN(Number(formData.value.businessInfo.annualIncome)) || Number(formData.value.businessInfo.annualIncome) <= 0) {
errors.businessInfo.annualIncome = '请输入正确的金额'
isValid = false
}
if (formData.value.businessInfo.hasDebt === 'yes' && !formData.value.businessInfo.debtAmount.trim()) {
errors.businessInfo.debtAmount = '请输入负债金额'
isValid = false
} else if (formData.value.businessInfo.hasDebt === 'yes' && (isNaN(Number(formData.value.businessInfo.debtAmount)) || Number(formData.value.businessInfo.debtAmount) <= 0)) {
errors.businessInfo.debtAmount = '请输入正确的金额'
isValid = false
}
if (!formData.value.businessInfo.loanDemand.trim()) {
errors.businessInfo.loanDemand = '请输入贷款需求'
isValid = false
} else if (isNaN(Number(formData.value.businessInfo.loanDemand)) || Number(formData.value.businessInfo.loanDemand) <= 0) {
errors.businessInfo.loanDemand = '请输入正确的金额'
isValid = false
}
if (formData.value.businessInfo.assets.length === 0) {
errors.businessInfo.assets = '请至少选择一项家庭主要资产'
isValid = false
}
// 验证证件信息
if (!formData.value.documentInfo.businessLicense) {
errors.documentInfo.businessLicense = '请上传营业执照或租赁合同'
isValid = false
}
return isValid
}
// 提交表单
async function handleSubmit() {
if (!validateForm()) return
uni.showLoading({
title: '提交中...'
})
try {
// 收集选中的商家
const selectedMerchants = merchantList.value.filter(item => item.selected)
// 构建提交数据
const submitData = {
...formData.value,
relatedMerchants: selectedMerchants
}
await submitLoanApplication(submitData)
uni.hideLoading()
uni.showToast({
title: '提交成功',
icon: 'success'
})
// 延迟返回
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
uni.hideLoading()
uni.showToast({
title: '提交失败',
icon: 'none'
})
}
}
// 返回上一页
function handleBack() {
uni.navigateBack()
}
// 商家选择相关
import { getUserMerchants, submitLoanApplication } from '@/api/loan'
import type { RelatedMerchant } from '@/typings/loan'
const merchantList = ref<RelatedMerchant[]>([])
onMounted(async () => {
const res = await getUserMerchants()
merchantList.value = res.list
})
function toggleMerchant(item: RelatedMerchant) {
item.selected = !item.selected
}
// 展开/收起逻辑
const isExpanded = ref(false)
const displayedMerchants = computed(() => {
if (isExpanded.value) {
return merchantList.value
}
return merchantList.value.slice(0, 3)
})
function toggleExpand() {
isExpanded.value = !isExpanded.value
}
</script>
<template>
<view class="loan-application-page">
<!-- 个人信息模块 -->
<view class="form-card">
<view class="card-title">
<view class="title-bar"></view>
<text class="title-text">个人信息</text>
</view>
<view class="form-content">
<view class="form-item">
<view class="label">姓名</view>
<input
class="input"
v-model="formData.personalInfo.name"
placeholder="请输入姓名"
:maxlength="20"
/>
<text v-if="formErrors.personalInfo.name" class="error-text">{{ formErrors.personalInfo.name }}</text>
</view>
<view class="form-item">
<view class="label">联系方式</view>
<input
class="input"
v-model="formData.personalInfo.phone"
placeholder="请输入联系方式"
type="number"
:maxlength="11"
/>
<text v-if="formErrors.personalInfo.phone" class="error-text">{{ formErrors.personalInfo.phone }}</text>
</view>
<view class="form-item">
<view class="label">身份证号码</view>
<input
class="input"
v-model="formData.personalInfo.idCard"
placeholder="请输入身份证号码"
:maxlength="18"
/>
<text v-if="formErrors.personalInfo.idCard" class="error-text">{{ formErrors.personalInfo.idCard }}</text>
</view>
<view class="form-item" @click="handleRegionPicker">
<view class="label">经营地址</view>
<view class="picker-input">
<text v-if="formData.personalInfo.region.some(item => item)" class="picker-text">
{{ regionOptions.find(p => p.value === formData.personalInfo.region[0])?.label }}
{{ regionOptions.find(p => p.value === formData.personalInfo.region[0])?.children?.find(c => c.value === formData.personalInfo.region[1])?.label }}
{{ regionOptions.find(p => p.value === formData.personalInfo.region[0])?.children?.find(c => c.value === formData.personalInfo.region[1])?.children?.find(d => d.value === formData.personalInfo.region[2])?.label }}
</text>
<text v-else class="picker-placeholder">选择省,,</text>
<text class="i-carbon-chevron-right picker-arrow"></text>
</view>
<text v-if="formErrors.personalInfo.region" class="error-text">{{ formErrors.personalInfo.region }}</text>
</view>
<view class="form-item">
<view class="label">详细地址</view>
<textarea
class="textarea"
v-model="formData.personalInfo.detailAddress"
placeholder="请输入街道小区楼牌号等"
:maxlength="100"
/>
<text v-if="formErrors.personalInfo.detailAddress" class="error-text">{{ formErrors.personalInfo.detailAddress }}</text>
</view>
</view>
</view>
<!-- 经营信息模块 -->
<view class="form-card">
<view class="card-title">
<view class="title-bar"></view>
<text class="title-text">经营信息</text>
</view>
<view class="form-content">
<view class="form-item">
<view class="label">经营项目</view>
<input
class="input"
v-model="formData.businessInfo.businessProject"
placeholder="请输入经营项目"
/>
<text v-if="formErrors.businessInfo.businessProject" class="error-text">{{ formErrors.businessInfo.businessProject }}</text>
</view>
<view class="form-item">
<view class="label">经营时间</view>
<input
class="input"
v-model="formData.businessInfo.businessTime"
placeholder="请输入经营时间"
/>
<text v-if="formErrors.businessInfo.businessTime" class="error-text">{{ formErrors.businessInfo.businessTime }}</text>
</view>
<view class="form-item">
<view class="label">最近1年经营收入</view>
<view class="input-with-suffix">
<input
class="input"
v-model="formData.businessInfo.annualIncome"
placeholder="请输入金额"
type="digit"
/>
<text class="suffix">万元</text>
</view>
<text v-if="formErrors.businessInfo.annualIncome" class="error-text">{{ formErrors.businessInfo.annualIncome }}</text>
</view>
<view class="form-item">
<view class="label">负债情况</view>
<view class="radio-group">
<view
class="radio-item"
:class="{ active: formData.businessInfo.hasDebt === 'no' }"
@click="formData.businessInfo.hasDebt = 'no'"
>
<text class="radio-dot"></text>
<text>无负债</text>
</view>
<view
class="radio-item"
:class="{ active: formData.businessInfo.hasDebt === 'yes' }"
@click="formData.businessInfo.hasDebt = 'yes'"
>
<text class="radio-dot"></text>
<text>有负债</text>
</view>
</view>
<view v-if="formData.businessInfo.hasDebt === 'yes'" class="debt-amount">
<input
class="input"
v-model="formData.businessInfo.debtAmount"
placeholder="请输入负债金额"
type="digit"
/>
<text v-if="formErrors.businessInfo.debtAmount" class="error-text">{{ formErrors.businessInfo.debtAmount }}</text>
</view>
</view>
<view class="form-item">
<view class="label">贷款需求</view>
<view class="input-with-suffix">
<input
class="input"
v-model="formData.businessInfo.loanDemand"
placeholder="请输入金额"
type="digit"
/>
<text class="suffix">万元</text>
</view>
<text v-if="formErrors.businessInfo.loanDemand" class="error-text">{{ formErrors.businessInfo.loanDemand }}</text>
</view>
<view class="form-item">
<view class="label">家庭主要资产</view>
<view class="checkbox-group">
<view
v-for="option in assetOptions"
:key="option.value"
class="checkbox-item"
:class="{ active: formData.businessInfo.assets.includes(option.value) }"
@click="handleAssetChange(option.value)"
>
<text class="checkbox-icon"></text>
<text>{{ option.label }}</text>
</view>
</view>
<text v-if="formErrors.businessInfo.assets" class="error-text">{{ formErrors.businessInfo.assets }}</text>
</view>
</view>
</view>
<!-- 关联商家模块 -->
<view class="form-card">
<view class="card-title">
<view class="title-bar"></view>
<text class="title-text">关联商家 (辅助证明)</text>
</view>
<view class="form-content">
<view class="merchant-tip">
选择交易过的商家系统将通知商家为您提供交易辅助材料有助于提高审批通过率
</view>
<view class="merchant-list">
<view
v-for="item in displayedMerchants"
:key="item.merchantId"
class="merchant-item"
:class="{ active: item.selected }"
@click="toggleMerchant(item)"
>
<view class="check-box">
<text v-if="item.selected" class="i-carbon-checkmark"></text>
</view>
<view class="merchant-info">
<text class="name">{{ item.merchantName }}</text>
<text class="time">最近交易: {{ item.lastTradeTime }}</text>
</view>
</view>
<!-- 展开/收起按钮 -->
<view
v-if="merchantList.length > 3"
class="expand-btn"
@click="toggleExpand"
>
<text>{{ isExpanded ? '收起' : '展开更多 (' + (merchantList.length - 3) + ')' }}</text>
<text
class="i-carbon-chevron-down arrow"
:class="{ up: isExpanded }"
></text>
</view>
</view>
</view>
</view>
<!-- 证件信息模块 -->
<view class="form-card">
<view class="card-title">
<view class="title-bar"></view>
<text class="title-text">证件信息</text>
</view>
<view class="form-content">
<view class="form-item">
<view class="label">营业执照(租赁合同)</view>
<view class="upload-area" @click="handleUploadBusinessLicense">
<image v-if="formData.documentInfo.businessLicense" :src="formData.documentInfo.businessLicense" class="uploaded-image" @click.stop="handlePreviewImage(formData.documentInfo.businessLicense)" />
<view v-else class="upload-placeholder">
<text class="i-carbon-camera upload-icon"></text>
<text class="upload-text">点击上传图片</text>
</view>
</view>
<text v-if="formErrors.documentInfo.businessLicense" class="error-text">{{ formErrors.documentInfo.businessLicense }}</text>
</view>
<view class="form-item">
<view class="label">其他辅助材料</view>
<view class="upload-list">
<view
v-for="(image, index) in formData.documentInfo.otherMaterials"
:key="index"
class="upload-item"
>
<image :src="image" class="uploaded-image" @click="handlePreviewImage(image)" />
<view class="delete-btn" @click="handleRemoveOtherMaterial(index)">
<text class="i-carbon-close"></text>
</view>
</view>
<view
v-if="formData.documentInfo.otherMaterials.length < 5"
class="upload-area small"
@click="handleUploadOtherMaterials"
>
<text class="i-carbon-add upload-icon"></text>
</view>
</view>
</view>
</view>
</view>
<!-- 底部提交按钮 -->
<view class="submit-bar">
<button class="submit-btn" @click="handleSubmit">提交资料</button>
</view>
</view>
</template>
<style lang="scss" scoped>
.loan-application-page {
min-height: 100vh;
background: #F5F7FA;
padding-bottom: 120rpx;
}
.form-card {
background: #FFFFFF;
margin: 20rpx;
border-radius: 12rpx;
overflow: hidden;
}
.card-title {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #F0F0F0;
.title-bar {
width: 6rpx;
height: 30rpx;
background: #FF6600;
border-radius: 3rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
}
.form-content {
padding: 30rpx;
}
.form-item {
margin-bottom: 40rpx;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 28rpx;
color: #333333;
margin-bottom: 16rpx;
}
.input {
width: 100%;
height: 80rpx;
background: #F8F8F8;
border-radius: 8rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
}
.textarea {
width: 100%;
min-height: 120rpx;
background: #F8F8F8;
border-radius: 8rpx;
padding: 24rpx;
font-size: 28rpx;
color: #333333;
box-sizing: border-box;
}
.picker-input {
width: 100%;
height: 80rpx;
background: #F8F8F8;
border-radius: 8rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
.picker-text {
font-size: 28rpx;
color: #333333;
}
.picker-placeholder {
font-size: 28rpx;
color: #999999;
}
.picker-arrow {
font-size: 32rpx;
color: #CCCCCC;
}
}
.input-with-suffix {
display: flex;
align-items: center;
.input {
flex: 1;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.suffix {
height: 80rpx;
padding: 0 24rpx;
background: #F0F0F0;
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
display: flex;
align-items: center;
font-size: 28rpx;
color: #666666;
box-sizing: border-box;
}
}
.radio-group {
display: flex;
gap: 40rpx;
.radio-item {
display: flex;
align-items: center;
gap: 12rpx;
.radio-dot {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
border: 2rpx solid #DDDDDD;
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 18rpx;
height: 18rpx;
border-radius: 50%;
background: #28C445;
opacity: 0;
}
}
&.active {
.radio-dot {
border-color: #28C445;
&::after {
opacity: 1;
}
}
}
}
}
.debt-amount {
margin-top: 20rpx;
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
.checkbox-item {
display: flex;
align-items: center;
gap: 12rpx;
padding: 16rpx 24rpx;
background: #F8F8F8;
border-radius: 8rpx;
.checkbox-icon {
width: 32rpx;
height: 32rpx;
border-radius: 4rpx;
border: 2rpx solid #DDDDDD;
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 16rpx;
height: 16rpx;
background: #28C445;
border-radius: 2rpx;
opacity: 0;
}
}
&.active {
.checkbox-icon {
border-color: #28C445;
&::after {
opacity: 1;
}
}
}
}
}
.upload-area {
width: 100%;
height: 200rpx;
background: #F8F8F8;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
&.small {
width: 160rpx;
height: 160rpx;
}
.upload-placeholder {
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
.upload-icon {
font-size: 48rpx;
color: #CCCCCC;
}
.upload-text {
font-size: 24rpx;
color: #999999;
}
}
.uploaded-image {
width: 100%;
height: 100%;
border-radius: 8rpx;
object-fit: cover;
}
}
.upload-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
.upload-item {
position: relative;
width: 160rpx;
height: 160rpx;
.uploaded-image {
width: 100%;
height: 100%;
border-radius: 8rpx;
object-fit: cover;
}
.delete-btn {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
.i-carbon-close {
font-size: 24rpx;
color: #FFFFFF;
}
}
}
}
.error-text {
display: block;
font-size: 24rpx;
color: #FF4D4F;
margin-top: 8rpx;
}
}
.submit-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx;
background: #FFFFFF;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.submit-btn {
width: 100%;
height: 88rpx;
background: #28C445;
border-radius: 44rpx;
color: #FFFFFF;
font-size: 32rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
&:active {
opacity: 0.8;
}
}
}
</style>
<style lang="scss" scoped>
/* 补充商家选择样式 */
.merchant-tip {
font-size: 26rpx;
color: #666;
background: #fdf5e6;
padding: 20rpx;
border-radius: 8rpx;
margin-bottom: 24rpx;
line-height: 1.5;
}
.merchant-list {
display: flex;
flex-direction: column;
gap: 20rpx;
.merchant-item {
display: flex;
align-items: center;
padding: 20rpx;
background: #f8f8f8;
border-radius: 12rpx;
border: 2rpx solid transparent;
transition: all 0.2s;
&.active {
background: #e6f7eb;
border-color: #28c445;
.check-box {
background: #28c445;
border-color: #28c445;
}
}
.check-box {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #ddd;
border-radius: 8rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
flex-shrink: 0; /* 防止压缩 */
text {
font-size: 28rpx;
color: #fff;
}
}
.merchant-info {
display: flex;
flex-direction: column;
.name {
font-size: 30rpx;
color: #333;
font-weight: 500;
margin-bottom: 6rpx;
}
.time {
font-size: 24rpx;
color: #999;
}
}
}
.expand-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 0;
gap: 8rpx;
font-size: 26rpx;
color: #666;
.arrow {
transition: transform 0.3s;
font-size: 24rpx;
&.up {
transform: rotate(180deg);
}
}
&:active {
opacity: 0.7;
}
}
}
</style>