feat: 完成项目基础功能搭建与样式优化
1. 新增评估选择组件、本地草稿存储与新闻/金融内容服务 2. 重构页面布局与样式:调整按钮阴影、图标尺寸、导航栏样式 3. 更新启动页、报告页、消息中心等页面UI与交互逻辑 4. 替换图标资源,调整禁用态透明度 5. 补充README文档与本地数据模拟实现
This commit is contained in:
@@ -1,120 +1,201 @@
|
||||
<template>
|
||||
<view class="page page-white" :style="pageStyle()">
|
||||
<AppHeader :title="titles[step]" />
|
||||
<view class="assessment-content" :style="contentStyle(96, true)">
|
||||
<view class="step-line"><view v-for="i in 4" :key="i" :class="i <= step + 1 ? 'step-segment done' : 'step-segment'"></view></view>
|
||||
<text class="step-count">{{ step + 1 }}/4</text>
|
||||
<view v-if="step == 0" class="form-list">
|
||||
<view class="form-row"><text class="field-label">姓名</text><input v-model="form.name" class="field-input" placeholder="请输入姓名" placeholder-class="placeholder" /></view>
|
||||
<view class="form-row"><text class="field-label">身份证号</text><input v-model="form.idCard" class="field-input" placeholder="请输入身份证号" placeholder-class="placeholder" /></view>
|
||||
<view class="form-row"><text class="field-label">手机号</text><input v-model="form.phone" class="field-input" type="number" placeholder="请输入手机号" placeholder-class="placeholder" /></view>
|
||||
<view class="form-row"><text class="field-label">所在城市</text><input v-model="form.city" class="field-input" placeholder="请选择所在城市" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">婚姻状况</text><input v-model="form.maritalStatus" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<AppHeader :title="titles[step]" :customBack="true" @back="back" />
|
||||
<scroll-view scroll-y :style="contentStyle(96, false)">
|
||||
<view class="assessment-content">
|
||||
<view class="progress-row"><view class="step-line"><view v-for="i in 5" :key="i" :class="i <= step + 1 ? 'step-segment done' : 'step-segment'"></view></view><text class="step-count">{{ step + 1 }}/5</text></view>
|
||||
<view v-if="step == 0" class="type-row"><text class="type-label">融资类型</text><view class="type-switch"><text :class="assessmentType == 'personal' ? 'type-item type-active' : 'type-item'" @click="switchType('personal')">个人</text><text :class="assessmentType == 'enterprise' ? 'type-item type-active' : 'type-item'" @click="switchType('enterprise')">企业</text></view></view>
|
||||
<text v-else class="section-hint">{{ assessmentType == 'enterprise' ? '企业信用融资' : '个人信用融资' }} · {{ step == 3 ? '资料与授权均为选填' : '请按实际情况填写' }}</text>
|
||||
<view v-if="step == 0" class="form-list">
|
||||
<view v-if="assessmentType == 'enterprise'" class="form-row"><text class="field-label">企业名称</text><input v-model="form.enterpriseName" class="field-input" placeholder="请输入企业名称" /></view>
|
||||
<view v-if="assessmentType == 'enterprise'" class="form-row"><text class="field-label">信用代码</text><input v-model="form.businessCode" class="field-input" maxlength="18" placeholder="统一社会信用代码" /></view>
|
||||
<view class="form-row"><text class="field-label">{{ assessmentType == 'enterprise' ? '联系人' : '姓名' }}</text><input v-model="form.name" class="field-input" placeholder="请输入姓名" /></view>
|
||||
<view v-if="assessmentType == 'personal'" class="form-row"><text class="field-label">身份证号</text><input v-model="form.idCard" class="field-input" maxlength="18" placeholder="请输入身份证号" /></view>
|
||||
<view class="form-row"><text class="field-label">手机号</text><input v-model="form.phone" class="field-input" type="number" maxlength="11" placeholder="请输入手机号" /></view>
|
||||
<AssessmentSelect label="所在城市" :modelValue="form.city" @update:modelValue="cityChanged" :options="['深圳市', '广州市', '北京市', '上海市', '杭州市', '其他城市']" />
|
||||
<view v-if="form.city == '其他城市' || customCity.length > 0" class="form-row"><text class="field-label">城市名称</text><input v-model="customCity" class="field-input" placeholder="请输入所在城市" /></view>
|
||||
<AssessmentSelect v-if="assessmentType == 'personal'" label="婚姻状况" v-model="form.maritalStatus" :options="['未婚', '已婚', '离异', '丧偶']" />
|
||||
</view>
|
||||
<view v-else-if="step == 1" class="form-list">
|
||||
<template v-if="assessmentType == 'enterprise'">
|
||||
<AssessmentSelect label="经营行业" v-model="form.occupation" :options="['商贸零售', '制造业', '科技服务', '餐饮住宿', '专业服务', '其他行业']" />
|
||||
<AssessmentSelect label="经营年限" v-model="form.operatingYears" :options="['不足 1 年', '1–3 年', '3–5 年', '5 年以上']" />
|
||||
<view class="form-row"><text class="field-label">年营收(万元)</text><input v-model="form.annualRevenue" class="field-input" type="digit" placeholder="请输入年营业收入" /></view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<AssessmentSelect label="职业类型" v-model="form.occupation" :options="['企业职员', '事业单位', '公务员', '个体经营', '自由职业', '其他']" />
|
||||
<view class="form-row"><text class="field-label">工作单位</text><input v-model="form.company" class="field-input" placeholder="请输入工作单位" /></view>
|
||||
<view class="form-row"><text class="field-label">月收入(元)</text><input v-model="form.monthlyIncome" class="field-input" type="digit" placeholder="请输入月收入" /></view>
|
||||
<AssessmentSelect label="社保缴纳" v-model="form.socialSecurity" :options="['连续缴纳 6 个月以上', '缴纳不足 6 个月', '未缴纳']" />
|
||||
<AssessmentSelect label="公积金缴纳" v-model="form.housingFund" :options="['连续缴纳 6 个月以上', '缴纳不足 6 个月', '未缴纳']" />
|
||||
</template>
|
||||
</view>
|
||||
<view v-else-if="step == 2" class="form-list">
|
||||
<AssessmentSelect label="房产情况" v-model="form.house" :options="['无房产', '全款房产', '按揭房产']" />
|
||||
<AssessmentSelect label="车辆情况" v-model="form.car" :options="['无车辆', '全款车辆', '按揭车辆']" />
|
||||
<AssessmentSelect label="存款情况" v-model="form.savings" :options="['5 万元以下', '5–20 万元', '20–50 万元', '50 万元以上']" />
|
||||
<AssessmentSelect label="信用卡使用" v-model="form.creditCard" :options="['无信用卡', '正常使用,无逾期', '当前存在逾期', '历史有逾期,已结清']" />
|
||||
<view class="form-row"><text class="field-label">其他资产</text><input v-model="form.otherAssets" class="field-input" placeholder="选填" /></view>
|
||||
</view>
|
||||
<view v-else class="upload-area">
|
||||
<text class="upload-title">资料选择 <text class="optional">(选填)</text></text>
|
||||
<text class="upload-desc">支持照片,仅在本机预览,尚未上传。</text>
|
||||
<view class="upload-grid"><view class="upload-card" v-for="(item, index) in uploadNames" :key="item" :class="index == 2 ? 'upload-last' : ''" @click="documentAction(item)"><image v-if="documentPath(item).length > 0" class="document-thumb" :src="documentPath(item)" mode="aspectFill" @error="documentExpired(item)" /><AppIcon v-else name="upload" :size="52" /><text class="upload-name">{{ item }}</text><text :class="documentPath(item).length > 0 ? 'upload-state selected-state' : 'upload-state'">{{ documentPath(item).length > 0 ? '已选择 · 管理' : '点击选择' }}</text></view></view>
|
||||
<view class="consent"><view class="check-hit" @click="documentConsent = !documentConsent"><view :class="documentConsent ? 'checkbox checked' : 'checkbox'"><text v-if="documentConsent" class="check-mark">✓</text></view></view><text class="consent-copy">我已阅读并同意<text class="consent-link" @click="showAgreement('资料使用协议')">《资料使用协议》</text></text></view>
|
||||
<view class="data-section"><text class="upload-title">数据授权 <text class="optional">(可选)</text></text><text class="upload-desc">自主选择授权项目,可随时取消选择。</text><view class="grant-list"><view v-for="grant in authorizations" :key="grant.key" :class="grant.selected ? 'grant-card grant-selected' : 'grant-card'" @click="grant.selected = !grant.selected"><text :class="grant.selected ? 'grant-name grant-name-active' : 'grant-name'">{{ grant.name }}</text><view :class="grant.selected ? 'checkbox checked' : 'checkbox'"><text v-if="grant.selected" class="check-mark">✓</text></view></view></view><view class="consent"><view class="check-hit" @click="dataConsent = !dataConsent"><view :class="dataConsent ? 'checkbox checked' : 'checkbox'"><text v-if="dataConsent" class="check-mark">✓</text></view></view><text class="consent-copy">我已阅读并同意<text class="consent-link" @click="showAgreement('数据授权协议')">《数据授权协议》</text></text></view><text class="local-note">当前仅保存选择意向,不查询外部数据。</text></view>
|
||||
</view>
|
||||
<view class="scroll-spacer" :style="bottomStyle(24)"></view>
|
||||
</view>
|
||||
<view v-else-if="step == 1" class="form-list">
|
||||
<view class="form-row"><text class="field-label">职业类型</text><input v-model="form.occupation" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">工作单位</text><input v-model="form.company" class="field-input" placeholder="请输入工作单位" placeholder-class="placeholder" /></view>
|
||||
<view class="form-row"><text class="field-label">月收入(元)</text><input v-model="form.monthlyIncome" class="field-input" type="number" placeholder="请输入月收入" placeholder-class="placeholder" /></view>
|
||||
<view class="form-row"><text class="field-label">社保缴纳</text><input v-model="form.socialSecurity" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">公积金缴纳</text><input v-model="form.housingFund" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
</view>
|
||||
<view v-else-if="step == 2" class="form-list">
|
||||
<view class="form-row"><text class="field-label">房产情况</text><input v-model="form.house" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">车辆情况</text><input v-model="form.car" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">存款情况</text><input v-model="form.savings" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">信用卡使用情况</text><input v-model="form.creditCard" class="field-input" placeholder="请选择" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
<view class="form-row"><text class="field-label">其他资产</text><input v-model="form.otherAssets" class="field-input" placeholder="选填" placeholder-class="placeholder" /><text class="field-arrow">⌄</text></view>
|
||||
</view>
|
||||
<view v-else class="upload-area">
|
||||
<text class="upload-title">上传资料(选填)</text>
|
||||
<view class="upload-grid"><view class="upload-card" v-for="item in uploads" :key="item" @click="chooseImage(item)" :class="item == uploads[uploads.length - 1] ? 'upload-last' : ''"><view class="upload-icon"><AppIcon name="upload" :size="38" /></view><text>{{ item }}</text><text class="upload-state">{{ uploaded[item] == true ? '已选择' : '点击上传' }}</text></view></view>
|
||||
<text class="upload-title other-title">其他资料</text>
|
||||
<view class="upload-grid"><view class="upload-card small-card" v-for="item in otherUploads" :key="item" @click="chooseImage(item)" :class="item == otherUploads[otherUploads.length - 1] ? 'upload-last' : ''"><view class="file-icon"><AppIcon name="file-text" :size="30" /></view><text>{{ item }}</text></view></view>
|
||||
<view class="consent" @click="consented = !consented"><view :class="consented ? 'checkbox checked' : 'checkbox'"><text v-if="consented">✓</text></view><text>我已阅读并同意《授权协议》</text></view>
|
||||
</view>
|
||||
<view class="bottom-action" :style="bottomStyle(20)"><button v-if="step > 0" class="back-button" @click="previous">上一步</button><button class="primary-button next-button" @click="next">{{ step == 3 ? '确认信息' : '继续' }}</button></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="bottom-action" :style="bottomStyle(20)"><button v-if="step > 0" class="back-button" @click="previous">上一步</button><button class="primary-button next-button" @click="next">{{ step == 3 ? '确认信息' : '下一步' }}</button></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { usePageLayout } from '@/services/layout.uts'
|
||||
const { bottomStyle, contentStyle, pageStyle } = usePageLayout()
|
||||
import AppHeader from '@/components/AppHeader.uvue'
|
||||
import AppIcon from '@/components/AppIcon.uvue'
|
||||
import AssessmentSelect from '@/components/AssessmentSelect.uvue'
|
||||
import { AssessmentForm, SelectedDocument, DataAuthorization, emptyAssessmentForm, activeAssessmentType, loadAssessmentDraft, formFromDraft, documentsFromDraft, saveAssessmentDraft, showAgreementNotice } from '@/services/assessment.uts'
|
||||
const { bottomStyle, contentStyle, pageStyle } = usePageLayout()
|
||||
const showAgreement = (title: string) => { showAgreementNotice(title) }
|
||||
const step = ref(0)
|
||||
const assessmentType = ref('personal')
|
||||
const consented = ref(true)
|
||||
const form = ref<AssessmentForm>(emptyAssessmentForm())
|
||||
const customCity = ref('')
|
||||
const cityChanged = (city: string) => { form.value.city = city; if (city != '其他城市') customCity.value = '' }
|
||||
const documentConsent = ref(false)
|
||||
const dataConsent = ref(false)
|
||||
const documents = ref<SelectedDocument[]>([])
|
||||
const authorizations = ref<DataAuthorization[]>([{ key: 'credit', name: '征信查询', selected: false }, { key: 'business', name: '经营数据', selected: false }, { key: 'fund', name: '公积金数据', selected: false }])
|
||||
const titles = ['基本信息', '经营 / 收入信息', '资产 / 负债信息', '资料上传 / 授权']
|
||||
const uploads = ['身份证正面', '银行卡', '收入证明']
|
||||
const otherUploads = ['房产证', '营业执照', '其他文件']
|
||||
type AssessmentForm = { name: string, idCard: string, phone: string, city: string, maritalStatus: string, occupation: string, company: string, monthlyIncome: string, socialSecurity: string, housingFund: string, house: string, car: string, savings: string, creditCard: string, otherAssets: string }
|
||||
const form = reactive<AssessmentForm>({ name: '', idCard: '', phone: '', city: '', maritalStatus: '', occupation: '', company: '', monthlyIncome: '', socialSecurity: '', housingFund: '', house: '', car: '', savings: '', creditCard: '', otherAssets: '' })
|
||||
const uploaded = reactive({ '身份证正面': false, '银行卡': false, '收入证明': false, '房产证': false, '营业执照': false, '其他文件': false })
|
||||
const saveDraft = () => { uni.setStorageSync('assessmentDraft', { type: assessmentType.value, name: form.name, idCard: form.idCard, phone: form.phone, city: form.city, maritalStatus: form.maritalStatus, occupation: form.occupation, company: form.company, monthlyIncome: form.monthlyIncome, socialSecurity: form.socialSecurity, housingFund: form.housingFund, house: form.house, car: form.car, savings: form.savings, creditCard: form.creditCard, otherAssets: form.otherAssets, consented: consented.value, uploaded: uploaded }) }
|
||||
const fillDraft = (saved: UTSJSONObject) => {
|
||||
const read = (key: string): string => { const value = saved[key]; return value == null ? '' : value as string }
|
||||
form.name = read('name'); form.idCard = read('idCard'); form.phone = read('phone'); form.city = read('city'); form.maritalStatus = read('maritalStatus'); form.occupation = read('occupation'); form.company = read('company'); form.monthlyIncome = read('monthlyIncome'); form.socialSecurity = read('socialSecurity'); form.housingFund = read('housingFund'); form.house = read('house'); form.car = read('car'); form.savings = read('savings'); form.creditCard = read('creditCard'); form.otherAssets = read('otherAssets')
|
||||
const savedConsent = saved['consented']; if (savedConsent != null) consented.value = savedConsent as boolean
|
||||
const uploadNames = computed((): string[] => assessmentType.value == 'enterprise' ? ['营业执照', '银行流水', '经营证明'] : ['身份证正面', '银行卡', '收入证明'])
|
||||
let initialized = false
|
||||
const saveDraft = () => {
|
||||
if (!initialized) return
|
||||
const source = form.value
|
||||
const draftForm: AssessmentForm = { name: source.name, idCard: source.idCard, phone: source.phone, city: source.city, maritalStatus: source.maritalStatus, occupation: source.occupation, company: source.company, monthlyIncome: source.monthlyIncome, socialSecurity: source.socialSecurity, housingFund: source.housingFund, house: source.house, car: source.car, savings: source.savings, creditCard: source.creditCard, otherAssets: source.otherAssets, enterpriseName: source.enterpriseName, businessCode: source.businessCode, annualRevenue: source.annualRevenue, operatingYears: source.operatingYears }
|
||||
if (draftForm.city == '其他城市' && customCity.value.trim().length > 0) draftForm.city = customCity.value.trim()
|
||||
saveAssessmentDraft(assessmentType.value, step.value, draftForm, documents.value, authorizations.value, documentConsent.value, dataConsent.value)
|
||||
}
|
||||
onLoad((options) => {
|
||||
const routeType = options != null && options['type'] == 'enterprise' ? 'enterprise' : ''
|
||||
const storedDraft = uni.getStorageSync('assessmentDraft')
|
||||
if (routeType.length > 0) assessmentType.value = routeType
|
||||
if (storedDraft != null && typeof storedDraft == 'object') {
|
||||
const saved = storedDraft as UTSJSONObject
|
||||
const savedType = saved['type'] == null ? '' : saved['type'] as string
|
||||
if (savedType.length > 0 && (routeType.length == 0 || savedType == routeType)) fillDraft(saved)
|
||||
const restore = (type: string) => {
|
||||
assessmentType.value = type; step.value = 0; form.value = emptyAssessmentForm(); customCity.value = ''; documents.value = []; documentConsent.value = false; dataConsent.value = false
|
||||
authorizations.value.forEach((item) => { item.selected = false })
|
||||
const saved = loadAssessmentDraft(type)
|
||||
if (saved != null) {
|
||||
form.value = formFromDraft(saved); documents.value = documentsFromDraft(saved)
|
||||
const savedStep = saved['step']; if (typeof savedStep == 'number') step.value = Math.max(0, Math.min(3, savedStep as number))
|
||||
documentConsent.value = saved['documentConsent'] == true; dataConsent.value = saved['dataConsent'] == true
|
||||
const grants = saved['authorizations'] as string[] | null
|
||||
if (grants != null) authorizations.value.forEach((item) => { item.selected = grants.includes(item.key) })
|
||||
if (form.value.city.length > 0 && !['深圳市', '广州市', '北京市', '上海市', '杭州市', '其他城市'].includes(form.value.city)) { customCity.value = form.value.city; form.value.city = '其他城市' }
|
||||
}
|
||||
initialized = true
|
||||
saveDraft()
|
||||
}
|
||||
const switchType = (type: string) => { if (assessmentType.value == type) return; saveDraft(); restore(type); step.value = 0; saveDraft() }
|
||||
onLoad((options) => {
|
||||
let type = activeAssessmentType()
|
||||
if (options != null && (options['type'] == 'enterprise' || options['type'] == 'personal')) type = options['type'] as string
|
||||
restore(type)
|
||||
})
|
||||
onShow(() => {
|
||||
const requestedStep = uni.getStorageSync('assessmentEditStep')
|
||||
if (typeof requestedStep == 'number') {
|
||||
const targetStep = requestedStep as number
|
||||
if (targetStep >= 0 && targetStep < 4) step.value = targetStep
|
||||
uni.removeStorageSync('assessmentEditStep')
|
||||
}
|
||||
if (typeof requestedStep == 'number') { step.value = Math.max(0, Math.min(3, requestedStep as number)); uni.removeStorageSync('assessmentEditStep'); saveDraft() }
|
||||
})
|
||||
const chooseImage = (name: string) => { uploaded[name] = true; saveDraft(); uni.showToast({ title: name + '上传入口已预留', icon: 'none' }) }
|
||||
const previous = () => { saveDraft(); if (step.value > 0) step.value-- }
|
||||
const validateStep = (): boolean => {
|
||||
if (step.value == 0) {
|
||||
if (form.name.trim().length < 2) { uni.showToast({ title: '请输入正确姓名', icon: 'none' }); return false }
|
||||
if (form.idCard.trim().length < 15) { uni.showToast({ title: '请输入正确身份证号', icon: 'none' }); return false }
|
||||
if (form.phone.trim().length != 11 || !form.phone.startsWith('1')) { uni.showToast({ title: '请输入正确手机号', icon: 'none' }); return false }
|
||||
if (form.city.trim().length == 0) { uni.showToast({ title: '请选择所在城市', icon: 'none' }); return false }
|
||||
}
|
||||
if (step.value == 1 && form.monthlyIncome.trim().length == 0) { uni.showToast({ title: '请输入月收入', icon: 'none' }); return false }
|
||||
return true
|
||||
onHide(() => saveDraft())
|
||||
onUnload(() => saveDraft())
|
||||
// 系统返回与顶部返回均先保存;页内返回优先回到上一步。
|
||||
onBackPress((): boolean => { saveDraft(); if (step.value > 0) { step.value--; saveDraft(); return true }; return false })
|
||||
const previous = () => { saveDraft(); if (step.value > 0) step.value--; saveDraft() }
|
||||
const back = () => { if (step.value > 0) { previous(); return }; saveDraft(); if (getCurrentPages().length > 1) uni.navigateBack(); else uni.redirectTo({ url: '/pages/entry/entry?type=' + assessmentType.value }) }
|
||||
const documentPath = (name: string): string => { const item = documents.value.find((file) => file.name == name); return item == null ? '' : item.path }
|
||||
const documentExpired = (name: string) => {
|
||||
documents.value = documents.value.filter((file) => file.name != name); saveDraft()
|
||||
uni.showToast({ title: name + '已失效,请重新选择', icon: 'none' })
|
||||
}
|
||||
const next = () => { if (!validateStep()) return; saveDraft(); if (step.value < 3) step.value++; else if (!consented.value) uni.showToast({ title: '请同意授权协议', icon: 'none' }); else uni.navigateTo({ url: '/pages/confirm/confirm' }) }
|
||||
const chooseDocument = (name: string) => {
|
||||
uni.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: (result) => {
|
||||
if (result.tempFilePaths.length == 0) return
|
||||
documents.value = documents.value.filter((file) => file.name != name)
|
||||
const document: SelectedDocument = { name, path: result.tempFilePaths[0] }
|
||||
documents.value.push(document); saveDraft()
|
||||
}, fail: (error) => { if (!error.errMsg.includes('cancel')) uni.showToast({ title: '选择失败,请重试或检查相册权限', icon: 'none' }) } })
|
||||
}
|
||||
const documentAction = (name: string) => {
|
||||
const path = documentPath(name)
|
||||
if (path.length == 0) { chooseDocument(name); return }
|
||||
uni.showActionSheet({ itemList: ['预览图片', '重新选择', '移除资料'], success: (result) => {
|
||||
if (result.tapIndex == 0) uni.previewImage({ urls: [path], fail: () => { uni.showToast({ title: '本地图片已失效,请重新选择', icon: 'none' }) } })
|
||||
else if (result.tapIndex == 1) chooseDocument(name)
|
||||
else if (result.tapIndex == 2) { documents.value = documents.value.filter((file) => file.name != name); saveDraft() }
|
||||
} })
|
||||
}
|
||||
const validateStep = (): boolean => {
|
||||
let message = ''
|
||||
if (step.value == 0) {
|
||||
if (assessmentType.value == 'enterprise' && form.value.enterpriseName.trim().length < 2) message = '请输入企业名称'
|
||||
else if (assessmentType.value == 'enterprise' && !/^[0-9A-Z]{18}$/.test(form.value.businessCode.trim().toUpperCase())) message = '请输入 18 位统一社会信用代码'
|
||||
else if (form.value.name.trim().length < 2) message = '请输入正确姓名'
|
||||
else if (assessmentType.value == 'personal' && !/(^[0-9]{15}$)|(^[0-9]{17}[0-9Xx]$)/.test(form.value.idCard.trim())) message = '请输入正确身份证号'
|
||||
else if (!/^1[3-9][0-9]{9}$/.test(form.value.phone)) message = '请输入正确手机号'
|
||||
else if (form.value.city.length == 0 || (form.value.city == '其他城市' && customCity.value.trim().length == 0)) message = '请选择或填写所在城市'
|
||||
}
|
||||
if (step.value == 1) {
|
||||
const amount = assessmentType.value == 'enterprise' ? form.value.annualRevenue : form.value.monthlyIncome
|
||||
if (!/^[0-9]+([.][0-9]{1,2})?$/.test(amount) || parseFloat(amount) <= 0) message = assessmentType.value == 'enterprise' ? '请输入有效的年营业收入' : '请输入有效的月收入'
|
||||
}
|
||||
if (step.value == 3 && documents.value.length > 0 && !documentConsent.value) message = '请阅读并同意资料使用协议,或移除资料'
|
||||
if (step.value == 3 && authorizations.value.some((item) => item.selected) && !dataConsent.value) message = '请阅读并同意数据授权协议,或取消授权选择'
|
||||
if (message.length == 0) return true
|
||||
uni.showToast({ title: message, icon: 'none' }); return false
|
||||
}
|
||||
const next = () => { if (!validateStep()) return; if (step.value < 3) { step.value++; saveDraft() } else { saveDraft(); uni.navigateTo({ url: '/pages/confirm/confirm' }) } }
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.assessment-content { padding: 24rpx 30rpx 190rpx; position: relative; }
|
||||
.step-line { height: 8rpx; flex-direction: row; margin-right: 70rpx; }
|
||||
.assessment-content { padding: 26rpx 30rpx 0; }
|
||||
.progress-row { flex-direction: row; align-items: center; }
|
||||
.step-line { height: 8rpx; flex: 1; flex-direction: row; }
|
||||
.step-segment { flex: 1; height: 8rpx; border-radius: 8rpx; background-color: #e8edf4; margin-right: 8rpx; }
|
||||
.step-segment.done { background-color: #0868f7; }
|
||||
.step-count { position: absolute; top: 16rpx; right: 30rpx; color: #7f8da2; font-size: 22rpx; }
|
||||
.form-list { margin-top: 42rpx; }
|
||||
.form-row { min-height: 104rpx; flex-direction: row; align-items: center; border-bottom: 1rpx solid #edf1f6; }
|
||||
.field-label { width: 230rpx; font-size: 27rpx; color: #27354b; }
|
||||
.field-input { flex: 1; text-align: right; font-size: 26rpx; color: #18253d; }
|
||||
.placeholder { color: #b0bac9; }
|
||||
.field-arrow { color: #a5b0c0; margin-left: 10rpx; }
|
||||
.upload-title { font-size: 29rpx; font-weight: 700; margin-top: 40rpx; }
|
||||
.done { background-color: #0868f7; }
|
||||
.step-count { color: #758297; font-size: 24rpx; margin-left: 20rpx; }
|
||||
.type-row { margin-top: 30rpx; flex-direction: row; align-items: center; justify-content: space-between; }
|
||||
.type-label { font-size: 28rpx; color: #29374e; }
|
||||
.type-switch { flex-direction: row; padding: 5rpx; border-radius: 14rpx; background-color: #eef4fd; }
|
||||
.type-item { width: 130rpx; padding: 13rpx 0; border-radius: 10rpx; text-align: center; color: #68809f; font-size: 26rpx; }
|
||||
.type-active { color: #0868f7; font-weight: 600; background-color: #fff; }
|
||||
.section-hint { color: #738198; font-size: 24rpx; line-height: 36rpx; margin-top: 30rpx; }
|
||||
.form-list { margin-top: 14rpx; }
|
||||
.form-row { min-height: 106rpx; flex-direction: row; align-items: center; border-bottom: 1rpx solid #edf1f6; }
|
||||
.field-label { font-size: 28rpx; color: #29374e; margin-right: 18rpx; flex-shrink: 0; }
|
||||
.field-input { flex: 1; min-width: 0; text-align: right; font-size: 27rpx; color: #22324a; }
|
||||
.upload-title { font-size: 30rpx; font-weight: 600; color: #20304a; margin-top: 28rpx; }
|
||||
.optional { font-size: 24rpx; color: #748198; font-weight: 400; }
|
||||
.upload-desc { font-size: 24rpx; line-height: 36rpx; color: #748198; margin-top: 10rpx; }
|
||||
.upload-grid { flex-direction: row; margin-top: 22rpx; }
|
||||
.upload-card { flex: 1; height: 210rpx; margin-right: 14rpx; border-radius: 16rpx; background-color: #f2f7fd; align-items: center; justify-content: center; color: #35445a; font-size: 22rpx; }
|
||||
.upload-card { flex: 1; min-width: 0; height: 200rpx; margin-right: 14rpx; border-radius: 16rpx; background-color: #f1f6fd; align-items: center; justify-content: center; }
|
||||
.upload-last { margin-right: 0; }
|
||||
.upload-icon { width: 70rpx; height: 70rpx; border-radius: 18rpx; background-color: #dfeeff; align-items: center; justify-content: center; margin-bottom: 14rpx; }
|
||||
.upload-state { color: #9ca8b9; font-size: 19rpx; margin-top: 8rpx; }
|
||||
.other-title { margin-top: 42rpx; }
|
||||
.small-card { height: 150rpx; }
|
||||
.file-icon { width: 54rpx; height: 54rpx; border-radius: 14rpx; background-color: #e6f0ff; align-items: center; justify-content: center; margin-bottom: 10rpx; }
|
||||
.consent { margin-top: 34rpx; flex-direction: row; align-items: center; color: #67758a; font-size: 22rpx; }
|
||||
.checkbox { width: 32rpx; height: 32rpx; border-radius: 50%; border: 2rpx solid #aeb9c8; align-items: center; justify-content: center; margin-right: 12rpx; }
|
||||
.checkbox.checked { background-color: #0868f7; border-color: #0868f7; color: white; }
|
||||
.document-thumb { width: 74rpx; height: 62rpx; border-radius: 8rpx; }
|
||||
.upload-name { font-size: 25rpx; color: #304260; margin-top: 16rpx; }
|
||||
.upload-state { color: #7a889e; font-size: 22rpx; margin-top: 9rpx; }
|
||||
.selected-state { color: #0868f7; }
|
||||
.consent { margin-top: 24rpx; flex-direction: row; align-items: flex-start; }
|
||||
.check-hit { width: 44rpx; height: 42rpx; flex-shrink: 0; justify-content: center; }
|
||||
.checkbox { width: 30rpx; height: 30rpx; border-radius: 8rpx; border: 2rpx solid #9aa8ba; align-items: center; justify-content: center; flex-shrink: 0; }
|
||||
.checked { background-color: #0868f7; border-color: #0868f7; }
|
||||
.check-mark { color: #fff; font-size: 22rpx; }
|
||||
.consent-copy { flex: 1; min-width: 0; color: #687991; font-size: 24rpx; line-height: 40rpx; }
|
||||
.consent-link { color: #0868f7; font-size: 24rpx; line-height: 40rpx; }
|
||||
.data-section { margin-top: 24rpx; padding-top: 4rpx; border-top: 1rpx solid #e9eef6; }
|
||||
.grant-list { margin-top: 18rpx; }
|
||||
.grant-card { min-height: 78rpx; padding: 0 22rpx; border: 1rpx solid #e3eaf4; border-radius: 14rpx; margin-top: 12rpx; flex-direction: row; align-items: center; justify-content: space-between; }
|
||||
.grant-selected { border-color: #c3d9ff; background-color: #f1f6ff; }
|
||||
.grant-name { font-size: 27rpx; color: #344761; }
|
||||
.grant-name-active { color: #0868f7; }
|
||||
.local-note { color: #8290a4; font-size: 22rpx; line-height: 34rpx; margin-top: 14rpx; }
|
||||
.scroll-spacer { min-height: 160rpx; }
|
||||
.bottom-action { position: fixed; left: 0; right: 0; bottom: 0; padding: 20rpx 30rpx; background-color: #fff; border-top: 1rpx solid #edf1f6; flex-direction: row; }
|
||||
.back-button { width: 180rpx; height: 92rpx; line-height: 92rpx; margin-right: 18rpx; border-radius: 16rpx; background-color: #eef3f9; color: #526075; font-size: 27rpx; }
|
||||
.back-button { width: 180rpx; height: 92rpx; line-height: 92rpx; margin-right: 18rpx; border-radius: 16rpx; background-color: #eef3f9; color: #526075; font-size: 28rpx; }
|
||||
.next-button { flex: 1; margin: 0; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user