feat(login): CASSIC 红金风登录页 + 玻璃按钮欢迎页
需求:
1. 默认访问 /metalinfo 未登录时跳到 CASSIC 风格登录页
2. 登录页支持两种模式: 账号密码登录 / 统一身份登录(CAS)
3. 登录成功跳转 /welcome (原蓝色登录页布局,但右侧表单换成玻璃风"立即体验"按钮)
变更:
- 新增 chat_web_front/src/views/welcome/index.vue
- 复用现有蓝色 Waves + projectLogo + "聚尖端之力" 文案
- 玻璃磨砂按钮(backdrop-filter blur),圆角胶囊 + 圆形箭头
- 点击 → router.push('/chat')
- 重写 chat_web_front/src/views/login/index.vue
- CASSIC 红金背景图(cassicLoginBg.jpg, 1920x1080 by /Users/jayliu/gangyan/ui)
- "登录注册中心" 标题 + 红色短分隔条
- 账号/密码/验证码 三段式表单 (el-icon User/Lock/Stamp)
- "短信验证登录" 链接切换到 SMS 模式
- 主红登录按钮 + 次级"统一身份登录(CASSIC)"白底红边按钮
- 登录成功后 router.push('/welcome')
- CAS 回调 cas_token 处理保留
- chat_web_front/src/router/index.ts:
- / → 默认重定向改为 /welcome (原来到 /chat)
- 新增 /welcome 路由
- 复制 ui/微信图片_20260423163044_262_1531.jpg 到
src/assets/images/login/cassicLoginBg.jpg
未做:
- SMS 验证码后端接口 (loginByTel) 仅留前端倒计时占位
- 图形验证码后端 (showCaptcha 默认关)
- 老素材 loginBg.png 仍由 welcome 页使用,未删
测试:
- 访问 /metalinfo → 未登录跳 /login (CASSIC 红金)
- 账号密码登录 / CAS 登录 → 跳 /welcome
- /welcome 点"立即体验" → /chat
This commit is contained in:
BIN
chat_web_front/src/assets/images/login/cassicLoginBg.jpg
Normal file
BIN
chat_web_front/src/assets/images/login/cassicLoginBg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -7,13 +7,18 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: '/',
|
name: '/',
|
||||||
redirect: '/chat'
|
redirect: '/welcome'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
component: () => import('@/views/login/index.vue'),
|
component: () => import('@/views/login/index.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/welcome',
|
||||||
|
name: 'Welcome',
|
||||||
|
component: () => import('@/views/welcome/index.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/chat',
|
path: '/chat',
|
||||||
name: 'Chat',
|
name: 'Chat',
|
||||||
|
|||||||
@@ -1,215 +1,351 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="loginPage">
|
<div class="cassicLogin">
|
||||||
<Waves></Waves>
|
<!-- 背景:CASSIC logo + 红金渐变 + 波纹粒子(图片直接做底) -->
|
||||||
<div>
|
<div class="bgImage"></div>
|
||||||
<img :src="projectLogo" alt="" class="loginLogo" />
|
|
||||||
</div>
|
<!-- 中央登录卡 -->
|
||||||
<div class="loginContent">
|
<div class="loginCard">
|
||||||
<div class="loginTitle">
|
<h2 class="title">登录注册中心</h2>
|
||||||
<div>
|
<div class="titleBar"></div>
|
||||||
聚尖端之力,创多维平台
|
|
||||||
<br />
|
|
||||||
<span class="loginInfo">
|
|
||||||
聚合科技动能,扩展创新疆界,引领行业跃迁升级
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="loginOperate">
|
|
||||||
<img
|
|
||||||
:src="projectLogo2"
|
|
||||||
class="logoImg"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<el-form
|
<el-form
|
||||||
ref="ruleFormRef"
|
ref="formRef"
|
||||||
label-position="top"
|
:model="form"
|
||||||
label-width="auto"
|
|
||||||
:model="ruleForm"
|
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
style="width: 20vw; margin-top: 5%"
|
|
||||||
hide-required-asterisk
|
hide-required-asterisk
|
||||||
|
class="form"
|
||||||
|
@submit.prevent
|
||||||
>
|
>
|
||||||
<el-form-item label="手机号" prop="tel">
|
<!-- 账号 -->
|
||||||
<el-input v-model.trim="ruleForm.tel" />
|
<el-form-item prop="tel">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item label="密码" prop="password">
|
v-model.trim="form.tel"
|
||||||
<el-input v-model.trim="ruleForm.password" show-password />
|
:placeholder="loginMode === 'sms' ? '请输入手机号' : '请输入账号'"
|
||||||
</el-form-item>
|
size="large"
|
||||||
<el-form-item prop="checked">
|
|
||||||
<el-checkbox v-model="ruleForm.checked" label="" size="large" />
|
|
||||||
<span
|
|
||||||
>勾选即代表您阅读并同意<a
|
|
||||||
target="_blank"
|
|
||||||
href="http://www.metalinfo.cn/agreement.html?pageId=c03923c64e6b4d0896488212054b1742"
|
|
||||||
style="color: #0969da"
|
|
||||||
>《用户协议》</a
|
|
||||||
></span
|
|
||||||
>
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<span class="iconBox"><el-icon><User /></el-icon></span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
|
||||||
|
<!-- 密码 -->
|
||||||
|
<el-form-item v-if="loginMode === 'password'" prop="password">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="form.password"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
size="large"
|
||||||
|
show-password
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<span class="iconBox"><el-icon><Lock /></el-icon></span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 验证码(图形 / 短信) -->
|
||||||
|
<el-form-item prop="captcha" v-if="loginMode === 'sms' || showCaptcha">
|
||||||
|
<div class="captchaRow">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="form.captcha"
|
||||||
|
:placeholder="loginMode === 'sms' ? '请输入短信验证码' : '请输入验证码'"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<span class="iconBox"><el-icon><Stamp /></el-icon></span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="captchaBtn"
|
||||||
|
:disabled="smsCountdown > 0"
|
||||||
|
@click="handleCaptcha"
|
||||||
|
>
|
||||||
|
{{ smsCountdown > 0 ? `${smsCountdown}s` : (loginMode === 'sms' ? '获取验证码' : '看不清') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 切换模式 -->
|
||||||
|
<div class="switchModeRow">
|
||||||
|
<a class="modeLink" @click="toggleMode">
|
||||||
|
{{ loginMode === 'password' ? '短信验证登录' : '账号密码登录' }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主登录按钮 -->
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
class="primaryBtn"
|
||||||
style="width: 100%; margin-top: 20px"
|
:loading="submitting"
|
||||||
@click="submitForm(ruleFormRef)"
|
@click="handleSubmit"
|
||||||
:disabled="isDisabled"
|
|
||||||
>
|
>
|
||||||
{{ loginTip }}
|
登 录
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<!-- 统一身份登录 -->
|
||||||
<el-button
|
<el-button class="casBtn" @click="goCasLogin">
|
||||||
style="width: 100%; background: #FF2500; color: #fff; border-color: #FF2500;"
|
统一身份登录(CASSIC)
|
||||||
@click="goCasLogin"
|
|
||||||
>
|
|
||||||
通过统一身份登录
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang='ts'>
|
|
||||||
import { computed, ref, onMounted, reactive } from "vue";
|
<script setup lang="ts">
|
||||||
import projectLogo from "@/assets/images/login/projectLogo-white.svg";
|
import { onMounted, reactive, ref } from "vue";
|
||||||
import projectLogo2 from "@/assets/images/login/projectLogo.svg";
|
import { useRouter } from "vue-router";
|
||||||
import type { FormInstance, FormRules } from "element-plus";
|
import type { FormInstance, FormRules } from "element-plus";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { User, Lock, Stamp } from "@element-plus/icons-vue";
|
||||||
import { fetchVerify } from "@/api";
|
import { fetchVerify } from "@/api";
|
||||||
import { useAuthStore } from "@/store";
|
import { useAuthStore } from "@/store";
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import Waves from "../../components/Waves.vue";
|
|
||||||
|
|
||||||
interface RuleForm {
|
interface LoginForm {
|
||||||
tel: string;
|
tel: string;
|
||||||
password: string;
|
password: string;
|
||||||
checked: boolean;
|
captcha: string;
|
||||||
loginType: number;
|
loginType: number;
|
||||||
}
|
}
|
||||||
interface Token {
|
|
||||||
token: string;
|
const form = reactive<LoginForm>({
|
||||||
refreshToken: string;
|
|
||||||
expiresIn: number;
|
|
||||||
}
|
|
||||||
const ruleForm = reactive<RuleForm>({
|
|
||||||
tel: "",
|
tel: "",
|
||||||
password: "",
|
password: "",
|
||||||
checked: true,
|
captcha: "",
|
||||||
loginType: 3,
|
loginType: 3,
|
||||||
});
|
});
|
||||||
const ruleFormRef = ref<FormInstance>();
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
const router = useRouter();
|
|
||||||
const isDisabled = ref<Boolean>(false);
|
|
||||||
const loginTip = ref<string>("登录");
|
|
||||||
|
|
||||||
const validateChecked = (rule: any, value: any, callback: any) => {
|
const formRef = ref<FormInstance>();
|
||||||
if (!value) {
|
const router = useRouter();
|
||||||
callback(new Error("请勾选“用户协议”"));
|
const authStore = useAuthStore();
|
||||||
} else {
|
const submitting = ref(false);
|
||||||
callback();
|
const loginMode = ref<"password" | "sms">("password"); // password = 账号密码登录;sms = 短信验证登录
|
||||||
}
|
const showCaptcha = ref(false); // 账号密码模式下,可选图形验证码(暂未启用,留位)
|
||||||
};
|
const smsCountdown = ref(0);
|
||||||
const rules = reactive<FormRules<RuleForm>>({
|
|
||||||
tel: [{ required: true, message: "请输入手机号", trigger: "blur" }],
|
const rules = reactive<FormRules<LoginForm>>({
|
||||||
|
tel: [{ required: true, message: "请输入账号 / 手机号", trigger: "blur" }],
|
||||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||||
checked: {
|
|
||||||
required: true,
|
|
||||||
message: "请勾选“用户协议”",
|
|
||||||
trigger: "blur",
|
|
||||||
validator: validateChecked,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const submitForm = async (formEl: FormInstance | undefined) => {
|
|
||||||
if (!formEl) return;
|
const toggleMode = () => {
|
||||||
await formEl.validate((valid, fields) => {
|
loginMode.value = loginMode.value === "password" ? "sms" : "password";
|
||||||
if (valid) {
|
form.captcha = "";
|
||||||
isDisabled.value = true;
|
|
||||||
loginTip.value = "登录中...";
|
|
||||||
handleVerify();
|
|
||||||
} else {
|
|
||||||
console.log("error submit!", fields);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
const handleVerify = async () => {
|
|
||||||
|
let countdownTimer: number | null = null;
|
||||||
|
const handleCaptcha = () => {
|
||||||
|
if (loginMode.value === "sms") {
|
||||||
|
if (!form.tel) {
|
||||||
|
ElMessage.warning("请先输入手机号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 触发短信发送(后端接口待联调;先做倒计时占位)
|
||||||
|
smsCountdown.value = 60;
|
||||||
|
countdownTimer = window.setInterval(() => {
|
||||||
|
smsCountdown.value -= 1;
|
||||||
|
if (smsCountdown.value <= 0 && countdownTimer) {
|
||||||
|
clearInterval(countdownTimer);
|
||||||
|
countdownTimer = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
ElMessage.info("短信验证码功能尚未接入后端,先用账号密码模式登录");
|
||||||
|
} else {
|
||||||
|
ElMessage.info("图形验证码暂未启用");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
await formRef.value.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
fetchVerify<Token>(ruleForm).then((res) => {
|
const res = await fetchVerify<{ token: string }>(form);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
authStore.setToken(res.data.token);
|
authStore.setToken(res.data.token);
|
||||||
router.push("/chat");
|
router.push("/welcome");
|
||||||
} else {
|
} else {
|
||||||
isDisabled.value = false;
|
ElMessage.error(res.msg || "登录失败");
|
||||||
loginTip.value = "登录";
|
}
|
||||||
ElMessage.error(res.msg);
|
} finally {
|
||||||
|
submitting.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳后端 CAS 入口;后端 302 跳 CAS 服务器
|
|
||||||
const goCasLogin = () => {
|
const goCasLogin = () => {
|
||||||
window.location.href = `/chat_web_backend/cas/login`;
|
window.location.href = `/chat_web_backend/cas/login`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理 CAS 回调:URL 含 cas_token 参数 → 存 token 后跳首页
|
// CAS 回调:URL 含 cas_token → 存 token + 跳 welcome
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const casToken = params.get("cas_token");
|
const casToken = params.get("cas_token");
|
||||||
if (casToken) {
|
if (casToken) {
|
||||||
authStore.setToken(casToken);
|
authStore.setToken(casToken);
|
||||||
window.history.replaceState({}, document.title, window.location.pathname + window.location.hash.split("?")[0]);
|
window.history.replaceState(
|
||||||
router.push("/chat");
|
{},
|
||||||
|
document.title,
|
||||||
|
window.location.pathname + window.location.hash.split("?")[0]
|
||||||
|
);
|
||||||
|
router.push("/welcome");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.loginPage {
|
.cassicLogin {
|
||||||
|
position: relative;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-image: url("../../assets/images/login/loginBg.png");
|
overflow: hidden;
|
||||||
background-size: cover;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.loginLogo {
|
|
||||||
|
.bgImage {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 6.1vh;
|
inset: 0;
|
||||||
margin: 2rem;
|
background-image: url("../../assets/images/login/cassicLoginBg.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
z-index: 0;
|
||||||
}
|
}
|
||||||
.loginContent {
|
|
||||||
height: 100vh;
|
.loginCard {
|
||||||
display: flex;
|
position: relative;
|
||||||
justify-content: space-around;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
width: 460px;
|
||||||
|
padding: 40px 40px 36px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
box-shadow: 0 12px 40px rgba(120, 0, 0, 0.18);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
}
|
}
|
||||||
.loginTitle {
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 26px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 7vh;
|
color: #c10b08;
|
||||||
color: white;
|
letter-spacing: 2px;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
.loginInfo {
|
|
||||||
font-weight: 300;
|
.titleBar {
|
||||||
font-size: 2vh;
|
width: 36px;
|
||||||
|
height: 3px;
|
||||||
|
background: #c10b08;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 12px auto 28px;
|
||||||
}
|
}
|
||||||
.loginOperate {
|
|
||||||
background: white;
|
.form {
|
||||||
display: flex;
|
:deep(.el-form-item) {
|
||||||
flex-direction: column;
|
margin-bottom: 18px;
|
||||||
border-radius: 0.75rem;
|
}
|
||||||
align-items: center;
|
|
||||||
padding: 4vh;
|
:deep(.el-input__wrapper) {
|
||||||
.logoImg {
|
border-radius: 4px;
|
||||||
height: 5vh;
|
box-shadow: 0 0 0 1px #f3d2cf inset;
|
||||||
|
background: #fff;
|
||||||
|
padding: 4px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper.is-focus) {
|
||||||
|
box-shadow: 0 0 0 1px #c10b08 inset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::v-deep .is-required .el-form-item__label::after {
|
|
||||||
content: "*";
|
.iconBox {
|
||||||
color: #ff0000;
|
display: inline-flex;
|
||||||
margin-left: 4px;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #c10b08;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
margin-right: 4px;
|
||||||
|
i {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.captchaRow {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: stretch;
|
||||||
|
.el-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.captchaBtn {
|
||||||
|
flex: 0 0 110px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f3d2cf;
|
||||||
|
color: #c10b08;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
.captchaBtn:hover:not(:disabled) {
|
||||||
|
background: #e8b9b6;
|
||||||
|
}
|
||||||
|
.captchaBtn:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchModeRow {
|
||||||
|
margin: 4px 0 18px;
|
||||||
|
}
|
||||||
|
.modeLink {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #c10b08;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.primaryBtn {
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #c10b08;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #a30907;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.casBtn {
|
||||||
|
width: 100%;
|
||||||
|
height: 44px;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-left: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #c10b08;
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
color: #c10b08;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
border-color: #a30907;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
111
chat_web_front/src/views/welcome/index.vue
Normal file
111
chat_web_front/src/views/welcome/index.vue
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<template>
|
||||||
|
<div class="welcomePage">
|
||||||
|
<Waves></Waves>
|
||||||
|
<img :src="projectLogo" alt="" class="welcomeLogo" />
|
||||||
|
<div class="welcomeContent">
|
||||||
|
<div class="welcomeTitle">
|
||||||
|
<div>
|
||||||
|
聚尖端之力,创多维平台
|
||||||
|
<br />
|
||||||
|
<span class="welcomeInfo">
|
||||||
|
聚合科技动能,扩展创新疆界,引领行业跃迁升级
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="enterAction">
|
||||||
|
<button class="glassBtn" @click="goChat">
|
||||||
|
<span>立即体验</span>
|
||||||
|
<i class="arrow">→</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import projectLogo from "@/assets/images/login/projectLogo-white.svg";
|
||||||
|
import Waves from "../../components/Waves.vue";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const goChat = () => {
|
||||||
|
router.push("/chat");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.welcomePage {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url("../../assets/images/login/loginBg.png");
|
||||||
|
background-size: cover;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.welcomeLogo {
|
||||||
|
position: absolute;
|
||||||
|
height: 6.1vh;
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
.welcomeContent {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.welcomeTitle {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 7vh;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.welcomeInfo {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 2vh;
|
||||||
|
}
|
||||||
|
.enterAction {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.glassBtn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
padding: 18px 44px;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.35);
|
||||||
|
border-radius: 999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||||
|
0 8px 32px rgba(0, 0, 0, 0.18);
|
||||||
|
}
|
||||||
|
.glassBtn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.18);
|
||||||
|
border-color: rgba(255, 255, 255, 0.6);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
.glassBtn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
.glassBtn .arrow {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 18px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user