<route lang="yaml"> meta: title: 网关集成 constant: true layout: false </route> <script lang="ts" setup name="SmGateway"> import type { FormInstance, FormRules } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus' import useUserStore from '@/store/modules/user' import { RSAdecrypt, RSAencrypt } from '@/utils/security' import { getPrivateKey, removePrivateKey } from '@/utils/auth' import JIT_GW_ExtInterface from '/public/smGateway/pnxclient.js' import JIT_AUTHEN from '/public/smGateway/authen.js' import { debounce } from 'lodash-es' // import { fetchGwUrl } from '@/api/smGateway/smGateway' const route = useRoute() const router = useRouter() const userStore = useUserStore() const showKaptcha = ref(false) const publicKey = ref('') // 公钥 const sid = ref('') // sid const haveExe = ref(true) // 是否有安装插件 const preventReclick = ref(0) // 网关认证允许几秒点击一次 const passwordType = ref('password') // 密码类型:password 密码 const form = ref({ username: '', password: '', }) const btnColor = ref('#2af598') const resultForm = ref({ // 认证结果 certAttributeNodeMap: '', // 证书信息 umsAttributeNodeMap: '', // UMS信息 pmsAttributeNodeMap: '', // PMS信息 customAttributeNodeMap: '', // 自定义信息 result: '', // 认证结果 errCode: '', // 错误码 errDesc: '', // 错误描述 }) // 校验规则 const rules: FormRules = reactive({ username: [{ required: true, message: '用户名必填', trigger: ['blur', 'change'] }], password: [{ required: true, message: '密码必填', trigger: ['blur', 'change'] }], })// 前端校验规则 // 获取系统基础配置: 公钥,是否开启验证码 function getBaseConfig() { userStore.getBaseConfig().then((res) => { showKaptcha.value = res.kaptcha publicKey.value = res.publicKey sid.value = res.sid ElMessage({ message: '连接服务器成功', type: 'success', }) }) } // 获取控件版本-如果未安装插件,则提示安装。 const fetchVersion = () => { try { console.log('JIT_GW_ExtInterface', JIT_GW_ExtInterface) const res = JIT_GW_ExtInterface.GetVersion() console.log('new: 获取网关插件版本', res) haveExe.value = true } catch (e) { haveExe.value = false console.log('new: 获取网关版本插件失败, 没有插件') ElMessageBox.confirm( '未安装PNXClient插件,请先下载安装插件?', '警告', { confirmButtonText: '下载并安装', cancelButtonText: '取消', type: 'warning', }, ) .then(() => { installExe() }) .catch(() => { }) } } // 点击安装插件 function installExe() { fetch('./smGateway/PNXClient.exe').then((res: any) => { res.blob().then((blob: any) => { const blobUrl = window.URL.createObjectURL(blob) const filename = 'PNXClient.exe' const a = document.createElement('a') a.href = blobUrl a.download = filename a.click() window.URL.revokeObjectURL(blobUrl) }) }) } // 重新认证 const reAuthentication = () => { resultForm.value = { // 认证结果 certAttributeNodeMap: '', // 证书信息 umsAttributeNodeMap: '', // UMS信息 pmsAttributeNodeMap: '', // PMS信息 customAttributeNodeMap: '', // 自定义信息 result: '', // 认证结果 errCode: '', // 错误码 errDesc: '', // 错误描述 } } // async function authentication() { // const token = '20d8008f-44ee-46dc-ac67-f5eba0dcb493' // localStorage.setItem('token', token) // await userStore.setToken(token) // router.push({ path: '/dashboard' }) // } // 认证 async function authentication() { if (resultForm.value.result === '失败') { reAuthentication() return false } // 1发起随机数请求 const random = JIT_AUTHEN.random() if (random != '') { // 2对随机数做p7签名 const P7SignResutl = JIT_AUTHEN.AuthP7Sign(random) if (P7SignResutl != '') { // 3请求网关认证 const authResult = JIT_AUTHEN.P7certAuth(random, P7SignResutl) // const contextForm = JSON.stringify(authResult) // localStorage.setItem('contextForm', contextForm) if (authResult.isSuccess != null && authResult.isSuccess == 'true') { resultForm.value.result = '成功' resultForm.value.certAttributeNodeMap = authResult.certAttributeNodeMap resultForm.value.umsAttributeNodeMap = authResult.umsAttributeNodeMap resultForm.value.pmsAttributeNodeMap = authResult.pmsAttributeNodeMap resultForm.value.customAttributeNodeMap = authResult.customAttributeNodeMap // ======================认证成功跳转首页======================= const token = authResult.casicToken if (authResult.casicToken) { localStorage.setItem('token', token) await userStore.setToken(token) router.push({ path: '/dashboard' }) } else { ElMessage.warning('该用户未授权,请联系管理员') } } else if (authResult.isSuccess != null && authResult.isSuccess == 'false') { resultForm.value.result = '失败' resultForm.value.errCode = authResult.errCode resultForm.value.errDesc = authResult.errDesc ElMessage.warning(`网关认证失败:${authResult.errDesc}`) resultForm.value.result = '失败' btnColor.value = '#fcbb02' } } else { console.log('验证接口返回空字符串, 验证失败') } } else { resultForm.value.result = '失败' resultForm.value.errDesc = '随机数获取失败!' } } onBeforeMount(async () => { getBaseConfig() fetchVersion() }) onMounted(() => { preventReclick.value = Number(localStorage.getItem('preventReclick')) || 2000 }) </script> <template> <div class="bg-banner" /> <div style="display: flex;justify-content: center;align-items: center;height: 100%;margin-top: -120px;"> <div class="main"> <div class="main-title"> <span style="color: #fff;">安全生产智慧监管系统</span> <!-- <span class="load-span">安</span> <span class="load-span">全</span> <span class="load-span">生</span> <span class="load-span">产</span> <span class="load-span">智</span> <span class="load-span">慧</span> <span class="load-span">监</span> <span class="load-span">管</span> <span class="load-span">系</span> <span class="load-span">统</span> --> </div> <div class="exe"> <!-- <el-result v-if="!haveExe" icon="warning" title="警告提示" sub-title="未安装PNXClient插件,请先下载安装插件"> <template #extra> <el-button type="primary" size="large" @click="installExe"> 下载插件 </el-button> </template> </el-result> --> <!-- <el-result v-if="resultForm.result === '失败'" icon="error" title="认证失败" :sub-title="resultForm.errDesc"> <template #extra> <el-button type="primary" size="large" @click="reAuthentication">重新认证</el-button> </template> </el-result> --> <!-- <el-result v-if="resultForm.result === '成功'" icon="success" title="认证成功"> </el-result> --> <!-- <div v-if="resultForm.result === ''" class="form"> <el-form ref="dataFormRef" label-position="left" label-width="80px" :model="form" :rules="rules" > <el-row :gutter="24"> <el-col :span="24"> <el-form-item label="用户名" prop="oldpassword"> <el-input v-model.trim="form.username" disabled placeholder="请输入用户名" /> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="密码" prop="oldpassword"> <el-input v-model="form.password" disabled placeholder="请输入密码" show-password /> </el-form-item> </el-col> <el-col :span="24" style="display: flex;justify-content: center;"> <el-button plain style="margin-top: 32px;" type="primary" size="large" @click="authentication">认证</el-button> </el-col> </el-row> </el-form> </div> --> <div class="button-container"> <button v-prevent-reclick="preventReclick" class="glow-button" :style="{ '--btn-color': btnColor }" @click="authentication"> <span>{{ resultForm.result === '失败' ? '重新认证' : '网关认证' }}</span> <div class="border-lines"> <span class="line top" /> <span class="line right" /> <span class="line bottom" /> <span class="line left" /> </div> </button> </div> </div> </div> </div> </template> <style lang="scss" scoped> .bg-banner { position: fixed; z-index: -1; top: 0; width: 100%; height: 100%; // background: radial-gradient(circle at center, const(--el-fill-color-lighter), const(--el-bg-color-page)); background: url("../assets/images/login-image/bg.png") no-repeat center / cover; } .main { // position: fixed; // width: 500px; // top: 20%; // left: 37%; z-index: 0; .main-title { // text-align: center; // font-size: 30px; // color: #fff; // font-weight: 700; // letter-spacing: 2px; height: 48px; font-size: 52px; font-weight: 800; letter-spacing: 24px; color: black; display: flex; justify-content: center; align-items: center; } .main-title .load-span { animation: text-load17 2.8s linear infinite; } .main-title .load-span:nth-of-type(1) { color: #3185fa; animation-delay: 0.4s; } .main-title .load-span:nth-of-type(2) { color: #38e740; animation-delay: 0.8s; } .main-title .load-span:nth-of-type(3) { color: #fcbb02; animation-delay: 0.12s; } .main-title .load-span:nth-of-type(4) { color: #3285ff; animation-delay: 1.6s; } .main-title .load-span:nth-of-type(5) { color: #2ab148; animation-delay: 2s; } .main-title .load-span:nth-of-type(6) { color: #7737d7; animation-delay: 4s; } .main-title .load-span:nth-of-type(7) { color: #c41dc1; animation-delay: 3.6s; } .main-title .load-span:nth-of-type(8) { color: #20fbae; animation-delay: 1.4s; } .main-title .load-span:nth-of-type(9) { color: #ebe008; animation-delay: 1.8s; } .main-title .load-span:nth-of-type(10) { color: #f03985; animation-delay: 0.8s; } @keyframes text-load17 { 0% { transform: translateY(0); } 50% { transform: translateY(-20px); } 100% { transform: translateY(0); } } .exe { margin-top: 80px; } .form { width: 500px; background: url("../assets//images/login_images/theme2/bg-blue.png") no-repeat center / cover; padding: 50px 30px 20px; border-radius: 8px; margin-top: 20px; } // =========================按钮=================================== .button-container { position: relative; display: flex; justify-content: center; align-items: center; margin-top: 160px; } .glow-button { position: relative; width: 240px; height: 72px; border: none; border-radius: 4px; background: transparent; color: var(--btn-color); font-size: 32px; font-weight: 700; text-align: center; line-height: 72px; cursor: pointer; overflow: hidden; box-shadow: 0 0 1px var(--btn-color); transition: box-shadow 0.3s, background-color 0.3s, color 0.3s; margin-top: 80px; } // .glow-button:hover { // background-color: var(--btn-color); // color: #fff; // box-shadow: 0 0 5px var(--btn-color), 0 0 25px var(--btn-color), 0 0 50px var(--btn-color), 0 0 100px var(--btn-color); // } // .glow-button:active { // background-color: var(--btn-color); // color: #fff; // box-shadow: 0 0 15px var(--btn-color), 0 0 30px var(--btn-color), 0 0 60px var(--btn-color), 0 0 120px var(--btn-color); // transform: scale(0.95); // } .border-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .line { position: absolute; display: block; background: linear-gradient(90deg, transparent, var(--btn-color)); } .top { top: 0; left: -100%; width: 100%; height: 2px; animation: topAnim 4s linear infinite; } @keyframes topAnim { 0% { left: -100%; } 50%, 100% { left: 100%; } } .right { top: -100%; right: 0; width: 2px; height: 100%; animation: rightAnim 4s linear infinite 1s; background: linear-gradient(180deg, transparent, var(--btn-color)); } @keyframes rightAnim { 0% { top: -100%; } 50%, 100% { top: 100%; } } .bottom { bottom: 0; right: -100%; width: 100%; height: 2px; animation: bottomAnim 4s linear infinite 2s; background: linear-gradient(270deg, transparent, var(--btn-color)); } @keyframes bottomAnim { 0% { right: -100%; } 50%, 100% { right: 100%; } } .left { bottom: -100%; left: 0; width: 2px; height: 100%; animation: leftAnim 4s linear infinite 3s; background: linear-gradient(360deg, transparent, var(--btn-color)); } @keyframes leftAnim { 0% { bottom: -100%; } 50%, 100% { bottom: 100%; } } // =========================================================== } </style>