style: save login page redesign before internal pages update

This commit is contained in:
root
2026-02-16 06:32:31 +01:00
parent 537d81beb1
commit 213b115524
5 changed files with 666 additions and 506 deletions

View File

@@ -24,7 +24,12 @@ steps:
volumes: volumes:
- name: docker-sock - name: docker-sock
path: /var/run/docker.sock path: /var/run/docker.sock
- name: web-dist
path: /opt/jshERP-web
commands: commands:
- rm -rf /opt/jshERP-web/*
- cp -r jshERP-web/dist/* /opt/jshERP-web/
- chmod -R 755 /opt/jshERP-web/
- docker build -t jsherp:latest . - docker build -t jsherp:latest .
- docker stop jsherp || true - docker stop jsherp || true
- docker rm jsherp || true - docker rm jsherp || true
@@ -37,6 +42,9 @@ volumes:
- name: docker-sock - name: docker-sock
host: host:
path: /var/run/docker.sock path: /var/run/docker.sock
- name: web-dist
host:
path: /opt/jshERP-web
trigger: trigger:
branch: branch:

26
AGENTS.md Normal file
View File

@@ -0,0 +1,26 @@
# ERP 开发助手
## 角色
你是 jshERP管伊佳ERP的专属开发助手。
## 项目信息
- 技术栈SpringBoot 2.0 (JDK 8) + Vue.js + MyBatis + MariaDB + Redis
- 代码位置:/root/jshERP
- 前端构建cd /root/jshERP/jshERP-web && npm run build输出到 /opt/jshERP-web/
- 后端构建cd /root/jshERP/jshERP-boot && mvn clean package -DskipTests
- 部署Docker 容器 jsherphost network, 端口 9999
- CI/CDgit push 到 Gitea 自动触发 Drone CI 构建
## 工作流程
1. 分析需求
2. 阅读相关代码
3. 提出修改方案
4. 用户确认后执行修改
5. git add/commit/push
6. Drone CI 自动构建部署
## 注意事项
- 修改代码前先 git status 检查当前状态
- 每次修改都要有清晰的 commit message
- 前端修改后需要 npm run build
- 后端修改后 Drone CI 会自动构建 Docker 镜像并部署

8
SOUL.md Normal file
View File

@@ -0,0 +1,8 @@
# ERP Dev Agent
专注于 jshERP 开发的 AI 助手。简洁、高效、直接。
- 先分析再动手
- 给出修改方案让用户确认
- 代码修改要精准,不做不必要的改动
- 每次改动都 commitmessage 清晰

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

View File

@@ -1,75 +1,142 @@
<!-- b y 7 5 2 7 1 8 9 2 0 --> <!-- b y 7 5 2 7 1 8 9 2 0 -->
<template> <template>
<div class="main" :style="mainStyle"> <div class="login-page">
<a-form :form="form" class="user-layout-login" ref="formLogin" id="formLogin"> <!-- Background -->
<a-form-item> <div class="login-bg"></div>
<a-input <div class="login-overlay"></div>
size="large"
v-decorator="['loginName',{initialValue:'', rules: validatorRules.loginName.rules}]"
type="text"
placeholder="请输入用户名">
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
<a-form-item> <!-- Content -->
<a-input-password <div class="login-content">
v-decorator="['password',{initialValue:'', rules: validatorRules.password.rules}]" <!-- Left: Branding (desktop) -->
size="large" <div class="login-brand" v-if="device !== 'mobile'">
type="password" <div class="brand-inner">
autocomplete="false" <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 320" width="200" height="160" class="brand-logo">
placeholder="请输入密码"> <defs>
<a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/> <linearGradient id="lg1" x1="0%" y1="0%" x2="100%" y2="0%">
</a-input-password> <stop offset="0%" style="stop-color:#c8962a" />
</a-form-item> <stop offset="50%" style="stop-color:#f0c040" />
<stop offset="100%" style="stop-color:#c8962a" />
<a-row :gutter="0" v-if="checkcodeFlag==='1'"> </linearGradient>
<a-col :span="14"> <filter id="s1" x="-5%" y="-5%" width="115%" height="115%">
<a-form-item> <feDropShadow dx="2" dy="4" stdDeviation="4" flood-color="#000" flood-opacity="0.3"/>
<a-input </filter>
v-decorator="['inputCode',{initialValue:'', rules: validatorRules.inputCode.rules}]" <filter id="g1">
size="large" <feGaussianBlur stdDeviation="2" result="blur"/>
type="text" <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
default-value="" </filter>
placeholder="请输入验证码"> </defs>
<a-icon slot="prefix" type="smile" :style="{ color: 'rgba(0,0,0,.25)' }"/> <polygon points="70,210 130,70 190,210" fill="rgba(255,255,255,0.85)" filter="url(#s1)" opacity="0.9"/>
</a-input> <polygon points="130,70 135,78 75,210 70,210" fill="rgba(255,255,255,0.5)" opacity="0.6"/>
</a-form-item> <polygon points="140,210 200,30 260,210" fill="rgba(255,255,255,0.95)" filter="url(#s1)"/>
</a-col> <polygon points="200,30 206,40 146,210 140,210" fill="rgba(255,255,255,0.6)" opacity="0.7"/>
<a-col :span="10" style="text-align: right"> <polygon points="210,210 270,70 330,210" fill="rgba(255,255,255,0.85)" filter="url(#s1)" opacity="0.9"/>
<img v-if="requestCodeSuccess" style="margin-top: 2px;" :src="randCodeImage" @click="handleChangeCheckCode"/> <polygon points="270,70 275,78 215,210 210,210" fill="rgba(255,255,255,0.5)" opacity="0.6"/>
<img v-else style="margin-top: 2px;" src="../../assets/checkcode.png" @click="handleChangeCheckCode"/> <rect x="60" y="218" width="280" height="5" rx="2.5" fill="url(#lg1)" filter="url(#g1)"/>
</a-col> <text x="200" y="258" text-anchor="middle" font-family="'Arial Black','Helvetica Neue',sans-serif" font-size="38" font-weight="900" letter-spacing="8" fill="#ffffff">MILESTONE</text>
</a-row> <line x1="95" y1="266" x2="305" y2="266" stroke="url(#lg1)" stroke-width="1.5" opacity="0.6"/>
<text x="200" y="290" text-anchor="middle" font-family="'Helvetica Neue',Arial,sans-serif" font-size="11" letter-spacing="4" fill="rgba(255,255,255,0.7)" font-weight="300">INDUSTRIAL DEVELOPMENT CORPORATION</text>
<a-form-item> </svg>
<a-checkbox :checked="checked" @change="handleChange">记住密码</a-checkbox> <h2 class="brand-slogan">Building A Better Tomorrow</h2>
<router-link v-if="registerFlag==='1'" :to="{ name: 'register'}" class="forge-password" style="float: right;margin-right: 10px;" > <p class="brand-desc">
注册租户 Milestone Industrial Development Corporation is committed to delivering excellence in construction and industrial development. With years of experience and a dedication to quality, we build the foundations for a stronger future.
</router-link> </p>
</a-form-item> </div>
<a-form-item :style="btnStyle">
<a-button
size="large"
type="primary"
htmlType="submit"
class="login-button"
:loading="loginBtn"
@click.stop.prevent="handleSubmit"
:disabled="loginBtn">登 录
</a-button>
</a-form-item>
<div class="login-copyright" v-if="device === 'mobile'">
<a-row>
<a-col>
© 2015-2030 Powered By
<a style="color:#00458a;" :href="systemUrl" target="_blank">官方网站</a>
</a-col>
</a-row>
</div> </div>
</a-form>
<!-- Right: Login Form -->
<div class="login-form-wrapper">
<!-- Mobile logo -->
<div class="mobile-logo" v-if="device === 'mobile'">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 320" width="140" height="112">
<defs>
<linearGradient id="lg1m" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#c8962a" />
<stop offset="50%" style="stop-color:#f0c040" />
<stop offset="100%" style="stop-color:#c8962a" />
</linearGradient>
</defs>
<polygon points="70,210 130,70 190,210" fill="rgba(255,255,255,0.85)" opacity="0.9"/>
<polygon points="140,210 200,30 260,210" fill="rgba(255,255,255,0.95)"/>
<polygon points="210,210 270,70 330,210" fill="rgba(255,255,255,0.85)" opacity="0.9"/>
<rect x="60" y="218" width="280" height="5" rx="2.5" fill="url(#lg1m)"/>
<text x="200" y="258" text-anchor="middle" font-family="'Arial Black','Helvetica Neue',sans-serif" font-size="38" font-weight="900" letter-spacing="8" fill="#ffffff">MILESTONE</text>
<text x="200" y="290" text-anchor="middle" font-family="'Helvetica Neue',Arial,sans-serif" font-size="11" letter-spacing="4" fill="rgba(255,255,255,0.7)" font-weight="300">INDUSTRIAL DEVELOPMENT CORPORATION</text>
</svg>
</div>
<div class="login-card">
<h3 class="login-title">Welcome Back</h3>
<p class="login-subtitle">Sign in to your account</p>
<a-form :form="form" class="user-layout-login" ref="formLogin" id="formLogin">
<a-form-item>
<a-input
size="large"
v-decorator="['loginName',{initialValue:'', rules: validatorRules.loginName.rules}]"
type="text"
placeholder="请输入用户名">
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
<a-form-item>
<a-input-password
v-decorator="['password',{initialValue:'', rules: validatorRules.password.rules}]"
size="large"
type="password"
autocomplete="false"
placeholder="请输入密码">
<a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input-password>
</a-form-item>
<a-row :gutter="0" v-if="checkcodeFlag==='1'">
<a-col :span="14">
<a-form-item>
<a-input
v-decorator="['inputCode',{initialValue:'', rules: validatorRules.inputCode.rules}]"
size="large"
type="text"
default-value=""
placeholder="请输入验证码">
<a-icon slot="prefix" type="smile" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
</a-col>
<a-col :span="10" style="text-align: right">
<img v-if="requestCodeSuccess" style="margin-top: 2px;" :src="randCodeImage" @click="handleChangeCheckCode"/>
<img v-else style="margin-top: 2px;" src="../../assets/checkcode.png" @click="handleChangeCheckCode"/>
</a-col>
</a-row>
<a-form-item>
<a-checkbox :checked="checked" @change="handleChange">记住密码</a-checkbox>
<router-link v-if="registerFlag==='1'" :to="{ name: 'register'}" class="forge-password" style="float: right;margin-right: 10px;" >
注册租户
</router-link>
</a-form-item>
<a-form-item style="margin-top:16px">
<a-button
size="large"
type="primary"
htmlType="submit"
class="login-button"
:loading="loginBtn"
@click.stop.prevent="handleSubmit"
:disabled="loginBtn">登 录
</a-button>
</a-form-item>
</a-form>
</div>
</div>
</div>
<!-- Footer -->
<div class="login-footer">
© 2015-2030 MILESTONE INDUSTRIAL DEVELOPMENT CORPORATION. All Rights Reserved.
<a style="color:rgba(255,255,255,0.6);margin-left:8px;" :href="systemUrl" target="_blank">Official Website</a>
</div>
</div> </div>
</template> </template>
<!-- BY cao_yu_li --> <!-- BY cao_yu_li -->
@@ -96,7 +163,6 @@
systemTitle: window.SYS_TITLE, systemTitle: window.SYS_TITLE,
systemUrl: window.SYS_URL, systemUrl: window.SYS_URL,
loginBtn: false, loginBtn: false,
// login type: 0 email, 1 username, 2 telephone
loginType: 0, loginType: 0,
requiredTwoStepCaptcha: false, requiredTwoStepCaptcha: false,
stepCaptchaVisible: false, stepCaptchaVisible: false,
@@ -115,7 +181,7 @@
inputCode:{rules: [{ required: true, message: '请输入验证码!',validator: 'click'}]} inputCode:{rules: [{ required: true, message: '请输入验证码!',validator: 'click'}]}
}, },
verifiedCode:"", verifiedCode:"",
inputCodeContent:"", //20200510 cfm: 为方便测试,不输入验证码可 ""-->"xxxx" inputCodeContent:"",
inputCodeNull:true, inputCodeNull:true,
departList:[], departList:[],
departVisible:false, departVisible:false,
@@ -135,7 +201,6 @@
}, },
created () { created () {
this.loadInfo() this.loadInfo()
this.checkScreen()
this.currdatetime = new Date().getTime(); this.currdatetime = new Date().getTime();
Vue.ls.remove(ACCESS_TOKEN) Vue.ls.remove(ACCESS_TOKEN)
this.getRouterData() this.getRouterData()
@@ -145,9 +210,7 @@
}, },
methods: { methods: {
...mapActions([ "Login", "Logout" ]), ...mapActions([ "Login", "Logout" ]),
// handler
loadInfo() { loadInfo() {
//从缓存中获取登录名和密码
this.$nextTick(() => { this.$nextTick(() => {
if(Vue.ls.get('cache_loginName') && Vue.ls.get('cache_password')) { if(Vue.ls.get('cache_loginName') && Vue.ls.get('cache_password')) {
this.form.setFieldsValue({'loginName': Vue.ls.get('cache_loginName')}) this.form.setFieldsValue({'loginName': Vue.ls.get('cache_loginName')})
@@ -155,10 +218,8 @@
this.checked = true this.checked = true
} }
}) })
//从注册页面跳转过来,给登录名进行赋值
if(this.$route.params.loginName) { if(this.$route.params.loginName) {
this.$nextTick(() => { this.$nextTick(() => {
//先清空缓存
Vue.ls.remove('cache_loginName') Vue.ls.remove('cache_loginName')
Vue.ls.remove('cache_password') Vue.ls.remove('cache_password')
this.form.setFieldsValue({'loginName':this.$route.params.loginName}) this.form.setFieldsValue({'loginName':this.$route.params.loginName})
@@ -176,7 +237,6 @@
} }
callback() callback()
}, },
//切换勾选
handleChange(e) { handleChange(e) {
this.checked = e.target.checked this.checked = e.target.checked
}, },
@@ -198,7 +258,6 @@
let that = this let that = this
let loginParams = {}; let loginParams = {};
that.loginBtn = true; that.loginBtn = true;
// 使用账户密码登陆
if (that.customActiveKey === 'tab1') { if (that.customActiveKey === 'tab1') {
that.form.validateFields([ 'loginName', 'password', 'inputCode' ], { force: true }, (err, values) => { that.form.validateFields([ 'loginName', 'password', 'inputCode' ], { force: true }, (err, values) => {
if (!err) { if (!err) {
@@ -207,11 +266,9 @@
loginParams.code = values.inputCode loginParams.code = values.inputCode
loginParams.uuid = that.uuid loginParams.uuid = that.uuid
if(that.checked) { if(that.checked) {
//勾选的时候进行缓存
Vue.ls.set('cache_loginName', values.loginName) Vue.ls.set('cache_loginName', values.loginName)
Vue.ls.set('cache_password', values.password) Vue.ls.set('cache_password', values.password)
} else { } else {
//没勾选的时候清缓存
Vue.ls.remove('cache_loginName') Vue.ls.remove('cache_loginName')
Vue.ls.remove('cache_password') Vue.ls.remove('cache_password')
} }
@@ -257,16 +314,14 @@
}) })
getAction("/user/infoWithTenant",{}).then(res=>{ getAction("/user/infoWithTenant",{}).then(res=>{
if(res && res.code === 200) { if(res && res.code === 200) {
let currentTime = new Date(); //新建一个日期对象,默认现在的时间 let currentTime = new Date();
let expireTime = new Date(res.data.expireTime); //设置过去的一个时间点,"yyyy-MM-dd HH:mm:ss"格式化日期 let expireTime = new Date(res.data.expireTime);
let type = res.data.type //租户类型0免费租户1付费租户 let type = res.data.type
let difftime = expireTime - currentTime; //计算时间差 let difftime = expireTime - currentTime;
let tipInfo = '您好,服务即将到期,请及时续费!' let tipInfo = '您好,服务即将到期,请及时续费!'
//0免费租户-如果距离到期还剩5天就进行提示续费
if(type === '0' && difftime<86400000*5) { if(type === '0' && difftime<86400000*5) {
this.$message.warning(tipInfo,8) this.$message.warning(tipInfo,8)
} }
//1付费租户-如果距离到期还剩15天就进行提示续费
if(type === '1' && difftime<86400000*15) { if(type === '1' && difftime<86400000*15) {
this.$message.warning(tipInfo,8) this.$message.warning(tipInfo,8)
} }
@@ -289,7 +344,6 @@
description: ((err.response || {}).data || {}).message || err.message || err.data.message || "请求出现错误请稍后再试", description: ((err.response || {}).data || {}).message || err.message || err.data.message || "请求出现错误请稍后再试",
duration: 4, duration: 4,
}); });
//验证码刷新
this.form.setFieldsValue({'inputCode':''}) this.form.setFieldsValue({'inputCode':''})
this.handleChangeCheckCode() this.handleChangeCheckCode()
this.loginBtn = false; this.loginBtn = false;
@@ -353,16 +407,8 @@
getCheckcodeFlag(){ getCheckcodeFlag(){
getAction('/platformConfig/getPlatform/checkcodeFlag').then((res) => { getAction('/platformConfig/getPlatform/checkcodeFlag').then((res) => {
this.checkcodeFlag = res + '' this.checkcodeFlag = res + ''
if(this.checkcodeFlag === '1') {
this.mainStyle = ''
this.btnStyle = 'margin-top:16px'
} else {
this.mainStyle = 'padding-top:20px'
this.btnStyle = 'margin-top:26px'
}
}) })
}, },
//获取密码加密规则
getEncrypte(){ getEncrypte(){
var encryptedString = Vue.ls.get(ENCRYPTED_STRING); var encryptedString = Vue.ls.get(ENCRYPTED_STRING);
if(encryptedString == null){ if(encryptedString == null){
@@ -373,67 +419,121 @@
this.encryptedString = encryptedString; this.encryptedString = encryptedString;
} }
}, },
//加载商品属性
initMPropertyShort(){ initMPropertyShort(){
getAction('/materialProperty/getAllList').then((res) => { getAction('/materialProperty/getAllList').then((res) => {
if(res && res.code === 200){ if(res && res.code === 200){
if(res.data) { if(res.data) {
let thisRows = res.data; //属性列表 let thisRows = res.data;
Vue.ls.set('materialPropertyList', thisRows, 7 * 24 * 60 * 60 * 1000); Vue.ls.set('materialPropertyList', thisRows, 7 * 24 * 60 * 60 * 1000);
} }
} }
}) })
}, },
checkScreen() {
let percentage = '100%'
let basicWidth = 1920
const currentWidth = window.screen.width
const currentHeight = window.screen.height
//浏览器的当前比例
const currentRatio = window.devicePixelRatio.toFixed(2)
//浏览器需要调整的比例
let needRatio = 1
let ratio = currentWidth/basicWidth
if(ratio>0.5 && ratio<0.67) {
percentage = '50%'
needRatio = 0.5
} if(ratio>=0.67 && ratio<0.75) {
percentage = '67%'
needRatio = 0.67
} else if(ratio>=0.75 && ratio<0.8) {
percentage = '75%'
needRatio = 0.75
} else if(ratio>=0.8 && ratio<0.9) {
percentage = '80%'
needRatio = 0.8
} else if(ratio>=1.1 && ratio<1.25) {
percentage = '110%'
needRatio = 1.1
} else if(ratio>=1.25 && ratio<1.5) {
percentage = '125%'
needRatio = 1.25
} else if(ratio>=1.5 && ratio<1.75) {
percentage = '150%'
needRatio = 1.5
}
//console.log(currentRatio)
//console.log(needRatio)
if(currentRatio-0 !== needRatio) {
this.openNotificationWithIcon('warning', currentWidth, currentHeight, percentage)
}
},
openNotificationWithIcon(type, currentWidth, currentHeight, percentage) {
this.$notification[type]({
message: '浏览器的缩放比例调整提示',
description: '检测到您显示器的分辨率为:' + currentWidth + '*' + currentHeight + ' ,为了获得更好的操作体验,建议您将浏览器的缩放比例调整至' + percentage,
duration: 10
});
},
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.login-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
}
.login-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('/static/bg-construction.jpg') center center / cover no-repeat;
z-index: 0;
}
.login-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 26, 58, 0.75);
z-index: 1;
}
.login-content {
position: relative;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
min-height: calc(100vh - 50px);
padding: 40px;
max-width: 1200px;
margin: 0 auto;
}
.login-brand {
flex: 0 0 55%;
padding-right: 60px;
.brand-inner {
max-width: 500px;
}
.brand-logo {
margin-bottom: 24px;
}
.brand-slogan {
color: #f0c040;
font-size: 28px;
font-weight: 300;
letter-spacing: 2px;
margin-bottom: 20px;
font-family: 'Georgia', serif;
font-style: italic;
}
.brand-desc {
color: rgba(255, 255, 255, 0.7);
font-size: 15px;
line-height: 1.8;
letter-spacing: 0.3px;
}
}
.login-form-wrapper {
flex: 0 0 400px;
max-width: 400px;
width: 100%;
}
.login-card {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 16px;
padding: 40px 36px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
.login-title {
color: #ffffff;
font-size: 26px;
font-weight: 600;
margin-bottom: 4px;
}
.login-subtitle {
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
margin-bottom: 30px;
}
}
.user-layout-login { .user-layout-login {
label { label {
font-size: 14px; font-size: 14px;
@@ -443,12 +543,6 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
.getCaptcha {
display: block;
width: 100%;
height: 40px;
}
.forge-password { .forge-password {
font-size: 14px; font-size: 14px;
font-weight: bolder; font-weight: bolder;
@@ -457,50 +551,74 @@
button.login-button { button.login-button {
padding: 0 15px; padding: 0 15px;
font-size: 16px; font-size: 16px;
height: 40px; height: 44px;
width: 100%; width: 100%;
} border-radius: 8px;
background: linear-gradient(135deg, #0077cc, #00458a);
border: none;
font-weight: 600;
letter-spacing: 2px;
.user-login-other { &:hover {
text-align: left; background: linear-gradient(135deg, #0088ee, #0055aa);
margin-top: 24px;
line-height: 22px;
.item-icon {
font-size: 24px;
color: rgba(0,0,0,.2);
margin-left: 16px;
vertical-align: middle;
cursor: pointer;
transition: color .3s;
&:hover {
color: #1890ff;
}
} }
.register {
float: right;
}
}
.weixin {
padding-left:10px;
color: red;
cursor:pointer
} }
} }
.login-footer {
position: relative;
z-index: 2;
text-align: center;
padding: 15px;
color: rgba(255, 255, 255, 0.45);
font-size: 12px;
}
.mobile-logo {
text-align: center;
margin-bottom: 24px;
}
// Mobile responsive
@media (max-width: 768px) {
.login-content {
flex-direction: column;
padding: 20px;
justify-content: center;
}
.login-form-wrapper {
flex: none;
max-width: 100%;
}
.login-card {
padding: 30px 24px;
}
}
</style> </style>
<style> <style>
.login-card .ant-input {
background: rgba(255, 255, 255, 0.9) !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important;
border-radius: 6px !important;
}
.login-card .ant-input:focus,
.login-card .ant-input-focused {
background: #ffffff !important;
border-color: #0077cc !important;
}
.login-card .ant-checkbox-wrapper {
color: rgba(255, 255, 255, 0.8);
}
.login-card .forge-password {
color: #f0c040 !important;
}
.login-card .ant-form-explain {
color: #ff6b6b;
}
.valid-error .ant-select-selection__placeholder{ .valid-error .ant-select-selection__placeholder{
color: #f5222d; color: #f5222d;
} }
.login-copyright {
text-align: center;
margin-top: 20px
}
.login-copyright, .login-copyright a {
color: #666
}
</style> </style>