| | |
| | | { |
| | | "name": "vue3-element-admin", |
| | | "name": "hm-lock", |
| | | "version": "1.0.0", |
| | | "lockfileVersion": 3, |
| | | "requires": true, |
| | | "packages": { |
| | | "": { |
| | | "name": "vue3-element-admin", |
| | | "name": "hm-lock", |
| | | "version": "1.0.0", |
| | | "dependencies": { |
| | | "axios": "^1.7.2", |
| | |
| | | "file-saver": "^2.0.5", |
| | | "fuse.js": "^6.6.2", |
| | | "js-cookie": "^3.0.5", |
| | | "js-md5": "^0.8.3", |
| | | "jsencrypt": "^3.3.2", |
| | | "jszip": "^3.10.1", |
| | | "nprogress": "^0.2.0", |
| | | "path-browserify": "^1.0.1", |
| | |
| | | "node": ">=14" |
| | | } |
| | | }, |
| | | "node_modules/js-md5": { |
| | | "version": "0.8.3", |
| | | "resolved": "https://r.cnpmjs.org/js-md5/-/js-md5-0.8.3.tgz", |
| | | "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==" |
| | | }, |
| | | "node_modules/js-tokens": { |
| | | "version": "9.0.0", |
| | | "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.0.tgz", |
| | |
| | | "js-yaml": "bin/js-yaml.js" |
| | | } |
| | | }, |
| | | "node_modules/jsencrypt": { |
| | | "version": "3.3.2", |
| | | "resolved": "https://r.cnpmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz", |
| | | "integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==" |
| | | }, |
| | | "node_modules/json-buffer": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", |
| | |
| | | "file-saver": "^2.0.5", |
| | | "fuse.js": "^6.6.2", |
| | | "js-cookie": "^3.0.5", |
| | | "js-md5": "^0.8.3", |
| | | "jsencrypt": "^3.3.2", |
| | | "jszip": "^3.10.1", |
| | | "nprogress": "^0.2.0", |
| | | "path-browserify": "^1.0.1", |
| | |
| | | import request from '@/utils/request'; |
| | | import formatPassword from '@/utils/formatPassword.js'; |
| | | |
| | | export function login(data) { |
| | | export function login(uname, usnId) { |
| | | return request({ |
| | | url: '/user/login', |
| | | method: 'post', |
| | | data |
| | | method: 'GET', |
| | | url: '/login/login', |
| | | params: { |
| | | uname, |
| | | usnId: encodeURIComponent(formatPassword(usnId)) |
| | | } |
| | | }); |
| | | } |
| | | |
| | | export function getInfo(token) { |
| | | export function getInfo(uname, usnId) { |
| | | return request({ |
| | | url: '/vue-element-admin/user/info', |
| | | method: 'get', |
| | | params: { token } |
| | | method: 'GET', |
| | | url: '/login/login', |
| | | params: { |
| | | uname, |
| | | usnId: encodeURIComponent(formatPassword(usnId)) |
| | | } |
| | | }); |
| | | } |
| | | |
| | | export function logout(token) { |
| | | return request({ |
| | | url: '/vue-element-admin/user/logout', |
| | | method: 'post', |
| | | params: { token } |
| | | url: '/login/logout', |
| | | method: 'post' |
| | | }); |
| | | } |
| | |
| | | import { mapState } from 'pinia'; |
| | | import store from '@/store'; |
| | | import { defineComponent } from 'vue'; |
| | | import changeTheme from '@/utils/changeTheme.js'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'LayoutIndex', |
| | |
| | | Sidebar, |
| | | TagsView |
| | | }, |
| | | watch: { |
| | | theme() { |
| | | changeTheme(this.theme); |
| | | } |
| | | }, |
| | | mixins: [ResizeMixin], |
| | | computed: { |
| | | ...mapState(store.app, ['sidebar', 'device']), |
| | | ...mapState(store.settings, { |
| | | theme: 'theme', |
| | | showSettings: 'showSettings', |
| | | needTagsView: 'tagsView', |
| | | fixedHeader: 'fixedHeader' |
| | |
| | | handleClickOutside() { |
| | | store.app().closeSidebar({ withoutAnimation: false }); |
| | | } |
| | | }, |
| | | beforeMount() { |
| | | changeTheme(this.theme); |
| | | }, |
| | | mounted() { |
| | | |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/styles/mixin.scss"; |
| | | // @import "@/styles/variables.module.scss"; |
| | | @import "@/styles/element/index.scss"; |
| | | |
| | | .app-wrapper { |
| | | @include clearfix; |
| | |
| | | import { defineStore } from 'pinia'; |
| | | import defaultSettings from '@/settings'; |
| | | import changeTheme from '@/utils/changeTheme'; |
| | | |
| | | const { showSettings, tagsView, fixedHeader, sidebarLogo, secondMenuPopup } = defaultSettings; |
| | | |
| | | export default defineStore({ |
| | | id: 'settings', |
| | | state: () => ({ |
| | | theme: '#1890ff', |
| | | theme: 'blue', |
| | | showSettings: showSettings, |
| | | tagsView: tagsView, |
| | | fixedHeader: fixedHeader, |
| | |
| | | // eslint-disable-next-line no-prototype-builtins |
| | | if (this.hasOwnProperty(key)) { |
| | | this[key] = value; |
| | | // 如果是修改主题,就切换html标签的class |
| | | if (key === 'theme') { |
| | | changeTheme(value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import { defineStore } from 'pinia'; |
| | | import { logout as apiLogout, getInfo as apiGetInfo } from '@/api/user'; |
| | | import { getToken, setToken, removeToken } from '@/utils/auth'; |
| | | import { login as apiLogin, logout as apiLogout } from '@/api/user'; |
| | | import { getToken, removeToken, setToken } from '@/utils/auth'; |
| | | import router, { resetRouter } from '@/router'; |
| | | import tagsViewStore from './tagsView'; |
| | | import permissionStore from './permission'; |
| | |
| | | getters: {}, |
| | | actions: { |
| | | // user login |
| | | login():Promise<void> { |
| | | // const { username, password } = userInfo; |
| | | return new Promise((resolve) => { |
| | | login(userInfo):Promise<void> { |
| | | const { username, password } = userInfo; |
| | | return new Promise((resolve, reject) => { |
| | | apiLogin(username.trim(), password).then(response => { |
| | | this.token = 'admin'; |
| | | setToken('admin'); |
| | | console.log(response); |
| | | resolve(); |
| | | // apiLogin({ username: username.trim(), password: password }).then(response => { |
| | | // const { data } = response; |
| | | // this.token = data.token; |
| | | // setToken(data.token); |
| | | // resolve(); |
| | | // }).catch(error => { |
| | | // reject(error); |
| | | // }); |
| | | }).catch(error => { |
| | | reject(error); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | |
| | | // user logout |
| | | logout():Promise<void> { |
| | | return new Promise((resolve, reject) => { |
| | | apiLogout(this.token).then(() => { |
| | | apiLogout().then(() => { |
| | | this.token = ''; |
| | | this.roles = []; |
| | | removeToken(); |
New file |
| | |
| | | .hdw-card { |
| | | border: 2px solid #143a92; |
| | | } |
| | | |
| | |
| | | |
| | | // custom dark variables |
| | | @use "./dark.scss"; |
| | | @use './blue.scss'; |
| | |
| | | -moz-osx-font-smoothing: grayscale; |
| | | text-rendering: optimizeLegibility; |
| | | margin: 0; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | label { |
New file |
| | |
| | | import { JSEncrypt } from 'jsencrypt'; |
| | | import const_num from '@/utils/const/const_num.js'; |
| | | |
| | | export default { |
| | | /** |
| | | * 非对称加密算法-加密 |
| | | * @param word 需要加密的字符串 |
| | | * @returns {string | false} |
| | | */ |
| | | encrypt(word) { |
| | | const encryptor = new JSEncrypt(); |
| | | const publicKey = const_num.publicKey; |
| | | encryptor.setPublicKey(publicKey); |
| | | return encryptor.encrypt(word); |
| | | }, |
| | | /** |
| | | * 非对称加密算法-解密 |
| | | * @param word |
| | | * @param privateKey |
| | | * @returns {string | false} |
| | | */ |
| | | decrypt(word, privateKey) { |
| | | if (!privateKey) { |
| | | return '请写入私钥'; |
| | | } |
| | | const decrypt = new JSEncrypt(); |
| | | decrypt.setPrivateKey(privateKey); |
| | | return decrypt.decrypt(word); |
| | | } |
| | | }; |
New file |
| | |
| | | function changeTheme(theme) { |
| | | const htmlTag = document.querySelector('html'); |
| | | // 清空所有类 |
| | | htmlTag.className = ''; |
| | | htmlTag.classList.add(theme); |
| | | } |
| | | |
| | | export default changeTheme; |
New file |
| | |
| | | export default { |
| | | //privateKey: "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KF"+ |
| | | // "Xt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp"+ |
| | | // "9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAP"+ |
| | | // "vTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZsti"+ |
| | | // "IBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59"+ |
| | | // "K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7Nb"+ |
| | | // "AUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73"+ |
| | | // "J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34"+ |
| | | // "lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==", |
| | | //privateKey: "", |
| | | //publicKey: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdH"+ |
| | | // "XXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB" |
| | | publicKey: "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu7CdCMIoWXUX584JpmE1bTE1r1MtmZGswsSbsm4s9zqETQ4BmUT2kz/wvvGsI8" + |
| | | "T3ZvTT4KIyKP4Ez+yNVejMM5XwR95KF4e3UwMc724buWKl4pVL09kvkCZt8ZKf359VAvhyHHz80wIiVmJs6xbho7OBsv/s7Hwho0n4HPL4u/eNR5vWa" + |
| | | "2rtgQG1+fi1XP0UiSRKKW15Va9R2CI3zB+sffquhyX5fi+06NibWzk7OPU+EGvAwkaJtrmfLAvpwr4+G0MBLIsPVFV17Sgpoj62rtfbhHwmLSo1JTw+" + |
| | | "/JskDQOjxXfw+w3uHAZgPTlEmn2Ya9ssIljqCBfvM9nbGUWcnmppKlPm6kECa4RsgPiRgPFV+nT/Q98kfUTb798Sy63x4NIZkLQn1DDbmcAgUqLR6y" + |
| | | "1r0fD8Ne3vVtuZlVR/8ZlcRAfb+th2cNN0rytrnUreJo7kPtTFdkNtmj0KdUkRO8ea0YymEQal+b0tCl3V8osSy+qO2OVRd7yCvpOWEYOBAgMBAAE=", |
| | | privateKey: "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" |
| | | } |
New file |
| | |
| | | export default [ |
| | | { |
| | | label: '默认主题', |
| | | value: 'default' |
| | | }, |
| | | { |
| | | label: '暗黑主题', |
| | | value: 'dark' |
| | | }, |
| | | { |
| | | label: '科技主题', |
| | | value: 'blue' |
| | | } |
| | | ]; |
New file |
| | |
| | | import { md5 } from 'js-md5'; |
| | | import RSA from '@/utils/RSA.js'; |
| | | |
| | | function formatPassword(pwd) { |
| | | const password = pwd + '&&&&&&&&&&' + md5(pwd); |
| | | return RSA.encrypt(password); |
| | | } |
| | | |
| | | export default formatPassword; |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import HdwCard from '@/components/HdwCard/index.vue'; |
| | | import const_theme from '@/utils/const/const_theme'; |
| | | import store from '@/store'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'LockManage', |
| | | components: { HdwCard }, |
| | | data() { |
| | | return { |
| | | theme: store.settings().theme, |
| | | themes: const_theme, |
| | | tableData: [ |
| | | { |
| | | type: '蓝牙', |
| | |
| | | }; |
| | | }, |
| | | methods: { |
| | | |
| | | handleChangeTheme(val) { |
| | | console.log(val); |
| | | store.settings().changeSetting({ |
| | | key: 'theme', |
| | | value: val |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | </script> |
| | |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">主题:</div> |
| | | <div class="filter-content"> |
| | | <el-select |
| | | v-model="theme" |
| | | placeholder="请选择" |
| | | size="small" |
| | | @change="handleChangeTheme" |
| | | style="width: 180px"> |
| | | <el-option |
| | | v-for="item in themes" :key="item.label" |
| | | :label="item.label" :value="item.value"/> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" size="small" :icon="Search">查询</el-button> |
| | | </div> |
| | |
| | | name: 'Login', |
| | | data() { |
| | | const validateUsername: FormItemRule['validator'] = (_rule, value, callback) => { |
| | | if (!validUsername(value)) { |
| | | if (!value.trim()) { |
| | | callback(new Error('请输入用户名')); |
| | | } else { |
| | | callback(); |
| | |
| | | } else if (this.loginForm.password === '') { |
| | | (this.$refs.password as HTMLElement).focus(); |
| | | } |
| | | this.themeChange('blue'); |
| | | }, |
| | | unmounted() { |
| | | // window.removeEventListener('storage', this.afterQRScan) |
| | | }, |
| | | methods: { |
| | | themeChange(val) { |
| | | store.settings().changeSetting({ |
| | | key: 'theme', |
| | | value: val |
| | | }); |
| | | }, |
| | | checkCapslock(e) { |
| | | const { key } = e; |
| | | this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z'); |