zory 1 tháng trước cách đây
mục cha
commit
49b3887cbc

+ 3 - 3
.env.development

@@ -2,13 +2,13 @@
 NODE_ENV = development
 
 # 标题
-VUE_APP_TITLE = 印美打印
+VUE_APP_TITLE = 交易小程序
 
 # 接口地址
-VUE_APP_API_BASEURL = http://127.0.0.1:8890/api/
+VUE_APP_API_BASEURL = http://127.0.0.1:9881/api/
 
 # 本地端口
-VUE_APP_PORT = 2808
+VUE_APP_PORT = 2908
 
 # 是否开启代理
 VUE_APP_PROXY = true

+ 7 - 0
src/api/model/auth.js

@@ -30,4 +30,11 @@ export default {
 			return await http.get(this.url, data);
 		}
 	},
+	data: {
+		url: `${config.API_URL}/login/data`,
+		name: "-",
+		get: async function(data={}){
+			return await http.get(this.url, data);
+		}
+	},
 }

BIN
src/assets/image/login-broadcast-1.webp


+ 3 - 0
src/components/imFloat/index.vue

@@ -0,0 +1,3 @@
+<template>
+
+</template>

+ 2 - 2
src/config/index.js

@@ -31,7 +31,7 @@ const DEFAULT_CONFIG = {
 
 	//布局 默认:default | 通栏:header | 经典:menu | 功能坞:dock
 	//dock将关闭标签和面包屑栏
-	LAYOUT: 'menu',
+	LAYOUT: 'default',
 
 	//菜单是否折叠
 	MENU_IS_COLLAPSE: false,
@@ -46,7 +46,7 @@ const DEFAULT_CONFIG = {
 	LANG: 'zh-cn',
 
 	//主题颜色
-	COLOR: '#20222A',
+	COLOR: '#1c5cfb',
 
 	//是否加密localStorage, 为空不加密,可填写AES(模式ECB,移位Pkcs7)加密
 	LS_ENCRYPTION: '',

+ 66 - 4
src/layout/index.vue

@@ -203,13 +203,17 @@
 
 	<div class="main-maximize-exit" @click="exitMaximize"><el-icon><el-icon-close /></el-icon></div>
 
-	<!-- <div class="layout-setting" @click="openSetting"><el-icon><el-icon-brush-filled /></el-icon></div>
+	<div class="layout-setting" @click="sendTestNotification">
+		<el-icon><el-icon-chat-round /></el-icon>
+		<span>99</span>
+	</div>
 
 	<el-drawer title="布局实时演示" v-model="settingDialog" :size="400" append-to-body destroy-on-close>
 		<setting></setting>
-	</el-drawer> -->
+	</el-drawer>
 
 	<auto-exit></auto-exit>
+	<imFloat></imFloat>
 </template>
 
 <script>
@@ -221,6 +225,7 @@ import userbar from './components/userbar.vue';
 import setting from './components/setting.vue';
 import iframeView from './components/iframeView.vue';
 import autoExit from './other/autoExit.js';
+import imFloat from '@/components/imFloat/index';
 
 export default {
 	name: 'index',
@@ -232,7 +237,8 @@ export default {
 		userbar,
 		setting,
 		iframeView,
-		autoExit
+		autoExit,
+		imFloat
 	},
 	data() {
 		return {
@@ -243,7 +249,8 @@ export default {
 			userName: "",
 			active: '',
 			baseData: {},
-			userInfo:{}
+			userInfo:{},
+			notificationPermission: 'default'
 		}
 	},
 	computed: {
@@ -272,6 +279,10 @@ export default {
 		var baseData = this.$TOOL.data.get("SERVICE");
 		this.baseData = baseData;
 		this.showThis()
+		// 页面加载时检查权限
+		if (window.Notification && Notification.permission !== 'denied') {
+			this.requestPermission()
+		}
 	},
 	watch: {
 		$route() {
@@ -285,6 +296,57 @@ export default {
 		}
 	},
 	methods: {
+		async requestPermission() {
+			if (!("Notification" in window)) {
+				alert("当前浏览器不支持通知功能")
+				return false
+			}
+			
+			try {
+				const permission = await Notification.requestPermission()
+				this.notificationPermission = permission
+				return permission === "granted"
+			} catch (error) {
+				console.error('请求通知权限失败:', error)
+				return false
+			}
+		},
+		showNotification(title, options = {}) {
+			if (this.notificationPermission !== 'granted') {
+				console.warn('没有通知权限')
+				return null
+			}
+			
+			const notification = new Notification(title, {
+				body: options.body || '',
+				icon: options.icon || '/favicon.ico',
+				tag: options.tag || Date.now().toString(),
+				requireInteraction: options.requireInteraction || false,
+				silent: options.silent || false,
+				...options
+			})
+			
+			// 点击通知回调
+			notification.onclick = () => {
+				window.focus()
+				notification.close()
+				if (options.onClick) options.onClick()
+			}
+			
+			// 关闭通知回调
+			notification.onclose = () => {
+				if (options.onClose) options.onClose()
+			}
+			
+			return notification
+		},
+		sendTestNotification() {
+			this.showNotification('Vue 2 通知', {
+				body: '这是一条测试通知',
+				icon: 'https://vuejs.org/images/logo.png',
+				tag: 'test-notification'
+			})
+		},
 		openSetting() {
 			this.settingDialog = true;
 		},

+ 2 - 2
src/locales/lang/zh-cn.js

@@ -26,7 +26,7 @@ export default {
 		signInFs: "前往飞书授权",
 		signInOther: "其他登录方式",
 		userName: "用户名",
-		PWName: "登录密码",
+		PWName: "密码",
 		code: "验证码",
 		codeErr: "请输入验证码",
 		codeTips: "点击验证码图片可切换",
@@ -49,7 +49,7 @@ export default {
 		wechatLoginTitle: "二维码登录",
 		wechatLoginMsg: "请使用微信扫一扫登录 | 模拟3秒后自动扫描",
 		wechatLoginResult: "已扫描 | 请在设备中点击授权登录",
-		privacy: "请先阅读《隐私协议》",
+		privacy: "请先阅读《用户协议》",
 	},
 	user: {
 		dynamic: "近期动态",

+ 27 - 2
src/style/app.scss

@@ -86,7 +86,17 @@ textarea {
 ::-webkit-scrollbar-track:hover {
 	background-color: rgba(50, 50, 50, 0.2);
 }
-
+@keyframes flash {
+	0% {
+		background-color: #f00;
+	}
+	50% {
+	  transform: scale(1.3); /* 可选:放大效果 */
+	}
+	100% {
+		background-color: #f00;
+	}
+}
 /*布局设置*/
 .layout-setting {
 	position: fixed;
@@ -94,15 +104,30 @@ textarea {
 	height: 40px;
 	border-radius: 3px 0 0 3px;
 	bottom: 100px;
-	right: 0px;
+	right: 20px;
 	z-index: 100;
 	background: #409EFF;
 	display: flex;
+	border-radius: 100%;
 	flex-direction: column;
 	align-items: center;
 	justify-content: center;
 	cursor: pointer;
 }
+.layout-setting span{
+	color: #fff;
+	position: fixed;
+	bottom: 130px;
+	right: 20px;
+	animation: flash 0.5s ease-in-out infinite;
+	background-color: #f00;
+	border-radius: 100%;
+	width: 20px;
+	height: 20px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
 
 .layout-setting i {
 	font-size: 18px;

+ 58 - 247
src/views/login/index.vue

@@ -1,21 +1,26 @@
 <template>
 	<div class="login_bg">
-		<main class="login-main">
-			<section class="login-form">
-				<div class="form-container">
-					<div class="login-for">
-						<div class="tab-menu">
-							<div :class="tabMenu==1?'tab-item active':'tab-item'" @click="menuType(1)">{{ $t('login.accountLogin') }}</div>
+		<div class="login-banner"></div>
+		<div class="login-header"></div>
+		<div class="flex-1">
+			<div class="login-main">
+				<div class="flex-1" style="height: 600px;">
+
+				</div>
+				<div class="login-form">
+					<div class="form-container">
+						<div class="login-for">
+							<div class="tab-menu">
+								<div :class="tabMenu==1?'tab-item active':'tab-item'" @click="menuType(1)">欢迎登录{{ baseData.title?baseData.title:$CONFIG.APP_NAME }}</div>
+							</div>
+							<phoneForm :baseData="baseData" :captcha="captcha" @success="handleSuccess" @upCaptcha="getService" v-if="tabMenu==2"></phoneForm>
+							<passwordForm :baseData="baseData" :captcha="captcha" @success="handleSuccess" @upCaptcha="getService" v-if="tabMenu==1"></passwordForm>
 						</div>
-						<phoneForm :baseData="baseData" :captcha="captcha" @success="handleSuccess" @upCaptcha="getService" v-if="tabMenu==2"></phoneForm>
-						<passwordForm :baseData="baseData" :captcha="captcha" @success="handleSuccess" @upCaptcha="getService" v-if="tabMenu==1"></passwordForm>
 					</div>
 				</div>
-			</section>
-		</main>
-		<footer class="login-footer">
-			{{ baseData.copyright }} <span v-html="baseData.miitbeian"></span> <span v-html="baseData.beian"></span>
-		</footer>
+			</div>
+		</div>
+		<div class="login-footer">{{ baseData.copyright }} <span v-html="baseData.miitbeian"></span> <span v-html="baseData.beian"></span></div>
 	</div>
 </template>
 
@@ -67,7 +72,7 @@ export default {
 			this.islogin = true;
 		},
 		async getService() {
-			var resp = await this.$API.service.data.get();
+			var resp = await this.$API.auth.data.get();
 			if (resp.code == 0) {
 				return this.$message.warning(resp.msg)
 			}
@@ -80,239 +85,45 @@ export default {
 </script>
 
 <style scoped>
-.privacy {
-	color: #333;
-}
-.tab-menu{
-	display: flex;
-	align-items: center;
-	font-size: 20px;
-	font-weight: 400;
-	color: #b6babf;
-	margin-bottom: 30px;
-}
-.tab-menu .line{width: 1px;background-color: #b6babf;margin: 0 15px;height: 20px;}
-.tab-menu .tab-item {cursor: pointer;}
-.tab-menu .tab-item.active{color: #000;font-weight: bold;}
-.showPrivacy {
-	max-height: 500px;
-	overflow: hidden;
-	overflow-y: scroll;
-	line-height: 1.5;
-}
-.privacy span {
-	color: #f00;
-}
-
-.right-tips {
-	width: 143px;
-	height: 37px;
-	position: absolute;
-	top: -42px;
-	right: 0;
-	background-repeat: no-repeat;
-	font-size: 14px;
-	font-weight: 400;
-	color: #2475FC;
-	line-height: 30px;
-	padding-left: 14px;
-}
-
-.right-tips img {
-	vertical-align: middle;
-	margin-right: 5px;
-	width: 20px;
-}
-
-.login-header-tips {
-	margin-bottom: 30px;
-	font-family: var(--font-family);
-}
-
-.login-header-tips h3 {
-	font-size: 28px;
-	color: #333;
-}
-
-.login-header-tips p {
-	font-size: 14px;
-	color: #959595;
-	line-height: 32px;
-}
-
-.loading-box {
-	display: flex;
-	height: 230px;
-}
-
-.login-forgot {
-	text-align: right;
-}
-
-.oauth-logo {
-	width: 100px;
-	height: 100px;
-	text-align: center;
-	border: 1px solid var(--el-color-primary-light-2);
-	border-radius: 100%;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	margin: 0 auto;
-}
-
-.oauth-text {
-	margin: 20px auto;
-	text-align: center;
-	font-size: 14px;
-	color: var(--el-color-primary-light-3);
-}
-
-.el-button--large {
-	--el-button-size: 50px;
-	font-size: 16px;
-	font-weight: 600;
-}
-
-.login-footer {
-	text-align: center;
-	color: #9598a6;
-	font-size: 12px;
-	line-height: 60px;
-}
-
-.right-qrcode-bg {
-	position: absolute;
-	right: -1px;
-	top: -1px;
-	width: 90px;
-	height: 90px;
-	border-radius: 0 10px 0 0;
-	border-color: #f2f7ff #f2f7ff #fff #fff;
-	border-style: solid;
-	border-width: 50px;
-	-webkit-box-sizing: border-box;
-	box-sizing: border-box;
-}
-
-.right-qrcode-user:hover {
-	background-image: url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/account_hover2.png);
-}
-
-.right-qrcode-user {
-	position: absolute;
-	top: 0;
-	right: 0;
-	width: 101px;
-	height: 101px;
-	display: block;
-	background: url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/account_2.png) no-repeat 50%;
-	background-size: 90px;
-	cursor: pointer;
-	z-index: 9;
-}
-
-.right-qrcode:hover {
-	background-image: url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/qrcode_hover2.png);
-}
-
-.right-qrcode {
-	position: absolute;
-	top: 0;
-	right: 0;
-	width: 101px;
-	height: 101px;
-	display: block;
-	background: url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/qrcode2.png) no-repeat 50%;
-	background-size: 90px;
-	cursor: pointer;
-	z-index: 9;
-}
-
-.el-form-item__label {
-	color: #1e2226 !important;
-	font-weight: 600 !important;
-}
-
-.login-main {
-	flex: 1;
-	height: 100%;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-}
-
-.login-form {
-	display: flex;
-	position: relative;
-	justify-content: center;
-	flex: 1;
-	flex-direction: column;
-	align-items: center;
-}
-.login-form .logo {
-	align-items: center;
-	display: flex;
-	font-family: var(--font-family);
-	margin-bottom: 20px;
-}
-
-.login-form .logo img {
-	height: 60px;
-	margin: 0 20px;
-}
-
-.login-form .logo label {
-	font-size: 26px;
-	color: #333;
-}
-
-.login-form h3 {
-	line-height: 28px;
-	margin-top: 12px;
-	font-size: 20px;
-	color: #1e2226;
-	cursor: pointer;
-	font-weight: 600;
-}
-
-.login-form .form-container {
-	width: 420px;
-	box-shadow: 0 20px 30px 0 rgb(63 63 65 / 6%);
-	border-radius: 10px;
-	border: 1px solid #fff;
-	box-sizing: border-box;
-	padding: 40px 40px 30px;
-	background: #fff;
-	position: relative;
-}
-
-.login_bg {
-	background: url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/bg.png) 0 0 no-repeat;
-	background-size: cover;
-	min-height: 680px;
-	height: 100vh;
-	display: flex;
-	flex-direction: column;
-}
-
-.login-header {
-	background: hsla(0, 0%, 100%, .3);
-	box-shadow: 0 2px 20px 0 rgba(140, 147, 161, .07);
-	height: 50px;
-	align-items: center;
-	display: flex;
-}
-
-.login-header img {
-	height: 28px;
-	margin: 0 20px;
-}
-
-.login-header label {
-	font-size: 16px;
-	color: #333;
-}
+.login_bg{position:relative;background-color: rgb(242, 246, 255);display: flex;flex-direction: column;overflow: hidden;height: 100vh;}
+.login-banner{position:absolute;top:50%;left:50%;width:1440px;z-index:1;transform:translate(-50%,-50%);background-image:url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/login-broadcast-1.webp);background-position:center center;background-size:cover;background-repeat:no-repeat;opacity:1;height: 900px;}
+.flex-1{flex: 1 1;}
+.login-main{display: flex;max-width: 1200px;min-height: 700px;height: calc(-150px + 100vh);margin: 0 auto;position: relative;z-index: 99;}
+
+.privacy{color:#333}
+.tab-menu{display:flex;align-items:center;font-size:20px;font-weight:400;color:#b6babf;margin-bottom:30px}
+.tab-menu .line{width:1px;background-color:#b6babf;margin:0 15px;height:20px}
+.tab-menu .tab-item{cursor:pointer}
+.tab-menu .tab-item.active{color:#000;font-weight:bold}
+.showPrivacy{max-height:500px;overflow:hidden;overflow-y:scroll;line-height:1.5}
+.privacy span{color:#f00}
+.right-tips{width:143px;height:37px;position:absolute;top:-42px;right:0;background-repeat:no-repeat;font-size:14px;font-weight:400;color:#2475FC;line-height:30px;padding-left:14px}
+.right-tips img{vertical-align:middle;margin-right:5px;width:20px}
+.login-header-tips{margin-bottom:30px;font-family:var(--font-family)}
+.login-header-tips h3{font-size:28px;color:#333}
+.login-header-tips p{font-size:14px;color:#959595;line-height:32px}
+.loading-box{display:flex;height:230px}
+.login-forgot{text-align:right}
+.oauth-logo{width:100px;height:100px;text-align:center;border:1px solid var(--el-color-primary-light-2);border-radius:100%;display:flex;align-items:center;justify-content:center;margin:0 auto}
+.oauth-text{margin:20px auto;text-align:center;font-size:14px;color:var(--el-color-primary-light-3)}
+.el-button--large{--el-button-size:50px;font-size:16px;font-weight:600}
+.login-footer{text-align:center;color:#9598a6;font-size:12px;line-height:60px}
+.right-qrcode-bg{position:absolute;right:-1px;top:-1px;width:90px;height:90px;border-radius:0 10px 0 0;border-color:#f2f7ff #f2f7ff #fff #fff;border-style:solid;border-width:50px;-webkit-box-sizing:border-box;box-sizing:border-box}
+.right-qrcode-user:hover{background-image:url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/account_hover2.png)}
+.right-qrcode-user{position:absolute;top:0;right:0;width:101px;height:101px;display:block;background:url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/account_2.png) no-repeat 50%;background-size:90px;cursor:pointer;z-index:9}
+.right-qrcode:hover{background-image:url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/qrcode_hover2.png)}
+.right-qrcode{position:absolute;top:0;right:0;width:101px;height:101px;display:block;background:url(https://blue-order.oss-cn-guangzhou.aliyuncs.com/qrcode2.png) no-repeat 50%;background-size:90px;cursor:pointer;z-index:9}
+.el-form-item__label{color:#1e2226!important;font-weight:600!important}
+
+.login-form{display:flex;position:relative;justify-content:center;flex:1;flex-direction:column;align-items:center}
+.login-form .logo{align-items:center;display:flex;font-family:var(--font-family);margin-bottom:20px}
+.login-form .logo img{height:60px;margin:0 20px}
+.login-form .logo label{font-size:26px;color:#333}
+.login-form h3{line-height:28px;margin-top:12px;font-size:20px;color:#1e2226;cursor:pointer;font-weight:600}
+.login-form .form-container{width:420px;box-shadow:0 20px 30px 0 rgb(63 63 65 / 6%);border-radius:10px;border:1px solid #fff;box-sizing:border-box;padding:40px 40px 30px;background:#fff;position:relative}
+.login-header{background:hsla(0,0%,100%,.3);box-shadow:0 2px 20px 0 rgba(140,147,161,.07);height:50px;align-items:center;display:flex}
+.login-header img{height:28px;margin:0 20px}
+.login-header label{font-size:16px;color:#333}
 .login-form:deep(.login-msg-yzm) {display: flex;width: 100%;}
 .login-form:deep(.login-msg-yzm) .el-button {margin-left: 10px;--el-button-size:42px;}
 @media only screen and (max-width: 800px) {

+ 1 - 1
src/views/manage/setting/basic/index.vue

@@ -102,7 +102,7 @@
                 </el-tabs>
             </el-card>
         </el-main>
-        <el-footer style="text-align: right;">
+        <el-footer>
             <el-button type="primary" size="large" :loading="isSaveing" @click="saveForm">保存</el-button>
         </el-footer>
     </el-container>