2026-04-27 11:57:26 +08:00
|
|
|
|
<template>
|
2026-04-28 18:28:44 +08:00
|
|
|
|
<div class="register-container">
|
|
|
|
|
|
<div class="register-wrapper">
|
|
|
|
|
|
<!-- 左侧:背景图区域 -->
|
|
|
|
|
|
<div class="left-section">
|
|
|
|
|
|
<div class="slogan">
|
|
|
|
|
|
<p>{{ $t("login.titleSjtb") }}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧:注册表单区域 -->
|
|
|
|
|
|
<div class="right-section">
|
|
|
|
|
|
<a-tabs v-model:activeKey="activeTab" class="register-tabs">
|
|
|
|
|
|
<a-tab-pane key="register" tab="用户注册">
|
|
|
|
|
|
<a-form :model="registerData" :rules="registerRules" layout="horizontal"
|
|
|
|
|
|
:label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" class="form-container"
|
|
|
|
|
|
@finish="handleFormFinish">
|
|
|
|
|
|
<!-- 账号信息 -->
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
<div class="section-title">账号信息</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 账号 -->
|
|
|
|
|
|
<a-form-item name="username" label="账 号">
|
|
|
|
|
|
<a-input v-model:value="registerData.username" placeholder="请输入登录账号(4-20个字符)" />
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 密码 -->
|
2026-04-29 11:28:47 +08:00
|
|
|
|
<a-form-item name="password" label="密 码" :dependencies="['username']">
|
2026-04-28 18:28:44 +08:00
|
|
|
|
<a-input-password v-model:value="registerData.password"
|
|
|
|
|
|
placeholder="请设置密码(6-20个字符)" />
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 确认密码 -->
|
|
|
|
|
|
<a-form-item name="confirmPassword" label="确认密码">
|
|
|
|
|
|
<a-input-password v-model:value="registerData.confirmPassword"
|
|
|
|
|
|
placeholder="请再次输入密码" />
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</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 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-col :span="16">
|
|
|
|
|
|
<a-input v-model:value="registerData.phone" placeholder="请输入11位手机号" />
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
<a-col :span="8">
|
|
|
|
|
|
<a-button type="primary" :disabled="smsCountdown > 0" @click="handleSendSms"
|
|
|
|
|
|
style="width: 100%">
|
|
|
|
|
|
{{ smsCountdown > 0 ? `${smsCountdown}s` : '获取验证码' }}
|
|
|
|
|
|
</a-button>
|
|
|
|
|
|
</a-col>
|
|
|
|
|
|
</a-row>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 短信验证码 -->
|
|
|
|
|
|
<a-form-item name="smsCode" label="验证码">
|
|
|
|
|
|
<a-input v-model:value="registerData.smsCode" placeholder="请输入短信验证码" />
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 注册按钮 -->
|
|
|
|
|
|
<a-form-item style="display: flex;align-items: center;justify-content: center;width: 100%;">
|
|
|
|
|
|
<a-button type="primary" size="large" block htmlType="submit" :loading="loading"
|
|
|
|
|
|
style="margin-left: 20px;">
|
|
|
|
|
|
<span>立即注册</span>
|
|
|
|
|
|
</a-button>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 返回登录 -->
|
|
|
|
|
|
<a-form-item style="display: flex;align-items: center;justify-content: center;width: 100%;">
|
|
|
|
|
|
|
|
|
|
|
|
<a-button type="link" size="small" block @click="backToLogin"
|
|
|
|
|
|
style="margin-left: 20px;">
|
|
|
|
|
|
已有账号?返回登录
|
|
|
|
|
|
</a-button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-form>
|
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
|
</a-tabs>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 注册确认弹框 -->
|
|
|
|
|
|
<a-modal v-model:open="modalVisible" title="选择所属组织" width="600px" :confirm-loading="loading"
|
2026-04-29 10:51:30 +08:00
|
|
|
|
@ok="onRegister" @cancel="handleModalCancel" :maskClosable="false">
|
2026-04-28 18:28:44 +08:00
|
|
|
|
<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%"
|
2026-04-29 10:51:30 +08:00
|
|
|
|
show-search :filter-option="filterOption" @change="onGroupChange">
|
|
|
|
|
|
<a-select-option v-for="item in groupList" :key="item.hycd" :value="item.hycd"
|
|
|
|
|
|
:label="item.hynm">
|
2026-04-28 18:28:44 +08:00
|
|
|
|
{{ 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>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 流域(多选,数组,必填) -->
|
2026-04-30 17:40:40 +08:00
|
|
|
|
<a-form-item name="hbrvcdCode" label="流 域" required>
|
|
|
|
|
|
<a-select v-model:value="organizationData.hbrvcdCode" mode="multiple" placeholder="请选择流域"
|
2026-04-28 18:28:44 +08:00
|
|
|
|
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="请先选择流域"
|
2026-04-30 17:40:40 +08:00
|
|
|
|
:disabled="organizationData.hbrvcdCode.length === 0" style="width: 100%" show-search
|
2026-04-28 18:28:44 +08:00
|
|
|
|
: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>
|
2026-04-27 11:57:26 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-04-28 18:28:44 +08:00
|
|
|
|
import { reactive, ref, onMounted, onUnmounted } from "vue";
|
|
|
|
|
|
import {
|
|
|
|
|
|
getBasinList,
|
|
|
|
|
|
getGroupList,
|
|
|
|
|
|
getCompanyList,
|
|
|
|
|
|
getStationList,
|
|
|
|
|
|
sendSmsCode,
|
|
|
|
|
|
verifySmsCode,
|
|
|
|
|
|
registerUser
|
|
|
|
|
|
} from "@/api/auth";
|
2026-04-27 11:57:26 +08:00
|
|
|
|
import { message } from "ant-design-vue";
|
|
|
|
|
|
import router from "@/router";
|
|
|
|
|
|
import { encrypt } from "@/utils/rsaEncrypt";
|
|
|
|
|
|
|
|
|
|
|
|
// 注册表单数据
|
|
|
|
|
|
const registerData = reactive({
|
2026-04-28 18:28:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 用户信息
|
|
|
|
|
|
username: "",
|
|
|
|
|
|
password: "",
|
|
|
|
|
|
confirmPassword: "",
|
|
|
|
|
|
realName: "",
|
|
|
|
|
|
belongingUnit: "",
|
|
|
|
|
|
phone: "",
|
|
|
|
|
|
smsCode: "",
|
2026-04-27 11:57:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 下拉选项数据
|
|
|
|
|
|
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: '', // 公司(单选,字符串)
|
2026-04-30 17:40:40 +08:00
|
|
|
|
hbrvcdCode: [], // 流域(多选,数组)
|
2026-04-28 18:28:44 +08:00
|
|
|
|
stationCode: [] // 电站(多选,数组)
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 组织表单引用
|
|
|
|
|
|
const organizationFormRef = ref();
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 组织表单验证规则 ====================
|
|
|
|
|
|
const organizationRules = {
|
2026-04-30 17:40:40 +08:00
|
|
|
|
hbrvcdCode: [
|
2026-04-28 18:28:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
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"
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-27 11:57:26 +08:00
|
|
|
|
// 表单验证规则
|
|
|
|
|
|
const registerRules = {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 登录账号
|
|
|
|
|
|
username: [
|
|
|
|
|
|
{ required: true, message: "请输入登录账号", trigger: "blur" },
|
|
|
|
|
|
{ min: 4, max: 20, message: "账号长度4-20个字符", trigger: "blur" },
|
|
|
|
|
|
{ pattern: /^[a-zA-Z0-9_]+$/, message: "只能包含字母、数字和下划线", trigger: "blur" }
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
// 密码
|
|
|
|
|
|
password: [
|
|
|
|
|
|
{
|
|
|
|
|
|
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. 用户名关联检查(严格模式,忽略大小写)
|
2026-04-29 11:28:47 +08:00
|
|
|
|
// 4.0 先判断用户名是否为空,若为空则跳过该检查
|
|
|
|
|
|
const username = registerData.username;
|
|
|
|
|
|
if (!username || username.trim() === '') {
|
|
|
|
|
|
// 用户名为空,跳过用户名关联检查
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const usernameLower = username.toLowerCase();
|
2026-04-28 18:28:44 +08:00
|
|
|
|
const passwordLower = value.toLowerCase();
|
|
|
|
|
|
|
|
|
|
|
|
// 4.1 检查密码是否完整包含用户名
|
2026-04-29 11:28:47 +08:00
|
|
|
|
if (passwordLower.includes(usernameLower)) {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
return Promise.reject("密码不能包含用户名");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4.2 提取密码中的字母部分
|
|
|
|
|
|
const passwordLetters = passwordLower.replace(/[^a-z]/g, '');
|
|
|
|
|
|
|
|
|
|
|
|
// 4.3 如果密码字母部分长度 >= 3,检查是否是用户名的子串
|
2026-04-29 11:28:47 +08:00
|
|
|
|
if (passwordLetters.length >= 3 && usernameLower.includes(passwordLetters)) {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
return Promise.reject("密码的字母部分不能是用户名的子串");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4.4 检查用户名中是否包含密码的任意连续3位字母
|
|
|
|
|
|
for (let i = 0; i <= passwordLetters.length - 3; i++) {
|
|
|
|
|
|
const substring = passwordLetters.substring(i, i + 3);
|
2026-04-29 11:28:47 +08:00
|
|
|
|
if (usernameLower.includes(substring)) {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
return Promise.reject("密码不能与用户名存在明显关联");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
trigger: "blur"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
// 确认密码
|
|
|
|
|
|
confirmPassword: [
|
|
|
|
|
|
{ required: true, message: "请再次输入密码", trigger: "blur" },
|
|
|
|
|
|
{
|
|
|
|
|
|
validator: (rule: any, value: string) => {
|
|
|
|
|
|
if (value && value !== registerData.password) {
|
|
|
|
|
|
return Promise.reject("两次输入的密码不一致");
|
|
|
|
|
|
}
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
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" }
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
// 短信验证码
|
|
|
|
|
|
smsCode: [
|
|
|
|
|
|
{ required: true, message: "请输入短信验证码", trigger: "blur" },
|
|
|
|
|
|
{ len: 6, message: "验证码为6位数字", trigger: "blur" }
|
|
|
|
|
|
]
|
2026-04-27 11:57:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
const activeTab = ref("register");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
const modalVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化加载集团列表
|
|
|
|
|
|
const loadGroupList = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getGroupList();
|
|
|
|
|
|
groupList.value = res.data || [];
|
|
|
|
|
|
} catch (error) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// console.error("加载集团列表失败", error);
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-04-27 11:57:26 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 集团变化
|
|
|
|
|
|
const onGroupChange = async () => {
|
|
|
|
|
|
// 加载公司列表
|
|
|
|
|
|
// if (value) {
|
|
|
|
|
|
try {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// const res = await getCompanyList(organizationData.groupCode ? organizationData.groupCode : '');
|
2026-04-28 18:28:44 +08:00
|
|
|
|
const res = await getCompanyList();
|
|
|
|
|
|
companyList.value = res.data || [];
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
} catch (error) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// message.error("加载公司列表失败");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 公司变化
|
|
|
|
|
|
const onCompanyChange = async () => {
|
|
|
|
|
|
// 加载流域列表
|
|
|
|
|
|
// if (value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getBasinList();
|
|
|
|
|
|
basinList.value = res.data || [];
|
|
|
|
|
|
} catch (error) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// message.error("加载流域列表失败");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 流域变化
|
|
|
|
|
|
const onBasinChange = async (ids: any) => {
|
|
|
|
|
|
// 加载电站列表
|
|
|
|
|
|
// if (value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getStationList(ids);
|
|
|
|
|
|
stationList.value = res.data || [];
|
|
|
|
|
|
} catch (error) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// message.error("加载电站列表失败");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
// }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 流域变化处理(弹框内) ====================
|
|
|
|
|
|
const onRvcdChange = () => {
|
|
|
|
|
|
// 清空电站选择
|
|
|
|
|
|
organizationData.stationCode = [];
|
|
|
|
|
|
// 获取当前选中的所有流域ID,加载对应的电站列表
|
2026-04-30 17:40:40 +08:00
|
|
|
|
if (organizationData.hbrvcdCode && organizationData.hbrvcdCode.length > 0) {
|
|
|
|
|
|
onBasinChange({ hbrvcds: organizationData.hbrvcdCode });
|
2026-04-28 18:28:44 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 如果没有选择流域,清空电站列表
|
|
|
|
|
|
stationList.value = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 发送短信验证码
|
|
|
|
|
|
const handleSendSms = async () => {
|
|
|
|
|
|
// 验证手机号格式
|
|
|
|
|
|
if (!/^1[3-9]\d{9}$/.test(registerData.phone)) {
|
|
|
|
|
|
message.error("请输入正确的手机号");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-04-30 15:22:52 +08:00
|
|
|
|
const res:any = await sendSmsCode(registerData.phone, 1); // type=1 表示注册
|
|
|
|
|
|
if (res.code == 1) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-04-28 18:28:44 +08:00
|
|
|
|
message.success("验证码已发送");
|
|
|
|
|
|
|
|
|
|
|
|
// 启动60秒倒计时
|
|
|
|
|
|
smsCountdown.value = 60;
|
|
|
|
|
|
smsTimer = setInterval(() => {
|
|
|
|
|
|
smsCountdown.value--;
|
|
|
|
|
|
if (smsCountdown.value <= 0) {
|
|
|
|
|
|
clearInterval(smsTimer);
|
|
|
|
|
|
smsTimer = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
} catch (error: any) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// message.error(error.message || "发送失败,请重试");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 表单验证通过后的处理
|
|
|
|
|
|
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 = '';
|
2026-04-30 17:40:40 +08:00
|
|
|
|
organizationData.hbrvcdCode = [];
|
2026-04-28 18:28:44 +08:00
|
|
|
|
organizationData.stationCode = [];
|
|
|
|
|
|
// 清除表单验证状态
|
|
|
|
|
|
organizationFormRef.value?.clearValidate();
|
2026-04-27 11:57:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 注册提交
|
|
|
|
|
|
const onRegister = async () => {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 先验证组织表单
|
|
|
|
|
|
try {
|
|
|
|
|
|
await organizationFormRef.value.validate();
|
|
|
|
|
|
} catch (error) {
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// message.error("请完善组织信息");
|
2026-04-28 18:28:44 +08:00
|
|
|
|
return; // 验证失败,阻止提交
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:密码加密
|
|
|
|
|
|
const encryptedPassword = encrypt(registerData.password);
|
|
|
|
|
|
|
|
|
|
|
|
// 第三步:构造注册数据(包含组织信息)
|
|
|
|
|
|
const registerParams: any = {
|
|
|
|
|
|
type: 1, // 固定值:注册类型
|
|
|
|
|
|
phone: registerData.phone, // 手机号(必填)
|
|
|
|
|
|
code: registerData.smsCode, // 短信验证码(必填,字段改名)
|
|
|
|
|
|
username: registerData.username, // 用户名(必填)
|
|
|
|
|
|
password: encryptedPassword, // 加密后的密码(必填)
|
|
|
|
|
|
realName: registerData.realName, // 真实姓名(必填)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 可选字段:所属单位(如果有值才传)
|
|
|
|
|
|
if (registerData.belongingUnit) {
|
|
|
|
|
|
registerParams.belongingUnit = registerData.belongingUnit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可选字段:集团(如果有值才传)
|
|
|
|
|
|
if (organizationData.groupCode) {
|
|
|
|
|
|
registerParams.groupCode = organizationData.groupCode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可选字段:公司(如果有值才传)
|
|
|
|
|
|
if (organizationData.companyCode) {
|
|
|
|
|
|
registerParams.companyCode = organizationData.companyCode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可选字段:流域(如果有值才传,数组转逗号分隔字符串)
|
2026-04-30 17:40:40 +08:00
|
|
|
|
if (organizationData.hbrvcdCode && organizationData.hbrvcdCode.length > 0) {
|
|
|
|
|
|
registerParams.hbrvcdCode = organizationData.hbrvcdCode.join(',');
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可选字段:电站(如果有值才传,数组转逗号分隔字符串)
|
|
|
|
|
|
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("注册成功,等待管理员审核");
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭弹框
|
|
|
|
|
|
modalVisible.value = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟跳转到登录页
|
|
|
|
|
|
setTimeout(() => {
|
2026-05-05 22:38:24 +08:00
|
|
|
|
router.push({ path: "/login" });
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}, 1500);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
|
// 区分验证码错误和注册错误
|
|
|
|
|
|
// if (error.message && error.message.includes('验证码')) {
|
|
|
|
|
|
// message.error("验证码错误,请重试");
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// message.error(error.message || "注册失败,请重试");
|
|
|
|
|
|
// }
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false;
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 返回登录
|
|
|
|
|
|
const backToLogin = () => {
|
2026-05-05 22:38:24 +08:00
|
|
|
|
router.push({ path: "/login" });
|
2026-04-27 11:57:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 组件挂载时加载集团列表
|
2026-04-27 11:57:26 +08:00
|
|
|
|
onMounted(() => {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
loadGroupList()
|
|
|
|
|
|
onGroupChange()
|
|
|
|
|
|
onCompanyChange()
|
2026-04-29 10:51:30 +08:00
|
|
|
|
// modalVisible.value = true
|
2026-04-28 18:28:44 +08:00
|
|
|
|
|
2026-04-27 11:57:26 +08:00
|
|
|
|
});
|
2026-04-28 18:28:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 组件卸载时清除定时器
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
if (smsTimer) {
|
|
|
|
|
|
clearInterval(smsTimer);
|
|
|
|
|
|
smsTimer = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
const filterOption = (inputValue: string, option: any) => {
|
|
|
|
|
|
if (!option.label) return false;
|
|
|
|
|
|
return option.label.indexOf(inputValue) !== -1;
|
|
|
|
|
|
};
|
2026-04-27 11:57:26 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.register-container {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
margin: 0 auto;
|
2026-04-27 11:57:26 +08:00
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2026-04-28 18:28:44 +08:00
|
|
|
|
min-width: 1200px; // 降低最小宽度要求
|
2026-04-27 11:57:26 +08:00
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.register-wrapper {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
min-height: 600px;
|
|
|
|
|
|
background: url("@/assets/images/bg_sjtb.png");
|
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
background-size: cover; // 改为cover以更好地适配不同尺寸
|
|
|
|
|
|
background-position: center; // 居中显示背景图
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 左侧背景区域
|
|
|
|
|
|
.left-section {
|
|
|
|
|
|
.slogan {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 20%;
|
|
|
|
|
|
left: 5%; // 减小左边距,更靠左
|
|
|
|
|
|
width: 40vw; // 使用视口宽度百分比
|
|
|
|
|
|
max-width: 700px; // 保持最大宽度限制
|
|
|
|
|
|
min-width: 300px; // 设置最小宽度
|
|
|
|
|
|
color: #040504;
|
|
|
|
|
|
font-size: clamp(24px, 3vw, 40px); // 响应式字体大小
|
|
|
|
|
|
line-height: 1.5;
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
word-wrap: break-word; // 允许长文本换行
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 右侧注册卡片区域
|
|
|
|
|
|
.right-section {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 5%; // 改用right定位,更合理
|
|
|
|
|
|
top: 50%; // 垂直居中
|
|
|
|
|
|
transform: translateY(-50%); // 垂直居中对齐
|
|
|
|
|
|
width: clamp(380px, 30vw, 500px); // 响应式宽度
|
|
|
|
|
|
min-height: 600px; // 降低最小高度
|
|
|
|
|
|
max-height: 90vh; // 限制最大高度为视口的90%
|
|
|
|
|
|
border-radius: 8px; // 稍微增大圆角
|
|
|
|
|
|
padding: clamp(15px, 2vw, 24px) clamp(15px, 2vw, 24px); // 响应式内边距
|
|
|
|
|
|
background-color: rgba(255, 255, 255, 0.98); // 轻微透明效果
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); // 添加阴影提升层次感
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义滚动条样式
|
|
|
|
|
|
&::-webkit-scrollbar {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
}
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
&::-webkit-scrollbar-thumb {
|
|
|
|
|
|
background-color: rgba(0, 0, 0, 0.2);
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
}
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
&::-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) {
|
|
|
|
|
|
margin-bottom: clamp(10px, 1.2vh, 16px); // 响应式表单项间距
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
: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;
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
}
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 响应式媒体查询 - 小屏幕适配
|
|
|
|
|
|
@media (max-width: 1400px) {
|
|
|
|
|
|
.register-container {
|
|
|
|
|
|
.left-section {
|
|
|
|
|
|
.slogan {
|
|
|
|
|
|
left: 3%;
|
|
|
|
|
|
width: 45vw;
|
|
|
|
|
|
font-size: clamp(20px, 2.5vw, 32px);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.right-section {
|
|
|
|
|
|
right: 3%;
|
|
|
|
|
|
width: clamp(350px, 35vw, 450px);
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
}
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
// 中等屏幕适配
|
|
|
|
|
|
@media (min-width: 1401px) and (max-width: 1920px) {
|
|
|
|
|
|
.register-container {
|
|
|
|
|
|
.left-section {
|
|
|
|
|
|
.slogan {
|
|
|
|
|
|
left: 5%;
|
|
|
|
|
|
width: 40vw;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.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; // 小屏幕隐藏标语,聚焦表单
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.right-section {
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
right: auto;
|
|
|
|
|
|
transform: translate(-50%, -50%); // 水平垂直都居中
|
|
|
|
|
|
width: clamp(320px, 90vw, 420px);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 高缩放比例适配(125%、150%等)
|
2026-04-29 10:51:30 +08:00
|
|
|
|
@media (-webkit-min-device-pixel-ratio: 1.25),
|
|
|
|
|
|
(min-resolution: 120dpi) {
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.register-container {
|
|
|
|
|
|
.right-section {
|
|
|
|
|
|
padding: clamp(12px, 1.5vw, 20px);
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.form-section {
|
|
|
|
|
|
margin-bottom: clamp(10px, 1.2vh, 16px);
|
|
|
|
|
|
}
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
:deep(.ant-form-item) {
|
2026-04-29 11:28:47 +08:00
|
|
|
|
margin-bottom: 8px;
|
2026-04-28 18:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 横屏模式优化
|
|
|
|
|
|
@media (orientation: landscape) and (max-height: 700px) {
|
|
|
|
|
|
.register-container {
|
|
|
|
|
|
.right-section {
|
|
|
|
|
|
max-height: 95vh;
|
|
|
|
|
|
padding: 10px 15px;
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.form-section {
|
|
|
|
|
|
margin-bottom: 8px;
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
.section-title {
|
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
|
padding-bottom: 6px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-29 10:51:30 +08:00
|
|
|
|
|
2026-04-28 18:28:44 +08:00
|
|
|
|
:deep(.ant-form-item) {
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-27 11:57:26 +08:00
|
|
|
|
}
|
2026-04-29 11:28:47 +08:00
|
|
|
|
}</style>
|