|
@@ -0,0 +1,172 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="identity-page">
|
|
|
|
|
+ <van-nav-bar title="自然人开票" fixed placeholder />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 上传区域 -->
|
|
|
|
|
+ <div class="upload-section">
|
|
|
|
|
+ <div class="upload-item" v-for="(item, index) in uploadList" :key="index">
|
|
|
|
|
+ <van-uploader
|
|
|
|
|
+ v-model="item.fileList"
|
|
|
|
|
+ :max-count="1"
|
|
|
|
|
+ :after-read="(file) => handleAfterRead(file, index)"
|
|
|
|
|
+ :preview-size="previewSize"
|
|
|
|
|
+ :deletable="true"
|
|
|
|
|
+ :upload-text="item.label"
|
|
|
|
|
+ accept="image/*"
|
|
|
|
|
+ :multiple="false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #default>
|
|
|
|
|
+ <div class="upload-box" v-if="!item.fileList.length">
|
|
|
|
|
+ <van-icon name="photograph" class="camera-icon" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </van-uploader>
|
|
|
|
|
+ <p class="upload-text">{{ item.label }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 说明文字 -->
|
|
|
|
|
+ <div class="info-section">
|
|
|
|
|
+ <p class="info-title">当前操作可能用于:</p>
|
|
|
|
|
+ <ol class="info-list">
|
|
|
|
|
+ <li>开具数电发票</li>
|
|
|
|
|
+ <li>上传身份证信息登录电子税务局完成实名认证</li>
|
|
|
|
|
+ <li>办理其他涉税、高风险业务</li>
|
|
|
|
|
+ </ol>
|
|
|
|
|
+ <p class="info-tip">请您在如未认证用途中完成认证操作。</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 下一步按钮 -->
|
|
|
|
|
+ <div class="btn-section">
|
|
|
|
|
+ <van-button block type="primary" round class="next-btn" :disabled="!isReady" @click="onNext">
|
|
|
|
|
+ 下一步
|
|
|
|
|
+ </van-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { ref, computed } from 'vue'
|
|
|
|
|
+import { showToast } from 'vant'
|
|
|
|
|
+
|
|
|
|
|
+/** 上传项 */
|
|
|
|
|
+interface UploadItem {
|
|
|
|
|
+ label: string
|
|
|
|
|
+ fileList: any[]
|
|
|
|
|
+ field: string
|
|
|
|
|
+}
|
|
|
|
|
+const uploadList = ref<UploadItem[]>([
|
|
|
|
|
+ { label: '请上传身份证人像面', field: 'front', fileList: [] },
|
|
|
|
|
+ { label: '请上传身份证国徽面', field: 'back', fileList: [] },
|
|
|
|
|
+])
|
|
|
|
|
+
|
|
|
|
|
+/** 图片选择后处理*/
|
|
|
|
|
+const handleAfterRead = (file: any, index: number) => {
|
|
|
|
|
+ const target = uploadList.value[index]
|
|
|
|
|
+ if (!target) return // ✅ 防御性检查,防止未定义
|
|
|
|
|
+
|
|
|
|
|
+ showToast('上传中...')
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ target.fileList = [
|
|
|
|
|
+ {
|
|
|
|
|
+ url: URL.createObjectURL(file.file),
|
|
|
|
|
+ file: file.file,
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ showToast('上传成功')
|
|
|
|
|
+ }, 800)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 是否完成上传 */
|
|
|
|
|
+const isReady = computed(() => uploadList.value.every((item) => item.fileList.length > 0))
|
|
|
|
|
+
|
|
|
|
|
+/** 预览尺寸 */
|
|
|
|
|
+const previewSize = '35vw'
|
|
|
|
|
+
|
|
|
|
|
+/** 下一步 */
|
|
|
|
|
+const onNext = () => {
|
|
|
|
|
+ if (!isReady.value) return showToast('请先上传身份证正反面')
|
|
|
|
|
+ showToast('上传完成,进入下一步')
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.identity-page {
|
|
|
|
|
+ background-color: #f7f8fa;
|
|
|
|
|
+ min-height: 100vh;
|
|
|
|
|
+ padding: 4vw;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ font-size: 3.6vw;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 上传区域 */
|
|
|
|
|
+.upload-section {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ margin: 10vw 0;
|
|
|
|
|
+}
|
|
|
|
|
+.upload-item {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+.upload-box {
|
|
|
|
|
+ width: 35vw;
|
|
|
|
|
+ height: 22vw;
|
|
|
|
|
+ border-radius: 2vw;
|
|
|
|
|
+ background: #f0f0f0;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ margin-bottom: 3vw;
|
|
|
|
|
+ box-shadow: inset 0 0 2vw rgba(0, 0, 0, 0.05);
|
|
|
|
|
+}
|
|
|
|
|
+.camera-icon {
|
|
|
|
|
+ font-size: 8vw;
|
|
|
|
|
+ color: #ff7a00;
|
|
|
|
|
+}
|
|
|
|
|
+.upload-text {
|
|
|
|
|
+ font-size: 3.4vw;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 说明文字 */
|
|
|
|
|
+.info-section {
|
|
|
|
|
+ margin: 8vw 0 12vw;
|
|
|
|
|
+ line-height: 1.8;
|
|
|
|
|
+}
|
|
|
|
|
+.info-title {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ margin-bottom: 2vw;
|
|
|
|
|
+}
|
|
|
|
|
+.info-list {
|
|
|
|
|
+ padding-left: 5vw;
|
|
|
|
|
+ color: #444;
|
|
|
|
|
+}
|
|
|
|
|
+.info-list li {
|
|
|
|
|
+ margin-bottom: 1.5vw;
|
|
|
|
|
+}
|
|
|
|
|
+.info-tip {
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ font-size: 3.2vw;
|
|
|
|
|
+ margin-top: 3vw;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 按钮 */
|
|
|
|
|
+.btn-section {
|
|
|
|
|
+ padding: 0 5vw;
|
|
|
|
|
+}
|
|
|
|
|
+.next-btn {
|
|
|
|
|
+ font-size: 4vw;
|
|
|
|
|
+ height: 12vw;
|
|
|
|
|
+ background: linear-gradient(90deg, #ff7a00, #ff9800);
|
|
|
|
|
+ border: none;
|
|
|
|
|
+}
|
|
|
|
|
+.next-btn:disabled {
|
|
|
|
|
+ background: #ffd1a1;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|