|
- <template>
- <view class="page">
- <u-loading-page :loading="pageLoading" loading-text="加载中..." />
- <!-- 驳回原因提示 -->
- <view v-if="info.status === 2 && info.reject_reason" class="reject-tip">
- <u-icon name="warning-fill" size="20" color="#fa8c16" />
- <text class="reject-text">驳回原因:{{ info.reject_reason }}</text>
- </view>
-
- <!-- 基本信息 -->
- <view class="section">
- <view class="section-title">
- <u-icon name="account-fill" size="18" color="#0e63e3" />
- <text>基本信息</text>
- </view>
- <view class="info-compact">
- <view class="info-compact-row">
- <text class="info-compact-item">姓名:{{ info.name }}</text>
- <text class="info-compact-item" v-if="info.gender">性别:{{ info.gender }}</text>
- </view>
- <view class="info-compact-row">
- <text class="info-compact-item">身份证:{{ maskedIdCard }}</text>
- <text class="info-compact-item">手机号:{{ maskedPhone }}</text>
- </view>
- </view>
- <view class="form-group" v-if="!info.gender">
- <text class="form-label">性别</text>
- <view class="gender-row">
- <view class="gender-item" :class="{ active: form.gender === '男', disabled: isInfoApproved }" @tap="setGender('男')">男</view>
- <view class="gender-item" :class="{ active: form.gender === '女', disabled: isInfoApproved }" @tap="setGender('女')">女</view>
- </view>
- </view>
- <view class="form-group">
- <text class="form-label">联系地址</text>
- <view :class="['region-row', isInfoApproved ? 'disabled' : '']" @tap="openRegionPicker">
- <text :class="['region-text', regionText ? '' : 'placeholder']">{{ regionText || '请选择省/市/区' }}</text>
- <text class="arrow">›</text>
- </view>
- <u-input v-model="form.address" :disabled="isInfoApproved" placeholder="详细街道地址" border="surround"
- :customStyle="{ marginTop: '16rpx' }" />
- </view>
- <view class="form-group">
- <text class="form-label">紧急联系人</text>
- <view class="contact-row">
- <view class="contact-input">
- <u-input v-model="form.emergency_contact" :disabled="isInfoApproved" placeholder="联系人姓名" border="surround" />
- </view>
- <view class="contact-input">
- <u-input v-model="form.emergency_phone" :disabled="isInfoApproved" type="number" placeholder="联系人电话" border="surround" maxlength="11" />
- </view>
- </view>
- </view>
- <view class="form-group">
- <text class="form-label">医院名称</text>
- <view :class="['region-row', isInfoApproved ? 'disabled' : '']" @tap="openHospitalPicker">
- <text :class="['region-text', form.hospital ? '' : 'placeholder']">{{ form.hospital || '请选择就诊医院' }}</text>
- <text class="arrow">›</text>
- </view>
- </view>
- <view class="form-group">
- <text class="form-label">癌种</text>
- <u-radio-group v-model="form.tag" placement="row" :wrap="true">
- <u-radio v-for="t in tagOptions" :key="t" :label="t" :name="t"
- :disabled="isInfoApproved" activeColor="#0E63E3" :customStyle="{ marginRight: '24rpx', marginBottom: '16rpx' }" />
- </u-radio-group>
- </view>
- </view>
-
- <!-- 资料上传 -->
- <view class="section">
- <view class="section-title">
- <u-icon name="attach" size="18" color="#fa8c16" />
- <text>资料上传</text>
- </view>
- <view class="upload-tip">请上传您的检查报告单或出院诊断证明书,上传图片请尽量平整清晰。可上传多张。</view>
- <view class="upload-row">
- <view class="upload-item" v-for="(doc, idx) in form.documents" :key="idx">
- <image class="upload-img" :src="doc" mode="aspectFill" @tap="previewImage(idx)" />
- <view v-if="!isInfoApproved" class="upload-del" @tap="form.documents.splice(idx, 1)">×</view>
- </view>
- <view v-if="!isInfoApproved" class="upload-box" @tap="chooseDocument">
- <text class="upload-icon">+</text>
- <text class="upload-text">上传图片</text>
- </view>
- </view>
- </view>
-
- <!-- 授权签名 -->
- <view class="section">
- <view class="section-title">
- <u-icon name="edit-pen-fill" size="18" color="#52c41a" />
- <text>授权签名</text>
- </view>
- <view class="sign-item">
- <view class="sign-left">
- <text class="sign-name">个人可支配收入声明</text>
- <text :class="['sign-status', signedIncome ? 'signed' : '']">{{ signedIncome ? '已签署' : '未签署' }}</text>
- </view>
- <view class="sign-btns" v-if="signedIncome">
- <view class="sign-btn view" @tap="previewSign('income')">查看</view>
- <view v-if="!isInfoApproved" class="sign-btn resign" @tap="goSign('income')">重签</view>
- </view>
- <view class="sign-btn primary" v-else-if="!isInfoApproved" @tap="goSign('income')">去签署</view>
- </view>
- <view class="sign-item">
- <view class="sign-left">
- <text class="sign-name">个人信息处理同意书</text>
- <text :class="['sign-status', signedPrivacy ? 'signed' : '']">{{ signedPrivacy ? '已签署' : '未签署' }}</text>
- </view>
- <view class="sign-btns" v-if="signedPrivacy">
- <view class="sign-btn view" @tap="previewSign('privacy')">查看</view>
- <view v-if="!isInfoApproved" class="sign-btn resign" @tap="goSign('privacy')">重签</view>
- </view>
- <view class="sign-btn primary" v-else-if="!isInfoApproved" @tap="goSign('privacy')">去签署</view>
- </view>
- <view class="sign-item" v-if="isMinor">
- <view class="sign-left">
- <text class="sign-name">个人信息处理同意书(监护人)</text>
- <text :class="['sign-status', signedPrivacyJhr ? 'signed' : '']">{{ signedPrivacyJhr ? '已签署' : '未签署' }}</text>
- </view>
- <view class="sign-btns" v-if="signedPrivacyJhr">
- <view class="sign-btn view" @tap="previewSign('privacy_jhr')">查看</view>
- <view v-if="!isInfoApproved" class="sign-btn resign" @tap="goSign('privacy_jhr')">重签</view>
- </view>
- <view class="sign-btn primary" v-else-if="!isInfoApproved" @tap="goSign('privacy_jhr')">去签署</view>
- </view>
- <view class="sign-item">
- <view class="sign-left">
- <text class="sign-name">声明与承诺</text>
- <text :class="['sign-status', signedPromise ? 'signed' : '']">{{ signedPromise ? '已签署' : '未签署' }}</text>
- </view>
- <view class="sign-btns" v-if="signedPromise">
- <view class="sign-btn view" @tap="previewSign('promise')">查看</view>
- <view v-if="!isInfoApproved" class="sign-btn resign" @tap="goSign('promise')">重签</view>
- </view>
- <view class="sign-btn primary" v-else-if="!isInfoApproved" @tap="goSign('promise')">去签署</view>
- </view>
- </view>
-
- <!-- 提交按钮 -->
- <view class="btn-wrap">
- <view v-if="!isInfoApproved" class="agree-row" @tap="toggleAgree">
- <view :class="['agree-checkbox', agreed ? 'checked' : '']">
- <text v-if="agreed" class="agree-check-icon">✓</text>
- </view>
- <text class="agree-text">请阅读并同意</text>
- <text class="agree-link" @tap.stop="openNotice">《患者告知书》</text>
- </view>
- <u-button :text="submitButtonText" :disabled="isInfoApproved" :loading="submitting" @click="handleSubmit" color="#0E63E3" size="large" />
- </view>
-
- <!-- 地区选择器 -->
- <u-picker v-if="regionColumns[0].length" :show="showRegionPicker" :columns="regionColumns" @confirm="onRegionConfirm"
- @cancel="showRegionPicker = false" @change="onRegionChange" :defaultIndex="regionDefaultIndex" />
-
- <!-- 医院选择器组件 -->
- <hospital-picker ref="hospitalPickerRef" :hospital-data="hospitalTree" @confirm="onHospitalConfirm" />
- </view>
- </template>
-
- <script setup>
- import { ref, reactive, computed, onBeforeUnmount } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import { get, post, upload } from '@/utils/request.js'
-
- const info = ref({})
- const form = reactive({
- gender: '',
- province_code: '',
- city_code: '',
- district_code: '',
- address: '',
- hospital: '',
- hospital_province_code: '',
- hospital_city_code: '',
- hospital_district_code: '',
- emergency_contact: '',
- emergency_phone: '',
- tag: '',
- documents: [],
- sign_income: '',
- sign_privacy: '',
- sign_privacy_jhr: '',
- sign_promise: '',
- income_amount: ''
- })
- const submitting = ref(false)
- const pageLoading = ref(true)
- const showRegionPicker = ref(false)
- const subscribeTmplId = ref('')
- const agreed = ref(false)
-
- // 瘤种选项
- const tagOptions = ref([])
-
- // 医院选择器
- const hospitalTree = ref([])
- const hospitalPickerRef = ref(null)
-
- const isInfoApproved = computed(() => Number(info.value.status) === 1)
- const submitButtonText = computed(() => isInfoApproved.value ? '已通过审核' : '提交审核')
-
- const showApprovedTip = () => {
- uni.showToast({ title: '资料已审核通过,不能修改', icon: 'none' })
- }
-
- const setGender = (gender) => {
- if (isInfoApproved.value) return showApprovedTip()
- form.gender = gender
- }
-
- const openRegionPicker = () => {
- if (isInfoApproved.value) return showApprovedTip()
- showRegionPicker.value = true
- }
-
- const openHospitalPicker = () => {
- if (isInfoApproved.value) return showApprovedTip()
- if (!hospitalTree.value.length) {
- uni.showToast({ title: '医院列表加载中,请稍候', icon: 'none' })
- loadHospitalTree()
- return
- }
- hospitalPickerRef.value && hospitalPickerRef.value.open({
- hospital: form.hospital,
- province_code: form.hospital_province_code,
- city_code: form.hospital_city_code,
- district_code: form.hospital_district_code
- })
- }
-
- const onHospitalConfirm = (data) => {
- if (isInfoApproved.value) return
- form.hospital = data.hospitalName || ''
- form.hospital_province_code = data.province_code || ''
- form.hospital_city_code = data.city_code || ''
- form.hospital_district_code = data.district_code || ''
- }
-
- // 签署时的额外信息(用于重签回显)
- const signExtra = reactive({
- income_amount: '',
- guardian_name: '',
- guardian_id_card: '',
- guardian_relation: ''
- })
-
- // 加载订阅消息模板配置
- const loadSubscribeConfig = async () => {
- try {
- const res = await get('/api/mp/subscribeConfig')
- if (res.data && res.data.audit_result) {
- subscribeTmplId.value = res.data.audit_result
- }
- } catch (e) {}
- }
-
- // 请求订阅消息授权
- const requestSubscribe = () => {
- return new Promise((resolve) => {
- if (!subscribeTmplId.value) return resolve(false)
- // #ifdef MP-WEIXIN
- wx.requestSubscribeMessage({
- tmplIds: [subscribeTmplId.value],
- success: () => resolve(true),
- fail: () => resolve(false)
- })
- // #endif
- // #ifndef MP-WEIXIN
- resolve(false)
- // #endif
- })
- }
-
- // 地区数据
- const allRegions = ref([])
- const regionColumns = ref([[], [], []])
- const regionDefaultIndex = ref([0, 0, 0])
-
- const maskedIdCard = computed(() => {
- const v = info.value.id_card || ''
- if (v.length === 18) return v.slice(0, 3) + '****' + v.slice(-4)
- return v
- })
-
- const maskedPhone = computed(() => {
- const v = info.value.phone || ''
- if (v.length === 11) return v.slice(0, 3) + '****' + v.slice(-4)
- return v
- })
-
- // 签署状态:form 中有新签的 URL 或 info 中有已保存的 URL
- const signedIncome = computed(() => form.sign_income || info.value.sign_income)
- const signedPrivacy = computed(() => form.sign_privacy || info.value.sign_privacy)
- const signedPrivacyJhr = computed(() => form.sign_privacy_jhr || info.value.sign_privacy_jhr)
- const signedPromise = computed(() => form.sign_promise || info.value.sign_promise)
-
- // 判断是否未成年(从身份证号解析年龄)
- const isMinor = computed(() => {
- const idCard = info.value.id_card || ''
- if (idCard.length !== 18) return false
- const birthYear = parseInt(idCard.substring(6, 10))
- const birthMonth = parseInt(idCard.substring(10, 12))
- const birthDay = parseInt(idCard.substring(12, 14))
- const now = new Date()
- let age = now.getFullYear() - birthYear
- const monthDiff = (now.getMonth() + 1) - birthMonth
- if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < birthDay)) age--
- return age < 18
- })
-
- const regionText = computed(() => {
- const parts = []
- if (form.province_code) {
- const p = allRegions.value.find(r => r.code === form.province_code)
- if (p) parts.push(p.name)
- }
- if (form.city_code) {
- const prov = allRegions.value.find(r => r.code === form.province_code)
- if (prov && prov.children) {
- const c = prov.children.find(r => r.code === form.city_code)
- if (c) parts.push(c.name)
- }
- }
- if (form.district_code) {
- const prov = allRegions.value.find(r => r.code === form.province_code)
- if (prov && prov.children) {
- const city = prov.children.find(r => r.code === form.city_code)
- if (city && city.children) {
- const d = city.children.find(r => r.code === form.district_code)
- if (d) parts.push(d.name)
- }
- }
- }
- return parts.join(' ')
- })
-
- // 签署结果事件监听
- const onSignResult = (data) => {
- if (data.type === 'income') {
- form.sign_income = data.url
- if (data.amount) {
- form.income_amount = data.amount
- signExtra.income_amount = data.amount
- }
- } else if (data.type === 'privacy') {
- form.sign_privacy = data.url
- } else if (data.type === 'privacy_jhr') {
- form.sign_privacy_jhr = data.url
- if (data.guardianName) signExtra.guardian_name = data.guardianName
- if (data.guardianIdCard) signExtra.guardian_id_card = data.guardianIdCard
- if (data.guardianRelation) signExtra.guardian_relation = data.guardianRelation
- } else if (data.type === 'promise') {
- form.sign_promise = data.url
- }
- }
-
- onLoad(async () => {
- uni.$on('signResult', onSignResult)
- pageLoading.value = true
- try {
- await loadRegions()
- await Promise.all([
- loadInfo(),
- loadSubscribeConfig(),
- loadTagOptions(),
- loadHospitalTree()
- ])
- } finally {
- pageLoading.value = false
- }
- })
-
- onBeforeUnmount(() => {
- uni.$off('signResult', onSignResult)
- })
-
- const goSign = (type) => {
- if (isInfoApproved.value) return showApprovedTip()
- let url = `/pages/sign/sign?type=${type}`
- if (type === 'income') {
- const amt = form.income_amount || signExtra.income_amount || ''
- if (amt) url += `&amount=${encodeURIComponent(amt)}`
- }
- if (type === 'privacy_jhr') {
- const gn = signExtra.guardian_name || ''
- const gi = signExtra.guardian_id_card || ''
- const gr = signExtra.guardian_relation || ''
- if (gn) url += `&guardianName=${encodeURIComponent(gn)}`
- if (gi) url += `&guardianIdCard=${encodeURIComponent(gi)}`
- if (gr) url += `&guardianRelation=${encodeURIComponent(gr)}`
- }
- uni.navigateTo({ url })
- }
-
- const previewSign = (type) => {
- const urlMap = {
- income: form.sign_income || info.value.sign_income,
- privacy: form.sign_privacy || info.value.sign_privacy,
- privacy_jhr: form.sign_privacy_jhr || info.value.sign_privacy_jhr,
- promise: form.sign_promise || info.value.sign_promise
- }
- const url = urlMap[type]
- if (url) uni.previewImage({ urls: [url], current: 0 })
- }
-
- const loadRegions = async () => {
- try {
- const res = await get('/common/regions')
- allRegions.value = res.data || []
- buildRegionColumns()
- } catch (e) {}
- }
-
- const buildRegionColumns = (pIdx = 0, cIdx = 0) => {
- const provinces = allRegions.value
- const col0 = provinces.map(p => p.name)
- const cities = (provinces[pIdx] && provinces[pIdx].children) || []
- const col1 = cities.map(c => c.name)
- const districts = (cities[cIdx] && cities[cIdx].children) || []
- const col2 = districts.map(d => d.name)
- regionColumns.value = [col0, col1, col2]
- }
-
- const onRegionChange = (e) => {
- const { columnIndex, index } = e
- if (columnIndex === 0) {
- buildRegionColumns(index, 0)
- regionDefaultIndex.value = [index, 0, 0]
- } else if (columnIndex === 1) {
- const pIdx = regionDefaultIndex.value[0]
- buildRegionColumns(pIdx, index)
- regionDefaultIndex.value = [pIdx, index, 0]
- }
- }
-
- const onRegionConfirm = (e) => {
- if (isInfoApproved.value) {
- showRegionPicker.value = false
- return
- }
- const idxs = e.indexs || e.index || [0, 0, 0]
- const provinces = allRegions.value
- const prov = provinces[idxs[0]]
- const city = prov && prov.children ? prov.children[idxs[1]] : null
- const dist = city && city.children ? city.children[idxs[2]] : null
- form.province_code = prov ? prov.code : ''
- form.city_code = city ? city.code : ''
- form.district_code = dist ? dist.code : ''
- showRegionPicker.value = false
- }
-
- const loadInfo = async () => {
- try {
- const res = await get('/api/mp/myInfo')
- if (!res.data) return
- info.value = res.data
- // 填充表单
- form.gender = res.data.gender || ''
- form.province_code = res.data.province_code || ''
- form.city_code = res.data.city_code || ''
- form.district_code = res.data.district_code || ''
- form.address = res.data.address || ''
- form.hospital = res.data.hospital || ''
- form.hospital_province_code = res.data.hospital_province_code || ''
- form.hospital_city_code = res.data.hospital_city_code || ''
- form.hospital_district_code = res.data.hospital_district_code || ''
- form.emergency_contact = res.data.emergency_contact || ''
- form.emergency_phone = res.data.emergency_phone || ''
- form.tag = res.data.tag || ''
- form.documents = res.data.documents || []
- form.sign_income = res.data.sign_income || ''
- form.sign_privacy = res.data.sign_privacy || ''
- form.sign_privacy_jhr = res.data.sign_privacy_jhr || ''
- form.sign_promise = res.data.sign_promise || ''
- form.income_amount = res.data.income_amount || ''
- signExtra.income_amount = res.data.income_amount || ''
- signExtra.guardian_name = res.data.guardian_name || ''
- signExtra.guardian_id_card = res.data.guardian_id_card || ''
- signExtra.guardian_relation = res.data.guardian_relation || ''
- // 设置地区选择器默认索引
- if (form.province_code && allRegions.value.length) {
- const pIdx = allRegions.value.findIndex(r => r.code === form.province_code)
- if (pIdx >= 0) {
- const cities = allRegions.value[pIdx].children || []
- const cIdx = cities.findIndex(r => r.code === form.city_code)
- const ci = cIdx >= 0 ? cIdx : 0
- const districts = (cities[ci] && cities[ci].children) || []
- const dIdx = districts.findIndex(r => r.code === form.district_code)
- buildRegionColumns(pIdx, ci)
- regionDefaultIndex.value = [pIdx, ci, dIdx >= 0 ? dIdx : 0]
- }
- }
- } catch (e) {}
- }
-
- const loadTagOptions = async () => {
- try {
- const res = await get('/common/tagOptions')
- tagOptions.value = res.data || []
- } catch (e) {}
- }
-
- const loadHospitalTree = async () => {
- try {
- const res = await get('/common/hospitalTree')
- hospitalTree.value = res.data || []
- } catch (e) {}
- }
-
- const chooseDocument = () => {
- if (isInfoApproved.value) return showApprovedTip()
- uni.chooseImage({
- count: 9 - form.documents.length,
- sizeType: ['compressed'],
- sourceType: ['album', 'camera'],
- success: async (res) => {
- for (const filePath of res.tempFilePaths) {
- try {
- const uploadRes = await upload('/api/mp/upload', { filePath, name: 'file' })
- if (uploadRes.data && uploadRes.data.url) {
- form.documents.push(uploadRes.data.url)
- }
- } catch (e) {}
- }
- }
- })
- }
-
- const previewImage = (idx) => {
- uni.previewImage({ urls: form.documents, current: idx })
- }
-
- const openNotice = () => {
- uni.navigateTo({ url: '/pages/content/content?key=patient_information_sheet' })
- }
-
- const toggleAgree = () => {
- agreed.value = !agreed.value
- }
-
- const handleSubmit = async () => {
- if (isInfoApproved.value) return showApprovedTip()
- if (!agreed.value) {
- return uni.showToast({ title: '请阅读并同意《患者告知书》', icon: 'none' })
- }
- if (!info.value.gender && !form.gender) {
- return uni.showToast({ title: '请选择性别', icon: 'none' })
- }
- if (!form.province_code || !form.city_code || !form.district_code) {
- return uni.showToast({ title: '请选择省市区', icon: 'none' })
- }
- if (!form.address.trim()) {
- return uni.showToast({ title: '请填写详细地址', icon: 'none' })
- }
- if (!form.emergency_contact || !form.emergency_phone) {
- return uni.showToast({ title: '请填写紧急联系人信息', icon: 'none' })
- }
- if (form.emergency_phone === info.value.phone) {
- return uni.showToast({ title: '紧急联系人电话不能与本人手机号一致', icon: 'none' })
- }
- if (!form.hospital || !form.hospital.trim()) {
- return uni.showToast({ title: '请填写医院名称', icon: 'none' })
- }
- if (!form.tag) {
- return uni.showToast({ title: '请选择癌种', icon: 'none' })
- }
- // 资料上传校验:至少上传一个
- if (!form.documents || form.documents.length === 0) {
- return uni.showToast({ title: '请至少上传一份检查报告或诊断证明', icon: 'none' })
- }
- // 签名校验:全部必须签
- if (!signedIncome.value) {
- return uni.showToast({ title: '请签署个人可支配收入声明', icon: 'none' })
- }
- if (!signedPrivacy.value) {
- return uni.showToast({ title: '请签署个人信息处理同意书', icon: 'none' })
- }
- if (isMinor.value && !signedPrivacyJhr.value) {
- return uni.showToast({ title: '请签署个人信息处理同意书(监护人)', icon: 'none' })
- }
- if (!signedPromise.value) {
- return uni.showToast({ title: '请签署声明与承诺', icon: 'none' })
- }
- await doSubmit()
- }
-
- const doSubmit = async () => {
- if (isInfoApproved.value) return showApprovedTip()
- // 先请求订阅消息授权(用户拒绝也继续提交)
- await requestSubscribe()
- submitting.value = true
- try {
- const params = {
- gender: info.value.gender || form.gender,
- province_code: form.province_code,
- city_code: form.city_code,
- district_code: form.district_code,
- address: form.address.trim(),
- hospital: form.hospital,
- hospital_province_code: form.hospital_province_code,
- hospital_city_code: form.hospital_city_code,
- hospital_district_code: form.hospital_district_code,
- emergency_contact: form.emergency_contact,
- emergency_phone: form.emergency_phone,
- tag: form.tag,
- documents: form.documents,
- sign_income: form.sign_income,
- sign_privacy: form.sign_privacy,
- sign_privacy_jhr: form.sign_privacy_jhr,
- sign_promise: form.sign_promise,
- income_amount: form.income_amount || null,
- guardian_name: signExtra.guardian_name || '',
- guardian_id_card: signExtra.guardian_id_card || '',
- guardian_relation: signExtra.guardian_relation || '',
- // #ifdef MP-WEIXIN
- mp_env_version: uni.getAccountInfoSync().miniProgram.envVersion || 'release'
- // #endif
- }
- await post('/api/mp/saveMyInfo', params)
- uni.showToast({ title: '提交成功', icon: 'success' })
- setTimeout(() => uni.navigateBack(), 1500)
- } catch (e) {
- if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' })
- } finally {
- submitting.value = false
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .page {
- min-height: 100vh;
- background: #f4f4f5;
- padding: 24rpx;
- padding-bottom: 340rpx;
- }
-
- .section {
- background: #fff;
- border-radius: 10rpx;
- padding: 32rpx;
- margin-bottom: 24rpx;
- border: 1rpx solid #ebeef5;
- }
-
- .reject-tip {
- display: flex;
- align-items: flex-start;
- padding: 24rpx 28rpx;
- background: #fff2f0;
- border: 1rpx solid #ffccc7;
- border-radius: 10rpx;
- margin-bottom: 24rpx;
-
- .reject-text {
- flex: 1;
- font-size: 26rpx;
- color: #f5222d;
- margin-left: 16rpx;
- line-height: 1.5;
- }
- }
-
- .section-title {
- display: flex;
- align-items: center;
- gap: 12rpx;
- font-size: 32rpx;
- font-weight: 600;
- color: #333;
- margin-bottom: 28rpx;
- }
-
- .form-group {
- padding: 20rpx 0;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:last-child {
- border-bottom: none;
- }
- }
-
- .info-compact {
- padding-bottom: 20rpx;
- border-bottom: 1rpx solid #f0f0f0;
- }
-
- .info-compact-row {
- display: flex;
- gap: 32rpx;
- margin-bottom: 12rpx;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
-
- .info-compact-item {
- font-size: 26rpx;
- color: #666;
- }
-
- .form-label {
- font-size: 28rpx;
- color: #555;
- margin-bottom: 16rpx;
- display: block;
- }
-
- .readonly-input {
- padding: 20rpx 24rpx;
- background: #f5f5f5;
- border: 1rpx solid #ddd;
- border-radius: 12rpx;
- font-size: 28rpx;
- color: #333;
- }
-
- .gender-row {
- display: flex;
- gap: 20rpx;
- }
-
- .gender-item {
- flex: 1;
- text-align: center;
- padding: 16rpx 0;
- border: 1rpx solid #ddd;
- border-radius: 8rpx;
- font-size: 28rpx;
- color: #333;
-
- &.active {
- border-color: #0e63e3;
- color: #0e63e3;
- background: rgba(14, 99, 227, 0.05);
- }
-
- &.disabled {
- color: #909399;
- background: #f5f7fa;
- }
- }
-
- .region-row {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 20rpx 24rpx;
- border: 1rpx solid #ddd;
- border-radius: 8rpx;
-
- &.disabled {
- background: #f5f7fa;
- }
- }
-
- .region-text {
- font-size: 28rpx;
- color: #333;
-
- &.placeholder {
- color: #c0c4cc;
- }
- }
-
- .arrow {
- font-size: 28rpx;
- color: #c0c4cc;
- }
-
- .contact-row {
- display: flex;
- gap: 16rpx;
- }
-
- .contact-input {
- flex: 1;
- }
-
- .upload-tip {
- font-size: 26rpx;
- color: #888;
- line-height: 1.6;
- margin-bottom: 20rpx;
- }
-
- .upload-row {
- display: flex;
- gap: 16rpx;
- flex-wrap: wrap;
- }
-
- .upload-item {
- position: relative;
- width: 180rpx;
- height: 180rpx;
- }
-
- .upload-img {
- width: 180rpx;
- height: 180rpx;
- border-radius: 8rpx;
- border: 1rpx solid #eee;
- }
-
- .upload-del {
- position: absolute;
- top: -10rpx;
- right: -10rpx;
- width: 40rpx;
- height: 40rpx;
- background: rgba(0, 0, 0, 0.5);
- color: #fff;
- border-radius: 50%;
- font-size: 24rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .upload-box {
- width: 180rpx;
- height: 180rpx;
- border: 2rpx dashed #ccc;
- border-radius: 8rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background: #fafafa;
- }
-
- .upload-icon {
- font-size: 56rpx;
- color: #ccc;
- }
-
- .upload-text {
- font-size: 22rpx;
- color: #999;
- margin-top: 4rpx;
- }
-
- .sign-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 28rpx 0;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:last-child {
- border-bottom: none;
- }
- }
-
- .sign-left {
- display: flex;
- flex-direction: column;
- gap: 8rpx;
- }
-
- .sign-name {
- font-size: 28rpx;
- color: #333;
- }
-
- .sign-status {
- font-size: 24rpx;
- color: #f5222d;
-
- &.signed {
- color: #52c41a;
- }
- }
-
- .sign-btns {
- display: flex;
- gap: 12rpx;
- flex-shrink: 0;
- }
-
- .sign-btn {
- padding: 10rpx 28rpx;
- border-radius: 28rpx;
- font-size: 24rpx;
- text-align: center;
- flex-shrink: 0;
-
- &.primary {
- background: #0e63e3;
- color: #fff;
- }
-
- &.view {
- background: #f0f5ff;
- color: #0e63e3;
- border: 1rpx solid #d0e0ff;
- }
-
- &.resign {
- background: #fff7e6;
- color: #fa8c16;
- border: 1rpx solid #ffe7ba;
- }
-
- &:active {
- opacity: 0.7;
- }
- }
-
- .btn-wrap {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- background: #fff;
- padding: 20rpx 32rpx;
- padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
- box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
- z-index: 100;
- }
-
- .agree-row {
- display: flex;
- align-items: center;
- margin-bottom: 16rpx;
- padding-left: 4rpx;
- }
-
- .agree-checkbox {
- width: 36rpx;
- height: 36rpx;
- border: 2rpx solid #dcdfe6;
- border-radius: 50%;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- background: #fff;
- }
-
- .agree-checkbox.checked {
- border-color: #0e63e3;
- background: #0e63e3;
- }
-
- .agree-check-icon {
- font-size: 24rpx;
- line-height: 1;
- color: #fff;
- font-weight: 600;
- }
-
- .agree-text {
- font-size: 24rpx;
- color: #666;
- margin-left: 8rpx;
- }
-
- .agree-link {
- font-size: 24rpx;
- color: #0e63e3;
- }
-
- .confirm-popup {
- padding: 48rpx 40rpx 40rpx;
- width: 560rpx;
- }
-
- .confirm-title {
- font-size: 34rpx;
- font-weight: 600;
- color: #333;
- text-align: center;
- margin-bottom: 28rpx;
- }
-
- .confirm-content {
- font-size: 28rpx;
- color: #666;
- line-height: 1.7;
- text-align: center;
- margin-bottom: 40rpx;
- }
-
- .confirm-btns {
- display: flex;
- gap: 24rpx;
- }
-
- </style>
|