Merge branch 'main' of http://121.37.111.42:3000/zhengsl/WholeProcessPlatform into main_hzz
This commit is contained in:
commit
163f37dd1e
@ -34,3 +34,113 @@ export function getCaptcha(): AxiosPromise<VerifyCode> {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注册
|
||||||
|
*/
|
||||||
|
export function registerUser(data: any): AxiosPromise<any> {
|
||||||
|
return request({
|
||||||
|
url: '/sms/register',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流域列表
|
||||||
|
* @param companyId 公司ID(可选),如果传入则根据公司获取流域列表
|
||||||
|
*/
|
||||||
|
export function getBasinList(): AxiosPromise<any[]> {
|
||||||
|
return request({
|
||||||
|
url: '/env/hbrv/regDropdown',
|
||||||
|
method: 'get',
|
||||||
|
// params: baseid ? { baseid } : {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取集团列表(无参数,获取全量集团)
|
||||||
|
*/
|
||||||
|
export function getGroupList(): AxiosPromise<any[]> {
|
||||||
|
return request({
|
||||||
|
url: '/env/hycd/regDropdown',
|
||||||
|
method: 'get',
|
||||||
|
params:{lx:1}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据集团获取公司列表
|
||||||
|
*/
|
||||||
|
export function getCompanyList(): AxiosPromise<any[]> {
|
||||||
|
return request({
|
||||||
|
url: '/env/hycd/regDropdown',
|
||||||
|
method: 'get',
|
||||||
|
params: { lx:2 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据流域获取电站列表
|
||||||
|
*/
|
||||||
|
export function getStationList(params:any): AxiosPromise<any[]> {
|
||||||
|
return request({
|
||||||
|
url: '/env/engInfo/regDropdown',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信验证码
|
||||||
|
* @param phone 手机号
|
||||||
|
* @param type 验证码类型:1-注册 2-找回密码
|
||||||
|
*/
|
||||||
|
export function sendSmsCode(phone: string, type: number = 1): AxiosPromise<any> {
|
||||||
|
return request({
|
||||||
|
url: '/sms/sendCode',
|
||||||
|
method: 'post',
|
||||||
|
data: { phone, type }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证短信验证码
|
||||||
|
* @param phone 手机号
|
||||||
|
* @param code 验证码
|
||||||
|
* @param type 验证码类型:1-注册 2-找回密码
|
||||||
|
*/
|
||||||
|
export function verifySmsCode(phone: string, code: string, type: number = 1): AxiosPromise<any> {
|
||||||
|
return request({
|
||||||
|
url: '/sms/verifyCode',
|
||||||
|
method: 'post',
|
||||||
|
data: { phone, code, type }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信验证码登录
|
||||||
|
* @param phone 手机号
|
||||||
|
* @param code 验证码
|
||||||
|
*/
|
||||||
|
export function smsLoginApi(phone: string, code: string): AxiosPromise<TokenResult> {
|
||||||
|
return request({
|
||||||
|
url: '/sms/login',
|
||||||
|
method: 'post',
|
||||||
|
data: { phone, code }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置密码
|
||||||
|
* @param phone 手机号
|
||||||
|
* @param code 验证码
|
||||||
|
* @param password 新密码
|
||||||
|
*/
|
||||||
|
export function resetPassword(phone: string, code: string, password: string): AxiosPromise<any> {
|
||||||
|
return request({
|
||||||
|
url: '/sms/resetPassword',
|
||||||
|
method: 'post',
|
||||||
|
data: { phone, code, password }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -17,6 +17,14 @@ export function gettableData(queryParams:any) {
|
|||||||
params: queryParams
|
params: queryParams
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 审核用户列表
|
||||||
|
export function queryPendingAuditUsers(queryParams:any) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/queryPendingAuditUsers',
|
||||||
|
method: 'get',
|
||||||
|
params: queryParams
|
||||||
|
});
|
||||||
|
}
|
||||||
//用户-禁用,启用
|
//用户-禁用,启用
|
||||||
export function DataStatus (queryParams:any) {
|
export function DataStatus (queryParams:any) {
|
||||||
return request({
|
return request({
|
||||||
@ -105,7 +113,7 @@ export function updatePassword (queryParams:any) {
|
|||||||
//获取过鱼设施权限树
|
//获取过鱼设施权限树
|
||||||
export function getFishtree(queryParams:any) {
|
export function getFishtree(queryParams:any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/env/tree/rvcdEng',
|
url: '/env/tree/hbrvEng',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: queryParams
|
params: queryParams
|
||||||
});
|
});
|
||||||
@ -127,6 +135,15 @@ export function getuserdata(queryParams:any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 审计用户(审批通过/驳回)
|
||||||
|
export function auditUser(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/auditUser',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
||||||
*/
|
*/
|
||||||
|
|||||||
BIN
frontend/src/assets/components/shenpibohui.png
Normal file
BIN
frontend/src/assets/components/shenpibohui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 440 B |
BIN
frontend/src/assets/components/shenpitongguo.png
Normal file
BIN
frontend/src/assets/components/shenpitongguo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 431 B |
BIN
frontend/src/assets/components/审批通过.png
Normal file
BIN
frontend/src/assets/components/审批通过.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 553 B |
@ -9,7 +9,7 @@ NProgress.configure({ showSpinner: false });
|
|||||||
const permissionStore = usePermissionStoreHook();
|
const permissionStore = usePermissionStoreHook();
|
||||||
|
|
||||||
// 白名单路由
|
// 白名单路由
|
||||||
const whiteList = ['/login']; //login
|
const whiteList = ['/login','/register']; //login
|
||||||
|
|
||||||
// 查找第一个可用路由
|
// 查找第一个可用路由
|
||||||
function findFirstAvailableRoute(routes: any[]): string | undefined {
|
function findFirstAvailableRoute(routes: any[]): string | undefined {
|
||||||
|
|||||||
@ -26,6 +26,11 @@ export const constantRoutes: RouteRecordRaw[] = [
|
|||||||
component: () => import('@/views/login-sjtb/index.vue'),
|
component: () => import('@/views/login-sjtb/index.vue'),
|
||||||
meta: { hidden: true }
|
meta: { hidden: true }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/register',
|
||||||
|
component: () => import('@/views/register/index.vue'),
|
||||||
|
meta: { hidden: true }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/404',
|
path: '/404',
|
||||||
component: () => import('@/views/error-page/404.vue'),
|
component: () => import('@/views/error-page/404.vue'),
|
||||||
|
|||||||
@ -25,14 +25,9 @@
|
|||||||
<!-- <h3 class="forgot-password-title">忘记密码</h3> -->
|
<!-- <h3 class="forgot-password-title">忘记密码</h3> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-form
|
<a-form :model="forgotPasswordForm" :rules="forgotPasswordRules" layout="vertical" class="form-container">
|
||||||
:model="forgotPasswordForm"
|
|
||||||
:rules="forgotPasswordRules"
|
|
||||||
layout="vertical"
|
|
||||||
class="form-container"
|
|
||||||
>
|
|
||||||
<a-form-item label="" name="phone">
|
<a-form-item label="" name="phone">
|
||||||
<a-input placeholder="请输入手机号" size="large">
|
<a-input v-model:value="forgotPasswordForm.phone" placeholder="请输入手机号" size="large">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<MobileOutlined />
|
<MobileOutlined />
|
||||||
</template>
|
</template>
|
||||||
@ -41,23 +36,13 @@
|
|||||||
|
|
||||||
<a-form-item label="" name="captcha">
|
<a-form-item label="" name="captcha">
|
||||||
<div class="captcha-row">
|
<div class="captcha-row">
|
||||||
<a-input
|
<a-input v-model:value="forgotPasswordForm.captcha" placeholder="请输入验证码" size="large" class="captcha-input">
|
||||||
v-model="forgotPasswordForm.captcha"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
size="large"
|
|
||||||
class="captcha-input"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<LockOutlined />
|
<LockOutlined />
|
||||||
</template>
|
</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<a-button
|
<a-button type="text" size="small" @click="sendForgotPasswordSms" :disabled="smsButtonDisabled"
|
||||||
type="text"
|
:loading="loading">
|
||||||
size="small"
|
|
||||||
@click="sendForgotPasswordSms"
|
|
||||||
:disabled="smsButtonDisabled"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
smsCountdown > 0 ? `${smsCountdown}秒后重新获取` : "获取验证码"
|
smsCountdown > 0 ? `${smsCountdown}秒后重新获取` : "获取验证码"
|
||||||
}}
|
}}
|
||||||
@ -68,24 +53,22 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="" name="newPassword">
|
<a-form-item label="" name="newPassword">
|
||||||
<a-input-password
|
<a-input-password v-model:value="forgotPasswordForm.newPassword" placeholder="请输入新密码" size="large">
|
||||||
v-model="forgotPasswordForm.newPassword"
|
|
||||||
placeholder="请输入新密码"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<LockOutlined />
|
<LockOutlined />
|
||||||
</template>
|
</template>
|
||||||
</a-input-password>
|
</a-input-password>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-button
|
<a-form-item label="" name="confirmPassword">
|
||||||
type="primary"
|
<a-input-password v-model:value="forgotPasswordForm.confirmPassword" placeholder="请再次输入密码" size="large">
|
||||||
size="large"
|
<template #prefix>
|
||||||
block
|
<LockOutlined />
|
||||||
@click="handleResetPassword"
|
</template>
|
||||||
:loading="loading"
|
</a-input-password>
|
||||||
>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-button type="primary" size="large" block @click="handleResetPassword" :loading="loading">
|
||||||
<span>提交</span>
|
<span>提交</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
@ -96,23 +79,12 @@
|
|||||||
<!-- Tabs 切换:账号登录 / 短信登录 -->
|
<!-- Tabs 切换:账号登录 / 短信登录 -->
|
||||||
<a-tabs v-model:activeKey="activeTab" class="login-tabs">
|
<a-tabs v-model:activeKey="activeTab" class="login-tabs">
|
||||||
<a-tab-pane key="account" tab="账号登录">
|
<a-tab-pane key="account" tab="账号登录">
|
||||||
<a-form
|
<a-form :model="loginData" :rules="loginRules" layout="vertical" class="form-container"
|
||||||
:model="loginData"
|
@finish="onFinish">
|
||||||
:rules="loginRules"
|
|
||||||
layout="vertical"
|
|
||||||
class="form-container"
|
|
||||||
@finish="onFinish"
|
|
||||||
>
|
|
||||||
<!-- 用户名/账号/手机号输入框 -->
|
<!-- 用户名/账号/手机号输入框 -->
|
||||||
<a-form-item label="" name="username">
|
<a-form-item label="" name="username">
|
||||||
<a-input
|
<a-input ref="username" v-model:value="loginData.username" clearable type="text"
|
||||||
ref="username"
|
placeholder="请输入用户账号/身份证号/手机号" size="large">
|
||||||
v-model:value="loginData.username"
|
|
||||||
clearable
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入用户账号/身份证号/手机号"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UserOutlined />
|
<UserOutlined />
|
||||||
</template>
|
</template>
|
||||||
@ -121,12 +93,7 @@
|
|||||||
|
|
||||||
<!-- 密码输入框 -->
|
<!-- 密码输入框 -->
|
||||||
<a-form-item label="" name="password">
|
<a-form-item label="" name="password">
|
||||||
<a-input-password
|
<a-input-password type="password" v-model:value="loginData.password" placeholder="请输入密码" size="large">
|
||||||
type="password"
|
|
||||||
v-model:value="loginData.password"
|
|
||||||
placeholder="请输入密码"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<LockOutlined />
|
<LockOutlined />
|
||||||
</template>
|
</template>
|
||||||
@ -136,65 +103,38 @@
|
|||||||
<a-form-item label="" name="captcha">
|
<a-form-item label="" name="captcha">
|
||||||
<div class="captcha-row">
|
<div class="captcha-row">
|
||||||
<a-row :gutter="24" align="middle">
|
<a-row :gutter="24" align="middle">
|
||||||
<a-col :span="10"
|
<a-col :span="10"><a-input v-model:value="loginData.code" placeholder="请输入验证码" size="large"
|
||||||
><a-input
|
class="captcha-input" /></a-col>
|
||||||
v-model:value="loginData.code"
|
<a-col :span="10"><img :src="codeUrl" alt="验证码" class="captcha-img" /></a-col>
|
||||||
placeholder="请输入验证码"
|
|
||||||
size="large"
|
|
||||||
class="captcha-input"
|
|
||||||
/></a-col>
|
|
||||||
<a-col :span="10"
|
|
||||||
><img :src="codeUrl" alt="验证码" class="captcha-img"
|
|
||||||
/></a-col>
|
|
||||||
<a-col :span="4"> <a @click="getCode">换一张</a></a-col>
|
<a-col :span="4"> <a @click="getCode">换一张</a></a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button
|
<a-button type="primary" size="large" block htmlType="submit" :loading="loading">
|
||||||
type="primary"
|
|
||||||
size="large"
|
|
||||||
block
|
|
||||||
htmlType="submit"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<span>登录</span>
|
<span>登录</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
<!-- <a-button
|
<div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
|
||||||
type="link"
|
<a-button type="link" size="mini" block @click="showForgotPasswordPage"
|
||||||
size="mini"
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
block
|
|
||||||
@click="showForgotPasswordPage"
|
|
||||||
:style="{ marginTop: '10px', border: 'none' }"
|
|
||||||
>
|
|
||||||
忘记密码
|
忘记密码
|
||||||
</a-button> -->
|
</a-button>
|
||||||
<a-button
|
<a-button type="link" size="mini" block @click="goRegister"
|
||||||
type="link"
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
size="mini"
|
|
||||||
block
|
|
||||||
:style="{ marginTop: '10px', border: 'none' }"
|
|
||||||
>
|
|
||||||
注册
|
注册
|
||||||
</a-button>
|
</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- 忘记密码 -->
|
<!-- 忘记密码 -->
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
|
||||||
<!-- 短信登录 Tab (占位) -->
|
<!-- 短信登录 Tab (占位) -->
|
||||||
<!-- <a-tab-pane key="sms" tab="短信登录">
|
<a-tab-pane key="sms" tab="短信登录">
|
||||||
<a-form
|
<a-form :model="loginData" :rules="state.smsLoginRules" layout="vertical" class="form-container"
|
||||||
:model="loginData"
|
@finish="onSmsLogin">
|
||||||
:rules="loginRules"
|
|
||||||
layout="vertical"
|
|
||||||
class="form-container"
|
|
||||||
>
|
|
||||||
<a-form-item label="" name="username">
|
<a-form-item label="" name="username">
|
||||||
<a-input
|
<a-input v-model:value="loginData.username" placeholder="请输入手机号" size="large">
|
||||||
v-model:value="loginData.username"
|
|
||||||
placeholder="请输入手机号"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<MobileOutlined />
|
<MobileOutlined />
|
||||||
</template>
|
</template>
|
||||||
@ -202,23 +142,13 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="" name="captcha">
|
<a-form-item label="" name="captcha">
|
||||||
<div class="captcha-row">
|
<div class="captcha-row">
|
||||||
<a-input
|
<a-input v-model:value="loginData.code" placeholder="请输入验证码" size="large" class="captcha-input">
|
||||||
v-model="loginData.code"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
size="large"
|
|
||||||
class="captcha-input"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<LockOutlined />
|
<LockOutlined />
|
||||||
</template>
|
</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<a-button
|
<a-button type="text" size="small" @click="sendSms" :disabled="smsButtonDisabled"
|
||||||
type="text"
|
:loading="loading">
|
||||||
size="small"
|
|
||||||
@click="sendSms"
|
|
||||||
:disabled="smsButtonDisabled"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
smsCountdown > 0
|
smsCountdown > 0
|
||||||
? `${smsCountdown}秒后重新获取`
|
? `${smsCountdown}秒后重新获取`
|
||||||
@ -229,17 +159,21 @@
|
|||||||
</a-input>
|
</a-input>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button
|
<a-button type="primary" size="large" block htmlType="submit" :loading="loading">
|
||||||
type="primary"
|
|
||||||
size="large"
|
|
||||||
block
|
|
||||||
htmlType="submit"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<span>登录</span>
|
<span>登录</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
|
||||||
|
<a-button type="link" size="mini" block @click="showForgotPasswordPage"
|
||||||
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
|
忘记密码
|
||||||
|
</a-button>
|
||||||
|
<a-button type="link" size="mini" block @click="goRegister"
|
||||||
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
|
注册
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-tab-pane> -->
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -251,9 +185,9 @@
|
|||||||
import { onMounted, reactive, ref, toRefs, watch } from "vue";
|
import { onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||||
import loginImg from "@/assets/images/logo.png";
|
import loginImg from "@/assets/images/logo.png";
|
||||||
import { UserOutlined, LockOutlined, MobileOutlined } from "@ant-design/icons-vue";
|
import { UserOutlined, LockOutlined, MobileOutlined } from "@ant-design/icons-vue";
|
||||||
import { getCaptcha } from "@/api/auth";
|
import { getCaptcha, sendSmsCode, smsLoginApi, resetPassword } from "@/api/auth";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import { setPath } from "@/utils/auth";
|
import { setPath, setToken } from "@/utils/auth";
|
||||||
// 组件依赖
|
// 组件依赖
|
||||||
|
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
@ -266,6 +200,7 @@ import { encrypt, decrypt } from "@/utils/rsaEncrypt";
|
|||||||
|
|
||||||
// 状态管理依赖
|
// 状态管理依赖
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
@ -285,6 +220,7 @@ const forgotPasswordForm = ref({
|
|||||||
phone: "",
|
phone: "",
|
||||||
captcha: "",
|
captcha: "",
|
||||||
newPassword: "",
|
newPassword: "",
|
||||||
|
confirmPassword: "",
|
||||||
});
|
});
|
||||||
// 忘记密码
|
// 忘记密码
|
||||||
const showForgotPassword = ref(false);
|
const showForgotPassword = ref(false);
|
||||||
@ -304,6 +240,10 @@ const state = reactive({
|
|||||||
password: [{ required: true, trigger: "blur", message: t("login.rulesPassword") }],
|
password: [{ required: true, trigger: "blur", message: t("login.rulesPassword") }],
|
||||||
code: [{ required: true, trigger: "blur", message: "请输入验证码" }],
|
code: [{ required: true, trigger: "blur", message: "请输入验证码" }],
|
||||||
},
|
},
|
||||||
|
smsLoginRules: {
|
||||||
|
username: [{ required: true, trigger: "blur", message: "请输入手机号" }],
|
||||||
|
code: [{ required: true, trigger: "blur", message: "请输入验证码" }]
|
||||||
|
},
|
||||||
loginImg: loginImg[0],
|
loginImg: loginImg[0],
|
||||||
loading: false,
|
loading: false,
|
||||||
passwordType: "password",
|
passwordType: "password",
|
||||||
@ -325,7 +265,67 @@ const forgotPasswordRules = ref({
|
|||||||
captcha: [{ required: true, message: "验证码不能为空", trigger: "blur" }],
|
captcha: [{ required: true, message: "验证码不能为空", trigger: "blur" }],
|
||||||
newPassword: [
|
newPassword: [
|
||||||
{ required: true, message: "新密码不能为空", trigger: "blur" },
|
{ required: true, message: "新密码不能为空", trigger: "blur" },
|
||||||
{ min: 6, message: "密码长度不能少于6位", trigger: "blur" },
|
{ min: 10, message: "密码长度不能少于10位", trigger: "blur" },
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: string) => {
|
||||||
|
if (!value) return Promise.resolve();
|
||||||
|
|
||||||
|
// 检查密码复杂度:至少包含四类字符中的三类
|
||||||
|
const hasUpperCase = /[A-Z]/.test(value);
|
||||||
|
const hasLowerCase = /[a-z]/.test(value);
|
||||||
|
const hasNumber = /\d/.test(value);
|
||||||
|
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value);
|
||||||
|
|
||||||
|
const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecialChar].filter(Boolean).length;
|
||||||
|
|
||||||
|
if (typeCount < 3) {
|
||||||
|
return Promise.reject(new Error('密码必须包含大写字母、小写字母、数字、特殊字符中的至少三种'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续重复字符
|
||||||
|
if (/(.)\1{1,}/.test(value)) {
|
||||||
|
return Promise.reject(new Error('密码不能包含连续重复字符'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续递增/递减数字
|
||||||
|
for (let i = 0; i < value.length - 1; i++) {
|
||||||
|
if (/\d/.test(value[i]) && /\d/.test(value[i + 1])) {
|
||||||
|
const diff = value.charCodeAt(i + 1) - value.charCodeAt(i);
|
||||||
|
if (Math.abs(diff) === 1) {
|
||||||
|
return Promise.reject(new Error('密码不能包含连续递增或递减的数字'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续递增/递减字母
|
||||||
|
for (let i = 0; i < value.length - 1; i++) {
|
||||||
|
if (/[a-zA-Z]/.test(value[i]) && /[a-zA-Z]/.test(value[i + 1])) {
|
||||||
|
const diff = value.charCodeAt(i + 1) - value.charCodeAt(i);
|
||||||
|
if (Math.abs(diff) === 1) {
|
||||||
|
return Promise.reject(new Error('密码不能包含连续递增或递减的字母'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
trigger: "blur"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
confirmPassword: [
|
||||||
|
{ required: true, message: "请再次输入密码", trigger: "blur" },
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject(new Error('请再次输入密码'));
|
||||||
|
}
|
||||||
|
if (value !== forgotPasswordForm.value.newPassword) {
|
||||||
|
return Promise.reject(new Error('两次输入的密码不一致'));
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
trigger: "blur"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -382,6 +382,96 @@ function onFinish() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信验证码登录
|
||||||
|
*/
|
||||||
|
const onSmsLogin = async () => {
|
||||||
|
try {
|
||||||
|
// ========== 第一部分:表单验证 ==========
|
||||||
|
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||||
|
if (!loginData.value.username || !phoneRegex.test(loginData.value.username)) {
|
||||||
|
message.error("请输入正确的手机号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loginData.value.code || loginData.value.code.trim() === '') {
|
||||||
|
message.error("请输入验证码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 第二部分:设置加载状态 ==========
|
||||||
|
state.loading = true;
|
||||||
|
|
||||||
|
// ========== 第三部分:调用短信登录 API ==========
|
||||||
|
console.log('开始调用短信登录API, 手机号:', loginData.value.username);
|
||||||
|
const res: any = await smsLoginApi(
|
||||||
|
loginData.value.username, // 手机号
|
||||||
|
loginData.value.code // 短信验证码
|
||||||
|
);
|
||||||
|
console.log('短信登录API响应:', res);
|
||||||
|
|
||||||
|
// ========== 第四部分:检查响应结果 ==========
|
||||||
|
console.log('检查响应结果, res.code:', res.code, '类型:', typeof res.code);
|
||||||
|
|
||||||
|
// 注意:code 可能是字符串 "0" 或数字 0,需要兼容处理
|
||||||
|
if (res.code !== 0 && res.code !== '0') {
|
||||||
|
console.error('短信登录失败, 错误码:', res.code, '错误信息:', res.msg);
|
||||||
|
message.error(res.msg || "登录失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 第五部分:提取并存储 Token ==========
|
||||||
|
console.log('开始提取Token, res.data:', res.data);
|
||||||
|
const token = res.data?.token || res.data; // 兼容两种结构
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
console.error('Token为空, res.data结构:', JSON.stringify(res.data));
|
||||||
|
message.error("登录失败:未获取到Token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Token获取成功:', token);
|
||||||
|
// 存储到 Cookie
|
||||||
|
setToken(token);
|
||||||
|
|
||||||
|
// 更新 Store 状态(注意是大写 Token)
|
||||||
|
userStore.Token = token;
|
||||||
|
console.log('Token已存储到Store');
|
||||||
|
|
||||||
|
// ========== 第六部分:获取用户信息和角色 ==========
|
||||||
|
console.log('开始获取用户信息...');
|
||||||
|
const userInfo = await userStore.getInfo();
|
||||||
|
console.log('用户信息获取成功:', userInfo);
|
||||||
|
const roles = userInfo.roles;
|
||||||
|
console.log('用户角色:', roles);
|
||||||
|
|
||||||
|
// ========== 第七部分:生成路由(获取菜单)==========
|
||||||
|
console.log('开始生成路由...');
|
||||||
|
const permissionStore = usePermissionStoreHook();
|
||||||
|
const accessRoutes:any = await permissionStore.generateRoutes(roles);
|
||||||
|
console.log('路由生成成功, 路由数量:', accessRoutes.length);
|
||||||
|
|
||||||
|
// ========== 第八部分:动态添加路由 ==========
|
||||||
|
accessRoutes.forEach((route: any) => {
|
||||||
|
router.addRoute(route);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ========== 第九部分:设置路径并跳转 ==========
|
||||||
|
setPath("/login-sjtb");
|
||||||
|
router.push({ path: accessRoutes[0].children[0].opturl });
|
||||||
|
message.success("登录成功");
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
// ========== 第十部分:错误处理 ==========
|
||||||
|
console.error("短信登录失败", error);
|
||||||
|
message.error(error.message || "登录失败,请重试");
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
// ========== 第十一部分:关闭加载状态 ==========
|
||||||
|
state.loading = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
route,
|
route,
|
||||||
() => {
|
() => {
|
||||||
@ -426,9 +516,9 @@ const startCountdown = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 显示忘记密码页面
|
// 显示忘记密码页面
|
||||||
// const showForgotPasswordPage = () => {
|
const showForgotPasswordPage = () => {
|
||||||
// showForgotPassword.value = true;
|
showForgotPassword.value = true;
|
||||||
// };
|
};
|
||||||
//注册用户页面
|
//注册用户页面
|
||||||
const goRegister = () => {
|
const goRegister = () => {
|
||||||
router.push({ path: "/register" });
|
router.push({ path: "/register" });
|
||||||
@ -441,49 +531,53 @@ const backToLogin = () => {
|
|||||||
phone: "",
|
phone: "",
|
||||||
captcha: "",
|
captcha: "",
|
||||||
newPassword: "",
|
newPassword: "",
|
||||||
|
confirmPassword: "",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 发送短信验证码
|
// 发送短信验证码
|
||||||
// const sendSms = async () => {
|
const sendSms = async () => {
|
||||||
// // 检查手机号是否为空
|
// 检查手机号是否为空
|
||||||
// if (!loginData.value.username) {
|
if (!loginData.value.username) {
|
||||||
// message.error("请输入手机号");
|
message.error("请输入手机号");
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // 检查手机号格式
|
// 检查手机号格式
|
||||||
// const phoneRegex = /^1[3-9]\d{9}$/;
|
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||||
// if (!phoneRegex.test(loginData.value.username)) {
|
if (!phoneRegex.test(loginData.value.username)) {
|
||||||
// message.error("请输入正确的手机号");
|
message.error("请输入正确的手机号");
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // 如果正在倒计时,不允许重复发送
|
// 如果正在倒计时,不允许重复发送
|
||||||
// if (smsCountdown.value > 0) {
|
if (smsCountdown.value > 0) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// loading.value = true;
|
loading.value = true;
|
||||||
// smsButtonDisabled.value = true;
|
smsButtonDisabled.value = true;
|
||||||
|
|
||||||
// try {
|
try {
|
||||||
// // 模拟发送短信验证码接口
|
// 调用发送短信验证码接口,type默认为1(注册类型)
|
||||||
// // await axios.post('/sms/send', { phone: loginForm.value.username })
|
const res: any = await sendSmsCode(loginData.value.username, 3);
|
||||||
|
if (res.code == 1) {
|
||||||
|
message.success(res.msg);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 发送成功
|
||||||
|
message.success("验证码发送成功");
|
||||||
|
|
||||||
// // 模拟发送成功
|
// 开始倒计时
|
||||||
// message.success("验证码发送成功");
|
startCountdown();
|
||||||
|
} catch (error) {
|
||||||
// // 开始倒计时
|
console.error("发送验证码失败", error);
|
||||||
// startCountdown();
|
message.error("验证码发送失败,请重试");
|
||||||
// } catch (error) {
|
smsButtonDisabled.value = false;
|
||||||
// console.error("发送验证码失败", error);
|
} finally {
|
||||||
// message.error("验证码发送失败,请重试");
|
loading.value = false;
|
||||||
// smsButtonDisabled.value = false;
|
}
|
||||||
// } finally {
|
};
|
||||||
// loading.value = false;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// 发送忘记密码短信验证码
|
// 发送忘记密码短信验证码
|
||||||
const sendForgotPasswordSms = async () => {
|
const sendForgotPasswordSms = async () => {
|
||||||
// 检查手机号是否为空
|
// 检查手机号是否为空
|
||||||
@ -508,17 +602,23 @@ const sendForgotPasswordSms = async () => {
|
|||||||
smsButtonDisabled.value = true;
|
smsButtonDisabled.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 模拟发送短信验证码接口
|
// 调用发送短信验证码接口,type=3表示找回密码类型
|
||||||
// await axios.post('/sms/forgot-password', { phone: forgotPasswordForm.value.phone })
|
const res: any = await sendSmsCode(forgotPasswordForm.value.phone, 2);
|
||||||
|
|
||||||
// 模拟发送成功
|
if (res.code == 1) {
|
||||||
|
message.error(res.msg);
|
||||||
|
smsButtonDisabled.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送成功
|
||||||
message.success("验证码发送成功");
|
message.success("验证码发送成功");
|
||||||
|
|
||||||
// 开始倒计时
|
// 开始倒计时
|
||||||
startCountdown();
|
startCountdown();
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("发送验证码失败", error);
|
// console.error("发送验证码失败", error);
|
||||||
message.error("验证码发送失败,请重试");
|
// message.error(error.message || "验证码发送失败,请重试");
|
||||||
smsButtonDisabled.value = false;
|
smsButtonDisabled.value = false;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@ -526,23 +626,111 @@ const sendForgotPasswordSms = async () => {
|
|||||||
};
|
};
|
||||||
// 处理密码重置
|
// 处理密码重置
|
||||||
const handleResetPassword = async () => {
|
const handleResetPassword = async () => {
|
||||||
loading.value = true;
|
// 先进行表单验证
|
||||||
try {
|
try {
|
||||||
// 2. 模拟接口请求 (实际替换为真实重置密码接口)
|
// 手动验证各个字段
|
||||||
// await axios.post('/user/reset-password', {
|
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||||
// phone: forgotPasswordForm.value.phone,
|
if (!forgotPasswordForm.value.phone || !phoneRegex.test(forgotPasswordForm.value.phone)) {
|
||||||
// captcha: forgotPasswordForm.value.captcha,
|
message.error("请输入正确的手机号");
|
||||||
// newPassword: forgotPasswordForm.value.newPassword
|
return;
|
||||||
// })
|
}
|
||||||
|
|
||||||
// 3. 模拟重置成功
|
if (!forgotPasswordForm.value.captcha) {
|
||||||
message.success("密码重置成功");
|
message.error("请输入验证码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!forgotPasswordForm.value.newPassword) {
|
||||||
|
message.error("请输入新密码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证确认密码
|
||||||
|
if (!forgotPasswordForm.value.confirmPassword) {
|
||||||
|
message.error("请再次输入密码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证两次密码是否一致
|
||||||
|
if (forgotPasswordForm.value.newPassword !== forgotPasswordForm.value.confirmPassword) {
|
||||||
|
message.error("两次输入的密码不一致");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密码复杂度校验
|
||||||
|
const password = forgotPasswordForm.value.newPassword;
|
||||||
|
if (password.length < 10) {
|
||||||
|
message.error("密码长度不能少于10位");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasUpperCase = /[A-Z]/.test(password);
|
||||||
|
const hasLowerCase = /[a-z]/.test(password);
|
||||||
|
const hasNumber = /\d/.test(password);
|
||||||
|
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password);
|
||||||
|
|
||||||
|
const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecialChar].filter(Boolean).length;
|
||||||
|
if (typeCount < 3) {
|
||||||
|
message.error('密码必须包含大写字母、小写字母、数字、特殊字符中的至少三种');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续重复字符
|
||||||
|
if (/(.)\1{1,}/.test(password)) {
|
||||||
|
message.error('密码不能包含连续重复字符');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续递增/递减数字
|
||||||
|
for (let i = 0; i < password.length - 1; i++) {
|
||||||
|
if (/\d/.test(password[i]) && /\d/.test(password[i + 1])) {
|
||||||
|
const diff = password.charCodeAt(i + 1) - password.charCodeAt(i);
|
||||||
|
if (Math.abs(diff) === 1) {
|
||||||
|
message.error('密码不能包含连续递增或递减的数字');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连续递增/递减字母
|
||||||
|
for (let i = 0; i < password.length - 1; i++) {
|
||||||
|
if (/[a-zA-Z]/.test(password[i]) && /[a-zA-Z]/.test(password[i + 1])) {
|
||||||
|
const diff = password.charCodeAt(i + 1) - password.charCodeAt(i);
|
||||||
|
if (Math.abs(diff) === 1) {
|
||||||
|
message.error('密码不能包含连续递增或递减的字母');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 返回登录页面
|
|
||||||
backToLogin();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("密码重置失败", error);
|
console.error("表单验证失败", error);
|
||||||
message.error("密码重置失败,请重试");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 对密码进行 RSA 加密
|
||||||
|
const encryptedPassword = encrypt(forgotPasswordForm.value.newPassword);
|
||||||
|
|
||||||
|
// 调用重置密码接口,使用加密后的密码
|
||||||
|
const res: any = await resetPassword(
|
||||||
|
forgotPasswordForm.value.phone,
|
||||||
|
forgotPasswordForm.value.captcha,
|
||||||
|
encryptedPassword
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.code == 0 ) {
|
||||||
|
message.success("密码重置成功");
|
||||||
|
// 返回登录页面
|
||||||
|
backToLogin();
|
||||||
|
} else {
|
||||||
|
message.error(res.msg || "密码重置失败");
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
// console.error("密码重置失败", error);
|
||||||
|
// message.error(error.message || "密码重置失败,请重试");
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
@ -632,7 +820,7 @@ onMounted(() => {
|
|||||||
left: 74%;
|
left: 74%;
|
||||||
top: 30%;
|
top: 30%;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
max-height: 402px;
|
max-height: 420px;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-height: 362px;
|
min-height: 362px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@ -647,10 +835,12 @@ onMounted(() => {
|
|||||||
/* 验证码布局 */
|
/* 验证码布局 */
|
||||||
.captcha-row {
|
.captcha-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.ant-row {
|
.ant-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gap: 12px;
|
/* gap: 12px;
|
||||||
align-items: center; */
|
align-items: center; */
|
||||||
|
|
||||||
|
|||||||
@ -12,133 +12,219 @@
|
|||||||
<div class="right-section">
|
<div class="right-section">
|
||||||
<a-tabs v-model:activeKey="activeTab" class="register-tabs">
|
<a-tabs v-model:activeKey="activeTab" class="register-tabs">
|
||||||
<a-tab-pane key="register" tab="用户注册">
|
<a-tab-pane key="register" tab="用户注册">
|
||||||
<a-form
|
<a-form :model="registerData" :rules="registerRules" layout="horizontal"
|
||||||
:model="registerData"
|
:label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" class="form-container"
|
||||||
:rules="registerRules"
|
@finish="handleFormFinish">
|
||||||
layout="vertical"
|
<!-- 账号信息 -->
|
||||||
class="form-container"
|
<div class="form-section">
|
||||||
@finish="onRegister"
|
<div class="section-title">账号信息</div>
|
||||||
>
|
|
||||||
<!-- 登录账号 -->
|
|
||||||
<a-form-item name="username" label="登录账号">
|
|
||||||
<a-input
|
|
||||||
v-model:value="registerData.username"
|
|
||||||
placeholder="请输入登录账号(4-20个字符)"
|
|
||||||
:prefix="h(UserOutlined)"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<!-- 真实姓名 -->
|
<!-- 账号 -->
|
||||||
<a-form-item name="realName" label="真实姓名">
|
<a-form-item name="username" label="账 号">
|
||||||
<a-input
|
<a-input v-model:value="registerData.username" placeholder="请输入登录账号(4-20个字符)" />
|
||||||
v-model:value="registerData.realName"
|
|
||||||
placeholder="请输入真实姓名"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<!-- 手机号 -->
|
|
||||||
<a-form-item name="phone" label="手机号">
|
|
||||||
<a-input
|
|
||||||
v-model:value="registerData.phone"
|
|
||||||
placeholder="请输入11位手机号"
|
|
||||||
:prefix="h(MobileOutlined)"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 密码 -->
|
<!-- 密码 -->
|
||||||
<a-form-item name="password" label="密码">
|
<a-form-item name="password" label="密 码">
|
||||||
<a-input-password
|
<a-input-password v-model:value="registerData.password"
|
||||||
v-model:value="registerData.password"
|
placeholder="请设置密码(6-20个字符)" />
|
||||||
placeholder="请设置密码(6-20个字符)"
|
|
||||||
:prefix="h(LockOutlined)"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 确认密码 -->
|
<!-- 确认密码 -->
|
||||||
<a-form-item name="confirmPassword" label="确认密码">
|
<a-form-item name="confirmPassword" label="确认密码">
|
||||||
<a-input-password
|
<a-input-password v-model:value="registerData.confirmPassword"
|
||||||
v-model:value="registerData.confirmPassword"
|
placeholder="请再次输入密码" />
|
||||||
placeholder="请再次输入密码"
|
</a-form-item>
|
||||||
:prefix="h(LockOutlined)"
|
</div>
|
||||||
/>
|
|
||||||
|
<!-- 个人信息 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-title">个人信息</div>
|
||||||
|
|
||||||
|
<!-- 真实姓名 -->
|
||||||
|
<a-form-item name="realName" label="真实姓名">
|
||||||
|
<a-input v-model:value="registerData.realName" placeholder="请输入真实姓名" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 验证码 -->
|
<!-- 所属单位 -->
|
||||||
<a-form-item name="code" label="验证码">
|
<a-form-item name="belongingUnit" label="所属单位">
|
||||||
|
<a-input v-model:value="registerData.belongingUnit" placeholder="请输入所属单位(选填)" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 手机号 -->
|
||||||
|
<a-form-item name="phone" label="手 机 号">
|
||||||
<a-row :gutter="8">
|
<a-row :gutter="8">
|
||||||
<a-col :span="16">
|
<a-col :span="16">
|
||||||
<a-input
|
<a-input v-model:value="registerData.phone" placeholder="请输入11位手机号" />
|
||||||
v-model:value="registerData.code"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
/>
|
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="8">
|
<a-col :span="8">
|
||||||
<img
|
<a-button type="primary" :disabled="smsCountdown > 0" @click="handleSendSms"
|
||||||
v-if="captchaImg"
|
style="width: 100%">
|
||||||
:src="captchaImg"
|
{{ smsCountdown > 0 ? `${smsCountdown}s` : '获取验证码' }}
|
||||||
@click="refreshCaptcha"
|
</a-button>
|
||||||
style="cursor: pointer; width: 100%; height: 36px;"
|
|
||||||
/>
|
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 短信验证码 -->
|
||||||
|
<a-form-item name="smsCode" label="验证码">
|
||||||
|
<a-input v-model:value="registerData.smsCode" placeholder="请输入短信验证码" />
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 注册按钮 -->
|
<!-- 注册按钮 -->
|
||||||
<a-button
|
<a-form-item style="display: flex;align-items: center;justify-content: center;width: 100%;">
|
||||||
type="primary"
|
<a-button type="primary" size="large" block htmlType="submit" :loading="loading"
|
||||||
size="large"
|
style="margin-left: 20px;">
|
||||||
block
|
|
||||||
htmlType="submit"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<span>立即注册</span>
|
<span>立即注册</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<!-- 返回登录 -->
|
<!-- 返回登录 -->
|
||||||
<a-button
|
<a-form-item style="display: flex;align-items: center;justify-content: center;width: 100%;">
|
||||||
type="link"
|
|
||||||
size="small"
|
<a-button type="link" size="small" block @click="backToLogin"
|
||||||
block
|
style="margin-left: 20px;">
|
||||||
@click="backToLogin"
|
|
||||||
:style="{ marginTop: '10px' }"
|
|
||||||
>
|
|
||||||
已有账号?返回登录
|
已有账号?返回登录
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
|
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
|
||||||
|
<!-- 注册确认弹框 -->
|
||||||
|
<a-modal v-model:open="modalVisible" title="选择所属组织" width="600px" :confirm-loading="loading"
|
||||||
|
@ok="onRegister" @cancel="handleModalCancel">
|
||||||
|
<a-form :model="organizationData" :rules="organizationRules" layout="horizontal"
|
||||||
|
ref="organizationFormRef" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
|
|
||||||
|
<!-- 集团(单选,字符串) -->
|
||||||
|
<a-form-item name="groupCode" label="集 团">
|
||||||
|
<a-select v-model:value="organizationData.groupCode" placeholder="请选择集团" style="width: 100%"
|
||||||
|
show-search :filter-option="filterOption">
|
||||||
|
<a-select-option v-for="item in groupList" :key="item.hycd" :value="item.hycd" :label="item.hynm">
|
||||||
|
{{ item.hynm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 公司(单选,字符串) -->
|
||||||
|
<a-form-item name="companyCode" label="公 司">
|
||||||
|
<a-select v-model:value="organizationData.companyCode" placeholder="请选择公司"
|
||||||
|
style="width: 100%" show-search :filter-option="filterOption" allow-clear>
|
||||||
|
<a-select-option v-for="item in companyList" :key="item.hycd" :value="item.hycd"
|
||||||
|
:label="item.hynm">
|
||||||
|
{{ item.hynm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 流域(多选,数组,必填) -->
|
||||||
|
<a-form-item name="rvcdCode" label="流 域" required>
|
||||||
|
<a-select v-model:value="organizationData.rvcdCode" mode="multiple" placeholder="请选择流域"
|
||||||
|
style="width: 100%" show-search :filter-option="filterOption" @change="onRvcdChange">
|
||||||
|
<a-select-option v-for="item in basinList" :key="item.hbrvcd" :value="item.hbrvcd"
|
||||||
|
:label="item.hbrvnm">
|
||||||
|
{{ item.hbrvnm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<!-- 电站(多选,数组,必填,依赖流域) -->
|
||||||
|
<a-form-item name="stationCode" label="电 站" required>
|
||||||
|
<a-select v-model:value="organizationData.stationCode" mode="multiple" placeholder="请先选择流域"
|
||||||
|
:disabled="organizationData.rvcdCode.length === 0" style="width: 100%" show-search
|
||||||
|
:filter-option="filterOption">
|
||||||
|
<a-select-option v-for="item in stationList" :key="item.stcd" :value="item.stcd"
|
||||||
|
:label="item.ennm">
|
||||||
|
{{ item.ennm }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, h } from "vue";
|
import { reactive, ref, onMounted, onUnmounted } from "vue";
|
||||||
import { UserOutlined, LockOutlined, MobileOutlined } from "@ant-design/icons-vue";
|
import {
|
||||||
import { getCaptcha,
|
getBasinList,
|
||||||
// registerUser
|
getGroupList,
|
||||||
} from "@/api/auth";
|
getCompanyList,
|
||||||
|
getStationList,
|
||||||
|
sendSmsCode,
|
||||||
|
verifySmsCode,
|
||||||
|
registerUser
|
||||||
|
} from "@/api/auth";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { encrypt } from "@/utils/rsaEncrypt";
|
import { encrypt } from "@/utils/rsaEncrypt";
|
||||||
|
|
||||||
// 注册表单数据
|
// 注册表单数据
|
||||||
const registerData = reactive({
|
const registerData = reactive({
|
||||||
// 必填字段
|
|
||||||
|
// 用户信息
|
||||||
username: "",
|
username: "",
|
||||||
realName: "",
|
|
||||||
phone: "",
|
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: "",
|
confirmPassword: "",
|
||||||
code: "",
|
realName: "",
|
||||||
uuid: "",
|
belongingUnit: "",
|
||||||
|
phone: "",
|
||||||
// 系统字段
|
smsCode: "",
|
||||||
userType: 1,
|
|
||||||
status: 1,
|
|
||||||
regStatus: 0
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 下拉选项数据
|
||||||
|
const basinList = ref<any[]>([]);
|
||||||
|
const groupList = ref<any[]>([]);
|
||||||
|
const companyList = ref<any[]>([]);
|
||||||
|
const stationList = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 短信验证码倒计时
|
||||||
|
const smsCountdown = ref(0);
|
||||||
|
let smsTimer: any = null;
|
||||||
|
|
||||||
|
// ==================== 组织表单数据 ====================
|
||||||
|
const organizationData = reactive({
|
||||||
|
groupCode: '', // 集团(单选,字符串)
|
||||||
|
companyCode: '', // 公司(单选,字符串)
|
||||||
|
rvcdCode: [], // 流域(多选,数组)
|
||||||
|
stationCode: [] // 电站(多选,数组)
|
||||||
|
});
|
||||||
|
|
||||||
|
// 组织表单引用
|
||||||
|
const organizationFormRef = ref();
|
||||||
|
|
||||||
|
// ==================== 组织表单验证规则 ====================
|
||||||
|
const organizationRules = {
|
||||||
|
rvcdCode: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any[]) => {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return Promise.reject("请至少选择一个流域");
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
trigger: "change"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stationCode: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any[]) => {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return Promise.reject("请至少选择一个电站");
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
trigger: "change"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
const registerRules = {
|
const registerRules = {
|
||||||
// 登录账号
|
// 登录账号
|
||||||
@ -148,22 +234,96 @@ const registerRules = {
|
|||||||
{ pattern: /^[a-zA-Z0-9_]+$/, message: "只能包含字母、数字和下划线", trigger: "blur" }
|
{ pattern: /^[a-zA-Z0-9_]+$/, message: "只能包含字母、数字和下划线", trigger: "blur" }
|
||||||
],
|
],
|
||||||
|
|
||||||
// 真实姓名
|
|
||||||
realName: [
|
|
||||||
{ required: true, message: "请输入真实姓名", trigger: "blur" },
|
|
||||||
{ min: 2, max: 20, message: "姓名长度2-20个字符", trigger: "blur" }
|
|
||||||
],
|
|
||||||
|
|
||||||
// 手机号
|
|
||||||
phone: [
|
|
||||||
{ required: true, message: "请输入手机号", trigger: "blur" },
|
|
||||||
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的11位手机号", trigger: "blur" }
|
|
||||||
],
|
|
||||||
|
|
||||||
// 密码
|
// 密码
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||||
{ min: 6, max: 20, message: "密码长度6-20个字符", trigger: "blur" }
|
{
|
||||||
|
validator: (rule: any, value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject("请输入密码");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 长度检查:不低于10位
|
||||||
|
if (value.length < 10) {
|
||||||
|
return Promise.reject("密码长度不能少于10位");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 复杂度检查:四类字符中至少包含三类
|
||||||
|
const hasUpperCase = /[A-Z]/.test(value);
|
||||||
|
const hasLowerCase = /[a-z]/.test(value);
|
||||||
|
const hasNumber = /[0-9]/.test(value);
|
||||||
|
const hasSpecial = /[^a-zA-Z0-9]/.test(value);
|
||||||
|
const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecial].filter(Boolean).length;
|
||||||
|
|
||||||
|
if (typeCount < 3) {
|
||||||
|
return Promise.reject("密码必须包含大写字母、小写字母、数字、特殊字符中的至少三类");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 禁止连续重复序列检查
|
||||||
|
// 3.1 检查是否有2位及以上相同字符重复
|
||||||
|
for (let i = 0; i <= value.length - 2; i++) {
|
||||||
|
if (value[i] === value[i + 1]) {
|
||||||
|
return Promise.reject("密码不能包含2位及以上相同字符的连续重复(如11、aa)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.2 检查是否有2位及以上连续递增/递减的数字
|
||||||
|
for (let i = 0; i <= value.length - 2; i++) {
|
||||||
|
const char1 = value.charCodeAt(i);
|
||||||
|
const char2 = value.charCodeAt(i + 1);
|
||||||
|
|
||||||
|
// 检查是否都是数字
|
||||||
|
if (/\d/.test(value[i]) && /\d/.test(value[i + 1])) {
|
||||||
|
// 检查递增或递减
|
||||||
|
if (Math.abs(char2 - char1) === 1) {
|
||||||
|
return Promise.reject("密码不能包含2位及以上连续递增或递减的数字(如12、21)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.3 检查是否有2位及以上连续递增/递减的字母
|
||||||
|
for (let i = 0; i <= value.length - 2; i++) {
|
||||||
|
const char1 = value.charCodeAt(i);
|
||||||
|
const char2 = value.charCodeAt(i + 1);
|
||||||
|
|
||||||
|
// 检查是否都是字母
|
||||||
|
if (/[a-zA-Z]/.test(value[i]) && /[a-zA-Z]/.test(value[i + 1])) {
|
||||||
|
// 检查递增或递减
|
||||||
|
if (Math.abs(char2 - char1) === 1) {
|
||||||
|
return Promise.reject("密码不能包含2位及以上连续递增或递减的字母(如ab、ba)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 用户名关联检查(严格模式,忽略大小写)
|
||||||
|
const username = registerData.username.toLowerCase();
|
||||||
|
const passwordLower = value.toLowerCase();
|
||||||
|
|
||||||
|
// 4.1 检查密码是否完整包含用户名
|
||||||
|
if (passwordLower.includes(username)) {
|
||||||
|
return Promise.reject("密码不能包含用户名");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.2 提取密码中的字母部分
|
||||||
|
const passwordLetters = passwordLower.replace(/[^a-z]/g, '');
|
||||||
|
|
||||||
|
// 4.3 如果密码字母部分长度 >= 3,检查是否是用户名的子串
|
||||||
|
if (passwordLetters.length >= 3 && username.includes(passwordLetters)) {
|
||||||
|
return Promise.reject("密码的字母部分不能是用户名的子串");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.4 检查用户名中是否包含密码的任意连续3位字母
|
||||||
|
for (let i = 0; i <= passwordLetters.length - 3; i++) {
|
||||||
|
const substring = passwordLetters.substring(i, i + 3);
|
||||||
|
if (username.includes(substring)) {
|
||||||
|
return Promise.reject("密码不能与用户名存在明显关联");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
trigger: "blur"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
// 确认密码
|
// 确认密码
|
||||||
@ -180,66 +340,220 @@ const registerRules = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
// 验证码
|
// 真实姓名
|
||||||
code: [
|
realName: [
|
||||||
{ required: true, message: "请输入验证码", trigger: "blur" }
|
{ required: true, message: "请输入真实姓名", trigger: "blur" },
|
||||||
|
{ min: 2, max: 20, message: "姓名长度2-20个字符", trigger: "blur" }
|
||||||
|
],
|
||||||
|
|
||||||
|
// 所属单位(选填,无验证规则)
|
||||||
|
|
||||||
|
// 手机号
|
||||||
|
phone: [
|
||||||
|
{ required: true, message: "请输入手机号", trigger: "blur" },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的11位手机号", trigger: "blur" }
|
||||||
|
],
|
||||||
|
|
||||||
|
// 短信验证码
|
||||||
|
smsCode: [
|
||||||
|
{ required: true, message: "请输入短信验证码", trigger: "blur" },
|
||||||
|
{ len: 6, message: "验证码为6位数字", trigger: "blur" }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const captchaImg = ref("");
|
|
||||||
const activeTab = ref("register");
|
const activeTab = ref("register");
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
|
||||||
// 获取验证码
|
// 初始化加载集团列表
|
||||||
const refreshCaptcha = async () => {
|
const loadGroupList = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await getCaptcha();
|
const res = await getGroupList();
|
||||||
registerData.uuid = res.data.verifyCodeKey;
|
groupList.value = res.data || [];
|
||||||
captchaImg.value = res.data.verifyCodeImg; // base64图片
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error("获取验证码失败");
|
console.error("加载集团列表失败", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 集团变化
|
||||||
|
const onGroupChange = async () => {
|
||||||
|
// 加载公司列表
|
||||||
|
// if (value) {
|
||||||
|
try {
|
||||||
|
const res = await getCompanyList();
|
||||||
|
companyList.value = res.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
message.error("加载公司列表失败");
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 公司变化
|
||||||
|
const onCompanyChange = async () => {
|
||||||
|
// 加载流域列表
|
||||||
|
// if (value) {
|
||||||
|
try {
|
||||||
|
const res = await getBasinList();
|
||||||
|
basinList.value = res.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
message.error("加载流域列表失败");
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 流域变化
|
||||||
|
const onBasinChange = async (ids: any) => {
|
||||||
|
// 加载电站列表
|
||||||
|
// if (value) {
|
||||||
|
try {
|
||||||
|
const res = await getStationList(ids);
|
||||||
|
stationList.value = res.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
message.error("加载电站列表失败");
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== 流域变化处理(弹框内) ====================
|
||||||
|
const onRvcdChange = () => {
|
||||||
|
// 清空电站选择
|
||||||
|
organizationData.stationCode = [];
|
||||||
|
// 获取当前选中的所有流域ID,加载对应的电站列表
|
||||||
|
if (organizationData.rvcdCode && organizationData.rvcdCode.length > 0) {
|
||||||
|
onBasinChange({ hbrvcds: organizationData.rvcdCode });
|
||||||
|
} else {
|
||||||
|
// 如果没有选择流域,清空电站列表
|
||||||
|
stationList.value = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发送短信验证码
|
||||||
|
const handleSendSms = async () => {
|
||||||
|
// 验证手机号格式
|
||||||
|
if (!/^1[3-9]\d{9}$/.test(registerData.phone)) {
|
||||||
|
message.error("请输入正确的手机号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendSmsCode(registerData.phone, 1); // type=1 表示注册
|
||||||
|
message.success("验证码已发送");
|
||||||
|
|
||||||
|
// 启动60秒倒计时
|
||||||
|
smsCountdown.value = 60;
|
||||||
|
smsTimer = setInterval(() => {
|
||||||
|
smsCountdown.value--;
|
||||||
|
if (smsCountdown.value <= 0) {
|
||||||
|
clearInterval(smsTimer);
|
||||||
|
smsTimer = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} catch (error: any) {
|
||||||
|
message.error(error.message || "发送失败,请重试");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单验证通过后的处理
|
||||||
|
const handleFormFinish = async () => {
|
||||||
|
// 第一步:验证短信验证码
|
||||||
|
// const res: any = await verifySmsCode(registerData.phone, registerData.smsCode, 1);
|
||||||
|
// if (res.code == 1) {
|
||||||
|
// message.error('短信验证码错误,请重试')
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// 打开确认弹框
|
||||||
|
modalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 弹框取消
|
||||||
|
const handleModalCancel = () => {
|
||||||
|
// 关闭弹框,不做任何操作
|
||||||
|
modalVisible.value = false;
|
||||||
|
// 重置组织表单数据
|
||||||
|
organizationData.groupCode = '';
|
||||||
|
organizationData.companyCode = '';
|
||||||
|
organizationData.rvcdCode = [];
|
||||||
|
organizationData.stationCode = [];
|
||||||
|
// 清除表单验证状态
|
||||||
|
organizationFormRef.value?.clearValidate();
|
||||||
|
};
|
||||||
|
|
||||||
// 注册提交
|
// 注册提交
|
||||||
const onRegister = async () => {
|
const onRegister = async () => {
|
||||||
|
// 先验证组织表单
|
||||||
|
try {
|
||||||
|
await organizationFormRef.value.validate();
|
||||||
|
} catch (error) {
|
||||||
|
message.error("请完善组织信息");
|
||||||
|
return; // 验证失败,阻止提交
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 密码加密
|
|
||||||
|
// 第二步:密码加密
|
||||||
const encryptedPassword = encrypt(registerData.password);
|
const encryptedPassword = encrypt(registerData.password);
|
||||||
|
|
||||||
// 构造注册数据
|
// 第三步:构造注册数据(包含组织信息)
|
||||||
const registerParams = {
|
const registerParams: any = {
|
||||||
username: registerData.username,
|
type: 1, // 固定值:注册类型
|
||||||
realName: registerData.realName,
|
phone: registerData.phone, // 手机号(必填)
|
||||||
phone: registerData.phone,
|
code: registerData.smsCode, // 短信验证码(必填,字段改名)
|
||||||
password: encryptedPassword,
|
username: registerData.username, // 用户名(必填)
|
||||||
|
password: encryptedPassword, // 加密后的密码(必填)
|
||||||
// 系统字段
|
realName: registerData.realName, // 真实姓名(必填)
|
||||||
userType: 1,
|
|
||||||
status: 1,
|
|
||||||
regStatus: 0,
|
|
||||||
|
|
||||||
// 验证码相关
|
|
||||||
code: registerData.code,
|
|
||||||
uuid: registerData.uuid
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 调用注册接口
|
// 可选字段:所属单位(如果有值才传)
|
||||||
// await registerUser(registerParams);
|
if (registerData.belongingUnit) {
|
||||||
|
registerParams.belongingUnit = registerData.belongingUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选字段:集团(如果有值才传)
|
||||||
|
if (organizationData.groupCode) {
|
||||||
|
registerParams.groupCode = organizationData.groupCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选字段:公司(如果有值才传)
|
||||||
|
if (organizationData.companyCode) {
|
||||||
|
registerParams.companyCode = organizationData.companyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选字段:流域(如果有值才传,数组转逗号分隔字符串)
|
||||||
|
if (organizationData.rvcdCode && organizationData.rvcdCode.length > 0) {
|
||||||
|
registerParams.rvcdCode = organizationData.rvcdCode.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选字段:电站(如果有值才传,数组转逗号分隔字符串)
|
||||||
|
if (organizationData.stationCode && organizationData.stationCode.length > 0) {
|
||||||
|
registerParams.stationCode = organizationData.stationCode.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第四步:调用注册接口
|
||||||
|
const res1: any = await registerUser(registerParams);
|
||||||
|
if (res1.code == 1) {
|
||||||
|
message.error('注册失败,请重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
message.success("注册成功,等待管理员审核");
|
message.success("注册成功,等待管理员审核");
|
||||||
|
|
||||||
|
// 关闭弹框
|
||||||
|
modalVisible.value = false;
|
||||||
|
|
||||||
// 延迟跳转到登录页
|
// 延迟跳转到登录页
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.push({ path: "/login" });
|
router.push({ path: "/login-sjtb" });
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
message.error(error.message || "注册失败,请重试");
|
// 区分验证码错误和注册错误
|
||||||
// 刷新验证码
|
// if (error.message && error.message.includes('验证码')) {
|
||||||
refreshCaptcha();
|
// message.error("验证码错误,请重试");
|
||||||
|
// } else {
|
||||||
|
// message.error(error.message || "注册失败,请重试");
|
||||||
|
// }
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
@ -247,13 +561,28 @@ const onRegister = async () => {
|
|||||||
|
|
||||||
// 返回登录
|
// 返回登录
|
||||||
const backToLogin = () => {
|
const backToLogin = () => {
|
||||||
router.push({ path: "/login" });
|
router.push({ path: "/login-sjtb" });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化
|
// 组件挂载时加载集团列表
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
refreshCaptcha();
|
loadGroupList()
|
||||||
|
onGroupChange()
|
||||||
|
onCompanyChange()
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 组件卸载时清除定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (smsTimer) {
|
||||||
|
clearInterval(smsTimer);
|
||||||
|
smsTimer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const filterOption = (inputValue: string, option: any) => {
|
||||||
|
if (!option.label) return false;
|
||||||
|
return option.label.indexOf(inputValue) !== -1;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -262,7 +591,7 @@ onMounted(() => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-width: 1500px;
|
min-width: 1200px; // 降低最小宽度要求
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
.register-wrapper {
|
.register-wrapper {
|
||||||
@ -272,7 +601,8 @@ onMounted(() => {
|
|||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
background: url("@/assets/images/bg_sjtb.png");
|
background: url("@/assets/images/bg_sjtb.png");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: cover; // 改为cover以更好地适配不同尺寸
|
||||||
|
background-position: center; // 居中显示背景图
|
||||||
}
|
}
|
||||||
|
|
||||||
// 左侧背景区域
|
// 左侧背景区域
|
||||||
@ -280,45 +610,217 @@ onMounted(() => {
|
|||||||
.slogan {
|
.slogan {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20%;
|
top: 20%;
|
||||||
left: 18%;
|
left: 5%; // 减小左边距,更靠左
|
||||||
width: 700px;
|
width: 40vw; // 使用视口宽度百分比
|
||||||
height: 112px;
|
max-width: 700px; // 保持最大宽度限制
|
||||||
|
min-width: 300px; // 设置最小宽度
|
||||||
color: #040504;
|
color: #040504;
|
||||||
font-size: 40px;
|
font-size: clamp(24px, 3vw, 40px); // 响应式字体大小
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
word-wrap: break-word; // 允许长文本换行
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右侧注册卡片区域
|
// 右侧注册卡片区域
|
||||||
.right-section {
|
.right-section {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 70%;
|
right: 5%; // 改用right定位,更合理
|
||||||
top: 15%;
|
top: 50%; // 垂直居中
|
||||||
width: 25%;
|
transform: translateY(-50%); // 垂直居中对齐
|
||||||
// max-height: 650px;
|
width: clamp(380px, 30vw, 500px); // 响应式宽度
|
||||||
// max-width: 400px;
|
min-height: 600px; // 降低最小高度
|
||||||
min-height: 650px;
|
max-height: 90vh; // 限制最大高度为视口的90%
|
||||||
border-radius: 3px;
|
border-radius: 8px; // 稍微增大圆角
|
||||||
padding: 20px 24px 24px;
|
padding: clamp(15px, 2vw, 24px) clamp(15px, 2vw, 24px); // 响应式内边距
|
||||||
background-color: #fff;
|
background-color: rgba(255, 255, 255, 0.98); // 轻微透明效果
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); // 添加阴影提升层次感
|
||||||
|
|
||||||
|
// 自定义滚动条样式
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-tabs-nav) {
|
||||||
|
height: auto; // 自动高度
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单分区样式
|
||||||
|
.form-section {
|
||||||
|
margin-bottom: clamp(12px, 1.5vh, 20px); // 响应式间距
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: clamp(13px, 1.2vw, 15px); // 响应式字体
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: clamp(8px, 1vh, 12px);
|
||||||
|
padding-bottom: clamp(6px, 0.8vh, 10px);
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.ant-form-item) {
|
:deep(.ant-form-item) {
|
||||||
margin-bottom: 14px;
|
margin-bottom: clamp(10px, 1.2vh, 16px); // 响应式表单项间距
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-form-item-label > label) {
|
:deep(.ant-form-item-label) {
|
||||||
|
text-align: right !important;
|
||||||
|
|
||||||
|
>label {
|
||||||
|
font-size: clamp(12px, 1vw, 14px); // 响应式标签字体
|
||||||
|
color: #333;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input),
|
||||||
|
:deep(.ant-input-password) {
|
||||||
|
font-size: clamp(12px, 1vw, 14px); // 输入框字体响应式
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-btn) {
|
||||||
|
font-size: clamp(12px, 1vw, 14px); // 按钮字体响应式
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-radio-group) {
|
||||||
|
display: flex;
|
||||||
|
gap: clamp(12px, 1.5vw, 20px); // 响应式间距
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-form-item-control-input-content) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式媒体查询 - 小屏幕适配
|
||||||
|
@media (max-width: 1400px) {
|
||||||
|
.register-container {
|
||||||
|
.left-section {
|
||||||
|
.slogan {
|
||||||
|
left: 3%;
|
||||||
|
width: 45vw;
|
||||||
|
font-size: clamp(20px, 2.5vw, 32px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-section {
|
||||||
|
right: 3%;
|
||||||
|
width: clamp(350px, 35vw, 450px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中等屏幕适配
|
||||||
|
@media (min-width: 1401px) and (max-width: 1920px) {
|
||||||
|
.register-container {
|
||||||
|
.left-section {
|
||||||
|
.slogan {
|
||||||
|
left: 5%;
|
||||||
|
width: 40vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-section {
|
||||||
|
right: 5%;
|
||||||
|
width: clamp(380px, 30vw, 480px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 大屏幕适配
|
||||||
|
@media (min-width: 1921px) {
|
||||||
|
.register-container {
|
||||||
|
.left-section {
|
||||||
|
.slogan {
|
||||||
|
left: 8%;
|
||||||
|
width: 35vw;
|
||||||
|
font-size: clamp(32px, 3.5vw, 48px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-section {
|
||||||
|
right: 8%;
|
||||||
|
width: clamp(420px, 28vw, 550px);
|
||||||
|
padding: 24px 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超小屏幕适配
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.register-container {
|
||||||
|
.left-section {
|
||||||
|
.slogan {
|
||||||
|
display: none; // 小屏幕隐藏标语,聚焦表单
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-section {
|
||||||
|
left: 50%;
|
||||||
|
right: auto;
|
||||||
|
transform: translate(-50%, -50%); // 水平垂直都居中
|
||||||
|
width: clamp(320px, 90vw, 420px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 高缩放比例适配(125%、150%等)
|
||||||
|
@media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {
|
||||||
|
.register-container {
|
||||||
|
.right-section {
|
||||||
|
padding: clamp(12px, 1.5vw, 20px);
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
margin-bottom: clamp(10px, 1.2vh, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin-bottom: clamp(8px, 1vh, 14px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 横屏模式优化
|
||||||
|
@media (orientation: landscape) and (max-height: 700px) {
|
||||||
|
.register-container {
|
||||||
|
.right-section {
|
||||||
|
max-height: 95vh;
|
||||||
|
padding: 10px 15px;
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
padding-bottom: 6px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-form-item) {
|
||||||
:deep(.ant-input-prefix) {
|
margin-bottom: 8px;
|
||||||
display: flex;
|
|
||||||
width: 26px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1209
frontend/src/views/system/review/index.vue
Normal file
1209
frontend/src/views/system/review/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -282,57 +282,80 @@ const userId = ref('')
|
|||||||
// 回显的权限ID数组
|
// 回显的权限ID数组
|
||||||
const fishhui = ref<any[]>([])
|
const fishhui = ref<any[]>([])
|
||||||
const fishTreeDialog = ref(false)
|
const fishTreeDialog = ref(false)
|
||||||
function openFishway(row: any) {
|
|
||||||
|
// 添加标志位,标识数据是否已加载完成
|
||||||
|
const isFishDataLoaded = ref(false)
|
||||||
|
|
||||||
|
async function openFishway(row: any) {
|
||||||
fishway.value = true
|
fishway.value = true
|
||||||
userId.value = row.id
|
userId.value = row.id
|
||||||
// 临时模拟数据
|
|
||||||
getFishTree()
|
// 重置状态
|
||||||
// 打开对话框,watch 会处理回显逻辑
|
|
||||||
fishhui.value = []
|
fishhui.value = []
|
||||||
tableDatafish.value = []
|
tableDatafish.value = []
|
||||||
|
isFishDataLoaded.value = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 使用 Promise.all 并行等待两个请求都完成
|
||||||
|
await Promise.all([
|
||||||
|
getFishTree(), // 获取树形数据
|
||||||
getuserdata({ userId: userId.value }).then((res: any) => {
|
getuserdata({ userId: userId.value }).then((res: any) => {
|
||||||
console.log(res)
|
console.log('用户权限数据:', res)
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
res.data.forEach((item: any) => {
|
res.data.forEach((item: any) => {
|
||||||
fishhui.value.push(item.orgId)
|
fishhui.value.push(item.orgId)
|
||||||
tableDatafish.value.push({
|
tableDatafish.value.push({
|
||||||
name: item.orgName,
|
name: item.orgName,
|
||||||
type: item.orgType, // 默认类型为'站点'
|
type: item.orgType,
|
||||||
id: item.orgId.toString(), // 使用code作为id
|
id: item.orgId.toString(),
|
||||||
code: item.orgId,
|
code: item.orgId,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
userId: item.userId,
|
userId: item.userId,
|
||||||
parentId: item.parentId,
|
parentId: item.parentId,
|
||||||
orgLevel: item.orgLevel,
|
orgLevel: item.orgLevel,
|
||||||
permissionType: item.permissionType // 默认选择读权限
|
permissionType: item.permissionType
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
// 两个请求都完成后,标记数据已加载
|
||||||
|
isFishDataLoaded.value = true
|
||||||
|
console.log('所有数据加载完成,准备回显')
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据失败:', error)
|
||||||
|
ElMessage.error('加载数据失败,请重试')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听fishway对话框打开,延迟回显
|
// 监听fishway对话框打开,延迟回显
|
||||||
watch(fishway, (newVal) => {
|
watch([fishway, isFishDataLoaded], ([newFishway, newDataLoaded]) => {
|
||||||
if (newVal) {
|
if (newFishway && newDataLoaded) {
|
||||||
// dialog打开后,延迟回显确保tree组件完全渲染
|
// 确保两个数据都已加载完成后再执行回显
|
||||||
setTimeout(() => {
|
|
||||||
console.log('开始回显, fishTreeRef:', fishTreeRef.value);
|
console.log('开始回显, fishTreeRef:', fishTreeRef.value);
|
||||||
console.log('回显ID:', fishhui.value);
|
console.log('回显ID:', fishhui.value);
|
||||||
|
console.log('树数据:', fishData.value);
|
||||||
|
|
||||||
|
// 使用 nextTick 确保 DOM 已更新
|
||||||
|
nextTick(() => {
|
||||||
if (fishTreeRef.value && fishhui.value.length > 0) {
|
if (fishTreeRef.value && fishhui.value.length > 0) {
|
||||||
// 清除所有选中状态
|
// 清除所有选中状态
|
||||||
fishTreeRef.value.setCheckedKeys([], false);
|
fishTreeRef.value.setCheckedKeys([], false);
|
||||||
|
|
||||||
// 延迟一点再设置,确保清除生效
|
// 再设置新的选中状态
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fishTreeRef.value.setCheckedKeys(fishhui.value, false);
|
fishTreeRef.value.setCheckedKeys(fishhui.value, false);
|
||||||
|
|
||||||
// 验证回显结果
|
// 验证回显结果
|
||||||
const checkedKeys = fishTreeRef.value.getCheckedKeys();
|
const checkedKeys = fishTreeRef.value.getCheckedKeys();
|
||||||
const halfCheckedKeys = fishTreeRef.value.getHalfCheckedKeys();
|
const halfCheckedKeys = fishTreeRef.value.getHalfCheckedKeys();
|
||||||
console.log('回显完成 - 全选节点:', checkedKeys);
|
console.log('回显完成 - 全选节点:', checkedKeys);
|
||||||
console.log('回显完成 - 半选节点:', halfCheckedKeys);
|
console.log('回显完成 - 半选节点:', halfCheckedKeys);
|
||||||
|
|
||||||
|
// 同步表格数据
|
||||||
|
fishTableData.value = tableDatafish.value
|
||||||
}, 100);
|
}, 100);
|
||||||
} else if (fishTreeRef.value) {
|
} else if (fishTreeRef.value) {
|
||||||
// 如果fishhui.value为空,也需要清空表格数据
|
// 如果fishhui.value为空,也需要清空表格数据
|
||||||
@ -341,20 +364,12 @@ watch(fishway, (newVal) => {
|
|||||||
fishTableData.value = [];
|
fishTableData.value = [];
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
fishTableData.value = tableDatafish.value
|
});
|
||||||
// if (fishhui.value.length > 0 && activeName.value == '1') {
|
} else if (!newFishway) {
|
||||||
// isCompanyDisabled.value = true
|
|
||||||
// } else if (fishhui.value.length > 0 && activeName.value == '2') {
|
|
||||||
// isBaseDisabled.value = true
|
|
||||||
// } else {
|
|
||||||
// isCompanyDisabled.value = false
|
|
||||||
// isBaseDisabled.value = false
|
|
||||||
// }
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
// 关闭时清空回显数据
|
// 关闭时清空回显数据
|
||||||
console.log('关闭对话框,清理数据');
|
console.log('关闭对话框,清理数据');
|
||||||
fishhui.value = [];
|
fishhui.value = [];
|
||||||
|
isFishDataLoaded.value = false;
|
||||||
// 清除tree选中状态
|
// 清除tree选中状态
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (fishTreeRef.value) {
|
if (fishTreeRef.value) {
|
||||||
@ -367,6 +382,7 @@ watch(fishway, (newVal) => {
|
|||||||
|
|
||||||
function fishHandleClose() {
|
function fishHandleClose() {
|
||||||
fishway.value = false
|
fishway.value = false
|
||||||
|
isFishDataLoaded.value = false
|
||||||
fishTableData.value = []
|
fishTableData.value = []
|
||||||
fishData.value = []
|
fishData.value = []
|
||||||
}
|
}
|
||||||
@ -406,19 +422,21 @@ const fishData: any = ref([])
|
|||||||
//获取左侧树的数据
|
//获取左侧树的数据
|
||||||
// const huixiandata = ref([])
|
// const huixiandata = ref([])
|
||||||
let tableDatafish: any = []
|
let tableDatafish: any = []
|
||||||
|
// 修改为返回 Promise,便于外部等待
|
||||||
function getFishTree() {
|
function getFishTree() {
|
||||||
fishTreeDialog.value = true
|
fishTreeDialog.value = true
|
||||||
const params = {
|
const params = {
|
||||||
// type:'1',
|
// type:'1',
|
||||||
engName: treeInput.value
|
engName: treeInput.value
|
||||||
}
|
}
|
||||||
getFishtree(params).then((res: any) => {
|
return getFishtree(params).then((res: any) => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
fishData.value = res.data
|
fishData.value = res.data
|
||||||
}
|
|
||||||
})
|
|
||||||
fishTreeDialog.value = false
|
fishTreeDialog.value = false
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
fishTreeDialog.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过鱼设施权限维护 - 获取所有子节点ID的辅助函数
|
// 过鱼设施权限维护 - 获取所有子节点ID的辅助函数
|
||||||
@ -1000,7 +1018,7 @@ function handleClearSelection() {
|
|||||||
<!-- 过鱼设施权限维护 -->
|
<!-- 过鱼设施权限维护 -->
|
||||||
<el-dialog v-model="fishway" :close-on-click-modal="false" :before-close="fishHandleClose" title="过鱼设施权限维护"
|
<el-dialog v-model="fishway" :close-on-click-modal="false" :before-close="fishHandleClose" title="过鱼设施权限维护"
|
||||||
append-to-body width="1600px" draggable>
|
append-to-body width="1600px" draggable>
|
||||||
<el-scrollbar height="610px">
|
<!-- <el-scrollbar height="610px"> -->
|
||||||
<!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
<!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||||
<el-tab-pane label="基地" name="1" :disabled="isBaseDisabled"></el-tab-pane>
|
<el-tab-pane label="基地" name="1" :disabled="isBaseDisabled"></el-tab-pane>
|
||||||
<el-tab-pane label="公司" name="2" :disabled="isCompanyDisabled"></el-tab-pane>
|
<el-tab-pane label="公司" name="2" :disabled="isCompanyDisabled"></el-tab-pane>
|
||||||
@ -1021,9 +1039,9 @@ function handleClearSelection() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-scrollbar height="460px">
|
<el-scrollbar height="450px" style="margin-top: 10px;">
|
||||||
<el-tree ref="fishTreeRef" style="max-width: 300px" :data="fishData" show-checkbox default-expand-all
|
<el-tree ref="fishTreeRef" style="max-width: 300px" :data="fishData" show-checkbox default-expand-all
|
||||||
:v-loading="fishTreeDialog" node-key="code" highlight-current :props="fishProps"
|
v-loading="fishTreeDialog" node-key="code" highlight-current :props="fishProps"
|
||||||
@check="handleFishCheckChange" />
|
@check="handleFishCheckChange" />
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
@ -1053,7 +1071,7 @@ function handleClearSelection() {
|
|||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
<!-- </el-scrollbar> -->
|
||||||
<span class="dialog-footer"
|
<span class="dialog-footer"
|
||||||
style="display: flex;display: -webkit-flex; justify-content: flex-end;-webkit-justify-content: flex-end;margin-top: 20px;">
|
style="display: flex;display: -webkit-flex; justify-content: flex-end;-webkit-justify-content: flex-end;margin-top: 20px;">
|
||||||
<el-button @click="fishHandleClose">取 消</el-button>
|
<el-button @click="fishHandleClose">取 消</el-button>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user