Merge branch 'main' of http://1.117.67.95:3000/ZhangRongHong/tyapi-frontend
This commit is contained in:
2
.env
2
.env
@@ -1 +1,3 @@
|
|||||||
VITE_API_URL="https://api.tianyuanapi.com"
|
VITE_API_URL="https://api.tianyuanapi.com"
|
||||||
|
VITE_CAPTCHA_SCENE_ID="wynt39to"
|
||||||
|
VITE_CAPTCHA_ENCRYPTED_MODE=false
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"until": true,
|
"until": true,
|
||||||
"upperCase": true,
|
"upperCase": true,
|
||||||
"useActiveElement": true,
|
"useActiveElement": true,
|
||||||
|
"useAliyunCaptcha": true,
|
||||||
"useAnimate": true,
|
"useAnimate": true,
|
||||||
"useAppStore": true,
|
"useAppStore": true,
|
||||||
"useArrayDifference": true,
|
"useArrayDifference": true,
|
||||||
|
|||||||
2
auto-imports.d.ts
vendored
2
auto-imports.d.ts
vendored
@@ -225,6 +225,7 @@ declare global {
|
|||||||
const until: typeof import('@vueuse/core')['until']
|
const until: typeof import('@vueuse/core')['until']
|
||||||
const upperCase: typeof import('lodash-es')['upperCase']
|
const upperCase: typeof import('lodash-es')['upperCase']
|
||||||
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
||||||
|
const useAliyunCaptcha: typeof import('./src/composables/useAliyunCaptcha.js')['default']
|
||||||
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
||||||
const useAppStore: typeof import('./src/stores/app.js')['useAppStore']
|
const useAppStore: typeof import('./src/stores/app.js')['useAppStore']
|
||||||
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
||||||
@@ -668,6 +669,7 @@ declare module 'vue' {
|
|||||||
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
|
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
|
||||||
readonly upperCase: UnwrapRef<typeof import('lodash-es')['upperCase']>
|
readonly upperCase: UnwrapRef<typeof import('lodash-es')['upperCase']>
|
||||||
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
|
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
|
||||||
|
readonly useAliyunCaptcha: UnwrapRef<typeof import('./src/composables/useAliyunCaptcha.js')['default']>
|
||||||
readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
|
readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
|
||||||
readonly useAppStore: UnwrapRef<typeof import('./src/stores/app.js')['useAppStore']>
|
readonly useAppStore: UnwrapRef<typeof import('./src/stores/app.js')['useAppStore']>
|
||||||
readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
|
readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
|
||||||
|
|||||||
@@ -5,9 +5,18 @@
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>天远数据</title>
|
<title>天远数据</title>
|
||||||
|
<!-- 阿里云滑块验证码 -->
|
||||||
|
<script>
|
||||||
|
window.AliyunCaptchaConfig = { region: "cn", prefix: "12zxnj" };
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="https://o.alicdn.com/captcha-frontend/aliyunCaptcha/AliyunCaptcha.js"
|
||||||
|
></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<div id="captcha-element"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ export const userApi = {
|
|||||||
getUserStats: () => request.get('/users/admin/stats')
|
getUserStats: () => request.get('/users/admin/stats')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证码(阿里云滑块)相关接口
|
||||||
|
export const captchaApi = {
|
||||||
|
// 获取加密场景 ID,用于前端加密模式初始化滑块
|
||||||
|
getEncryptedSceneId: (params) => request.post('/captcha/encryptedSceneId', params || {}),
|
||||||
|
// 获取验证码配置(是否启用、场景 ID)
|
||||||
|
getConfig: () => request.get('/captcha/config')
|
||||||
|
}
|
||||||
|
|
||||||
// 产品相关接口
|
// 产品相关接口
|
||||||
export const productApi = {
|
export const productApi = {
|
||||||
// 产品列表(用户端接口)
|
// 产品列表(用户端接口)
|
||||||
|
|||||||
176
src/composables/useAliyunCaptcha.js
Normal file
176
src/composables/useAliyunCaptcha.js
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { captchaApi } from '@/api'
|
||||||
|
|
||||||
|
// 阿里云验证码场景 ID(需与后端 config.sms.scene_id 一致;加密模式可由后端 config 下发)
|
||||||
|
const ALIYUN_CAPTCHA_SCENE_ID = import.meta.env.VITE_CAPTCHA_SCENE_ID || "wynt39to"
|
||||||
|
// 是否启用加密模式:通过环境变量 VITE_CAPTCHA_ENCRYPTED_MODE 控制,为 'true' 不加密
|
||||||
|
const ENABLE_ENCRYPTED = import.meta.env.VITE_CAPTCHA_ENCRYPTED_MODE === true
|
||||||
|
|
||||||
|
let captchaInitialised = false
|
||||||
|
let captchaReadyPromise = null
|
||||||
|
let captchaReadyResolve = null
|
||||||
|
|
||||||
|
async function ensureCaptchaInit() {
|
||||||
|
console.log("ENABLE_ENCRYPTED", ENABLE_ENCRYPTED)
|
||||||
|
if (captchaInitialised || typeof window === "undefined") return
|
||||||
|
if (typeof window.initAliyunCaptcha !== "function") return
|
||||||
|
|
||||||
|
captchaInitialised = true
|
||||||
|
window.captcha = null
|
||||||
|
window.__lastBizResponse = null
|
||||||
|
window.__onCaptchaBizSuccess = null
|
||||||
|
captchaReadyPromise = new Promise((resolve) => {
|
||||||
|
captchaReadyResolve = resolve
|
||||||
|
})
|
||||||
|
|
||||||
|
// 非加密模式:仅传 SceneId,不调用后端接口
|
||||||
|
if (!ENABLE_ENCRYPTED) {
|
||||||
|
console.log("NON-ENCRYPTED")
|
||||||
|
window.initAliyunCaptcha({
|
||||||
|
SceneId: ALIYUN_CAPTCHA_SCENE_ID,
|
||||||
|
mode: "popup",
|
||||||
|
element: "#captcha-element",
|
||||||
|
getInstance(instance) {
|
||||||
|
window.captcha = instance
|
||||||
|
if (typeof captchaReadyResolve === "function") {
|
||||||
|
captchaReadyResolve()
|
||||||
|
captchaReadyResolve = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
captchaVerifyCallback(param) {
|
||||||
|
console.log("captchaVerifyCallback", param)
|
||||||
|
return typeof window.__captchaVerifyCallback === "function"
|
||||||
|
? window.__captchaVerifyCallback(param)
|
||||||
|
: Promise.resolve({
|
||||||
|
captchaResult: false,
|
||||||
|
bizResult: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onBizResultCallback(bizResult) {
|
||||||
|
if (typeof window.__onBizResultCallback === "function") {
|
||||||
|
window.__onBizResultCallback(bizResult)
|
||||||
|
}
|
||||||
|
window.__lastBizResponse = null
|
||||||
|
window.__onCaptchaBizSuccess = null
|
||||||
|
},
|
||||||
|
slideStyle: { width: 360, height: 40 },
|
||||||
|
language: "cn",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密模式:先从后端获取 EncryptedSceneId,再初始化
|
||||||
|
try {
|
||||||
|
const resp = await captchaApi.getEncryptedSceneId()
|
||||||
|
const encryptedSceneId = resp?.data?.data?.encryptedSceneId ?? resp?.data?.encryptedSceneId
|
||||||
|
if (!encryptedSceneId) {
|
||||||
|
ElMessage.error("获取验证码参数失败,请稍后重试")
|
||||||
|
captchaInitialised = false
|
||||||
|
captchaReadyPromise = null
|
||||||
|
captchaReadyResolve = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.initAliyunCaptcha({
|
||||||
|
SceneId: ALIYUN_CAPTCHA_SCENE_ID,
|
||||||
|
EncryptedSceneId: encryptedSceneId,
|
||||||
|
mode: "popup",
|
||||||
|
element: "#captcha-element",
|
||||||
|
getInstance(instance) {
|
||||||
|
window.captcha = instance
|
||||||
|
if (typeof captchaReadyResolve === "function") {
|
||||||
|
captchaReadyResolve()
|
||||||
|
captchaReadyResolve = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
captchaVerifyCallback(param) {
|
||||||
|
return typeof window.__captchaVerifyCallback === "function"
|
||||||
|
? window.__captchaVerifyCallback(param)
|
||||||
|
: Promise.resolve({ captchaResult: false, bizResult: false })
|
||||||
|
},
|
||||||
|
onBizResultCallback(bizResult) {
|
||||||
|
if (typeof window.__onBizResultCallback === "function") {
|
||||||
|
window.__onBizResultCallback(bizResult)
|
||||||
|
}
|
||||||
|
window.__lastBizResponse = null
|
||||||
|
window.__onCaptchaBizSuccess = null
|
||||||
|
},
|
||||||
|
slideStyle: { width: 360, height: 40 },
|
||||||
|
language: "cn",
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error("获取验证码参数失败,请稍后重试")
|
||||||
|
captchaInitialised = false
|
||||||
|
captchaReadyPromise = null
|
||||||
|
captchaReadyResolve = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云滑块验证码通用封装。
|
||||||
|
* 依赖 index.html 中已加载的 AliyunCaptcha.js;初始化在首次调起时执行。
|
||||||
|
*/
|
||||||
|
export function useAliyunCaptcha() {
|
||||||
|
/**
|
||||||
|
* 先弹出滑块,通过后执行 bizVerify(captchaVerifyParam),再根据结果调用 onSuccess。
|
||||||
|
* @param { (captchaVerifyParam: string) => Promise<{ success: boolean, data: any, error?: any }> } bizVerify - 业务请求函数,接收滑块参数
|
||||||
|
* @param { (res: any) => void } onSuccess - 业务成功回调
|
||||||
|
*/
|
||||||
|
async function runWithCaptcha(bizVerify, onSuccess) {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
ElMessage.error("验证码仅支持浏览器环境")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadingInstance = ElMessage({
|
||||||
|
message: "安全验证加载中...",
|
||||||
|
type: "info",
|
||||||
|
duration: 0,
|
||||||
|
iconClass: "el-icon-loading"
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.__captchaVerifyCallback = async (captchaVerifyParam) => {
|
||||||
|
window.__lastBizResponse = null
|
||||||
|
try {
|
||||||
|
const result = await bizVerify(captchaVerifyParam)
|
||||||
|
window.__lastBizResponse = result
|
||||||
|
const captchaOk = result?.data?.captchaVerifyResult !== false
|
||||||
|
const bizOk = result.success === true
|
||||||
|
return { captchaResult: captchaOk, bizResult: bizOk }
|
||||||
|
} catch (error) {
|
||||||
|
return { captchaResult: false, bizResult: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.__onBizResultCallback = (bizResult) => {
|
||||||
|
if (
|
||||||
|
bizResult === true &&
|
||||||
|
window.__lastBizResponse &&
|
||||||
|
typeof window.__onCaptchaBizSuccess === "function"
|
||||||
|
) {
|
||||||
|
window.__onCaptchaBizSuccess(window.__lastBizResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await ensureCaptchaInit()
|
||||||
|
|
||||||
|
// 首次初始化时 SDK 会异步调用 getInstance,需等待实例就绪后再 show
|
||||||
|
if (captchaReadyPromise) {
|
||||||
|
await captchaReadyPromise
|
||||||
|
captchaReadyPromise = null
|
||||||
|
}
|
||||||
|
if (!window.captcha) {
|
||||||
|
ElMessage.error("验证码未加载,请刷新页面重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.__onCaptchaBizSuccess = onSuccess
|
||||||
|
window.captcha.show()
|
||||||
|
} finally {
|
||||||
|
loadingInstance.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { runWithCaptcha }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useAliyunCaptcha
|
||||||
@@ -115,10 +115,12 @@
|
|||||||
|
|
||||||
<script setup name="UserLogin">
|
<script setup name="UserLogin">
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useAliyunCaptcha } from '@/composables/useAliyunCaptcha'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha()
|
||||||
|
|
||||||
// 登录方式
|
// 登录方式
|
||||||
const loginMethod = ref('sms')
|
const loginMethod = ref('sms')
|
||||||
@@ -157,11 +159,19 @@ const sendCode = async () => {
|
|||||||
|
|
||||||
sendingCode.value = true
|
sendingCode.value = true
|
||||||
try {
|
try {
|
||||||
const result = await userStore.sendCode(form.value.phone, 'login')
|
await runWithCaptcha(
|
||||||
if (result.success) {
|
async (captchaVerifyParam) => {
|
||||||
ElMessage.success('验证码发送成功')
|
return await userStore.sendCode(form.value.phone, 'login', captchaVerifyParam)
|
||||||
startCountdown()
|
},
|
||||||
}
|
(res) => {
|
||||||
|
if (res.success) {
|
||||||
|
ElMessage.success('验证码发送成功')
|
||||||
|
startCountdown()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.error?.message || '验证码发送失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('验证码发送失败:', error)
|
console.error('验证码发送失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -138,10 +138,12 @@
|
|||||||
|
|
||||||
<script setup name="UserRegister">
|
<script setup name="UserRegister">
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useAliyunCaptcha } from '@/composables/useAliyunCaptcha'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha()
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const form = ref({
|
const form = ref({
|
||||||
@@ -175,17 +177,25 @@ const canSubmit = computed(() => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 发送验证码
|
// 发送验证码(先通过滑块再请求后端发码)
|
||||||
const sendCode = async () => {
|
const sendCode = async () => {
|
||||||
if (!canSendCode.value) return
|
if (!canSendCode.value) return
|
||||||
|
|
||||||
sendingCode.value = true
|
sendingCode.value = true
|
||||||
try {
|
try {
|
||||||
const result = await userStore.sendCode(form.value.phone, 'register')
|
await runWithCaptcha(
|
||||||
if (result.success) {
|
async (captchaVerifyParam) => {
|
||||||
ElMessage.success('验证码发送成功')
|
return await userStore.sendCode(form.value.phone, 'register', captchaVerifyParam)
|
||||||
startCountdown()
|
},
|
||||||
}
|
(res) => {
|
||||||
|
if (res.success) {
|
||||||
|
ElMessage.success('验证码发送成功')
|
||||||
|
startCountdown()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.error?.message || '验证码发送失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('验证码发送失败:', error)
|
console.error('验证码发送失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -126,10 +126,12 @@
|
|||||||
|
|
||||||
<script setup name="UserResetPassword">
|
<script setup name="UserResetPassword">
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useAliyunCaptcha } from '@/composables/useAliyunCaptcha'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha()
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const form = ref({
|
const form = ref({
|
||||||
@@ -157,17 +159,25 @@ const canSubmit = computed(() => {
|
|||||||
form.value.confirmNewPassword && form.value.confirmNewPassword === form.value.newPassword
|
form.value.confirmNewPassword && form.value.confirmNewPassword === form.value.newPassword
|
||||||
})
|
})
|
||||||
|
|
||||||
// 发送验证码
|
// 发送验证码(先通过滑块再请求后端发码)
|
||||||
const sendCode = async () => {
|
const sendCode = async () => {
|
||||||
if (!canSendCode.value) return
|
if (!canSendCode.value) return
|
||||||
|
|
||||||
sendingCode.value = true
|
sendingCode.value = true
|
||||||
try {
|
try {
|
||||||
const result = await userStore.sendCode(form.value.phone, 'reset_password')
|
await runWithCaptcha(
|
||||||
if (result.success) {
|
async (captchaVerifyParam) => {
|
||||||
ElMessage.success('验证码发送成功')
|
return await userStore.sendCode(form.value.phone, 'reset_password', captchaVerifyParam)
|
||||||
startCountdown()
|
},
|
||||||
}
|
(res) => {
|
||||||
|
if (res.success) {
|
||||||
|
ElMessage.success('验证码发送成功')
|
||||||
|
startCountdown()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.error?.message || '验证码发送失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('验证码发送失败:', error)
|
console.error('验证码发送失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<div class="success-text">
|
<div class="success-text">
|
||||||
<h2 class="success-title">恭喜!企业入驻已完成</h2>
|
<h2 class="success-title">恭喜!企业入驻已完成</h2>
|
||||||
<p class="success-desc">您的企业已完成入驻,现在可以使用完整的API服务功能。</p>
|
<p class="success-desc">您的企业已完成入驻,现在可以使用完整的API服务功能。</p>
|
||||||
|
<p class="success-desc">下一步,您只需要订阅贵司需要的api接口就可以实现在线调试和使用</p>
|
||||||
<div class="completion-info">
|
<div class="completion-info">
|
||||||
<h3 class="info-title">入驻信息</h3>
|
<h3 class="info-title">入驻信息</h3>
|
||||||
<div class="info-grid">
|
<div class="info-grid">
|
||||||
|
|||||||
@@ -190,7 +190,8 @@ import {
|
|||||||
CheckIcon,
|
CheckIcon,
|
||||||
DocumentIcon
|
DocumentIcon
|
||||||
} from '@heroicons/vue/24/outline'
|
} from '@heroicons/vue/24/outline'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { useAliyunCaptcha } from '@/composables/useAliyunCaptcha'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
formData: {
|
formData: {
|
||||||
@@ -210,6 +211,7 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(['submit'])
|
const emit = defineEmits(['submit'])
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha()
|
||||||
|
|
||||||
// 表单引用
|
// 表单引用
|
||||||
const enterpriseFormRef = ref()
|
const enterpriseFormRef = ref()
|
||||||
@@ -345,14 +347,21 @@ const sendCode = async () => {
|
|||||||
|
|
||||||
sendingCode.value = true
|
sendingCode.value = true
|
||||||
try {
|
try {
|
||||||
const result = await userStore.sendCode(form.value.legalPersonPhone, 'certification')
|
await runWithCaptcha(
|
||||||
if (result.success) {
|
async (captchaVerifyParam) => {
|
||||||
ElMessage.success('验证码发送成功')
|
return await userStore.sendCode(form.value.legalPersonPhone, 'certification', captchaVerifyParam)
|
||||||
startCountdown()
|
},
|
||||||
}
|
(res) => {
|
||||||
|
if (res.success) {
|
||||||
|
ElMessage.success('验证码发送成功')
|
||||||
|
startCountdown()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.error?.message || '验证码发送失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('验证码发送失败:', error)
|
console.error('验证码发送失败:', error)
|
||||||
ElMessage.error('验证码发送失败,请重试')
|
|
||||||
} finally {
|
} finally {
|
||||||
sendingCode.value = false
|
sendingCode.value = false
|
||||||
}
|
}
|
||||||
@@ -428,6 +437,19 @@ const submitForm = async () => {
|
|||||||
try {
|
try {
|
||||||
await enterpriseFormRef.value.validate()
|
await enterpriseFormRef.value.validate()
|
||||||
|
|
||||||
|
// 显示确认对话框
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
'提交的信息必须为法人真实信息(包括手机号),如信息有误请联系客服。',
|
||||||
|
'提交确认',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确认提交',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
customClass: 'submit-confirm-dialog'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
|
|
||||||
// Mock API 调用
|
// Mock API 调用
|
||||||
@@ -436,7 +458,10 @@ const submitForm = async () => {
|
|||||||
emit('submit', form.value)
|
emit('submit', form.value)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('表单验证失败:', error)
|
// 用户点击取消或关闭对话框,不处理
|
||||||
|
if (error !== 'cancel' && error !== 'close') {
|
||||||
|
console.error('表单验证失败:', error)
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
}
|
}
|
||||||
@@ -723,3 +748,51 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* 提交确认对话框样式 */
|
||||||
|
.submit-confirm-dialog {
|
||||||
|
max-width: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-message-box__message {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #606266;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-message-box__title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-message-box__btns {
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-button--warning {
|
||||||
|
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||||
|
border: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-button--warning:hover {
|
||||||
|
background: linear-gradient(135deg, #d97706 0%, #b45309 100%);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(217, 119, 6, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-button--default {
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-confirm-dialog .el-button--default:hover {
|
||||||
|
color: #409eff;
|
||||||
|
border-color: #c6e2ff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -330,12 +330,17 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送验证码(使用自定义编码和签名)
|
// 发送验证码(使用自定义编码和签名)
|
||||||
const sendCode = async (phone, scene) => {
|
const sendCode = async (phone, scene, captchaVerifyParam = null) => {
|
||||||
try {
|
try {
|
||||||
// 1. 生成签名并编码请求数据
|
// 1. 生成签名并编码请求数据
|
||||||
const encodedRequest = await generateSMSRequest(phone, scene)
|
const encodedRequest = await generateSMSRequest(phone, scene)
|
||||||
|
|
||||||
// 2. 发送编码后的请求(只包含data字段)
|
// 2. 如果有滑块验证码参数,添加到请求数据中
|
||||||
|
if (captchaVerifyParam) {
|
||||||
|
encodedRequest.captchaVerifyParam = captchaVerifyParam
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 发送编码后的请求
|
||||||
const response = await userApi.sendCode(encodedRequest)
|
const response = await userApi.sendCode(encodedRequest)
|
||||||
|
|
||||||
// 后端返回格式: { success: true, data: {...}, message, ... }
|
// 后端返回格式: { success: true, data: {...}, message, ... }
|
||||||
|
|||||||
Reference in New Issue
Block a user