海信医疗-远程超声管理平台-信创国产化
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

404 lines
12 KiB

3 weeks ago
<template>
<div class="login">
3 weeks ago
<!-- 左侧品牌栏 -->
<div class="login_left">
<div class="brand-box">
<!-- 内嵌SVG 超声探头图标 -->
<img src="@/assets/images/login-background.jpg" alt="Hisense Icon" />
<div>信联</div>
3 weeks ago
</div>
<!-- 底部波浪装饰 -->
<div class="wave-wrapper">
<div class="wave wave-1"></div>
<div class="wave wave-2"></div>
<div class="wave wave-3"></div>
<div class="wave wave-4"></div>
</div>
3 weeks ago
</div>
<!-- 右侧登录表单区 -->
<div class="login_right">
<div class="login_header">
<i class="el-icon-setting" @click="showSettingsDialog = true"></i>
<i class="el-icon-close" @click="handleClose"></i>
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<div class="form-header">
<div class="role-icon">
<img :src="$store.state.user.avatar" alt="" />
</div>
<h3 class="title">你好, {{ $store.state.user.userName }}</h3>
3 weeks ago
</div>
3 weeks ago
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="请输入账号"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="请输入密码"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" />
</div>
</el-form-item>
<el-form-item>
<el-checkbox v-model="loginForm.rememberMe"> 自动登录 </el-checkbox>
</el-form-item>
3 weeks ago
<el-form-item>
<el-button
:loading="loading"
type="primary"
3 weeks ago
style="width: 100%"
@click.native.prevent="handleLogin"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
</el-form-item>
</el-form>
3 weeks ago
</div>
3 weeks ago
<!-- 登录设置弹窗 -->
<el-dialog
title="登录设置"
:visible.sync="showSettingsDialog"
width="500px"
:close-on-click-modal="false"
>
<el-form :model="settingsForm" label-width="80px">
<el-form-item label="地址">
<el-input v-model="settingsForm.address" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="端口">
<el-input v-model="settingsForm.port" placeholder="请输入端口" />
</el-form-item>
<el-form-item label="协议">
<el-radio-group v-model="settingsForm.protocol">
<el-radio label="HTTP">HTTP</el-radio>
<el-radio label="HTTPS">HTTPS</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSettingsConfirm">
3 weeks ago
确定
</el-button>
<el-button @click="showSettingsDialog = false">取消</el-button>
</div>
</el-dialog>
3 weeks ago
</div>
</template>
<script>
3 weeks ago
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
3 weeks ago
export default {
name: "Login",
data() {
return {
3 weeks ago
// 角色信息
roleName: "会诊专家", // 示例:你好, 会诊专家
roleIconText: "家", // 示例:顶部圆形图标文字
3 weeks ago
codeUrl: "",
loginForm: {
3 weeks ago
username: "hzzjys",
password: "",
3 weeks ago
rememberMe: false,
code: "",
3 weeks ago
uuid: "",
3 weeks ago
},
loginRules: {
username: [
3 weeks ago
{ required: true, trigger: "blur", message: "请输入您的账号" },
3 weeks ago
],
password: [
3 weeks ago
{ required: true, trigger: "blur", message: "请输入您的密码" },
3 weeks ago
],
},
loading: false,
captchaEnabled: true,
3 weeks ago
redirect: undefined,
showSettingsDialog: false,
settingsForm: {
address: "47.92.192.91",
port: "8688",
protocol: "HTTP",
},
};
3 weeks ago
},
watch: {
$route: {
3 weeks ago
handler(route) {
this.redirect = route.query && route.query.redirect;
3 weeks ago
},
3 weeks ago
immediate: true,
},
3 weeks ago
},
created() {
3 weeks ago
this.getCode();
this.getCookie();
// 实际业务中,这里可以调用接口获取当前角色信息
// this.getRoleInfo();
3 weeks ago
},
methods: {
getCode() {
3 weeks ago
getCodeImg().then((res) => {
this.captchaEnabled =
res.captchaEnabled === undefined ? true : res.captchaEnabled;
3 weeks ago
if (this.captchaEnabled) {
3 weeks ago
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
3 weeks ago
}
3 weeks ago
});
3 weeks ago
},
getCookie() {
3 weeks ago
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get("rememberMe");
3 weeks ago
this.loginForm = {
username: username === undefined ? this.loginForm.username : username,
3 weeks ago
password:
password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
3 weeks ago
},
handleLogin() {
3 weeks ago
this.$refs.loginForm.validate((valid) => {
3 weeks ago
if (valid) {
3 weeks ago
this.loading = true;
3 weeks ago
if (this.loginForm.rememberMe) {
3 weeks ago
Cookies.set("username", this.loginForm.username, { expires: 30 });
Cookies.set("password", encrypt(this.loginForm.password), {
expires: 30,
});
Cookies.set("rememberMe", this.loginForm.rememberMe, {
expires: 30,
});
3 weeks ago
} else {
3 weeks ago
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
3 weeks ago
}
3 weeks ago
this.$store
.dispatch("Login", this.loginForm)
.then(() => {
this.$router.push({ path: this.redirect || "/" }).catch(() => {});
})
.catch(() => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
});
3 weeks ago
}
3 weeks ago
});
},
handleClose() {
window.close();
},
// 登录设置确定逻辑
handleSettingsConfirm() {
// 这里可以添加保存地址、端口、协议的逻辑
console.log("保存设置:", this.settingsForm);
this.showSettingsDialog = false;
},
},
};
3 weeks ago
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.login {
display: flex;
3 weeks ago
height: 100vh;
overflow: hidden;
/* 左侧品牌栏 */
.login_left {
flex: 0 0 33%; /* 按参考图比例:左侧约占1/3 */
background-color: #009696; /* 海信医疗主色调 */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
.brand-box {
text-align: center;
color: #fff;
z-index: 2;
.brand-logo {
font-size: 22px;
font-weight: bold;
margin-bottom: 8px;
}
}
/* 优化后的水波纹容器 */
.wave-wrapper {
3 weeks ago
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 1;
pointer-events: none;
}
/* 三层波浪:速度、透明度、大小区分明显 */
.wave {
position: absolute;
left: 0;
width: 200%;
height: 100%;
background-size: 100% auto;
background-repeat: no-repeat;
background-position: center bottom;
3 weeks ago
opacity: 0.3;
animation: waveUpDown 6s ease-in-out infinite alternate;
}
.wave-1 {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 320'%3E%3Cpath fill='%23ffffff' fill-opacity='0.2' d='M0,160L48,181.3C96,203,192,245,288,245.3C384,245,480,203,576,181.3C672,160,768,160,864,176C960,192,1056,224,1152,218.7C1248,213,1344,171,1392,149.3L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z'%3E%3C/path%3E%3C/svg%3E");
bottom: -10%;
height: 40%;
animation-duration: 7s;
opacity: 0.25;
}
.wave-2 {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 320'%3E%3Cpath fill='%23ffffff' fill-opacity='0.15' d='M0,224L48,213.3C96,203,192,181,288,186.7C384,192,480,224,576,229.3C672,235,768,213,864,192C960,171,1056,149,1152,160C1248,171,1344,213,1392,234.7L1440,256L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z'%3E%3C/path%3E%3C/svg%3E");
bottom: -5%;
height: 35%;
animation-duration: 5s;
opacity: 0.2;
}
.wave-3 {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 320'%3E%3Cpath fill='%23ffffff' fill-opacity='0.1' d='M0,256L48,240C96,224,192,192,288,197.3C384,203,480,245,576,240C672,235,768,181,864,160C960,139,1056,149,1152,170.7C1248,192,1344,224,1392,240L1440,256L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z'%3E%3C/path%3E%3C/svg%3E");
bottom: 0;
height: 30%;
animation-duration: 4s;
opacity: 0.15;
}
/* 波浪上下起伏动画,更柔和 */
@keyframes waveUpDown {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-15px);
}
3 weeks ago
}
}
3 weeks ago
/* 右侧登录区 */
.login_right {
flex: 1;
background: #fff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
padding: 20px;
box-sizing: border-box;
.login_header {
position: absolute;
top: 20px;
right: 20px;
display: flex;
gap: 16px;
.el-icon-setting,
.el-icon-close {
cursor: pointer;
font-size: 28px;
color: #666;
}
}
.login-form {
border-radius: 6px;
width: 100%;
max-width: 400px;
padding: 25px 25px 5px 25px;
z-index: 1;
.form-header {
text-align: center;
.role-icon {
width: 60px;
height: 60px;
line-height: 60px;
3 weeks ago
background-color: #ff9900; /* 橙色圆形图标 */
border-radius: 50%;
color: #fff;
margin: 0 auto 10px;
img {
width: 100%;
height: 100%;
}
3 weeks ago
}
.title {
margin: 0;
color: #333;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 2px;
color: #009696;
}
.login-code {
width: 33%;
height: 36px;
3 weeks ago
float: right;
img {
height: 36px;
3 weeks ago
cursor: pointer;
vertical-align: middle;
}
}
}
3 weeks ago
}
}
3 weeks ago
</style>