diff --git a/nezha-fronted/src/assets/css/components/common/login.scss b/nezha-fronted/src/assets/css/components/common/login.scss index 0bd129072..a7c6d5b13 100644 --- a/nezha-fronted/src/assets/css/components/common/login.scss +++ b/nezha-fronted/src/assets/css/components/common/login.scss @@ -303,4 +303,62 @@ background: #CECECE; margin-right: 10px; } + .el-carousel__item{ + text-align: center; + } + .nz-license-footer{ + text-align: center; + margin-top: 30px; + margin-bottom: 15px; + .el-pagination{ + font-size: 14px; + .btn-prev, .btn-next{ + color: $--color-text-regular; + font-size: 14px; + margin: 0 5px; + border: none; + background-color: $--background-color-base !important; + border-radius: 50%; + height: 24px; + width: 24px; + } + .number { + font-size: 14px; + margin: 0px; + border: none; + background-color: transparent !important; + } + .number.active{ + color: #FA901C; + } + } + } + .el-carousel__indicators.el-carousel__indicators--horizontal{ + display: none; + } + .el-dialog__header { + border-bottom: 1px solid $--border-color-light; + height: 32px; + line-height: 32px; + .el-dialog__header-title { + font-weight: 600; + } + .top-tool-btn{ + height: 32px; + width: 36px; + padding: 0; + } + .el-dialog__headerbtn{ + line-height: 32px; + } + } + .el-dialog__body{ + + } + .el-button{ + //background-color: $--background-color-1 !important; + background: $--background-color-empty; + border: 1px solid $--border-color-light; + border-color: $--border-color-light; + } } diff --git a/nezha-fronted/src/components/common/login.vue b/nezha-fronted/src/components/common/login.vue index 7cf48f8be..cc03c9a2a 100644 --- a/nezha-fronted/src/components/common/login.vue +++ b/nezha-fronted/src/components/common/login.vue @@ -55,9 +55,14 @@
{{license.warnInfo}}
-
+ +
- + +
+ +
+ + QR code + +
+ + + + +
+
+
+ + + +
+ +
+
+
+ +
+
+
+ + +
{{index+1}} / {{qrCodeNum.length}}
+
+
+
@@ -144,9 +214,14 @@ import QRCode from 'qrcodejs2' import bus from '@/libs/bus.js' import { SVG } from '@svgdotjs/svg.js' import { coordinatePoint } from '@/components/common/js/common' +import VueQr from '@/components/common/vueQR/packages/vue-qr' import { get } from '@/http' +import SparkMD5 from 'spark-md5' export default { name: 'login', + components: { + VueQr + }, data () { return { loginData: { @@ -183,7 +258,20 @@ export default { bgImg: '', // 背景图 constellation: [], requestAnimationFrame: '', - speed: [-1.3, -1, -0.6, -0.3, 0.3, 0.6, 1, 1.3] + speed: [-1.3, -1, -0.6, -0.3, 0.3, 0.6, 1, 1.3], + stateItem: '', + endItem: '', + qrCodeShow: false, + qrCodeArr: [], + qrCodeNum: [], // 逐个加载 qr + totalQrCode: 10, + currentPage: 1, + qrloading: false, + dialogQrType: 'item', + boxWidth: '', + boxHeight: '', + qrWidth: 10, + paddingLeft: 0, } }, methods: { @@ -561,6 +649,119 @@ export default { } else { return false } + }, + closeQrCode () { + this.qrCodeShow = false + }, + openQrcode () { + this.qrCodeArr = [] + this.qrCodeNum = [] + this.qrCodeShow = true + this.qrloading = true + setTimeout(() => { + this.$get('/sys/license/token').then(res => { + this.totalQrCode = Math.ceil(res.data.length / (1024 + 512)) + if (this.totalQrCode < 1) { + this.totalQrCode = 1 + } + const total = this.totalQrCode < 10 ? ('0' + this.totalQrCode) : this.totalQrCode + const totalMD5 = SparkMD5.hashBinary(res.data).slice(0, 8) + const arr = [] + for (let i = 0; i < this.totalQrCode; i++) { + const num = (1024 + 512) + let str1 = res.data.slice(num * i, num * (i + 1)) + const index = i < 10 ? ('0' + (i + 1)) : (i + 1) + const md5 = SparkMD5.hashBinary(str1).slice(0, 8) + str1 = total + '' + index + totalMD5 + md5 + '' + str1 + arr.push(str1) + } + this.qrCodeArr = [] + this.qrCodeNum = arr.map(() => { + return true + }) + arr.forEach((item, index) => { + setTimeout(() => { + this.qrCodeArr.push(item) + this.qrCodeNum[index] = false + }, index * 100) + }) + this.getLayout(arr) + this.qrloading = false + }, error => { + const $self = this + const reader = new FileReader() + reader.onload = function (event) { + const responseText = reader.result + const exception = JSON.parse(responseText) + if (exception.message) { + $self.$message.error(exception.message) + } else { + console.error(error) + } + } + reader.readAsText(error.response.data) + }) + }, 100) + }, + getSrc (index) { + const cas = document.createElement('canvas') + const ctx = cas.getContext('2d') + + cas.width = 100 + cas.height = 100 + ctx.font = 'normal bold 40px Roboto-Regular' + let text = index + 1 + '' + if (text.length < 2) { + text = '0' + text + } + ctx.fillText(text, 25, 65) + // 把画布的内容转换为base64编码格式的图片 + const data = cas.toDataURL('image/png', 1) + return data + }, + setActiveItem (currentPage) { + this.$refs.carousel.setActiveItem('qr-' + (currentPage - 1)) + }, + getLayout () { + try { + this.boxWidth = document.body.offsetWidth - 30 - 40 + this.boxHeight = document.body.offsetHeight - 104 - 50 + } catch (error) {} + return new Promise(resolve => { + let rateMax = 0 + let col = 0 + let row = 0 + for (let i = 1; i <= this.qrCodeNum.length; i++) { + const cols = Math.ceil(this.qrCodeNum.length / i) + const w = this.boxWidth / i + const h = this.boxHeight / cols + const rate = w > h ? h / w : w / h + if (rate > rateMax) { + rateMax = rate + col = cols + row = i + } + } + if (this.qrCodeNum.length) { + while (col * row >= this.qrCodeNum.length) { // 避免出现空白 + row-- + } + } + row++ + if (col === 1 || row === 1) { // 行 或 列有一个为1时 需要调换位置 + const temp = col + col = row + row = temp + } + this.qrWidth = 10 + if (this.boxHeight / col < this.boxWidth / row) { + this.qrWidth = this.boxHeight / col + } else { + this.qrWidth = this.boxWidth / row + } + this.paddingLeft = (this.boxWidth - row * this.qrWidth) / 2 + resolve({ col, row }) + }) } }, watch: {