门店端优化
This commit is contained in:
@@ -1,14 +1,37 @@
|
|||||||
<script>
|
<script>
|
||||||
import { hasValidToken, redirectToLogin } from './api/utils/auth';
|
import { hasValidToken, redirectToLogin } from './api/utils/auth';
|
||||||
|
import { appApi } from './api/modules/app';
|
||||||
|
import UpdateModal from './components/UpdateModal.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
UpdateModal
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
// 更新弹窗相关数据(仅APP端)
|
||||||
|
showUpdateModal: false,
|
||||||
|
updateInfo: {
|
||||||
|
version: '',
|
||||||
|
updateContent: '',
|
||||||
|
downloadUrl: '',
|
||||||
|
forceUpdate: false
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
};
|
||||||
|
},
|
||||||
onLaunch: function() {
|
onLaunch: function() {
|
||||||
console.log('App Launch');
|
console.log('App Launch');
|
||||||
|
// 检测APP更新
|
||||||
|
this.checkAppUpdate();
|
||||||
// 全局检查token
|
// 全局检查token
|
||||||
this.checkToken();
|
this.checkToken();
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
console.log('App Show');
|
console.log('App Show');
|
||||||
|
// 每次显示时检测APP更新
|
||||||
|
this.checkAppUpdate();
|
||||||
// 应用恢复时再次检查token
|
// 应用恢复时再次检查token
|
||||||
this.checkToken();
|
this.checkToken();
|
||||||
},
|
},
|
||||||
@@ -21,12 +44,69 @@
|
|||||||
// 获取当前页面
|
// 获取当前页面
|
||||||
const pages = getCurrentPages();
|
const pages = getCurrentPages();
|
||||||
const currentPage = pages.length ? pages[pages.length - 1] : null;
|
const currentPage = pages.length ? pages[pages.length - 1] : null;
|
||||||
|
const currentRoute = currentPage ? currentPage.route : '';
|
||||||
|
|
||||||
// 如果token无效且不在登录页面,则跳转到登录页面
|
// 如果token无效且不在登录页面,则跳转到登录页面
|
||||||
if (!hasValidToken() && currentPage && currentPage.route !== 'pages/login/index') {
|
if (!hasValidToken() && currentRoute && currentRoute !== 'pages/login/index') {
|
||||||
|
console.log('Token无效,从', currentRoute, '重定向到登录页面');
|
||||||
redirectToLogin();
|
redirectToLogin();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检测APP更新
|
||||||
|
async checkAppUpdate() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
console.log('开始检测APP更新...');
|
||||||
|
const res = await appApi.checkUpdate();
|
||||||
|
console.log('更新检测结果:', res);
|
||||||
|
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
const data = res.data;
|
||||||
|
|
||||||
|
// 清理 downloadUrl 中的换行符
|
||||||
|
const downloadUrl = data.downloadUrl ? data.downloadUrl.trim() : '';
|
||||||
|
|
||||||
|
// 设置更新信息
|
||||||
|
this.updateInfo = {
|
||||||
|
version: data.version || '',
|
||||||
|
updateContent: data.updateContent || '本次更新包含性能优化和问题修复',
|
||||||
|
downloadUrl: downloadUrl,
|
||||||
|
forceUpdate: data.forceUpdate || false
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示更新弹窗
|
||||||
|
this.showUpdateModal = true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('检测更新失败:', error);
|
||||||
|
// 更新检测失败不影响应用正常使用,只记录日志
|
||||||
}
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理更新确认
|
||||||
|
handleUpdateConfirm(downloadUrl) {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (downloadUrl) {
|
||||||
|
plus.runtime.openURL(downloadUrl);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.showUpdateModal = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理更新取消
|
||||||
|
handleUpdateCancel() {
|
||||||
|
if (this.updateInfo.forceUpdate) {
|
||||||
|
// 强制更新时,取消则退出应用
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
plus.runtime.quit();
|
||||||
|
// #endif
|
||||||
|
} else {
|
||||||
|
// 关闭弹窗
|
||||||
|
this.showUpdateModal = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +139,21 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-PLUS -->
|
||||||
|
<!-- 更新弹窗(仅APP端) -->
|
||||||
|
<UpdateModal
|
||||||
|
:show="showUpdateModal"
|
||||||
|
:version="updateInfo.version"
|
||||||
|
:updateContent="updateInfo.updateContent"
|
||||||
|
:downloadUrl="updateInfo.downloadUrl"
|
||||||
|
:forceUpdate="updateInfo.forceUpdate"
|
||||||
|
@confirm="handleUpdateConfirm"
|
||||||
|
@cancel="handleUpdateCancel"
|
||||||
|
/>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/*每个页面公共css */
|
/*每个页面公共css */
|
||||||
@import 'uview-ui/index.scss';
|
@import 'uview-ui/index.scss';
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
//export const BASE_URL = 'http://yishi.com'
|
//export const BASE_URL = 'http://yishi.com'
|
||||||
export const BASE_URL = 'https://ckbapi.quwanzhi.com'
|
export const BASE_URL = 'https://ckbapi.quwanzhi.com'
|
||||||
|
|
||||||
|
// APP配置
|
||||||
|
export const APP_CONFIG = {
|
||||||
|
version: '1.1.0', // 当前APP版本号(与manifest.json保持一致)
|
||||||
|
type: 'aiStore' // APP类型标识
|
||||||
|
}
|
||||||
|
|
||||||
// 获取请求头
|
// 获取请求头
|
||||||
const getHeaders = (options = {}) => {
|
const getHeaders = (options = {}) => {
|
||||||
const token = uni.getStorageSync('token');
|
const token = uni.getStorageSync('token');
|
||||||
|
|||||||
19
Store_vue/api/modules/app.js
Normal file
19
Store_vue/api/modules/app.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { request, APP_CONFIG } from '../config'
|
||||||
|
|
||||||
|
// APP相关API
|
||||||
|
export const appApi = {
|
||||||
|
// 检测APP更新
|
||||||
|
// @param {string} version - APP版本号(可选,默认使用配置中的版本号)
|
||||||
|
// @returns {Promise} 返回更新信息
|
||||||
|
checkUpdate: (version) => {
|
||||||
|
return request({
|
||||||
|
url: '/v1/app/update',
|
||||||
|
method: 'GET',
|
||||||
|
data: {
|
||||||
|
type: APP_CONFIG.type, // 固定为 aiStore
|
||||||
|
version: version || APP_CONFIG.version // 使用传入的版本号或配置中的默认版本号
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -116,6 +116,21 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- #ifdef APP-PLUS -->
|
||||||
|
<view class="module-item" @tap="handleCheckUpdate">
|
||||||
|
<view class="module-left">
|
||||||
|
<view class="module-icon green">
|
||||||
|
<text class="iconfont icon-shezhi" style="color: #33cc99; font-size: 24px;"></text>
|
||||||
|
</view>
|
||||||
|
<view class="module-info">
|
||||||
|
<text class="module-name">检查更新</text>
|
||||||
|
<text class="module-desc" v-if="!checkingUpdate && !hasNewVersion">当前版本 {{ currentVersion }}</text>
|
||||||
|
<text class="module-desc" v-if="checkingUpdate" style="color: #33cc99;">检查中...</text>
|
||||||
|
<text class="module-desc" v-if="!checkingUpdate && hasNewVersion" style="color: #ff6699;">发现新版本 {{ latestVersion }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
<view class="module-item" @tap="showSettings" v-if='hide'>
|
<view class="module-item" @tap="showSettings" v-if='hide'>
|
||||||
<view class="module-left">
|
<view class="module-left">
|
||||||
<view class="module-icon gray">
|
<view class="module-icon gray">
|
||||||
@@ -158,6 +173,16 @@
|
|||||||
@close="closeLoginPage"
|
@close="closeLoginPage"
|
||||||
@login-success="handleLoginSuccess"
|
@login-success="handleLoginSuccess"
|
||||||
></login-register>
|
></login-register>
|
||||||
|
|
||||||
|
<!-- 更新弹窗 -->
|
||||||
|
<update-dialog
|
||||||
|
:show="showUpdateDialog"
|
||||||
|
:version="updateInfo.version"
|
||||||
|
:updateContent="updateInfo.updateContent"
|
||||||
|
:downloadUrl="updateInfo.downloadUrl"
|
||||||
|
:forceUpdate="updateInfo.forceUpdate"
|
||||||
|
@close="closeUpdateDialog"
|
||||||
|
></update-dialog>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -168,8 +193,10 @@
|
|||||||
import LoginRegister from './LoginRegister.vue';
|
import LoginRegister from './LoginRegister.vue';
|
||||||
import DataStatistics from './DataStatistics.vue';
|
import DataStatistics from './DataStatistics.vue';
|
||||||
import CustomerManagement from './CustomerManagement.vue';
|
import CustomerManagement from './CustomerManagement.vue';
|
||||||
|
import UpdateDialog from './UpdateDialog.vue';
|
||||||
import { hasValidToken, clearToken, redirectToLogin } from '../api/utils/auth';
|
import { hasValidToken, clearToken, redirectToLogin } from '../api/utils/auth';
|
||||||
import { request } from '../api/config';
|
import { request, APP_CONFIG } from '../api/config';
|
||||||
|
import { appApi } from '../api/modules/app';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SideMenu",
|
name: "SideMenu",
|
||||||
@@ -179,7 +206,8 @@
|
|||||||
SystemSettings,
|
SystemSettings,
|
||||||
LoginRegister,
|
LoginRegister,
|
||||||
DataStatistics,
|
DataStatistics,
|
||||||
CustomerManagement
|
CustomerManagement,
|
||||||
|
UpdateDialog
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
show: {
|
show: {
|
||||||
@@ -204,7 +232,20 @@
|
|||||||
showCustomerManagementPage: false,
|
showCustomerManagementPage: false,
|
||||||
showLoginPageFlag: false,
|
showLoginPageFlag: false,
|
||||||
isLoggedIn: false, // 用户登录状态
|
isLoggedIn: false, // 用户登录状态
|
||||||
userInfo: null // 用户信息
|
userInfo: null, // 用户信息
|
||||||
|
// 版本信息
|
||||||
|
currentVersion: APP_CONFIG.version, // 当前版本
|
||||||
|
latestVersion: '', // 最新版本
|
||||||
|
hasNewVersion: false, // 是否有新版本
|
||||||
|
checkingUpdate: false, // 是否正在检查更新
|
||||||
|
// 更新弹窗
|
||||||
|
showUpdateDialog: false,
|
||||||
|
updateInfo: {
|
||||||
|
version: '',
|
||||||
|
updateContent: '',
|
||||||
|
downloadUrl: '',
|
||||||
|
forceUpdate: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -454,6 +495,83 @@
|
|||||||
showSettings() {
|
showSettings() {
|
||||||
// 显示系统设置页面
|
// 显示系统设置页面
|
||||||
this.showSystemSettingsPage = true;
|
this.showSystemSettingsPage = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 版本号比较函数
|
||||||
|
// 返回值: 1表示v1>v2, -1表示v1<v2, 0表示相等
|
||||||
|
compareVersion(v1, v2) {
|
||||||
|
const arr1 = v1.split('.').map(Number);
|
||||||
|
const arr2 = v2.split('.').map(Number);
|
||||||
|
const maxLen = Math.max(arr1.length, arr2.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < maxLen; i++) {
|
||||||
|
const num1 = arr1[i] || 0;
|
||||||
|
const num2 = arr2[i] || 0;
|
||||||
|
|
||||||
|
if (num1 > num2) return 1;
|
||||||
|
if (num1 < num2) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查更新
|
||||||
|
async handleCheckUpdate() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (this.checkingUpdate) {
|
||||||
|
return; // 正在检查中,避免重复请求
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkingUpdate = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('开始检查更新,当前版本:', this.currentVersion);
|
||||||
|
const res = await appApi.checkUpdate();
|
||||||
|
console.log('更新检测结果:', res);
|
||||||
|
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
const data = res.data;
|
||||||
|
this.latestVersion = data.version || '';
|
||||||
|
|
||||||
|
// 比较版本号
|
||||||
|
const compareResult = this.compareVersion(this.latestVersion, this.currentVersion);
|
||||||
|
|
||||||
|
if (compareResult > 0) {
|
||||||
|
// 线上版本大于本地版本
|
||||||
|
this.hasNewVersion = true;
|
||||||
|
|
||||||
|
// 设置更新信息并显示自定义弹窗
|
||||||
|
this.updateInfo = {
|
||||||
|
version: data.version || '',
|
||||||
|
updateContent: data.updateContent || '',
|
||||||
|
downloadUrl: data.downloadUrl ? data.downloadUrl.trim() : '',
|
||||||
|
forceUpdate: data.forceUpdate || false
|
||||||
|
};
|
||||||
|
this.showUpdateDialog = true;
|
||||||
|
} else {
|
||||||
|
// 已是最新版本
|
||||||
|
this.hasNewVersion = false;
|
||||||
|
uni.showToast({
|
||||||
|
title: '已是最新版本',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('检查更新失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '检查更新失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this.checkingUpdate = false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关闭更新弹窗
|
||||||
|
closeUpdateDialog() {
|
||||||
|
this.showUpdateDialog = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
556
Store_vue/components/UpdateDialog.vue
Normal file
556
Store_vue/components/UpdateDialog.vue
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
<template>
|
||||||
|
<view class="update-dialog-mask" v-if="show" @tap.stop="handleMaskClick">
|
||||||
|
<view class="update-dialog-container" @tap.stop>
|
||||||
|
<!-- 火箭图标 -->
|
||||||
|
<view class="rocket-container">
|
||||||
|
<view class="rocket-wrapper">
|
||||||
|
<!-- 火箭 SVG 图片 -->
|
||||||
|
<image class="rocket-svg" :src="rocketBase64" mode="aspectFit"></image>
|
||||||
|
|
||||||
|
<!-- 火焰效果 -->
|
||||||
|
<view class="flame-container">
|
||||||
|
<view class="flame flame-1"></view>
|
||||||
|
<view class="flame flame-2"></view>
|
||||||
|
<view class="flame flame-3"></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 星星装饰 -->
|
||||||
|
<view class="star star-1"></view>
|
||||||
|
<view class="star star-2"></view>
|
||||||
|
<view class="star star-3"></view>
|
||||||
|
<view class="star star-4"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<view class="dialog-content">
|
||||||
|
|
||||||
|
<!-- 强制更新提示 -->
|
||||||
|
<view class="force-notice" v-if="forceUpdate">
|
||||||
|
<text class="force-notice-icon">⚠️</text>
|
||||||
|
<text class="force-notice-text">本次为重要更新,需要立即升级</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 更新内容 -->
|
||||||
|
<view class="update-content">
|
||||||
|
<text class="update-item" v-for="(item, index) in updateList" :key="index">{{ index + 1 }}.{{ item }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 下载进度 -->
|
||||||
|
<view class="progress-container" v-if="downloading">
|
||||||
|
<view class="progress-bar">
|
||||||
|
<view class="progress-fill" :style="{width: downloadProgress + '%'}"></view>
|
||||||
|
</view>
|
||||||
|
<text class="progress-text">{{ downloadProgress }}%</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 按钮 -->
|
||||||
|
<view class="button-container" v-if="!downloading">
|
||||||
|
<button class="update-button" @tap="handleUpdate">即刻升级</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 下载中按钮 -->
|
||||||
|
<view class="button-container" v-else>
|
||||||
|
<button class="update-button downloading">下载中...</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 关闭按钮 -->
|
||||||
|
<view class="close-button" @tap="handleClose" v-if="!forceUpdate && !downloading">
|
||||||
|
<text class="close-icon">×</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'UpdateDialog',
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
updateContent: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
downloadUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
forceUpdate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
downloading: false,
|
||||||
|
downloadProgress: 0,
|
||||||
|
downloadTask: null,
|
||||||
|
// 火箭 SVG 的 base64 图片
|
||||||
|
rocketBase64: 'data:image/svg+xml;base64,PHN2ZyB0PSIxNzYxODA0ODYyMzIwIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjIwNDAiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNMzk1LjI2NCAzMDQuMTI4Yy03MC42NTYgOTIuMTYtMTQ1LjQwOCAxOTQuNTYtMTg5LjQ0IDMwNC4xMjgtNS4xMiAxMi4yODggNi4xNDQgMjMuNTUyIDE4LjQzMiAyMC40OEwzNTguNCA1OTAuODQ4TTYyOC43MzYgMzA0LjEyOGM3MC42NTYgOTIuMTYgMTQ1LjQwOCAxOTQuNTYgMTg5LjQ0IDMwNC4xMjggNS4xMiAxMi4yODgtNi4xNDQgMjMuNTUyLTE4LjQzMiAyMC40OEw2NjUuNiA1OTAuODQ4IiBmaWxsPSIjRjc5ODM5IiBwLWlkPSIyMDQxIj48L3BhdGg+PHBhdGggZD0iTTY3Ni44NjQgNzExLjY4SDM0NS4wODhDMzE4LjQ2NCA2MjQuNjQgMzEyLjMyIDUzMi40OCAzMzEuNzc2IDQ0My4zOTJjMjIuNTI4LTEwMS4zNzYgNzAuNjU2LTE5Ny42MzIgMTQwLjI4OC0yNzcuNTA0bDcuMTY4LTguMTkyYzE2LjM4NC0xOS40NTYgNDYuMDgtMTkuNDU2IDYyLjQ2NCAwbDcuMTY4IDguMTkyYzcwLjY1NiA3OS44NzIgMTE3Ljc2IDE3Ni4xMjggMTQwLjI4OCAyNzcuNTA0IDIwLjQ4IDg5LjA4OCAxNC4zMzYgMTgxLjI0OC0xMi4yODggMjY4LjI4OHoiIGZpbGw9IiMwMDRGRkYiIHAtaWQ9IjIwNDIiPjwvcGF0aD48cGF0aCBkPSJNNDY3Ljk2OCA2NzUuODRjLTUxLjIgMC05NS4yMzItMzcuODg4LTEwMi40LTg4LjA2NC04LjE5Mi02MC40MTYtNi4xNDQtMTIwLjgzMiA2LjE0NC0xODAuMjI0IDIxLjUwNC05NS4yMzIgNjQuNTEyLTE4NS4zNDQgMTI2Ljk3Ni0yNjIuMTQ0LTguMTkyIDIuMDQ4LTE1LjM2IDYuMTQ0LTIwLjQ4IDEyLjI4OGwtNy4xNjggOC4xOTJDNDAyLjQzMiAyNDUuNzYgMzU0LjMwNCAzNDAuOTkyIDMzMS43NzYgNDQzLjM5MiAzMTIuMzIgNTMyLjQ4IDMxOC40NjQgNjI0LjY0IDM0NS4wODggNzExLjY4aDMzMS43NzZjNC4wOTYtMTIuMjg4IDcuMTY4LTIzLjU1MiAxMC4yNC0zNS44NEg0NjcuOTY4eiIgZmlsbD0iIzFENkZGRiIgcC1pZD0iMjA0MyI+PC9wYXRoPjxwYXRoIGQ9Ik0zODEuOTUyIDcyMS45MmgyMzYuNTQ0Vjc3OC4yNEgzODEuOTUyeiIgZmlsbD0iIzAwNEZGRiIgcC1pZD0iMjA0NCI+PC9wYXRoPjxwYXRoIGQ9Ik01MTQuNjk5Mjc2MjUgNDc0LjA2MzEyNjMxSDUwOC42MTAyMTEyM2wzLjA0NDUzMjUxIDIuODg3NTk3ODV6IiBmaWxsPSIjZmZmZmZmIiBwLWlkPSIyMDQ1Ij48L3BhdGg+PHBhdGggZD0iTTQzMC4wOCA0MjcuMDA4YTgwLjg5NiA3OS44NzIgMCAxIDAgMTYxLjc5MiAwIDgwLjg5NiA3OS44NzIgMCAxIDAgLTE2MS43OTIgMFoiIGZpbGw9IiNFOUYzRkIiIHAtaWQ9IjIwNDYiPjwvcGF0aD48L3N2Zz4='
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
updateList() {
|
||||||
|
if (!this.updateContent) {
|
||||||
|
return ['修复已知问题', '优化用户体验', '提升系统稳定性'];
|
||||||
|
}
|
||||||
|
// 将更新内容按换行或分号分割
|
||||||
|
return this.updateContent.split(/[\n;;]/).filter(item => item.trim());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleMaskClick() {
|
||||||
|
if (!this.forceUpdate && !this.downloading) {
|
||||||
|
this.handleClose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClose() {
|
||||||
|
if (this.forceUpdate || this.downloading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('close');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUpdate() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (this.downloading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.downloadUrl) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '下载地址无效',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.downloading = true;
|
||||||
|
this.downloadProgress = 0;
|
||||||
|
|
||||||
|
// 创建下载任务
|
||||||
|
const downloadTask = uni.downloadFile({
|
||||||
|
url: this.downloadUrl.trim(),
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
console.log('下载成功,文件路径:', res.tempFilePath);
|
||||||
|
// 下载完成,安装应用
|
||||||
|
this.installApp(res.tempFilePath);
|
||||||
|
} else {
|
||||||
|
console.error('下载失败,状态码:', res.statusCode);
|
||||||
|
uni.showToast({
|
||||||
|
title: '下载失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
this.downloading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('下载失败:', err);
|
||||||
|
uni.showToast({
|
||||||
|
title: '下载失败,请稍后重试',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
this.downloading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听下载进度
|
||||||
|
downloadTask.onProgressUpdate((res) => {
|
||||||
|
this.downloadProgress = res.progress;
|
||||||
|
console.log('下载进度:', res.progress + '%');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.downloadTask = downloadTask;
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
installApp(filePath) {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
console.log('开始安装应用:', filePath);
|
||||||
|
plus.runtime.install(
|
||||||
|
filePath,
|
||||||
|
{
|
||||||
|
force: false
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
console.log('安装成功');
|
||||||
|
uni.showToast({
|
||||||
|
title: '安装成功,请重启应用',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
|
||||||
|
// 安装成功后关闭弹窗
|
||||||
|
setTimeout(() => {
|
||||||
|
this.downloading = false;
|
||||||
|
this.downloadProgress = 0;
|
||||||
|
this.$emit('close');
|
||||||
|
|
||||||
|
// 如果是强制更新,重启应用
|
||||||
|
if (this.forceUpdate) {
|
||||||
|
plus.runtime.restart();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.error('安装失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '安装失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
this.downloading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 组件销毁时,取消下载任务
|
||||||
|
if (this.downloadTask) {
|
||||||
|
this.downloadTask.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.update-dialog-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-dialog-container {
|
||||||
|
width: 580rpx;
|
||||||
|
background: linear-gradient(180deg, #4A9FF5 0%, #2E7FD9 100%);
|
||||||
|
border-radius: 32rpx;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rocket-container {
|
||||||
|
position: absolute;
|
||||||
|
top: -120rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rocket-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
animation: rocketFloat 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 火箭 SVG 图片 */
|
||||||
|
.rocket-svg {
|
||||||
|
position: absolute;
|
||||||
|
top: 10rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 火焰容器 */
|
||||||
|
.flame-container {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 60rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 火焰效果 */
|
||||||
|
.flame {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: flameFlicker 0.3s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flame-1 {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
background: radial-gradient(ellipse at center, #FCD34D 0%, #FBBF24 50%, transparent 80%);
|
||||||
|
top: 0;
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flame-2 {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background: radial-gradient(ellipse at center, #FBBF24 0%, #F59E0B 50%, transparent 80%);
|
||||||
|
top: 15rpx;
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flame-3 {
|
||||||
|
width: 20rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
background: radial-gradient(ellipse at center, #F59E0B 0%, #EF4444 50%, transparent 80%);
|
||||||
|
top: 30rpx;
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 星星装饰 */
|
||||||
|
.star {
|
||||||
|
position: absolute;
|
||||||
|
width: 8rpx;
|
||||||
|
height: 8rpx;
|
||||||
|
background: #FCD34D;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 10rpx #FCD34D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-1 {
|
||||||
|
top: 30rpx;
|
||||||
|
left: 20rpx;
|
||||||
|
animation: starTwinkle 2s ease-in-out infinite;
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-2 {
|
||||||
|
top: 50rpx;
|
||||||
|
right: 15rpx;
|
||||||
|
animation: starTwinkle 2s ease-in-out infinite;
|
||||||
|
animation-delay: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-3 {
|
||||||
|
top: 80rpx;
|
||||||
|
left: 10rpx;
|
||||||
|
animation: starTwinkle 1.5s ease-in-out infinite;
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-4 {
|
||||||
|
top: 100rpx;
|
||||||
|
right: 20rpx;
|
||||||
|
animation: starTwinkle 1.5s ease-in-out infinite;
|
||||||
|
animation-delay: 1.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画定义 */
|
||||||
|
@keyframes rocketFloat {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-15rpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flameFlicker {
|
||||||
|
0% {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scaleY(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes starTwinkle {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 0.3;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
padding: 50rpx 40rpx 40rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
margin-top: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-tag {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
padding: 4rpx 16rpx;
|
||||||
|
background: linear-gradient(135deg, #FF6B6B 0%, #FF4757 100%);
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 20rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
font-weight: normal;
|
||||||
|
animation: tagPulse 1.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tagPulse {
|
||||||
|
0%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
box-shadow: 0 0 0 0 rgba(255, 71, 87, 0.7);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 0 0 8rpx rgba(255, 71, 87, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-notice {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
background: linear-gradient(135deg, #FFF5F5 0%, #FFE5E5 100%);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
border: 2rpx solid #FFB8B8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-notice-icon {
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-notice-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #FF4757;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-content {
|
||||||
|
background: #F8F9FA;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
max-height: 300rpx;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-item {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666666;
|
||||||
|
line-height: 44rpx;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 12rpx;
|
||||||
|
background: #E5E7EB;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #4A9FF5 0%, #2E7FD9 100%);
|
||||||
|
border-radius: 6rpx;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #4A9FF5;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
background: linear-gradient(135deg, #4A9FF5 0%, #2E7FD9 100%);
|
||||||
|
border-radius: 44rpx;
|
||||||
|
border: none;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(46, 127, 217, 0.4);
|
||||||
|
|
||||||
|
&.downloading {
|
||||||
|
background: #CCCCCC;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -120rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 2rpx solid rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-icon {
|
||||||
|
font-size: 60rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
131
Store_vue/components/UpdateModal.vue
Normal file
131
Store_vue/components/UpdateModal.vue
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
<template>
|
||||||
|
<view class="update-modal" v-if="show" @tap.stop="handleMaskClick">
|
||||||
|
<view class="modal-content" @tap.stop>
|
||||||
|
<!-- 版本号标题 -->
|
||||||
|
<view class="version-title">发现新版本 {{ version }}</view>
|
||||||
|
|
||||||
|
<!-- 更新内容 -->
|
||||||
|
<view class="update-content">
|
||||||
|
<text class="content-text">{{ updateContent }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 按钮区域 -->
|
||||||
|
<view class="button-area">
|
||||||
|
<view class="cancel-btn" v-if="!forceUpdate" @tap="handleCancel">稍后再说</view>
|
||||||
|
<view class="confirm-btn" @tap="handleConfirm">立即更新</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'UpdateModal',
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
updateContent: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
downloadUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
forceUpdate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleMaskClick() {
|
||||||
|
// 强制更新时,点击遮罩不关闭
|
||||||
|
if (!this.forceUpdate) {
|
||||||
|
this.handleCancel();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCancel() {
|
||||||
|
this.$emit('cancel');
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
this.$emit('confirm', this.downloadUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.update-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
width: 600rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.version-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
padding: 60rpx 40rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-content {
|
||||||
|
max-height: 600rpx;
|
||||||
|
padding: 0 40rpx 40rpx;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 44rpx;
|
||||||
|
color: #666666;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-area {
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #eeeeee;
|
||||||
|
|
||||||
|
.cancel-btn,
|
||||||
|
.confirm-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 100rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
color: #999999;
|
||||||
|
border-right: 1px solid #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
color: #007aff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
"name" : "AI数智员工",
|
"name" : "AI数智员工",
|
||||||
"appid" : "__UNI__9421F6C",
|
"appid" : "__UNI__9421F6C",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "1.0.1",
|
"versionName" : "1.1.0",
|
||||||
"versionCode" : "100",
|
"versionCode" : 100,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
@@ -107,5 +107,17 @@
|
|||||||
},
|
},
|
||||||
"vueVersion" : "2",
|
"vueVersion" : "2",
|
||||||
"locale" : "zh-Hans",
|
"locale" : "zh-Hans",
|
||||||
"fallbackLocale" : "zh-Hans"
|
"fallbackLocale" : "zh-Hans",
|
||||||
|
/* H5特有相关 */
|
||||||
|
"h5" : {
|
||||||
|
"router" : {
|
||||||
|
"mode" : "hash",
|
||||||
|
"base" : "./"
|
||||||
|
},
|
||||||
|
"title" : "AI数智员工",
|
||||||
|
"devServer" : {
|
||||||
|
"port" : 8080,
|
||||||
|
"disableHostCheck" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
},
|
},
|
||||||
"pages": [
|
"pages": [
|
||||||
{
|
{
|
||||||
"path": "pages/chat/index",
|
"path": "pages/login/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "AI数智员工",
|
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/login/index",
|
"path": "pages/chat/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
"navigationBarTitleText": "AI数智员工",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,80 +1,214 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="login-page">
|
<view class="login-page">
|
||||||
<!-- 页面顶部导航 -->
|
|
||||||
<view class="page-header">
|
<!-- #ifdef APP-PLUS -->
|
||||||
<view class="back-btn"></view>
|
<!-- APP端:返回按钮(仅显示登录表单时) -->
|
||||||
<view class="page-title">登录/注册</view>
|
<view class="back-button" v-if="showLoginForm" @tap="handleBack">
|
||||||
|
<u-icon name="arrow-left" size="24" color="#333"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- APP端:主界面 -->
|
||||||
<view class="content-area">
|
<view class="main-screen" v-if="!showLoginForm">
|
||||||
<!-- 登录标题 -->
|
<!-- Logo 区域 -->
|
||||||
<view class="login-title">账号密码登录</view>
|
<view class="logo-section">
|
||||||
|
<image class="logo-image" src="/static/logo.png" mode="aspectFit"></image>
|
||||||
<!-- 账号输入 -->
|
<text class="app-title">AI数智员工</text>
|
||||||
<view class="form-item">
|
|
||||||
<view class="input-item">
|
|
||||||
<u-input
|
|
||||||
v-model="account"
|
|
||||||
placeholder="请输入账号"
|
|
||||||
class="input-field"
|
|
||||||
border="0"
|
|
||||||
prefixIcon="account"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 密码输入 -->
|
<!-- 主按钮区域 -->
|
||||||
<view class="form-item">
|
<view class="main-buttons">
|
||||||
<view class="input-item">
|
<!-- 免密登录按钮 -->
|
||||||
<u-input
|
<u-button
|
||||||
:type="passwordVisible ? 'text' : 'password'"
|
text="免密登录"
|
||||||
v-model="password"
|
type="primary"
|
||||||
placeholder="请输入密码"
|
shape="circle"
|
||||||
class="input-field"
|
@click="showQuickLogin"
|
||||||
border="0"
|
:custom-style="{width: '100%', marginBottom: '30rpx', backgroundColor: '#4A90E2'}"
|
||||||
prefixIcon="lock"
|
></u-button>
|
||||||
/>
|
|
||||||
<view class="password-icon" @tap="passwordVisible = !passwordVisible">
|
<!-- 账号登录按钮 -->
|
||||||
<u-icon :name="passwordVisible ? 'eye' : 'eye-off'" size="20" color="#999"></u-icon>
|
<u-button
|
||||||
</view>
|
text="账号登录"
|
||||||
</view>
|
shape="circle"
|
||||||
|
:hairline="false"
|
||||||
|
@click="showAccountLogin"
|
||||||
|
:custom-style="{width: '100%', backgroundColor: '#f5f5f5', color: '#666', border: 'none'}"
|
||||||
|
></u-button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 用户协议 -->
|
<!-- 用户协议 -->
|
||||||
<view class="agreement-container">
|
<view class="agreement-container">
|
||||||
<checkbox-group @change="checkboxChange">
|
<checkbox-group @change="checkboxChange">
|
||||||
<checkbox :value="agreement" :checked="agreement" class="agreement-checkbox" color="#4080ff" />
|
<checkbox :value="agreement" :checked="agreement" class="agreement-checkbox" color="#4A90E2" />
|
||||||
</checkbox-group>
|
</checkbox-group>
|
||||||
<text class="agreement-text">已阅读并同意</text>
|
<text class="agreement-text">阅读并同意</text>
|
||||||
<text class="agreement-link" @tap="openAgreement('user')">用户协议</text>
|
<text class="agreement-link" @tap="openAgreement('user')">《用户协议》</text>
|
||||||
<text class="agreement-text">与</text>
|
<text class="agreement-text">与</text>
|
||||||
<text class="agreement-link" @tap="openAgreement('privacy')">隐私政策</text>
|
<text class="agreement-link" @tap="openAgreement('privacy')">《隐私权限》</text>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 登录按钮 -->
|
|
||||||
<view
|
|
||||||
class="login-btn"
|
|
||||||
:class="{ active: canLogin }"
|
|
||||||
@tap="handleLogin"
|
|
||||||
>
|
|
||||||
登录
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 免密登录按钮 -->
|
|
||||||
<view
|
|
||||||
class="no-password-login-btn"
|
|
||||||
@tap="handleNoPasswordLogin"
|
|
||||||
>
|
|
||||||
免密登录
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 联系我们 -->
|
|
||||||
<view class="contact-us" @tap="contactUs">
|
|
||||||
联系我们
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- APP端:登录表单 -->
|
||||||
|
<view v-if="showLoginForm" class="login-form">
|
||||||
|
<!-- Logo 区域 -->
|
||||||
|
<view class="logo-section-form">
|
||||||
|
<image class="logo-image-form" src="/static/logo.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class="form-title">{{ formTitle }}</text>
|
||||||
|
|
||||||
|
<!-- 账号登录表单 -->
|
||||||
|
<view v-if="loginMode === 'account'" class="form-content">
|
||||||
|
<!-- 账号输入 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<text class="input-label">账号</text>
|
||||||
|
<u-input
|
||||||
|
v-model="account"
|
||||||
|
:clearable="true"
|
||||||
|
placeholder="请输入账号"
|
||||||
|
:border="true"
|
||||||
|
></u-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 密码输入 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<text class="input-label">密码</text>
|
||||||
|
<u-input
|
||||||
|
v-model="password"
|
||||||
|
type="password"
|
||||||
|
:password="!passwordVisible"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
:border="true"
|
||||||
|
>
|
||||||
|
<template slot="suffix">
|
||||||
|
<u-icon
|
||||||
|
:name="passwordVisible ? 'eye-fill' : 'eye-off'"
|
||||||
|
size="22"
|
||||||
|
color="#c0c4cc"
|
||||||
|
@click="passwordVisible = !passwordVisible"
|
||||||
|
></u-icon>
|
||||||
|
</template>
|
||||||
|
</u-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 登录按钮 -->
|
||||||
|
<u-button
|
||||||
|
text="登录"
|
||||||
|
type="primary"
|
||||||
|
shape="circle"
|
||||||
|
:disabled="!canLogin"
|
||||||
|
@click="handleLogin"
|
||||||
|
:custom-style="{marginTop: '60rpx', width: '100%', backgroundColor: '#4A90E2'}"
|
||||||
|
></u-button>
|
||||||
|
|
||||||
|
<!-- 用户协议 -->
|
||||||
|
<view class="agreement-container form-agreement">
|
||||||
|
<checkbox-group @change="checkboxChange">
|
||||||
|
<checkbox :value="agreement" :checked="agreement" class="agreement-checkbox" color="#4A90E2" />
|
||||||
|
</checkbox-group>
|
||||||
|
<text class="agreement-text">阅读并同意</text>
|
||||||
|
<text class="agreement-link" @tap="openAgreement('user')">《用户协议》</text>
|
||||||
|
<text class="agreement-text">与</text>
|
||||||
|
<text class="agreement-link" @tap="openAgreement('privacy')">《隐私权限》</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 免密登录表单 -->
|
||||||
|
<view v-else-if="loginMode === 'quick'" class="form-content">
|
||||||
|
<!-- 设备ID显示(仅用于调试) -->
|
||||||
|
<view class="input-group">
|
||||||
|
<text class="input-label">设备ID</text>
|
||||||
|
<u-input
|
||||||
|
v-model="deviceId"
|
||||||
|
:disabled="true"
|
||||||
|
placeholder="自动获取设备ID"
|
||||||
|
:border="true"
|
||||||
|
></u-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 登录按钮 -->
|
||||||
|
<u-button
|
||||||
|
text="登录"
|
||||||
|
type="primary"
|
||||||
|
shape="circle"
|
||||||
|
:disabled="!deviceId"
|
||||||
|
@click="handleNoPasswordLogin"
|
||||||
|
:custom-style="{marginTop: '60rpx', width: '100%', backgroundColor: '#4A90E2'}"
|
||||||
|
></u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- #ifndef APP-PLUS -->
|
||||||
|
<!-- 非APP端:直接显示账号登录表单 -->
|
||||||
|
<view class="login-form h5-login">
|
||||||
|
<!-- Logo 区域 -->
|
||||||
|
<view class="logo-section-form">
|
||||||
|
<image class="logo-image-form" src="/static/logo.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class="form-title">{{ formTitle }}</text>
|
||||||
|
|
||||||
|
<view class="form-content">
|
||||||
|
<!-- 账号输入 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<text class="input-label">账号</text>
|
||||||
|
<u-input
|
||||||
|
v-model="account"
|
||||||
|
:clearable="true"
|
||||||
|
placeholder="请输入账号"
|
||||||
|
:border="true"
|
||||||
|
></u-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 密码输入 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<text class="input-label">密码</text>
|
||||||
|
<u-input
|
||||||
|
v-model="password"
|
||||||
|
type="password"
|
||||||
|
:password="!passwordVisible"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
:border="true"
|
||||||
|
>
|
||||||
|
<template slot="suffix">
|
||||||
|
<u-icon
|
||||||
|
:name="passwordVisible ? 'eye-fill' : 'eye-off'"
|
||||||
|
size="22"
|
||||||
|
color="#c0c4cc"
|
||||||
|
@click="passwordVisible = !passwordVisible"
|
||||||
|
></u-icon>
|
||||||
|
</template>
|
||||||
|
</u-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 登录按钮 -->
|
||||||
|
<u-button
|
||||||
|
text="登录"
|
||||||
|
type="primary"
|
||||||
|
shape="circle"
|
||||||
|
:disabled="!canLogin"
|
||||||
|
@click="handleLogin"
|
||||||
|
:custom-style="{marginTop: '60rpx', width: '100%', backgroundColor: '#4A90E2'}"
|
||||||
|
></u-button>
|
||||||
|
|
||||||
|
<!-- 用户协议 -->
|
||||||
|
<view class="agreement-container form-agreement">
|
||||||
|
<checkbox-group @change="checkboxChange">
|
||||||
|
<checkbox :value="agreement" :checked="agreement" class="agreement-checkbox" color="#4A90E2" />
|
||||||
|
</checkbox-group>
|
||||||
|
<text class="agreement-text">阅读并同意</text>
|
||||||
|
<text class="agreement-link" @tap="openAgreement('user')">《用户协议》</text>
|
||||||
|
<text class="agreement-text">与</text>
|
||||||
|
<text class="agreement-link" @tap="openAgreement('privacy')">《隐私权限》</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -85,11 +219,19 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
showLoginForm: false, // APP端:是否显示登录表单
|
||||||
|
loginMode: '', // APP端:'account' 或 'quick'
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
showLoginForm: true, // 非APP端:始终显示登录表单
|
||||||
|
loginMode: 'account', // 非APP端:始终为账号登录
|
||||||
|
// #endif
|
||||||
account: '', // 账号
|
account: '', // 账号
|
||||||
password: '', // 密码
|
password: '', // 密码
|
||||||
passwordVisible: false, // 密码是否可见
|
passwordVisible: false, // 密码是否可见
|
||||||
agreement: true, // 是否同意协议
|
agreement: true, // 是否同意协议
|
||||||
deviceId: '' // 设备ID
|
deviceId: '' // 设备ID
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 页面加载时检查token
|
// 页面加载时检查token
|
||||||
@@ -102,15 +244,65 @@
|
|||||||
this.checkTokenStatus();
|
this.checkTokenStatus();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
formTitle() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
return this.loginMode === 'account' ? '账号登录' : '免密登录';
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
return '账号登录';
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
// 验证是否可以登录
|
// 验证是否可以登录
|
||||||
canLogin() {
|
canLogin() {
|
||||||
return this.account &&
|
// #ifdef APP-PLUS
|
||||||
this.password &&
|
if (this.loginMode === 'account') {
|
||||||
this.password.length >= 6 &&
|
return this.account && this.password && this.password.length >= 6 && this.agreement;
|
||||||
this.agreement;
|
} else if (this.loginMode === 'quick') {
|
||||||
|
return this.deviceId && this.agreement;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
return this.account && this.password && this.password.length >= 6 && this.agreement;
|
||||||
|
// #endif
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 返回主界面
|
||||||
|
handleBack() {
|
||||||
|
this.showLoginForm = false;
|
||||||
|
this.loginMode = '';
|
||||||
|
this.account = '';
|
||||||
|
this.password = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
// 免密登录 - 直接登录,不跳转页面
|
||||||
|
async showQuickLogin() {
|
||||||
|
if (!this.agreement) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请先同意用户协议和隐私政策',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接调用免密登录
|
||||||
|
await this.handleNoPasswordLogin();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 显示账号登录表单
|
||||||
|
showAccountLogin() {
|
||||||
|
if (!this.agreement) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请先同意用户协议和隐私政策',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loginMode = 'account';
|
||||||
|
this.showLoginForm = true;
|
||||||
|
},
|
||||||
|
|
||||||
// 获取设备ID(仅APP端)
|
// 获取设备ID(仅APP端)
|
||||||
getDeviceId() {
|
getDeviceId() {
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
@@ -135,10 +327,10 @@
|
|||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifndef APP-PLUS
|
||||||
// H5端不传设备ID
|
// 非APP端不传设备ID
|
||||||
this.deviceId = '';
|
this.deviceId = '';
|
||||||
console.log('H5端不传设备ID');
|
console.log('非APP端不传设备ID');
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -150,17 +342,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 返回上一页
|
|
||||||
goBack() {
|
|
||||||
uni.navigateBack();
|
|
||||||
},
|
|
||||||
|
|
||||||
// 用户协议复选框变化
|
// 用户协议复选框变化
|
||||||
checkboxChange(){
|
checkboxChange(){
|
||||||
this.agreement = !this.agreement
|
this.agreement = !this.agreement
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// 处理登录
|
// 处理登录
|
||||||
async handleLogin() {
|
async handleLogin() {
|
||||||
// 检查是否同意协议
|
// 检查是否同意协议
|
||||||
@@ -211,8 +397,8 @@
|
|||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
console.log('APP端登录 - 设备ID:', this.deviceId);
|
console.log('APP端登录 - 设备ID:', this.deviceId);
|
||||||
// #endif
|
// #endif
|
||||||
// #ifdef H5
|
// #ifndef APP-PLUS
|
||||||
console.log('H5端登录 - 不传设备ID');
|
console.log('非APP端登录 - 不传设备ID');
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
if (response.code === 200) { // 成功code是200
|
if (response.code === 200) { // 成功code是200
|
||||||
@@ -284,7 +470,7 @@
|
|||||||
uni.setStorageSync('token_expired', token_expired);
|
uni.setStorageSync('token_expired', token_expired);
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '免密登录成功',
|
title: '登录成功',
|
||||||
icon: 'success'
|
icon: 'success'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -313,19 +499,12 @@
|
|||||||
|
|
||||||
// 打开协议
|
// 打开协议
|
||||||
openAgreement(type) {
|
openAgreement(type) {
|
||||||
|
// TODO: 跳转到对应的协议页面
|
||||||
|
const title = type === 'user' ? '用户协议' : '隐私权限';
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: `打开${type === 'user' ? '用户协议' : '隐私政策'}`,
|
title: `打开${title}`,
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
// 联系我们
|
|
||||||
contactUs() {
|
|
||||||
uni.showToast({
|
|
||||||
title: '联系方式: zhiqun@qq.com',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 3000
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,132 +513,153 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.login-page {
|
.login-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #fff;
|
background-color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-top: 40px; /* 为状态栏预留空间 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 10px 0;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-btn {
|
/* 返回按钮 */
|
||||||
|
.back-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 15px;
|
top: 40rpx;
|
||||||
width: 30px;
|
left: 30rpx;
|
||||||
height: 30px;
|
z-index: 100;
|
||||||
display: flex;
|
padding: 10rpx;
|
||||||
align-items: center;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-title {
|
/* 主界面 */
|
||||||
text-align: center;
|
.main-screen {
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-area {
|
/* Logo 区域 - 主界面 */
|
||||||
flex: 1;
|
.logo-section {
|
||||||
padding: 0 30px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 120rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-title {
|
.logo-image {
|
||||||
font-size: 24px;
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-title {
|
||||||
|
font-size: 40rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #333;
|
color: #333;
|
||||||
margin: 30px 0 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-item {
|
/* Logo 区域 - 登录表单 */
|
||||||
|
.logo-section-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid #eee;
|
margin-bottom: 60rpx;
|
||||||
padding: 12px 0;
|
|
||||||
min-height: 50px;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.logo-image-form {
|
||||||
flex: 1;
|
width: 200rpx;
|
||||||
height: 24px;
|
height: 200rpx;
|
||||||
font-size: 15px;
|
border-radius: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.password-icon {
|
/* 主按钮区域 */
|
||||||
position: absolute;
|
.main-buttons {
|
||||||
right: 0;
|
padding: 0 60rpx;
|
||||||
padding: 0 5px;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 登录表单 */
|
||||||
|
.login-form {
|
||||||
|
padding: 60rpx;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单内容区域 */
|
||||||
|
.form-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* H5端登录表单 */
|
||||||
|
.h5-login {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-title {
|
||||||
|
font-size: 44rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 60rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 用户协议 */
|
||||||
.agreement-container {
|
.agreement-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 15px 0;
|
justify-content: center;
|
||||||
|
padding: 40rpx 0 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单内的用户协议 */
|
||||||
|
.form-agreement {
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 30rpx 0 0;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agreement {
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agreement-checkbox {
|
.agreement-checkbox {
|
||||||
transform: scale(0.8);
|
transform: scale(0.8);
|
||||||
margin-right: 5px;
|
margin-right: 5rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agreement-text {
|
.agreement-text {
|
||||||
font-size: 13px;
|
font-size: 24rpx;
|
||||||
color: #666;
|
color: #999;
|
||||||
|
margin-left: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agreement-link {
|
.agreement-link {
|
||||||
font-size: 13px;
|
font-size: 24rpx;
|
||||||
color: #4080ff;
|
color: #4A90E2;
|
||||||
|
margin: 0 4rpx;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
.login-btn {
|
|
||||||
height: 44px;
|
|
||||||
line-height: 44px;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #dddddd;
|
|
||||||
color: #ffffff;
|
|
||||||
border-radius: 22px;
|
|
||||||
margin: 20px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn.active {
|
|
||||||
background-color: #4080ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-password-login-btn {
|
|
||||||
height: 44px;
|
|
||||||
line-height: 44px;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #4080ff;
|
|
||||||
border: 1px solid #4080ff;
|
|
||||||
border-radius: 22px;
|
|
||||||
margin: 10px 0 20px;
|
|
||||||
font-size: 16px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-password-login-btn:active {
|
|
||||||
background-color: #f0f5ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-us {
|
|
||||||
text-align: center;
|
|
||||||
color: #999;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 526 KiB |
Reference in New Issue
Block a user