feat: 添加二维码和加载组件功能
- 新增 qrcode.vue 依赖用于生成二维码 - 实现 Loading 组件,支持多种动画类型和配置 - 在首页表单中添加二维码显示功能 - 优化表单验证流程,添加加载状态管理 - 完善用户数据本地存储功能
This commit is contained in:
parent
0d3462a8f5
commit
b515b793b6
|
|
@ -12,6 +12,7 @@
|
||||||
"@tailwindcss/vite": "^4.1.17",
|
"@tailwindcss/vite": "^4.1.17",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
|
"qrcode.vue": "^3.6.0",
|
||||||
"tailwindcss": "^4.1.17",
|
"tailwindcss": "^4.1.17",
|
||||||
"vue": "^3.5.24",
|
"vue": "^3.5.24",
|
||||||
"vue-router": "^4.6.3"
|
"vue-router": "^4.6.3"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ importers:
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.19
|
specifier: ^1.11.19
|
||||||
version: 1.11.19
|
version: 1.11.19
|
||||||
|
qrcode.vue:
|
||||||
|
specifier: ^3.6.0
|
||||||
|
version: 3.6.0(vue@3.5.24(typescript@5.9.3))
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.1.17
|
specifier: ^4.1.17
|
||||||
version: 4.1.17
|
version: 4.1.17
|
||||||
|
|
@ -751,6 +754,11 @@ packages:
|
||||||
proxy-from-env@1.1.0:
|
proxy-from-env@1.1.0:
|
||||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||||
|
|
||||||
|
qrcode.vue@3.6.0:
|
||||||
|
resolution: {integrity: sha512-vQcl2fyHYHMjDO1GguCldJxepq2izQjBkDEEu9NENgfVKP6mv/e2SU62WbqYHGwTgWXLhxZ1NCD1dAZKHQq1fg==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.0
|
||||||
|
|
||||||
rollup@4.53.2:
|
rollup@4.53.2:
|
||||||
resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==}
|
resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||||
|
|
@ -1406,6 +1414,10 @@ snapshots:
|
||||||
|
|
||||||
proxy-from-env@1.1.0: {}
|
proxy-from-env@1.1.0: {}
|
||||||
|
|
||||||
|
qrcode.vue@3.6.0(vue@3.5.24(typescript@5.9.3)):
|
||||||
|
dependencies:
|
||||||
|
vue: 3.5.24(typescript@5.9.3)
|
||||||
|
|
||||||
rollup@4.53.2:
|
rollup@4.53.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.8
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,333 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="visible"
|
||||||
|
class="loading-container"
|
||||||
|
:class="{
|
||||||
|
'loading-container-fullscreen': fullscreen,
|
||||||
|
'loading-container-inline': !fullscreen
|
||||||
|
}"
|
||||||
|
:style="containerStyle"
|
||||||
|
>
|
||||||
|
<div class="loading-spinner-wrapper" :style="spinnerWrapperStyle">
|
||||||
|
<!-- 旋转圆环样式 -->
|
||||||
|
<div v-if="type === 'spinner'" class="loading-spinner" :style="spinnerStyle">
|
||||||
|
<svg class="loading-svg" viewBox="0 0 50 50" :style="svgStyle">
|
||||||
|
<circle
|
||||||
|
class="loading-path"
|
||||||
|
cx="25"
|
||||||
|
cy="25"
|
||||||
|
r="20"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
:stroke-width="strokeWidth"
|
||||||
|
:stroke-linecap="strokeLinecap"
|
||||||
|
stroke-dasharray="94.2 94.2"
|
||||||
|
stroke-dashoffset="94.2"
|
||||||
|
></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 点状加载样式 -->
|
||||||
|
<div v-else-if="type === 'dots'" class="loading-dots" :style="dotsContainerStyle">
|
||||||
|
<div
|
||||||
|
v-for="n in 3"
|
||||||
|
:key="n"
|
||||||
|
class="loading-dot"
|
||||||
|
:style="[
|
||||||
|
dotStyle,
|
||||||
|
{
|
||||||
|
animationDelay: `${n * 0.2}s`
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 脉冲样式 -->
|
||||||
|
<div v-else-if="type === 'pulse'" class="loading-pulse" :style="pulseStyle"></div>
|
||||||
|
|
||||||
|
<!-- 环形样式 -->
|
||||||
|
<div v-else-if="type === 'ring'" class="loading-ring" :style="ringStyle">
|
||||||
|
<div class="loading-ring-circle" :style="ringCircleStyle"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 默认样式(旋转圆环) -->
|
||||||
|
<div v-else class="loading-spinner" :style="spinnerStyle">
|
||||||
|
<svg class="loading-svg" viewBox="0 0 50 50" :style="svgStyle">
|
||||||
|
<circle
|
||||||
|
class="loading-path"
|
||||||
|
cx="25"
|
||||||
|
cy="25"
|
||||||
|
r="20"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
:stroke-width="strokeWidth"
|
||||||
|
:stroke-linecap="strokeLinecap"
|
||||||
|
stroke-dasharray="94.2 94.2"
|
||||||
|
stroke-dashoffset="94.2"
|
||||||
|
></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 加载文本 -->
|
||||||
|
<div v-if="text" class="loading-text" :style="textStyle">
|
||||||
|
{{ text }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
// 定义加载动画类型
|
||||||
|
type LoadingType = 'spinner' | 'dots' | 'pulse' | 'ring'
|
||||||
|
|
||||||
|
// Props 定义
|
||||||
|
const props = defineProps<{
|
||||||
|
// 是否显示加载组件
|
||||||
|
visible: boolean
|
||||||
|
// 加载动画类型
|
||||||
|
type?: LoadingType
|
||||||
|
// 加载动画大小
|
||||||
|
size?: number | string
|
||||||
|
// 加载动画颜色
|
||||||
|
color?: string
|
||||||
|
// 是否全屏显示
|
||||||
|
fullscreen?: boolean
|
||||||
|
// 加载文本
|
||||||
|
text?: string
|
||||||
|
// 遮罩层背景色
|
||||||
|
background?: string
|
||||||
|
// 遮罩层透明度
|
||||||
|
opacity?: number
|
||||||
|
// 线条宽度(仅适用于spinner和ring类型)
|
||||||
|
strokeWidth?: number
|
||||||
|
// 线条末端样式(仅适用于spinner类型)
|
||||||
|
strokeLinecap?: 'round' | 'butt' | 'square'
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// 计算容器样式
|
||||||
|
const containerStyle = computed(() => {
|
||||||
|
const style: any = {}
|
||||||
|
if (props.fullscreen) {
|
||||||
|
style.backgroundColor = props.background || 'rgba(255, 255, 255, 0.9)'
|
||||||
|
style.opacity = props.opacity ?? 1
|
||||||
|
}
|
||||||
|
return style
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算spinner包装器样式
|
||||||
|
const spinnerWrapperStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
color: props.color || '#1890ff'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算spinner样式
|
||||||
|
const spinnerStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
width: typeof props.size === 'number' ? `${props.size}px` : props.size || '40px',
|
||||||
|
height: typeof props.size === 'number' ? `${props.size}px` : props.size || '40px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算svg样式
|
||||||
|
const svgStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
animationDuration: '1.4s'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算线条宽度
|
||||||
|
const strokeWidth = computed(() => {
|
||||||
|
return props.strokeWidth || 3
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算线条末端样式
|
||||||
|
const strokeLinecap = computed(() => {
|
||||||
|
return props.strokeLinecap || 'round'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算点状加载容器样式
|
||||||
|
const dotsContainerStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
gap: typeof props.size === 'number' ? `${props.size / 6}px` : '6px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算点状加载样式
|
||||||
|
const dotStyle = computed(() => {
|
||||||
|
const dotSize = typeof props.size === 'number' ? props.size / 5 : 8
|
||||||
|
return {
|
||||||
|
width: `${dotSize}px`,
|
||||||
|
height: `${dotSize}px`,
|
||||||
|
backgroundColor: props.color || '#1890ff'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算脉冲样式
|
||||||
|
const pulseStyle = computed(() => {
|
||||||
|
const pulseSize = typeof props.size === 'number' ? props.size : 40
|
||||||
|
return {
|
||||||
|
width: `${pulseSize}px`,
|
||||||
|
height: `${pulseSize}px`,
|
||||||
|
backgroundColor: props.color || '#1890ff'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算环形样式
|
||||||
|
const ringStyle = computed(() => {
|
||||||
|
const ringSize = typeof props.size === 'number' ? props.size : 40
|
||||||
|
return {
|
||||||
|
width: `${ringSize}px`,
|
||||||
|
height: `${ringSize}px`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算环形内部圆样式
|
||||||
|
const ringCircleStyle = computed(() => {
|
||||||
|
const circleBorderWidth = props.strokeWidth || 3
|
||||||
|
return {
|
||||||
|
borderWidth: `${circleBorderWidth}px`,
|
||||||
|
borderColor: `${props.color || '#1890ff'} transparent ${props.color || '#1890ff'} transparent`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算文本样式
|
||||||
|
const textStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
marginTop: typeof props.size === 'number' ? `${props.size / 4}px` : '10px',
|
||||||
|
color: props.color || '#666'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 全屏容器样式 */
|
||||||
|
.loading-container-fullscreen {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内联容器样式 */
|
||||||
|
.loading-container-inline {
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 旋转圆环样式 */
|
||||||
|
.loading-spinner {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-svg {
|
||||||
|
animation: rotate 1.4s linear infinite;
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-path {
|
||||||
|
animation: dash 1.4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 点状加载样式 */
|
||||||
|
.loading-dots {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-dot {
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: bounce 1.4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 脉冲样式 */
|
||||||
|
.loading-pulse {
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: pulse 1.4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 环形样式 */
|
||||||
|
.loading-ring {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-ring-circle {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1.4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载文本样式 */
|
||||||
|
.loading-text {
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画定义 */
|
||||||
|
@keyframes rotate {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dash {
|
||||||
|
0% {
|
||||||
|
stroke-dashoffset: 94.2;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
stroke-dashoffset: 23.55;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
stroke-dashoffset: 94.2;
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce {
|
||||||
|
0%, 80%, 100% {
|
||||||
|
transform: scale(0);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.3);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,304 @@
|
||||||
|
# Loading 组件使用文档
|
||||||
|
|
||||||
|
## 组件介绍
|
||||||
|
|
||||||
|
Loading 组件是一个灵活的加载动画组件,支持多种动画类型、自定义大小、颜色等配置,可用于页面加载、数据请求等场景。
|
||||||
|
|
||||||
|
## 组件类型
|
||||||
|
|
||||||
|
- `spinner`:旋转圆环(默认)
|
||||||
|
- `dots`:点状加载动画
|
||||||
|
- `pulse`:脉冲加载动画
|
||||||
|
- `ring`:环形旋转动画
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
### 方式一:组件方式使用
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- 基本使用 -->
|
||||||
|
<Loading :visible="loadingVisible" />
|
||||||
|
|
||||||
|
<!-- 自定义配置 -->
|
||||||
|
<Loading
|
||||||
|
:visible="loadingVisible"
|
||||||
|
type="dots"
|
||||||
|
size="60"
|
||||||
|
color="#1890ff"
|
||||||
|
text="加载中..."
|
||||||
|
:fullscreen="true"
|
||||||
|
background="rgba(0, 0, 0, 0.7)"
|
||||||
|
:opacity="0.8"
|
||||||
|
:strokeWidth="4"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button @click="showLoading">显示加载</button>
|
||||||
|
<button @click="hideLoading">隐藏加载</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import Loading from './Loading.vue'
|
||||||
|
|
||||||
|
const loadingVisible = ref(false)
|
||||||
|
|
||||||
|
function showLoading() {
|
||||||
|
loadingVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideLoading() {
|
||||||
|
loadingVisible.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式二:编程方式使用
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button @click="showFullscreenLoading">显示全屏加载</button>
|
||||||
|
<button @click="showLoadingWithText">显示带文本的加载</button>
|
||||||
|
<button @click="showInlineLoading">显示内联加载</button>
|
||||||
|
<button @click="hideAllLoading">隐藏所有加载</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { showLoading, hideLoading, showLoadingWithText, showInlineLoading } from './loading'
|
||||||
|
import type { LoadingInstance } from './loading'
|
||||||
|
|
||||||
|
// 保存加载实例
|
||||||
|
let loadingInstance: LoadingInstance | null = null
|
||||||
|
|
||||||
|
// 显示全屏加载
|
||||||
|
function showFullscreenLoading() {
|
||||||
|
loadingInstance = showLoading({
|
||||||
|
type: 'spinner',
|
||||||
|
size: 50,
|
||||||
|
color: '#1890ff',
|
||||||
|
fullscreen: true,
|
||||||
|
background: 'rgba(255, 255, 255, 0.9)'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示带文本的加载
|
||||||
|
function showLoadingWithText() {
|
||||||
|
loadingInstance = showLoadingWithText('数据加载中,请稍候...', '#52c41a')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示内联加载
|
||||||
|
function showInlineLoading() {
|
||||||
|
loadingInstance = showInlineLoading(32, '#fa8c16', 'dots')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏所有加载
|
||||||
|
function hideAllLoading() {
|
||||||
|
// 方式1:隐藏特定实例
|
||||||
|
if (loadingInstance) {
|
||||||
|
loadingInstance.hide()
|
||||||
|
loadingInstance = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方式2:隐藏当前活动的全屏加载(如果有的话)
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟异步请求
|
||||||
|
function mockAsyncRequest() {
|
||||||
|
const loading = showLoadingWithText('处理中...')
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// 请求完成后隐藏加载
|
||||||
|
loading.hide()
|
||||||
|
console.log('请求完成')
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 文档
|
||||||
|
|
||||||
|
### Loading 组件 Props
|
||||||
|
|
||||||
|
| 属性名 | 类型 | 默认值 | 说明 |
|
||||||
|
|-------|------|-------|------|
|
||||||
|
| visible | boolean | false | 是否显示加载组件 |
|
||||||
|
| type | 'spinner' \| 'dots' \| 'pulse' \| 'ring' | 'spinner' | 加载动画类型 |
|
||||||
|
| size | number \| string | 40 | 加载动画大小 |
|
||||||
|
| color | string | '#1890ff' | 加载动画颜色 |
|
||||||
|
| fullscreen | boolean | true | 是否全屏显示 |
|
||||||
|
| text | string | '' | 加载文本 |
|
||||||
|
| background | string | 'rgba(255, 255, 255, 0.9)' | 遮罩层背景色(全屏模式下) |
|
||||||
|
| opacity | number | 1 | 遮罩层透明度(全屏模式下) |
|
||||||
|
| strokeWidth | number | 3 | 线条宽度(仅适用于spinner和ring类型) |
|
||||||
|
| strokeLinecap | 'round' \| 'butt' \| 'square' | 'round' | 线条末端样式(仅适用于spinner类型) |
|
||||||
|
|
||||||
|
### loading.ts 函数API
|
||||||
|
|
||||||
|
#### showLoading(options?: LoadingOptions): LoadingInstance
|
||||||
|
|
||||||
|
创建并显示一个加载组件。
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- options: LoadingOptions - 加载组件配置选项(与组件Props相同)
|
||||||
|
|
||||||
|
**返回值**:
|
||||||
|
- LoadingInstance - 加载组件实例,包含 show()、hide()、close() 方法
|
||||||
|
|
||||||
|
#### hideLoading(): void
|
||||||
|
|
||||||
|
隐藏当前活动的全屏加载组件。
|
||||||
|
|
||||||
|
#### showLoadingWithText(text: string, color?: string): LoadingInstance
|
||||||
|
|
||||||
|
显示一个带有文本的全屏加载组件。
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- text: string - 加载文本
|
||||||
|
- color: string - 加载动画颜色,默认为 '#1890ff'
|
||||||
|
|
||||||
|
**返回值**:
|
||||||
|
- LoadingInstance - 加载组件实例
|
||||||
|
|
||||||
|
#### showInlineLoading(size?: number, color?: string, type?: LoadingType): LoadingInstance
|
||||||
|
|
||||||
|
显示一个小型内联加载组件。
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- size: number - 加载组件大小,默认为 24
|
||||||
|
- color: string - 加载动画颜色,默认为 '#1890ff'
|
||||||
|
- type: LoadingType - 加载动画类型,默认为 'spinner'
|
||||||
|
|
||||||
|
**返回值**:
|
||||||
|
- LoadingInstance - 加载组件实例
|
||||||
|
|
||||||
|
### LoadingInstance 接口
|
||||||
|
|
||||||
|
| 方法名 | 说明 |
|
||||||
|
|-------|------|
|
||||||
|
| show() | 显示加载组件 |
|
||||||
|
| hide() | 隐藏加载组件并卸载 |
|
||||||
|
| close() | 同 hide(),隐藏加载组件并卸载 |
|
||||||
|
|
||||||
|
## 示例代码
|
||||||
|
|
||||||
|
### 场景1:页面加载
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div v-if="!loading">
|
||||||
|
<!-- 页面内容 -->
|
||||||
|
</div>
|
||||||
|
<Loading v-else :visible="loading" text="页面加载中..." />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import Loading from './components/Loading.vue'
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 模拟页面数据加载
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 2000)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景2:API请求加载
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button @click="fetchData" :disabled="loading">获取数据</button>
|
||||||
|
<div v-if="data">
|
||||||
|
<!-- 数据展示 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { showLoading, hideLoading } from './components/loading'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const data = ref(null)
|
||||||
|
|
||||||
|
async function fetchData() {
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 显示加载
|
||||||
|
const loadingInstance = showLoadingWithText('数据请求中...')
|
||||||
|
|
||||||
|
// 模拟API请求
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
data.value = { /* 数据内容 */ }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
// 隐藏加载
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景3:提交表单时的加载
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<form @submit.prevent="submitForm">
|
||||||
|
<!-- 表单内容 -->
|
||||||
|
<button type="submit" :disabled="submitting">
|
||||||
|
{{ submitting ? '提交中...' : '提交' }}
|
||||||
|
<Loading
|
||||||
|
v-if="submitting"
|
||||||
|
:visible="true"
|
||||||
|
:fullscreen="false"
|
||||||
|
type="spinner"
|
||||||
|
:size="16"
|
||||||
|
style="display: inline-block; margin-left: 8px;"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import Loading from './components/Loading.vue'
|
||||||
|
|
||||||
|
const submitting = ref(false)
|
||||||
|
|
||||||
|
async function submitForm() {
|
||||||
|
submitting.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 模拟表单提交
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1500))
|
||||||
|
console.log('表单提交成功')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('表单提交失败:', error)
|
||||||
|
} finally {
|
||||||
|
submitting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 当使用编程方式创建多个全屏加载组件时,最新创建的会替换之前的。
|
||||||
|
2. 请确保在不需要加载动画时调用 hide() 方法来卸载组件,避免内存泄漏。
|
||||||
|
3. 对于长时间运行的操作,建议添加加载文本以提高用户体验。
|
||||||
|
4. 内联加载组件不会自动居中,需要根据具体场景调整其位置。
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
import { createApp, h } from 'vue'
|
||||||
|
import Loading from './Loading.vue'
|
||||||
|
|
||||||
|
// 加载组件配置接口
|
||||||
|
export interface LoadingOptions {
|
||||||
|
// 加载动画类型
|
||||||
|
type?: 'spinner' | 'dots' | 'pulse' | 'ring'
|
||||||
|
// 加载动画大小
|
||||||
|
size?: number | string
|
||||||
|
// 加载动画颜色
|
||||||
|
color?: string
|
||||||
|
// 是否全屏显示
|
||||||
|
fullscreen?: boolean
|
||||||
|
// 加载文本
|
||||||
|
text?: string
|
||||||
|
// 遮罩层背景色
|
||||||
|
background?: string
|
||||||
|
// 遮罩层透明度
|
||||||
|
opacity?: number
|
||||||
|
// 线条宽度(仅适用于spinner和ring类型)
|
||||||
|
strokeWidth?: number
|
||||||
|
// 线条末端样式(仅适用于spinner类型)
|
||||||
|
strokeLinecap?: 'round' | 'butt' | 'square'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading 实例接口
|
||||||
|
interface LoadingInstance {
|
||||||
|
show: () => void
|
||||||
|
hide: () => void
|
||||||
|
close: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前活动的Loading实例
|
||||||
|
let activeInstance: LoadingInstance | null = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建并显示一个加载组件
|
||||||
|
* @param options 加载组件配置选项
|
||||||
|
* @returns 加载组件实例,可用于手动控制显示和隐藏
|
||||||
|
*/
|
||||||
|
export function showLoading(options: LoadingOptions = {}): LoadingInstance {
|
||||||
|
// 如果已经有一个活动的全屏Loading实例,先隐藏它
|
||||||
|
if (activeInstance && options.fullscreen !== false) {
|
||||||
|
activeInstance.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认配置
|
||||||
|
const defaultOptions: LoadingOptions = {
|
||||||
|
type: 'spinner',
|
||||||
|
size: 40,
|
||||||
|
color: '#1890ff',
|
||||||
|
fullscreen: true,
|
||||||
|
text: '',
|
||||||
|
background: 'rgba(0, 0, 0, 0.3)',
|
||||||
|
opacity: 1,
|
||||||
|
strokeWidth: 3,
|
||||||
|
strokeLinecap: 'round'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并配置
|
||||||
|
const mergedOptions = { ...defaultOptions, ...options }
|
||||||
|
|
||||||
|
// 创建一个容器元素
|
||||||
|
const container = document.createElement('div')
|
||||||
|
|
||||||
|
// 加载组件状态
|
||||||
|
let visible = true
|
||||||
|
|
||||||
|
// 创建应用实例
|
||||||
|
const app = createApp({
|
||||||
|
render() {
|
||||||
|
return h(Loading, {
|
||||||
|
visible,
|
||||||
|
type: mergedOptions.type,
|
||||||
|
size: mergedOptions.size,
|
||||||
|
color: mergedOptions.color,
|
||||||
|
fullscreen: mergedOptions.fullscreen,
|
||||||
|
text: mergedOptions.text,
|
||||||
|
background: mergedOptions.background,
|
||||||
|
opacity: mergedOptions.opacity,
|
||||||
|
strokeWidth: mergedOptions.strokeWidth,
|
||||||
|
strokeLinecap: mergedOptions.strokeLinecap
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 隐藏加载组件
|
||||||
|
function hideLoading() {
|
||||||
|
visible = false
|
||||||
|
// 卸载组件
|
||||||
|
setTimeout(() => {
|
||||||
|
app.unmount()
|
||||||
|
if (container.parentNode) {
|
||||||
|
container.parentNode.removeChild(container)
|
||||||
|
}
|
||||||
|
// 如果当前实例是活动实例,清除活动实例引用
|
||||||
|
if (activeInstance === instance) {
|
||||||
|
activeInstance = null
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示加载组件(默认为显示状态)
|
||||||
|
function showLoadingComp() {
|
||||||
|
visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 挂载组件
|
||||||
|
app.mount(container)
|
||||||
|
document.body.appendChild(container)
|
||||||
|
|
||||||
|
// 创建实例对象
|
||||||
|
const instance: LoadingInstance = {
|
||||||
|
show: showLoadingComp,
|
||||||
|
hide: hideLoading,
|
||||||
|
close: hideLoading
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是全屏Loading,保存为活动实例
|
||||||
|
if (mergedOptions.fullscreen) {
|
||||||
|
activeInstance = instance
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回控制方法
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏当前活动的全屏加载组件
|
||||||
|
*/
|
||||||
|
export function hideLoading() {
|
||||||
|
if (activeInstance) {
|
||||||
|
activeInstance.hide()
|
||||||
|
activeInstance = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示一个带有文本的全屏加载组件
|
||||||
|
* @param text 加载文本
|
||||||
|
* @param color 加载动画颜色
|
||||||
|
* @returns 加载组件实例
|
||||||
|
*/
|
||||||
|
export function showLoadingWithText(text: string, color: string = '#1890ff'): LoadingInstance {
|
||||||
|
return showLoading({
|
||||||
|
text,
|
||||||
|
color,
|
||||||
|
fullscreen: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示一个小型内联加载组件
|
||||||
|
* @param size 加载组件大小
|
||||||
|
* @param color 加载动画颜色
|
||||||
|
* @param type 加载动画类型
|
||||||
|
* @returns 加载组件实例
|
||||||
|
*/
|
||||||
|
export function showInlineLoading(size: number = 24, color: string = '#1890ff', type: 'spinner' | 'dots' | 'pulse' | 'ring' = 'spinner'): LoadingInstance {
|
||||||
|
return showLoading({
|
||||||
|
size,
|
||||||
|
color,
|
||||||
|
type,
|
||||||
|
fullscreen: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认导出
|
||||||
|
export default {
|
||||||
|
show: showLoading,
|
||||||
|
hide: hideLoading,
|
||||||
|
showWithText: showLoadingWithText,
|
||||||
|
showInline: showInlineLoading
|
||||||
|
}
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="formData.verifyCode">
|
<div v-if="formData.verifyCode && !formData.qrCode">
|
||||||
<!-- 结婚证信息 -->
|
<!-- 结婚证信息 -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<h3 class="text-base text-gray-800 mb-3 font-medium">结婚证信息:</h3>
|
<h3 class="text-base text-gray-800 mb-3 font-medium">结婚证信息:</h3>
|
||||||
|
|
@ -69,15 +69,15 @@
|
||||||
class="w-full flex flex-col items-start border border-gray-200 rounded-lg p-5 bg-[#FAFAFA]">
|
class="w-full flex flex-col items-start border border-gray-200 rounded-lg p-5 bg-[#FAFAFA]">
|
||||||
<div>
|
<div>
|
||||||
<span class="inline-block w-25 text-right">结婚证字号:</span>
|
<span class="inline-block w-25 text-right">结婚证字号:</span>
|
||||||
<span class="pl-2">{{ 11111 }}</span>
|
<span class="pl-2">{{ formData.marriageNo }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="inline-block w-25 text-right">男方姓名:</span>
|
<span class="inline-block w-25 text-right">男方姓名:</span>
|
||||||
<span class="pl-2">{{ 11111 }}</span>
|
<span class="pl-2">{{ formData.husbandName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="inline-block w-25 text-right">女方姓名:</span>
|
<span class="inline-block w-25 text-right">女方姓名:</span>
|
||||||
<span class="pl-2">{{ 11111 }}</span>
|
<span class="pl-2">{{ formData.wifeName }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,6 +88,15 @@
|
||||||
提交领取喜礼
|
提交领取喜礼
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="formData.qrCode">
|
||||||
|
<div>
|
||||||
|
<h3 class="text-base text-gray-800 mb-3 font-medium">请使用微信扫描下方二维码:</h3>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 flex justify-center items-center">
|
||||||
|
<qrcode-vue :value="formData.qrCode" :size="200" level="H" render-as="canvas" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="activityInfo.status === 2">
|
<div v-if="activityInfo.status === 2">
|
||||||
|
|
@ -119,6 +128,8 @@ import message from '../../components/message';
|
||||||
import apiService from '../../services/apiService'
|
import apiService from '../../services/apiService'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import QrcodeVue from 'qrcode.vue'
|
||||||
|
import { showLoading, hideLoading } from '../../components/loading'
|
||||||
|
|
||||||
const ocrUploadId = ref<HTMLInputElement>();
|
const ocrUploadId = ref<HTMLInputElement>();
|
||||||
|
|
||||||
|
|
@ -131,11 +142,13 @@ const formData = ref({
|
||||||
husbandName: '', // 男方姓名
|
husbandName: '', // 男方姓名
|
||||||
wifeName: '', // 女方姓名
|
wifeName: '', // 女方姓名
|
||||||
registerDate: '', // 登记日期
|
registerDate: '', // 登记日期
|
||||||
|
qrCode: '', // 二维码
|
||||||
})
|
})
|
||||||
|
|
||||||
const activityInfo = ref<any>({}); // 活动信息
|
const activityInfo = ref<any>({}); // 活动信息
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 检查活动是否已结束
|
// 检查活动是否已结束
|
||||||
|
showLoading();
|
||||||
apiService.getCurrentActivity().then((response: any) => {
|
apiService.getCurrentActivity().then((response: any) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
activityInfo.value = {
|
activityInfo.value = {
|
||||||
|
|
@ -147,11 +160,20 @@ onMounted(() => {
|
||||||
if (new Date(response.data.activityEndTime) < new Date()) {
|
if (new Date(response.data.activityEndTime) < new Date()) {
|
||||||
message.error('活动已结束');
|
message.error('活动已结束');
|
||||||
activityInfo.value.status = 2;
|
activityInfo.value.status = 2;
|
||||||
|
} else {
|
||||||
|
const user = JSON.parse(localStorage.getItem('userAs') || '{}');
|
||||||
|
if (user.phone && user.smsCode) {
|
||||||
|
formData.value.phone = user.phone;
|
||||||
|
formData.value.smsCode = user.smsCode;
|
||||||
|
verifyCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
message.error('获取活动信息失败,请稍后重试')
|
message.error('获取活动信息失败,请稍后重试')
|
||||||
activityInfo.value.status = 3;
|
activityInfo.value.status = 3;
|
||||||
|
}).finally(() => {
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -168,7 +190,7 @@ const sendVerificationCode = () => {
|
||||||
message.error('请输入正确的手机号码')
|
message.error('请输入正确的手机号码')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
showLoading();
|
||||||
// 调用发送短信验证码接口
|
// 调用发送短信验证码接口
|
||||||
apiService.sendSms({
|
apiService.sendSms({
|
||||||
mobile: phone,
|
mobile: phone,
|
||||||
|
|
@ -176,6 +198,7 @@ const sendVerificationCode = () => {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
formData.value.verifyCode = false;
|
formData.value.verifyCode = false;
|
||||||
formData.value.smsCode = '';
|
formData.value.smsCode = '';
|
||||||
|
formData.value.qrCode = '';
|
||||||
|
|
||||||
// 开始倒计时
|
// 开始倒计时
|
||||||
countdown.value = 60
|
countdown.value = 60
|
||||||
|
|
@ -196,6 +219,8 @@ const sendVerificationCode = () => {
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('发送验证码失败:', error)
|
console.error('发送验证码失败:', error)
|
||||||
message.error('验证码发送失败,请稍后重试')
|
message.error('验证码发送失败,请稍后重试')
|
||||||
|
}).finally(() => {
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,16 +233,53 @@ const verifyCode = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showLoading();
|
||||||
// 调用验证短信验证码接口
|
// 调用验证短信验证码接口
|
||||||
apiService.verifySms({
|
apiService.verifySms({
|
||||||
mobile: formData.value.phone,
|
mobile: formData.value.phone,
|
||||||
smsCode: smsCode,
|
smsCode: smsCode,
|
||||||
type: 3,
|
type: 3,
|
||||||
}).then(() => {
|
}).then((res) => {
|
||||||
|
localStorage.setItem('userAs', JSON.stringify({
|
||||||
|
phone: formData.value.phone,
|
||||||
|
smsCode: formData.value.smsCode,
|
||||||
|
}));
|
||||||
|
|
||||||
formData.value.verifyCode = true;
|
formData.value.verifyCode = true;
|
||||||
|
|
||||||
|
// 验证成功后重置倒计时
|
||||||
|
countdown.value = 0;
|
||||||
|
|
||||||
|
// 验证成功如果有二维码,保存到表单
|
||||||
|
if (res.data.code) {
|
||||||
|
formData.value = {
|
||||||
|
...formData.value,
|
||||||
|
qrCode: res.data.code,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.value = {
|
||||||
|
...formData.value,
|
||||||
|
marriageNo: "",
|
||||||
|
husbandName: "",
|
||||||
|
wifeName: "",
|
||||||
|
registerDate: "",
|
||||||
|
qrCode: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('验证验证码失败:', error)
|
localStorage.removeItem('userAs');
|
||||||
message.error('验证码验证失败,请重试')
|
|
||||||
|
message.error('验证码验证失败,请重试');
|
||||||
|
formData.value = {
|
||||||
|
...formData.value,
|
||||||
|
marriageNo: "",
|
||||||
|
husbandName: "",
|
||||||
|
wifeName: "",
|
||||||
|
registerDate: "",
|
||||||
|
qrCode: ""
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,6 +298,7 @@ const handleImageChange = () => {
|
||||||
const formFormData = new FormData()
|
const formFormData = new FormData()
|
||||||
formFormData.append('file', file)
|
formFormData.append('file', file)
|
||||||
|
|
||||||
|
showLoading();
|
||||||
apiService.uploadOcrImage(formFormData).then((response: any) => {
|
apiService.uploadOcrImage(formFormData).then((response: any) => {
|
||||||
apiService.parseOcrInfo({
|
apiService.parseOcrInfo({
|
||||||
mobile: formData.value.phone,
|
mobile: formData.value.phone,
|
||||||
|
|
@ -254,10 +317,13 @@ const handleImageChange = () => {
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
message.error('解析OCR信息失败,请稍后重试')
|
message.error('解析OCR信息失败,请稍后重试')
|
||||||
ocrUploadId.value && (ocrUploadId.value.value = '');
|
ocrUploadId.value && (ocrUploadId.value.value = '');
|
||||||
|
}).finally(() => {
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
message.error('图片上传失败,请稍后重试')
|
message.error('图片上传失败,请稍后重试')
|
||||||
ocrUploadId.value && (ocrUploadId.value.value = '');
|
ocrUploadId.value && (ocrUploadId.value.value = '');
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,16 +336,18 @@ const submitForm = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showLoading();
|
||||||
apiService.receiveCheck({
|
apiService.receiveCheck({
|
||||||
marriageNo: formData.value.marriageNo,
|
marriageNo: formData.value.marriageNo,
|
||||||
receiveName: formData.value.husbandName,
|
receiveName: formData.value.husbandName,
|
||||||
receiveMobile: formData.value.phone,
|
receiveMobile: formData.value.phone,
|
||||||
code: formData.value.smsCode,
|
|
||||||
smsCode: formData.value.smsCode,
|
smsCode: formData.value.smsCode,
|
||||||
}).then((res: any) => {
|
}).then((res: any) => {
|
||||||
console.log(res);
|
formData.value.qrCode = res.data.code;
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
message.error('领取失败,请稍后重试')
|
message.error(error?.msg || '提交失败,请稍后重试')
|
||||||
|
}).finally(() => {
|
||||||
|
hideLoading();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue