| | |
| | | <!DOCTYPE html> |
| | | <html lang="en"> |
| | | <html lang="zh-CN"> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>系统登录</title> |
| | | <link rel="stylesheet" href="../static/layui/css/layui.css" media="all"> |
| | | <link rel="icon" type="image/x-icon" href="../static/images/wcs_logo.png" /> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> |
| | | <link rel="icon" type="image/x-icon" href="../static/images/wcs_logo.png"> |
| | | <link rel="stylesheet" href="../static/vue/element/element.css"> |
| | | <link rel="stylesheet" href="../static/css/animate.min.css"> |
| | | <script type="text/javascript" src="../static/layui/layui.js"></script> |
| | | <script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script> |
| | | <style> |
| | | html{ |
| | | height: 100%; |
| | | } |
| | | body.login-bg { |
| | | color: #777; |
| | | height: 100%; |
| | | /*background-image: linear-gradient(to right, #ff9569 0%, #e92758 100%);*/ |
| | | /*background-image: linear-gradient(-90deg, #a2e7f3 0%, #98baee 100%);*/ |
| | | background-image: url("../static/images/login.png"); |
| | | /*background: -webkit-linear-gradient(red, blue); !* Safari 5.1 - 6.0 *!;*/ |
| | | /*background-image: url("../static/image/login_bg.jpg");*/ |
| | | /*background-repeat: no-repeat;*/ |
| | | /*background-size: cover;*/ |
| | | /*background-position: top center;*/ |
| | | [v-cloak] { |
| | | display: none; |
| | | } |
| | | |
| | | #login-wrapper { |
| | | box-sizing:border-box; |
| | | background: #fff; |
| | | position: absolute; |
| | | top: 45%; |
| | | left: 50%; |
| | | margin-top: -210px; |
| | | margin-left: -220px; |
| | | width: 400px; |
| | | min-height: 380px; |
| | | padding: 50px; |
| | | text-align: center; |
| | | border-radius: 5px; |
| | | box-shadow: 0px 0px 10px rgb(168, 165, 165); |
| | | transform-origin: 50% 50%; |
| | | /*animation: loading 1s 0s forwards;*/ |
| | | transform: rotateX(0deg); |
| | | html, |
| | | body { |
| | | min-height: 100%; |
| | | margin: 0; |
| | | font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei", sans-serif; |
| | | } |
| | | |
| | | #login-wrapper h2 { |
| | | color: rgba(64,158,255,0.9); |
| | | font-size: 26px; |
| | | font-weight: bold; |
| | | margin-bottom: 30px; |
| | | body { |
| | | background: |
| | | radial-gradient(900px 420px at 12% 14%, rgba(92, 176, 255, 0.20), transparent 60%), |
| | | radial-gradient(760px 360px at 86% 18%, rgba(54, 208, 177, 0.18), transparent 58%), |
| | | linear-gradient(135deg, rgba(6, 26, 58, 0.84), rgba(7, 38, 73, 0.64)), |
| | | url("../static/images/login.png") center center / cover no-repeat; |
| | | color: #243447; |
| | | } |
| | | |
| | | .layadmin-user-login-body .layui-form-item { |
| | | margin-bottom: 20px; |
| | | .login-shell { |
| | | min-height: 100vh; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 36px 16px; |
| | | box-sizing: border-box; |
| | | position: relative; |
| | | } |
| | | .layadmin-user-login-body .layui-form-item .layui-input { |
| | | height: 42px; |
| | | padding-left: 40px; |
| | | font-size: 16px; |
| | | border: 1px solid #c8cccf; |
| | | color: inherit; |
| | | } |
| | | .login-submit { |
| | | margin-top: 30px; |
| | | } |
| | | .layadmin-user-login-icon { |
| | | |
| | | .login-shell::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 1px; |
| | | top: 1px; |
| | | width: 38px; |
| | | line-height: 40px; |
| | | text-align: center; |
| | | color: #B2B2B2; |
| | | font-size: 18px; |
| | | inset: 0; |
| | | background: |
| | | linear-gradient(120deg, rgba(6, 18, 38, 0.40), transparent 42%), |
| | | linear-gradient(300deg, rgba(16, 66, 98, 0.30), transparent 38%); |
| | | pointer-events: none; |
| | | } |
| | | .layui-btn-normal { |
| | | background-color: rgba(64,158,255,0.9); |
| | | font-size: 20px; |
| | | border-radius: 4px; |
| | | height: 52px; |
| | | |
| | | .login-layout { |
| | | width: min(1180px, 100%); |
| | | display: grid; |
| | | grid-template-columns: minmax(0, 1.1fr) minmax(360px, 430px); |
| | | gap: 28px; |
| | | align-items: stretch; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | .login-lang { |
| | | |
| | | .lang-switch { |
| | | position: fixed; |
| | | top: 20px; |
| | | top: 18px; |
| | | right: 24px; |
| | | z-index: 2; |
| | | z-index: 3; |
| | | } |
| | | .login-lang select { |
| | | min-width: 140px; |
| | | |
| | | .lang-switch select { |
| | | min-width: 144px; |
| | | height: 34px; |
| | | padding: 0 10px; |
| | | border: 1px solid #d6dbe6; |
| | | border-radius: 17px; |
| | | background: rgba(255, 255, 255, 0.92); |
| | | padding: 0 12px; |
| | | border: 1px solid rgba(214, 219, 230, 0.94); |
| | | border-radius: 18px; |
| | | background: rgba(255, 255, 255, 0.94); |
| | | color: #3b4a5a; |
| | | outline: none; |
| | | } |
| | | |
| | | .hero-panel { |
| | | min-height: 620px; |
| | | border-radius: 30px; |
| | | padding: 42px 40px 36px; |
| | | box-sizing: border-box; |
| | | color: #eef5ff; |
| | | position: relative; |
| | | overflow: hidden; |
| | | background: |
| | | radial-gradient(520px 280px at 18% 12%, rgba(116, 193, 255, 0.30), transparent 64%), |
| | | radial-gradient(480px 260px at 92% 88%, rgba(58, 214, 182, 0.26), transparent 60%), |
| | | linear-gradient(155deg, rgba(13, 39, 73, 0.88), rgba(12, 76, 104, 0.62)); |
| | | border: 1px solid rgba(200, 225, 255, 0.18); |
| | | box-shadow: 0 32px 70px rgba(6, 17, 36, 0.32); |
| | | } |
| | | |
| | | .hero-panel::before, |
| | | .hero-panel::after { |
| | | content: ""; |
| | | position: absolute; |
| | | border-radius: 999px; |
| | | background: rgba(255, 255, 255, 0.07); |
| | | } |
| | | |
| | | .hero-panel::before { |
| | | width: 420px; |
| | | height: 420px; |
| | | top: -220px; |
| | | right: -140px; |
| | | } |
| | | |
| | | .hero-panel::after { |
| | | width: 260px; |
| | | height: 260px; |
| | | left: -80px; |
| | | bottom: -120px; |
| | | } |
| | | |
| | | .brand-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | padding: 8px 14px; |
| | | border-radius: 999px; |
| | | background: rgba(255, 255, 255, 0.10); |
| | | border: 1px solid rgba(255, 255, 255, 0.12); |
| | | font-size: 12px; |
| | | letter-spacing: 0.12em; |
| | | text-transform: uppercase; |
| | | } |
| | | |
| | | .brand-chip::before { |
| | | content: ""; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background: #7ff6d6; |
| | | box-shadow: 0 0 0 6px rgba(127, 246, 214, 0.12); |
| | | } |
| | | |
| | | .hero-title { |
| | | margin: 24px 0 14px; |
| | | font-size: 44px; |
| | | line-height: 1.08; |
| | | font-weight: 700; |
| | | letter-spacing: -0.02em; |
| | | } |
| | | |
| | | .hero-subtitle { |
| | | max-width: 560px; |
| | | color: rgba(236, 245, 255, 0.82); |
| | | line-height: 1.8; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .hero-metrics { |
| | | display: grid; |
| | | grid-template-columns: repeat(3, minmax(0, 1fr)); |
| | | gap: 14px; |
| | | margin-top: 34px; |
| | | } |
| | | |
| | | .metric-card { |
| | | padding: 18px 18px 16px; |
| | | border-radius: 20px; |
| | | background: rgba(255, 255, 255, 0.08); |
| | | border: 1px solid rgba(255, 255, 255, 0.10); |
| | | backdrop-filter: blur(8px); |
| | | } |
| | | |
| | | .metric-value { |
| | | font-size: 28px; |
| | | font-weight: 700; |
| | | line-height: 1.1; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .metric-label { |
| | | color: rgba(236, 245, 255, 0.70); |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .hero-footer { |
| | | position: absolute; |
| | | left: 40px; |
| | | right: 40px; |
| | | bottom: 30px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | gap: 16px; |
| | | font-size: 12px; |
| | | color: rgba(236, 245, 255, 0.60); |
| | | } |
| | | |
| | | .login-card { |
| | | width: 100%; |
| | | min-height: 620px; |
| | | border-radius: 30px; |
| | | background: rgba(255, 255, 255, 0.92); |
| | | border: 1px solid rgba(219, 227, 238, 0.96); |
| | | box-shadow: 0 28px 60px rgba(8, 28, 61, 0.18); |
| | | overflow: hidden; |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .login-head { |
| | | padding: 36px 38px 20px; |
| | | } |
| | | |
| | | .login-title { |
| | | margin: 0; |
| | | font-size: 32px; |
| | | font-weight: 700; |
| | | color: #17324f; |
| | | cursor: pointer; |
| | | user-select: none; |
| | | } |
| | | |
| | | .login-subtitle { |
| | | margin-top: 10px; |
| | | color: #6d7f90; |
| | | font-size: 14px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .login-body { |
| | | padding: 0 38px 38px; |
| | | } |
| | | |
| | | .login-form .el-form-item { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .login-form .el-input__inner, |
| | | .login-form .el-button { |
| | | height: 48px; |
| | | line-height: 48px; |
| | | } |
| | | |
| | | .login-form .el-input__prefix { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #91a0b2; |
| | | } |
| | | |
| | | .login-form .el-input__inner { |
| | | border-radius: 16px; |
| | | border-color: rgba(214, 223, 235, 0.94); |
| | | background: rgba(248, 251, 255, 0.84); |
| | | padding-left: 44px; |
| | | } |
| | | |
| | | .login-form .el-input__inner:focus { |
| | | background: #fff; |
| | | border-color: #4a8df0; |
| | | } |
| | | |
| | | .login-submit { |
| | | width: 100%; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | border-radius: 16px; |
| | | margin-top: 6px; |
| | | box-shadow: 0 14px 24px rgba(46, 115, 223, 0.28); |
| | | } |
| | | |
| | | .tools-dialog .el-dialog, |
| | | .text-dialog .el-dialog, |
| | | .upload-dialog .el-dialog { |
| | | border-radius: 20px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .tools-dialog .el-dialog__header, |
| | | .text-dialog .el-dialog__header, |
| | | .upload-dialog .el-dialog__header { |
| | | padding: 18px 20px 12px; |
| | | border-bottom: 1px solid rgba(222, 230, 239, 0.92); |
| | | background: #f8fbff; |
| | | } |
| | | |
| | | .tools-dialog .el-dialog__title, |
| | | .text-dialog .el-dialog__title, |
| | | .upload-dialog .el-dialog__title { |
| | | font-weight: 700; |
| | | color: #243447; |
| | | } |
| | | |
| | | .tools-dialog .el-dialog__body, |
| | | .text-dialog .el-dialog__body, |
| | | .upload-dialog .el-dialog__body { |
| | | padding: 18px 20px 20px; |
| | | } |
| | | |
| | | .tool-group + .tool-group { |
| | | margin-top: 18px; |
| | | padding-top: 18px; |
| | | border-top: 1px solid rgba(235, 240, 246, 0.95); |
| | | } |
| | | |
| | | .tool-title { |
| | | font-weight: 700; |
| | | color: #43576b; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .tool-desc { |
| | | margin-top: 8px; |
| | | font-size: 12px; |
| | | color: #8c9aac; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .tool-actions { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .tool-actions .el-button { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .dialog-text-label { |
| | | font-weight: 700; |
| | | color: #43576b; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .dialog-text-tip { |
| | | margin-bottom: 10px; |
| | | color: #8c9aac; |
| | | font-size: 12px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .text-footer, |
| | | .upload-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-top: 14px; |
| | | } |
| | | |
| | | .text-footer .el-button, |
| | | .upload-footer .el-button { |
| | | min-width: 96px; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | @media (max-width: 640px) { |
| | | .login-shell { |
| | | padding-top: 72px; |
| | | } |
| | | |
| | | .lang-switch { |
| | | right: 12px; |
| | | top: 12px; |
| | | } |
| | | |
| | | .login-head, |
| | | .login-body { |
| | | padding-left: 20px; |
| | | padding-right: 20px; |
| | | } |
| | | |
| | | .login-title { |
| | | font-size: 26px; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 980px) { |
| | | .login-layout { |
| | | grid-template-columns: 1fr; |
| | | max-width: 430px; |
| | | } |
| | | |
| | | .hero-panel { |
| | | min-height: auto; |
| | | padding: 28px 24px 78px; |
| | | } |
| | | |
| | | .hero-title { |
| | | font-size: 32px; |
| | | } |
| | | |
| | | .hero-metrics { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | |
| | | .hero-footer { |
| | | left: 24px; |
| | | right: 24px; |
| | | bottom: 22px; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .login-card { |
| | | min-height: auto; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | <body class="login-bg animsition"> |
| | | <body> |
| | | <div id="app" class="login-shell" v-cloak> |
| | | <div class="lang-switch"> |
| | | <select v-model="currentLocale" aria-label="Language" @change="handleLocaleChange"> |
| | | <option v-for="item in localeOptions" :key="item.tag" :value="item.tag">{{ item.label }}</option> |
| | | </select> |
| | | </div> |
| | | |
| | | <div class="login-lang"> |
| | | <select id="lang-switch" aria-label="Language"></select> |
| | | </div> |
| | | <div id="login-wrapper" class="animate__animated animate__bounceInDown"> |
| | | <header> |
| | | <h2 id="login-title" data-i18n-key="login.title" style="cursor: pointer; user-select: none;">WCS系统V3.0</h2> |
| | | </header> |
| | | <div class="layui-form layadmin-user-login-body"> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-icon layui-icon-cellphone layadmin-user-login-icon"></label> |
| | | <input id="mobile" class="layui-input" type="text" name="mobile" lay-verify="mobile" data-i18n-placeholder-key="login.username" placeholder="账号"> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-icon layui-icon-password layadmin-user-login-icon"></label> |
| | | <input id="password" class="layui-input" type="password" name="password" lay-verify="password" data-i18n-placeholder-key="login.password" placeholder="密码"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item login-submit"> |
| | | <button id="login-button" data-i18n-key="login.submit" class="layui-btn layui-btn-fluid layui-btn-normal" lay-submit="" lay-filter="login">登     录</button> |
| | | </div> |
| | | </div> |
| | | <div id="system-tools-panel" style="display: none; padding: 20px;"> |
| | | <div style="margin-bottom: 18px;"> |
| | | <div data-i18n-key="login.tools.recommended" style="margin-bottom: 10px; color: #666; font-weight: 600;">推荐操作</div> |
| | | <div style="display: flex; flex-wrap: wrap; gap: 12px;"> |
| | | <button data-i18n-key="login.tools.requestCode" class="layui-btn layui-btn-normal layui-btn-sm" id="btn-request-code">获取请求码</button> |
| | | <button data-i18n-key="login.tools.activate" class="layui-btn layui-btn-normal layui-btn-sm" id="btn-activate">一键激活</button> |
| | | </div> |
| | | <div data-i18n-key="login.tools.recommendedDesc" style="margin-top: 8px; color: #999; font-size: 12px;">优先使用“获取请求码”和“一键激活”完成许可证申请与激活。</div> |
| | | </div> |
| | | <div> |
| | | <div data-i18n-key="login.tools.others" style="margin-bottom: 10px; color: #666; font-weight: 600;">其他工具</div> |
| | | <div style="display: flex; flex-wrap: wrap; gap: 12px;"> |
| | | <button data-i18n-key="login.tools.projectName" class="layui-btn layui-btn-primary layui-btn-sm" id="btn-project-name">获取项目名称</button> |
| | | <button data-i18n-key="login.tools.serverInfo" class="layui-btn layui-btn-primary layui-btn-sm" id="btn-server-info">获取系统配置</button> |
| | | <button data-i18n-key="login.tools.uploadLicense" class="layui-btn layui-btn-primary layui-btn-sm" id="btn-upload-license">录入许可证</button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="login-layout"> |
| | | <section class="hero-panel animate__animated animate__fadeInLeft"> |
| | | <div class="brand-chip">Zoneyung WCS</div> |
| | | <div class="hero-title">WCS系统让设备调度、任务执行与现场监控保持在同一套业务链路中。</div> |
| | | <div class="hero-subtitle"> |
| | | Warehouse Control System 面向自动化立体仓库现场执行层,围绕堆垛机、RGV、输送站台、任务指令、 |
| | | 库位状态和日志追踪进行统一调度与可视化管理,帮助仓储系统实现稳定、可追溯、可联动的作业控制。 |
| | | 浙江中扬立库技术有限公司长期专注于自动化立体仓库与智能物流系统建设,覆盖方案设计、软件控制、 |
| | | 设备集成与项目实施交付。 |
| | | </div> |
| | | <div class="hero-metrics"> |
| | | <div class="metric-card"> |
| | | <div class="metric-value">调度</div> |
| | | <div class="metric-label">统一编排现场执行任务</div> |
| | | </div> |
| | | <div class="metric-card"> |
| | | <div class="metric-value">追溯</div> |
| | | <div class="metric-label">作业、设备、日志全链路留痕</div> |
| | | </div> |
| | | <div class="metric-card"> |
| | | <div class="metric-value">集成</div> |
| | | <div class="metric-label">对接WMS、设备与业务规则</div> |
| | | </div> |
| | | </div> |
| | | <div class="hero-footer"> |
| | | <span>浙江中扬立库技术有限公司</span> |
| | | <span>自动化立体仓库与智能物流系统解决方案</span> |
| | | </div> |
| | | </section> |
| | | |
| | | <section class="login-card animate__animated animate__fadeInUp"> |
| | | <div class="login-head"> |
| | | <h1 class="login-title" @click="handleTitleClick">{{ text('login.title', 'WCS系统V3.0') }}</h1> |
| | | <div class="login-subtitle">请输入账号和密码进入系统。</div> |
| | | </div> |
| | | <div class="login-body"> |
| | | <el-form ref="loginForm" class="login-form" :model="loginForm" :rules="loginRules" @submit.native.prevent> |
| | | <el-form-item prop="mobile"> |
| | | <el-input v-model.trim="loginForm.mobile" :placeholder="text('login.username', '账号')" clearable @keyup.enter.native="handleLogin"> |
| | | <i slot="prefix" class="el-input__icon el-icon-user"></i> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item prop="password"> |
| | | <el-input v-model="loginForm.password" type="password" show-password :placeholder="text('login.password', '密码')" @keyup.enter.native="handleLogin"> |
| | | <i slot="prefix" class="el-input__icon el-icon-lock"></i> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-button class="login-submit" type="primary" :loading="loginLoading" @click="handleLogin"> |
| | | {{ text('login.submit', '登录') }} |
| | | </el-button> |
| | | </el-form> |
| | | </div> |
| | | </section> |
| | | </div> |
| | | |
| | | <el-dialog class="tools-dialog" title="系统工具" :visible.sync="toolsDialogVisible" width="560px" :close-on-click-modal="true" append-to-body> |
| | | <div class="tool-group"> |
| | | <div class="tool-title">{{ text('login.tools.recommended', '推荐操作') }}</div> |
| | | <div class="tool-actions"> |
| | | <el-button type="primary" size="small" @click="requestCode">{{ text('login.tools.requestCode', '获取请求码') }}</el-button> |
| | | <el-button type="primary" size="small" plain @click="activateLicense">{{ text('login.tools.activate', '一键激活') }}</el-button> |
| | | </div> |
| | | <div class="tool-desc">{{ text('login.tools.recommendedDesc', '优先使用“获取请求码”和“一键激活”完成许可证申请与激活。') }}</div> |
| | | </div> |
| | | <div class="tool-group"> |
| | | <div class="tool-title">{{ text('login.tools.others', '其他工具') }}</div> |
| | | <div class="tool-actions"> |
| | | <el-button size="small" @click="getProjectName">{{ text('login.tools.projectName', '获取项目名称') }}</el-button> |
| | | <el-button size="small" @click="getServerInfo">{{ text('login.tools.serverInfo', '获取系统配置') }}</el-button> |
| | | <el-button size="small" @click="uploadDialogVisible = true">{{ text('login.tools.uploadLicense', '录入许可证') }}</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <el-dialog class="text-dialog" :title="textDialog.title" :visible.sync="textDialogVisible" width="720px" append-to-body> |
| | | <div class="dialog-text-label">{{ textDialog.label }}</div> |
| | | <div v-if="textDialog.tip" class="dialog-text-tip">{{ textDialog.tip }}</div> |
| | | <el-input v-model="textDialog.text" type="textarea" :rows="10" readonly></el-input> |
| | | <div class="text-footer"> |
| | | <el-button @click="textDialogVisible = false">关闭</el-button> |
| | | <el-button type="primary" @click="copyText">{{ text('copy', '复制') }}</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <el-dialog class="upload-dialog" title="录入许可证" :visible.sync="uploadDialogVisible" width="760px" append-to-body> |
| | | <div class="dialog-text-label">许可证 Base64</div> |
| | | <div class="dialog-text-tip">将许可证服务端返回的 license 字段完整粘贴到这里。</div> |
| | | <el-input v-model.trim="licenseBase64" type="textarea" :rows="10"></el-input> |
| | | <div class="upload-footer"> |
| | | <el-button @click="uploadDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="submitLicense">提交</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </body> |
| | | <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script> |
| | | <script type="text/javascript" src="../static/js/tools/md5.js"></script> |
| | | <script type="text/javascript"> |
| | | |
| | | layui.use(['form','layer'],function () { |
| | | var form = layui.form, |
| | | layer = layui.layer, |
| | | $ = layui.jquery; |
| | | |
| | | function initLanguageSwitch() { |
| | | WCS_I18N.onReady(function (i18n) { |
| | | var select = document.getElementById('lang-switch'); |
| | | var options = i18n.getLocaleOptions(); |
| | | var current = i18n.getLocale(); |
| | | var html = ''; |
| | | var i; |
| | | for (i = 0; i < options.length; i++) { |
| | | html += '<option value="' + options[i].tag + '"' + (options[i].tag === current ? ' selected' : '') + '>' + options[i].label + '</option>'; |
| | | } |
| | | select.innerHTML = html; |
| | | select.onchange = function () { |
| | | i18n.setLocale(this.value); |
| | | }; |
| | | document.title = i18n.t('login.title'); |
| | | }); |
| | | } |
| | | |
| | | initLanguageSwitch(); |
| | | |
| | | // 连续点击三次标题显示隐藏功能 |
| | | var titleClickCount = 0; |
| | | var titleClickTimer = null; |
| | | $('#login-title').click(function() { |
| | | titleClickCount++; |
| | | if (titleClickTimer) { |
| | | clearTimeout(titleClickTimer); |
| | | } |
| | | if (titleClickCount >= 3) { |
| | | titleClickCount = 0; |
| | | openSystemToolsDialog(); |
| | | } else { |
| | | titleClickTimer = setTimeout(function() { |
| | | titleClickCount = 0; |
| | | }, 500); |
| | | } |
| | | }); |
| | | |
| | | function openSystemToolsDialog() { |
| | | layer.open({ |
| | | type: 1, |
| | | title: '系统工具', |
| | | area: ['560px', '300px'], |
| | | shadeClose: true, |
| | | content: $('#system-tools-panel'), |
| | | end: function () { |
| | | $('#system-tools-panel').hide(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function fallbackCopy(text) { |
| | | try { |
| | | var textarea = document.createElement('textarea'); |
| | | textarea.value = text; |
| | | textarea.style.position = 'fixed'; |
| | | textarea.style.opacity = '0'; |
| | | document.body.appendChild(textarea); |
| | | textarea.select(); |
| | | document.execCommand('copy'); |
| | | document.body.removeChild(textarea); |
| | | layer.msg('已复制到剪贴板'); |
| | | } catch (err) { |
| | | layer.msg('复制失败'); |
| | | } |
| | | } |
| | | |
| | | function openTextDialog(title, label, text, tip) { |
| | | var html = '' |
| | | + '<div style="padding:15px 20px 5px 20px;">' |
| | | + '<div style="font-weight:600;margin-bottom:8px;">' + label + '</div>' |
| | | + (tip ? '<div style="color:#999;margin-bottom:8px;">' + tip + '</div>' : '') |
| | | + '<textarea id="dialog-text" readonly style="width:100%;min-height:220px;background:#f7f7f7;border:1px solid #e6e6e6;border-radius:6px;padding:12px;line-height:1.6;resize:none;">' |
| | | + text |
| | | + '</textarea>' |
| | | + '<div class="layui-btn-container" style="text-align:right;margin-top:10px;">' |
| | | + '<button class="layui-btn layui-btn-primary" id="copy-dialog-text">复制</button>' |
| | | + '</div>' |
| | | + '</div>'; |
| | | layer.open({ |
| | | type: 1, |
| | | title: title, |
| | | area: ['720px','460px'], |
| | | shadeClose: true, |
| | | content: html, |
| | | success: function (layero) { |
| | | layero.find('#copy-dialog-text').on('click', function () { |
| | | var value = layero.find('#dialog-text').val(); |
| | | if (navigator.clipboard && navigator.clipboard.writeText) { |
| | | navigator.clipboard.writeText(value).then(function () { |
| | | layer.msg('已复制到剪贴板'); |
| | | }).catch(function () { |
| | | fallbackCopy(value); |
| | | }); |
| | | } else { |
| | | fallbackCopy(value); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 获取请求码 |
| | | $('#btn-request-code').click(function() { |
| | | $.ajax({ |
| | | url: baseUrl + "/license/getRequestCode", |
| | | method: 'GET', |
| | | success: function (res) { |
| | | if (res.code === 200){ |
| | | openTextDialog('获取请求码', '请求码', res.msg || '', '请求码中已包含项目名称,直接发给许可证服务端即可。'); |
| | | } else { |
| | | layer.msg(res.msg || '获取请求码失败'); |
| | | } |
| | | }, |
| | | error: function () { |
| | | layer.msg('获取请求码失败'); |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | // 获取系统配置 |
| | | $('#btn-server-info').click(function() { |
| | | $.ajax({ |
| | | url: baseUrl + "/license/getServerInfos", |
| | | method: 'GET', |
| | | success: function (res) { |
| | | var pretty = ''; |
| | | try { |
| | | pretty = JSON.stringify(res, null, 2); |
| | | } catch (e) { |
| | | pretty = res; |
| | | } |
| | | openTextDialog('获取系统配置', '系统配置信息', pretty, '老项目仍可继续使用这份硬件信息 JSON 申请许可证。'); |
| | | }, |
| | | error: function () { |
| | | layer.msg('获取系统配置信息失败'); |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | // 录入许可证 |
| | | $('#btn-upload-license').click(function () { |
| | | layer.open({ |
| | | type: 1, |
| | | title: '录入许可证', |
| | | area: ['760px', '420px'], |
| | | shadeClose: true, |
| | | content: '' |
| | | + '<div style="padding:15px 20px 5px 20px;">' |
| | | + '<div style="font-weight:600;margin-bottom:8px;">许可证 Base64</div>' |
| | | + '<div style="color:#999;margin-bottom:8px;">将许可证服务端返回的 license 字段完整粘贴到这里。</div>' |
| | | + '<textarea id="license-base64-input" style="width:100%;min-height:240px;background:#fff;border:1px solid #e6e6e6;border-radius:6px;padding:12px;line-height:1.6;resize:none;"></textarea>' |
| | | + '</div>', |
| | | btn: ['提交', '取消'], |
| | | yes: function (index, layero) { |
| | | var license = $.trim(layero.find('#license-base64-input').val()); |
| | | if (!license) { |
| | | layer.msg('许可证内容不能为空'); |
| | | return; |
| | | } |
| | | $.ajax({ |
| | | url: baseUrl + '/license/updateLicense', |
| | | method: 'POST', |
| | | contentType: 'application/json;charset=UTF-8', |
| | | data: JSON.stringify({license: license}), |
| | | success: function (res) { |
| | | if (res.code === 200) { |
| | | layer.close(index); |
| | | layer.msg('许可证更新成功'); |
| | | } else { |
| | | layer.msg(res.msg || '许可证更新失败'); |
| | | } |
| | | }, |
| | | error: function () { |
| | | layer.msg('许可证录入失败'); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | // 一键激活 |
| | | $('#btn-activate').click(function() { |
| | | layer.confirm('确定执行一键激活吗', function(index){ |
| | | layer.close(index); |
| | | $.ajax({ |
| | | url: baseUrl + "/license/activate", |
| | | method: 'POST', |
| | | success: function (res) { |
| | | if (res.code === 200){ |
| | | layer.msg('激活成功'); |
| | | } else { |
| | | layer.msg(res.msg) |
| | | } |
| | | }, |
| | | error: function () { |
| | | layer.msg('激活失败'); |
| | | } |
| | | }); |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | // 获取项目名称 |
| | | $('#btn-project-name').click(function() { |
| | | $.ajax({ |
| | | url: baseUrl + "/license/getProjectName", |
| | | method: 'GET', |
| | | success: function (res) { |
| | | if (res.code === 200){ |
| | | layer.alert(res.msg); |
| | | } else { |
| | | layer.msg(res.msg) |
| | | } |
| | | }, |
| | | error: function () { |
| | | layer.msg('获取项目名称失败'); |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | form.on('submit(login)', function (data) { |
| | | var mobile = $("#mobile").val(); |
| | | if (mobile === "") { |
| | | layer.msg("请输入账号", {offset: '150px'}); |
| | | return; |
| | | } |
| | | var password = $("#password").val(); |
| | | if (password === "") { |
| | | layer.msg("请输入密码", {offset: '150px'}); |
| | | return; |
| | | } |
| | | |
| | | var user = { |
| | | mobile: mobile, |
| | | password: hex_md5(password) |
| | | }; |
| | | $.ajax({ |
| | | url: baseUrl+"/login.action", |
| | | data: user, |
| | | method: 'POST', |
| | | success: function (res) { |
| | | if (res.code === 200){ |
| | | localStorage.setItem("token", res.data.token); |
| | | localStorage.setItem("username", res.data.username); |
| | | window.location.href = "index.html"; |
| | | } else { |
| | | layer.msg(res.msg, {offset: '150px'}); |
| | | } |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | $('body').keydown(function () { |
| | | if (event.keyCode === 13) { |
| | | $("#login-button").click(); |
| | | } |
| | | }); |
| | | |
| | | }); |
| | | </script> |
| | | <script type></script> |
| | | <script type="text/javascript" src="../static/js/common.js?v=20260309_i18n_fix1"></script> |
| | | <script type="text/javascript" src="../static/vue/js/vue.min.js"></script> |
| | | <script type="text/javascript" src="../static/vue/element/element.js"></script> |
| | | <script type="text/javascript" src="../static/js/login/login.js?v=20260310_login_vue"></script> |
| | | </html> |