<template>
|
|
<view class="bodyView">
|
<view>
|
<uni-nav-bar :fixed="true" :statusBar="true" :title="$t('page.login')" right-icon="gear" @clickRight="openSettings"></uni-nav-bar>
|
</view>
|
<view class="topView">
|
<image src="/static/img/login_top.png" mode="aspectFill">
|
</image>
|
</view>
|
<view class="logoView">
|
<image src="/static/img/newLogo.png" mode="aspectFit">
|
</image>
|
</view>
|
<view class="bottomView">
|
<view class="itemView" style="margin-bottom: 40px;">
|
<view class="helloText">{{$t('index.hello')}}</view>
|
<view class="introText">{{$t('index.intro')}}</view>
|
</view>
|
<view class="itemView">
|
<view class="textType3">{{$t('login.user')}}:</view>
|
<view class="input-wrapper">
|
<input class="uni-input" v-model="user.userName" focus :placeholder="$t('login.inputUser')" />
|
</view>
|
</view>
|
<view class="itemView">
|
<view class="textType3">{{$t('login.pwd')}}:</view>
|
<view class="input-wrapper">
|
<input class="uni-input" v-model="user.password" :placeholder="$t('login.inputPwd')" :password="!showPassword" />
|
<image src="/static/img/login_noteye.png" class="eye-icon" v-if="showPassword"
|
@click="changePassword"></image>
|
<image src="/static/img/login_eye.png" class="eye-icon" v-if="!showPassword"
|
@click="changePassword"></image>
|
</view>
|
</view>
|
<view class="langAndRemView">
|
<view class="check">
|
<view >
|
<view>{{$t('login.remPwd')}}</view>
|
</view>
|
<view>
|
<switch :checked='remberPassword' color="#FFCC33" style="transform:scale(0.7)" @change="remberChange" />
|
</view>
|
</view>
|
<view class="langView">
|
|
</view>
|
</view>
|
<view class="itemView">
|
<button class="loadingButton" @click="onLogin()" :loading="loading">{{btnText}}</button>
|
</view>
|
</view>
|
|
<!-- 设置菜单 -->
|
<uni-popup ref="settingsMenu" type="bottom" background-color="#fff">
|
<view class="settings-menu">
|
<view class="settings-item" @click="openIpSetting">
|
<text>设置IP</text>
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
<view class="settings-item" @click="openLangSetting">
|
<text>国际化</text>
|
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
</view>
|
<view class="settings-cancel" @click="closeSettingsMenu">取消</view>
|
</view>
|
</uni-popup>
|
|
<!-- IP配置弹窗 -->
|
<uni-popup ref="inputDialog" type="center" :mask-click="false">
|
<view class="modal-container">
|
<view class="modal-header">
|
<text class="cuIcon-settings" style="font-size: 48rpx; color: #0081ff"></text>
|
<text class="modal-title">配置</text>
|
</view>
|
<view class="modal-body">
|
<view class="form-item">
|
<text class="form-label">IP</text>
|
<view class="modal-input-wrapper">
|
<input class="agv-input" type="text" v-model="url.ip" />
|
</view>
|
</view>
|
<view class="form-item">
|
<text class="form-label">端口</text>
|
<view class="modal-input-wrapper">
|
<input class="agv-input" type="text" v-model="url.port" />
|
</view>
|
</view>
|
<view class="form-item">
|
<text class="form-label">项目</text>
|
<view class="modal-input-wrapper">
|
<input class="agv-input" type="text" v-model="url.project" />
|
</view>
|
</view>
|
</view>
|
<view class="modal-footer">
|
<button class="modal-btn modal-btn-cancel" @click="closeIpDialog">取消</button>
|
<button class="modal-btn modal-btn-confirm" @click="settingConfirm">确认</button>
|
</view>
|
</view>
|
</uni-popup>
|
|
<!-- 语言设置弹窗 -->
|
<uni-popup ref="langDialog" type="center">
|
<view class="modal-container">
|
<view class="modal-header">
|
<text class="cuIcon-global" style="font-size: 48rpx; color: #0081ff"></text>
|
<text class="modal-title">选择语言</text>
|
</view>
|
<view class="modal-body">
|
<view class="language-list">
|
<view class="language-item" v-for="(item, index) in locales" :key="index" @click="onLocaleConfirm(item)">
|
<text>{{item.text}}</text>
|
<uni-icons type="checkmarkempty" size="20" color="#007AFF" v-if="item.code == applicationLocale"></uni-icons>
|
</view>
|
</view>
|
</view>
|
<view class="modal-footer">
|
<button class="modal-btn modal-btn-cancel" @click="closeLangDialog" style="width: 100%; border-right: none;">取消</button>
|
</view>
|
</view>
|
</uni-popup>
|
</view>
|
</template>
|
|
<script>
|
import md5 from '../../static/js/md5.js'
|
import {
|
request
|
} from '../../common/request.js'
|
export default{
|
data(){
|
return{
|
showPassword: false,
|
loading: false,
|
showLanguageDropdown: false,
|
loginButton: 'login.login',
|
systemLocale: '',
|
applicationLocale: '',
|
remberPassword: true,
|
user: {
|
userName: '',
|
password: '',
|
},
|
url: {
|
ip: '',
|
port: '',
|
project: ''
|
},
|
baseUrl: '',
|
}
|
},
|
computed:{
|
locales() {
|
return [{
|
text: this.$t('locale.auto'),
|
code: 'auto'
|
}, {
|
text: this.$t('locale.en'),
|
code: 'en'
|
},
|
{
|
text: this.$t('locale.zh-hans'),
|
code: 'zh-Hans'
|
},
|
{
|
text: this.$t('locale.zh-hant'),
|
code: 'zh-Hant'
|
},
|
{
|
text: this.$t('locale.ja'),
|
code: 'ja'
|
}
|
]
|
},
|
btnText() {
|
return this.$t(this.loginButton);
|
}
|
},
|
onLoad(){
|
let systemInfo = uni.getSystemInfoSync();
|
this.systemLocale = systemInfo.language;
|
this.applicationLocale = uni.getLocale();
|
this.isAndroid = systemInfo.platform.toLowerCase() === 'android';
|
uni.onLocaleChange((e) => {
|
this.applicationLocale = e.locale;
|
})
|
|
this.user = uni.getStorageSync('user')
|
if (!this.user) {
|
this.user = {
|
userName: '',
|
password: ''
|
}
|
}
|
},
|
methods:{
|
async onLogin() {
|
const {
|
code,
|
data,
|
msg
|
} = await request('/login', {
|
username: this.user.userName,
|
password: this.user.password,
|
})
|
if (code === 200) {
|
this.loading = true;
|
this.loginButton = 'login.loging';
|
uni.setStorageSync('token', data.accessToken);
|
uni.setStorageSync('userData', data.user);
|
if (this.remberPassword) {
|
uni.setStorageSync('user', this.user);
|
} else {
|
uni.removeStorageSync('user');
|
}
|
this.goHome()
|
} else {
|
uni.showToast({
|
title: msg
|
})
|
}
|
|
},
|
goHome() {
|
setTimeout(() => {
|
// this.getAuth2()
|
this.getFields()
|
uni.showToast({
|
title: '登录成功'
|
})
|
setTimeout(() => {
|
uni.reLaunch({
|
url: '../home/index'
|
});
|
}, 300)
|
}, 700)
|
},
|
async getFields() {
|
const {
|
code,
|
data,
|
msg
|
} = await request('/dynamic/fields', {}, 'get')
|
if (code === 200) {
|
this.$store.commit('user/setFields', data)
|
} else {
|
uni.showToast({
|
title: msg
|
})
|
}
|
},
|
remberChange(e) {
|
this.remberPassword = !this.remberPassword
|
},
|
// 显示/隐藏密码
|
changePassword() {
|
this.showPassword = !this.showPassword;
|
},
|
localChange() {
|
console.log(this.local)
|
if (this.isAndroid) {
|
uni.showModal({
|
content: this.$t('index.language-change-confirm'),
|
success: (res) => {
|
if (res.confirm) {
|
uni.setLocale(this.local.value);
|
}
|
}
|
})
|
} else {
|
uni.setLocale(this.local.value);
|
this.$i18n.locale = this.local.value;
|
}
|
},
|
// 切换语言下拉菜单显示状态
|
toggleLanguageDropdown() {
|
this.showLanguageDropdown = !this.showLanguageDropdown;
|
},
|
|
openSettings() {
|
this.$refs.settingsMenu.open()
|
},
|
openIpSetting() {
|
this.$refs.settingsMenu.close()
|
setTimeout(() => {
|
this.$refs.inputDialog.open()
|
}, 300)
|
},
|
openLangSetting() {
|
this.$refs.settingsMenu.close()
|
setTimeout(() => {
|
this.$refs.langDialog.open()
|
}, 300)
|
},
|
closeSettingsMenu() {
|
this.$refs.settingsMenu.close()
|
},
|
closeIpDialog() {
|
this.$refs.inputDialog.close()
|
},
|
closeLangDialog() {
|
this.$refs.langDialog.close()
|
},
|
settingConfirm() {
|
this.baseUrl = "http://" + this.url.ip + ':' + this.url.port + '/' + this.url.project
|
uni.setStorageSync('baseUrl', this.baseUrl);
|
uni.setStorageSync('url', this.url);
|
// uni.setStorageSync('project', 'tzsk')
|
this.$refs.inputDialog.close()
|
uni.showToast({
|
title: '配置已保存',
|
icon: 'success'
|
})
|
},
|
onLocaleConfirm(item) {
|
this.onLocaleChange(item)
|
this.$refs.langDialog.close()
|
},
|
|
// 获取当前选择的语言文本
|
getCurrentLanguageText() {
|
const currentLocale = this.locales.find(item => item.code === this.applicationLocale);
|
return currentLocale ? currentLocale.text : this.$t('locale.auto');
|
},
|
|
// 语言选择改变
|
onLocaleChange(e) {
|
if (this.isAndroid) {
|
uni.showModal({
|
content: this.$t('index.language-change-confirm'),
|
success: (res) => {
|
if (res.confirm) {
|
uni.setLocale(e.code);
|
this.showLanguageDropdown = false;
|
}
|
}
|
})
|
} else {
|
uni.setLocale(e.code);
|
this.$i18n.locale = e.code;
|
this.showLanguageDropdown = false;
|
}
|
},
|
}
|
}
|
</script>
|
|
<style>
|
.helloText{
|
font-family: a2;
|
font-size: 20px;
|
margin-top: 10px;
|
margin-bottom: 5px;
|
}
|
.introText{
|
font-family: a3;
|
font-size: 15px;
|
color: #ababab;
|
}
|
.textType3{
|
font-family: a4;
|
}
|
.bodyView{
|
display: flex;
|
flex-direction: column;
|
background-image: url("/static/img/login_backg.png");
|
background-repeat: no-repeat;
|
background-size: cover;
|
background-position: center;
|
height: 100vh;
|
width: 100%;
|
}
|
.topView{
|
flex: 7;
|
}
|
.topView image{
|
width: 100%;
|
}
|
.logoView{
|
flex: 1;
|
display: flex;
|
justify-content: flex-end;
|
align-items: center;
|
|
}
|
.logoView image{
|
width: 33%;
|
height: 50px;
|
margin-right: 20px;
|
}
|
.bottomView{
|
flex: 15;
|
display: flex;
|
flex-direction: column;
|
justify-content: flex-start;
|
align-items: center;
|
}
|
.itemView{
|
width: 90%;
|
height: 50px;
|
margin-bottom: 30px;
|
}
|
.langAndRemView{
|
width: 90%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
.langView{
|
width: 30%;
|
}
|
.textImage{
|
width: 60%;
|
height: 42px;
|
object-fit: cover;
|
margin-top: 20px;
|
margin-bottom: 30px;
|
}
|
|
.input-wrapper {
|
/* #ifndef APP-NVUE */
|
display: flex;
|
/* #endif */
|
padding: 8px 13px;
|
flex-direction: row;
|
flex-wrap: nowrap;
|
background-color: #FFFFFF;
|
border-radius: 10px;
|
height: 45px;
|
align-items: center;
|
margin-top: 5px;
|
}
|
|
.uni-input {
|
height: 28px;
|
line-height: 28px;
|
font-size: 15px;
|
padding: 0px;
|
flex: 1;
|
background-color: #FFFFFF;
|
|
}
|
|
.uni-icon {
|
font-family: uniicons;
|
font-size: 24px;
|
font-weight: normal;
|
font-style: normal;
|
width: 24px;
|
height: 24px;
|
line-height: 24px;
|
color: #999999;
|
}
|
|
.uni-eye-active {
|
color: #007AFF;
|
}
|
|
.eye-icon {
|
width: 20px;
|
height: 13px;
|
margin-left: 5px;
|
}
|
.loadingButton{
|
background-color: #ffda1e;
|
font-family: a1;
|
}
|
.check {
|
|
height: 100%;
|
display: flex;
|
font-size: 18px;
|
color: #606266;
|
justify-content: flex-start;
|
align-items: center;
|
|
}
|
/* 语言选择下拉菜单 */
|
.language-dropdown {
|
position: relative;
|
margin-bottom: 20rpx;
|
z-index: 10;
|
}
|
|
.selected-language {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 15rpx 20rpx;
|
background-color: #f8f8f8;
|
border-radius: 8rpx;
|
border: 1px solid #e0e0e0;
|
}
|
|
.language-options {
|
position: absolute;
|
bottom: 100%;
|
left: 0;
|
right: 0;
|
background-color: #ffffff;
|
border-radius: 8rpx;
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
border: 1px solid #e0e0e0;
|
margin-bottom: 5rpx;
|
}
|
|
.language-option {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 15rpx 20rpx;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.language-option:last-child {
|
border-bottom: none;
|
}
|
|
.language-option:active {
|
background-color: #f5f5f5;
|
}
|
|
/* Settings Menu */
|
.settings-menu {
|
background-color: #fff;
|
padding: 20rpx 0;
|
border-radius: 20rpx 20rpx 0 0;
|
}
|
.settings-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 30rpx 40rpx;
|
border-bottom: 1px solid #f0f0f0;
|
font-size: 32rpx;
|
color: #333;
|
}
|
.settings-item:active {
|
background-color: #f5f5f5;
|
}
|
.settings-cancel {
|
text-align: center;
|
padding: 30rpx;
|
margin-top: 20rpx;
|
border-top: 10rpx solid #f8f8f8;
|
font-size: 32rpx;
|
color: #333;
|
}
|
|
/* Custom Popup Styles */
|
/* 弹窗容器 */
|
.modal-container {
|
width: 600rpx;
|
background-color: #ffffff;
|
border-radius: 24rpx;
|
overflow: hidden;
|
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.15);
|
}
|
|
/* 弹窗头部 */
|
.modal-header {
|
padding: 40rpx 30rpx 20rpx;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
background: linear-gradient(135deg, #f0f7ff 0%, #e8f4ff 100%);
|
}
|
|
.modal-title {
|
font-size: 34rpx;
|
font-weight: bold;
|
color: #333;
|
margin-top: 16rpx;
|
}
|
|
/* 弹窗内容 */
|
.modal-body {
|
padding: 30rpx;
|
}
|
|
.form-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 24rpx;
|
}
|
|
.form-item:last-child {
|
margin-bottom: 0;
|
}
|
|
.form-label {
|
width: 100rpx;
|
font-size: 28rpx;
|
color: #333;
|
font-weight: 500;
|
margin-right: 20rpx;
|
text-align: right;
|
}
|
|
/* 输入框容器 - 弹窗专用 */
|
.modal-input-wrapper {
|
flex: 1;
|
background-color: #f5f7fa;
|
border-radius: 12rpx;
|
padding: 10rpx;
|
border: 2rpx solid #e4e7ed;
|
transition: border-color 0.2s;
|
}
|
|
.modal-input-wrapper:focus-within {
|
border-color: #0081ff;
|
}
|
|
.agv-input {
|
width: 100%;
|
height: 70rpx;
|
line-height: 70rpx;
|
font-size: 30rpx;
|
color: #333;
|
background-color: transparent;
|
}
|
|
/* 弹窗底部按钮 */
|
.modal-footer {
|
display: flex;
|
border-top: 1rpx solid #eee;
|
}
|
|
.modal-btn {
|
flex: 1;
|
height: 100rpx;
|
line-height: 100rpx;
|
font-size: 32rpx;
|
border: none;
|
border-radius: 0;
|
background-color: #fff;
|
}
|
|
.modal-btn::after {
|
border: none;
|
}
|
|
.modal-btn-cancel {
|
color: #999;
|
border-right: 1rpx solid #eee;
|
}
|
|
.modal-btn-confirm {
|
color: #fff;
|
background: linear-gradient(135deg, #0081ff 0%, #1890ff 100%);
|
font-weight: bold;
|
}
|
|
.modal-btn-confirm:active {
|
background: linear-gradient(135deg, #0070dd 0%, #1480e8 100%);
|
}
|
|
.modal-btn-cancel:active {
|
background-color: #f5f5f5;
|
}
|
|
/* Language List in Popup */
|
.language-list {
|
max-height: 200px;
|
overflow-y: auto;
|
}
|
.language-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 15px 0;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
</style>
|