4 文件已重命名
24个文件已修改
3个文件已删除
32个文件已添加
New file |
| | |
| | | -----BEGIN CERTIFICATE----- |
| | | MIIFyzCCA7OgAwIBAgIUals9i1HBk6U5fzCWQd0/B5YW/5cwDQYJKoZIhvcNAQEL |
| | | BQAwdTELMAkGA1UEBhMCemgxDTALBgNVBAgMBHdoeWMxDTALBgNVBAcMBHdoeWMx |
| | | DTALBgNVBAoMBHdoeWMxDTALBgNVBAsMBHdoeWMxDTALBgNVBAMMBHdoeWMxGzAZ |
| | | BgkqhkiG9w0BCQEWDHdoeWNAMTYzLmNvbTAeFw0yNTAxMTUwMTM5MTVaFw0yNjAx |
| | | MTUwMTM5MTVaMHUxCzAJBgNVBAYTAnpoMQ0wCwYDVQQIDAR3aHljMQ0wCwYDVQQH |
| | | DAR3aHljMQ0wCwYDVQQKDAR3aHljMQ0wCwYDVQQLDAR3aHljMQ0wCwYDVQQDDAR3 |
| | | aHljMRswGQYJKoZIhvcNAQkBFgx3aHljQDE2My5jb20wggIiMA0GCSqGSIb3DQEB |
| | | AQUAA4ICDwAwggIKAoICAQCcyay5Z0Qt2PnsyFYH0ZkhJRzN18nXLe9cnhMJ0FpF |
| | | IHOoQ8Bs4w/19ReODgvxo9gOMc3dQcWbArxTU3K6ZMML8BRoCyY7pB0uxOgFkmzj |
| | | vQWb1R/COCkPKDadF9juWMn0EnpNcS3CtLWyQ1urkNcn0M4vdJkoUxKT93Jd3lgf |
| | | kaDaa45ZxkNa9k8G6VNtiPFt+PGUAM0m5rTtYG/e0NNfqmEhLRvdcCRPpFIpQnxo |
| | | 8Xx57afFen6M9i9WWdA1+nLC9paZMKi8ld5qGieDI9+SFGLWBC19PvMb6BsE+TBT |
| | | nmRx4KyXM0460v7gTTgjnL5av4T+f8yfZ0MHv4Hc5d8H1ECLgj4MRkk1IwE0fDmN |
| | | w5VGwSYTUzg2rpRIz+5IDE6Wgck9puaWecihiuhnv1d85PQ2W38hIFfcaT+Ay/R8 |
| | | zmramqwv+cTXcTK6HwwsXF2V1VhFTSXYGVsXq1sA9bxNmfx4sUOK2budN5Xg0qKx |
| | | eVASw30/EckJ84ksgmnTT4jQ1MOLAorJR8aK40qBkL+R48BauTkGBdREBRyemfr9 |
| | | 3pNf/iUjpTBS78XqbjFWUEDZfpSf4INdFLOVQLl7/EISJ96nnBvzHngl/TP4dYAY |
| | | XijmYFWXa0XWSfr/DzhQkaozZwRoQpKGhHKKEbGyHgoAYBFBP2tU21lWNt4CuZM1 |
| | | GQIDAQABo1MwUTAdBgNVHQ4EFgQURw4lU60mPMpfnsF551ZybDrU2AgwHwYDVR0j |
| | | BBgwFoAURw4lU60mPMpfnsF551ZybDrU2AgwDwYDVR0TAQH/BAUwAwEB/zANBgkq |
| | | hkiG9w0BAQsFAAOCAgEAUMjfYRY1DSdwiItJg6mvwNxQlhC1EJFQjR/pkGRXqUEN |
| | | zQAUozyRlFVHC1BfXe9q3vs3JOLXW79u0xxmAS6K/doTky9vr20aUQTgUxvIFTWA |
| | | Qv/yOiG8JLr/dU6i+qG6CNFN8G2Fj7bQ2J2FzcdKsPeSPczj2y7URk9Urf4U/Hsz |
| | | TwHIt7Sis0H6XfuXHwZYweO+oVkpNUzD6oAOvFUqdqVmxvrqWjEeNE6dXgfINh7r |
| | | IcWRn2FrXsa2pBo1fSRSW9R2TZH3dxMFOXKF98UqZxvBr1jK1btYyjA4RfFLUoan |
| | | Op6Fx7p2BJizFV9NWmH9/gqPTQl0qRXsYN3A5u9+ZZkM6oIXsHLuSyEGT1K5QEOD |
| | | 988hGC4V3dK3DSgjdN9VoplNUh8eiA4XMIS6mLl4I2M1WHT9S+ct2TCVu9cziZ76 |
| | | VChFiMihq49r64mvbH4dI2zMu22nbgg2ZS+kHvq+LzirgLtkYaXwWwUw9rqIBnVy |
| | | AWJgHe8ROJolTi/yhOtiKeTrBRNiqd6cy3YT8IX9MgIwtzYsY10frS79sni+arWW |
| | | ZQKCNic/weE+L8Qy3le0ZsncTxaHR+gXFXXEOgP4FfU8i5MtE0iHuaFBfQGm72dV |
| | | EUVg9jsM3lXA7iyLKeexrRegpXsh7zO/ksF1Xk2WD4ZYSpBG8JbBT0tUJ9YoEzA= |
| | | -----END CERTIFICATE----- |
| | |
| | | DropdownMenu: typeof import('./src/components/Share/DropdownMenu.vue')['default'] |
| | | Dropzone: typeof import('./src/components/Dropzone/index.vue')['default'] |
| | | EditorImage: typeof import('./src/components/Tinymce/components/EditorImage.vue')['default'] |
| | | ElAvatar: typeof import('element-plus/es')['ElAvatar'] |
| | | ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] |
| | | ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] |
| | | ElButton: typeof import('element-plus/es')['ElButton'] |
| | | ElCascader: typeof import('element-plus/es')['ElCascader'] |
| | | ElCol: typeof import('element-plus/es')['ElCol'] |
| | | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] |
| | | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] |
| | |
| | | ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] |
| | | ElOption: typeof import('element-plus/es')['ElOption'] |
| | | ElPagination: typeof import('element-plus/es')['ElPagination'] |
| | | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] |
| | | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] |
| | | ElRow: typeof import('element-plus/es')['ElRow'] |
| | | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] |
| | | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| | | ElStep: typeof import('element-plus/es')['ElStep'] |
| | | ElSteps: typeof import('element-plus/es')['ElSteps'] |
| | | ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] |
| | | ElSwitch: typeof import('element-plus/es')['ElSwitch'] |
| | | ElTable: typeof import('element-plus/es')['ElTable'] |
| | | ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] |
| | | ElTooltip: typeof import('element-plus/es')['ElTooltip'] |
| | | ElTree: typeof import('element-plus/es')['ElTree'] |
| | | ElUpload: typeof import('element-plus/es')['ElUpload'] |
| | | ErrorLog: typeof import('./src/components/ErrorLog/index.vue')['default'] |
| | | GithubCorner: typeof import('./src/components/GithubCorner/index.vue')['default'] |
| | | Hamburger: typeof import('./src/components/Hamburger/index.vue')['default'] |
New file |
| | |
| | | -----BEGIN PRIVATE KEY----- |
| | | MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCcyay5Z0Qt2Pns |
| | | yFYH0ZkhJRzN18nXLe9cnhMJ0FpFIHOoQ8Bs4w/19ReODgvxo9gOMc3dQcWbArxT |
| | | U3K6ZMML8BRoCyY7pB0uxOgFkmzjvQWb1R/COCkPKDadF9juWMn0EnpNcS3CtLWy |
| | | Q1urkNcn0M4vdJkoUxKT93Jd3lgfkaDaa45ZxkNa9k8G6VNtiPFt+PGUAM0m5rTt |
| | | YG/e0NNfqmEhLRvdcCRPpFIpQnxo8Xx57afFen6M9i9WWdA1+nLC9paZMKi8ld5q |
| | | GieDI9+SFGLWBC19PvMb6BsE+TBTnmRx4KyXM0460v7gTTgjnL5av4T+f8yfZ0MH |
| | | v4Hc5d8H1ECLgj4MRkk1IwE0fDmNw5VGwSYTUzg2rpRIz+5IDE6Wgck9puaWecih |
| | | iuhnv1d85PQ2W38hIFfcaT+Ay/R8zmramqwv+cTXcTK6HwwsXF2V1VhFTSXYGVsX |
| | | q1sA9bxNmfx4sUOK2budN5Xg0qKxeVASw30/EckJ84ksgmnTT4jQ1MOLAorJR8aK |
| | | 40qBkL+R48BauTkGBdREBRyemfr93pNf/iUjpTBS78XqbjFWUEDZfpSf4INdFLOV |
| | | QLl7/EISJ96nnBvzHngl/TP4dYAYXijmYFWXa0XWSfr/DzhQkaozZwRoQpKGhHKK |
| | | EbGyHgoAYBFBP2tU21lWNt4CuZM1GQIDAQABAoICAAH34y/5rKixsGOJWVEkT7qT |
| | | i3LHGnzV0gs03dLR94wmHeWXIieLyzPAhbDuGrbIIop9FBNKw9cQF/qo0cgmwy8X |
| | | br4mo658fzRK2wnU3oKWaSdda9Zlm5hZ3iOnPL0zRqfGgpwNx3AKEjzgbRpwiU7x |
| | | 52C/ozuXHWTXpqsogy00SBNt5b3ZSBewf2n8DGTT4woJJclAoFK0c0GGpCjlML4i |
| | | 9rCyrwae5YnNa42ijMrJe1FRizlmsgeFgK8iFgPTdtTdQSM/seKaNA5bcTMLhH9C |
| | | O8Jpj4Oiwm0PgyVTFoj6NFMcqbYFOh5xbys0NPf3fAlKHbqPMquuoXALtq7mAOCE |
| | | eyhhrWyUvcwC9KhR2XoTNmukJ+F1DU/4yBOKjzHqkusM10yHfuqGt/Z0aJrpS3VT |
| | | kcEiGdPf9Cpp0A82QTMjWimVxe0rxNu9oQjV2rKMTlQ2kgrKrVOSqFrcKqbTjqQP |
| | | pXhTlUa6q3sikJMihYUF6aZ2xjjp3YGCn6GdEf+pw3ggHLeNm21Air05z0AFUcCq |
| | | RN4tI34Kg4HFEuBu74bh9YPf3OKNhq4bBniTSAP1FyjjRcysPCl/H/zN3BB5HEiA |
| | | 9juIn/6RLj0qh7wGCiDRBKul/SWA8X37F7NByRDoAICpgebX2ZX6yU4j+QWJGS08 |
| | | vYj6Y2q1UgNaMvWPlDNBAoIBAQDclQArQ8X/AR51Ll8LbZ3vNsM9l1m0XhxqIn3F |
| | | WzNhevDw2bW5U+HnvhQZTBexQ0yJDDnB3DULrQR/hpRVIiRdjiDv0BREpisLF2dP |
| | | ZpZcbfM/9rpWIDFoVbpSK+cmJLXjvuxpoE/AQD2YyZYjHC3Pv9lLvvIkD56lL2ya |
| | | HMS2NONYuExA3yPxiaoyt2i5mGn6qb3QxDAlAivjecVuG+9g8LKcdlm4Kp0iBSN+ |
| | | y8MymbA0vxEFeBkdR6qdfBi74FuK33P57k7shgW5bysMzkWoGBWXz6tJLTVUyirI |
| | | FV3em94uxUPSXnprbyOGsKcRAgEKEBKMj7FEHMbnl5xUShUhAoIBAQC19mtDvycw |
| | | hxiLi1a40FEBaOeuVYQLq8+3oieREvi8TYB1Xi+MC0UO+Nc6DSlFHZBDTNCKF0zq |
| | | uiGVuEswm04UM3pyJhoXR25n41PHeAhYzuFjwC0BuFR5gLsTe32gJtdUr0hG0+gd |
| | | 2baSrPV6WSZqbGcTLvTsWWPMUqzJYmBFvhCejZD0jM7Ou+ZaZKH1e6NuVCkAhKX1 |
| | | f1FHyM5+ulHIHDvZZTpHfrUKK6BaBAg7QPRp5v/e6DBaN5Zc9d/4CXdfjHdGiQ9p |
| | | AJCBuAdGk4fVaxNR9dyMM0F8VGzTDeK7VHJPLJj2zGi0gB4JNBHH96KjeXPMU8qR |
| | | Bb5OKrRTx6j5AoIBAQCQlv8AXTGZQVOEvnvA0v7Wwk/ivKYpjBMWIzvMNUcN2/e5 |
| | | +QucyvZm4Prtxio1oQa3QxNNFxqSZ7xuF3p9/55U0QiYCg5vHXlTkOjAbF+dgNkV |
| | | kZZ9RCb+3EsA+BRRtXihLBJt/o6oV7PIxkMrCpqg9oHqm+S/bJmyb87BiqALS8nG |
| | | 6y/YyiwWdQXirsTv+49kpwVspl1ktPKt7rFSxu733W9HDnErPou3tCSbRdfTAFk3 |
| | | ihMPQbU8szCMgL750ExRUL4GE4calZOFBPD0OPYCBJ+K3q7Jjd/Kj6bRdugMNqHC |
| | | iL43VITsjXJ9JKiuhmDGBtkR2FL7cd2UC5aGzfThAoIBAQConEaY6DAwT373D460 |
| | | gpQNcl/8s1FAX1yDFMcFL0c9dbNrDnOQmYDMdtk4+akcWmCrfCphS2YCu6cTTUqf |
| | | J8oZ/fmgfJ4ApDgyG/wuAZP6dvlzrUgHJ/9e92JikzO9i0BNQH8A4qtbvbnoAE0X |
| | | qjRmuTxqEkDyIYLQemuR0I7VEWHlCdkgQrn/5y105XsONhsiyOmViVUfP3LZycFO |
| | | vOe7Pi5XK+3tAgRQAEz+HG5kObRBzcObkhv7/TZfvZZkCKGM8GQ2ABs/eT5udVCI |
| | | nXxozmeAswpC/9vWkYSlrWBDpeSmaPT0/ESpvW4XqSAw487ZHFmpJJu39lJ5rCic |
| | | 2Y5BAoIBAGGV+l+e9zX45zUoql7ISi9u+czmAgENSYLAXrvGjuN6cP8Z+wJtjsRC |
| | | C3s+8Scz9sH35iCDW1L145cdIA7+f4l6mMCSw2q5OANyZapvFYC1EZy/ftiyzLkU |
| | | 4ixm0/hTtpAdbxDQJ7KSR2K6bgoAYoWRC1PobqEzWqCoN8bpfN1VpV8LGJEZFJ4r |
| | | 3giX434PyhnbEj3o0slSH5YF6Ip33QbnwNAFSw3kGNwizIf4P4OWOcWTYmU+DcAH |
| | | ewZcS6sP1N8j43QQmeQo2iMTv1jUaC2K/MUPT930b8uPxE0dwEJoT0BlA6UoIqHm |
| | | uZg/MOEcSLDUeoVr/e3yChqMt8FKWqE= |
| | | -----END PRIVATE KEY----- |
| | |
| | | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" |
| | | }, |
| | | "dependencies": { |
| | | "@element-plus/icons-vue": "^2.3.1", |
| | | "axios": "^1.7.2", |
| | | "clipboard": "^2.0.11", |
| | | "driver.js": "^1.3.1", |
| | | "dropzone": "^5.9.3", |
| | | "echarts": "^5.5.0", |
| | | "element-plus": "^2.7.6", |
| | | "element-plus": "^2.8.1", |
| | | "file-saver": "^2.0.5", |
| | | "fuse.js": "^6.6.2", |
| | | "js-cookie": "^3.0.5", |
| | |
| | | "vite": "^5.3.1", |
| | | "vite-plugin-inspect": "^0.8.4", |
| | | "vite-plugin-mock": "^2.9.8", |
| | | "vite-plugin-vue-setup-extend": "^0.4.0", |
| | | "vue-tsc": "^2.0.21" |
| | | } |
| | | } |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { defineComponent } from 'vue'; |
| | | import { ElConfigProvider } from 'element-plus'; |
| | | import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; |
| | | import { mapState } from 'pinia'; |
| | | import store from '@/store'; |
| | | import { defineComponent } from 'vue'; |
| | | import { ElConfigProvider } from 'element-plus'; |
| | | import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; |
| | | import { mapState } from 'pinia'; |
| | | import store from '@/store'; |
| | | |
| | | export default defineComponent({ |
| | | components: { |
| | | ElConfigProvider |
| | | }, |
| | | computed: { |
| | | ...mapState(store.app, ['size']) |
| | | }, |
| | | data() { |
| | | return { |
| | | locale: zhCn, |
| | | zIndex: 3000 |
| | | }; |
| | | } |
| | | }); |
| | | export default defineComponent({ |
| | | components: { |
| | | ElConfigProvider |
| | | }, |
| | | computed: { |
| | | ...mapState(store.app, ['size']), |
| | | ...mapState(store.ukey, ['isIn', 'connect']) |
| | | }, |
| | | data() { |
| | | return { |
| | | locale: zhCn, |
| | | zIndex: 3000 |
| | | }; |
| | | }, |
| | | |
| | | watch: { |
| | | isIn(isIn) { |
| | | store.ukey().changeId(isIn); |
| | | }, |
| | | connect(connect) { |
| | | store.ukey().checkIsIn(connect); |
| | | } |
| | | }, |
| | | mounted() { |
| | | store.ukey().load(true); |
| | | }, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | @import "@/styles/element/index.scss"; |
| | | @use "@/styles/element/index.scss"; |
| | | |
| | | html, |
| | | body, |
| | | #app { |
| | |
| | | */ |
| | | export function getAreaTreeApi() { |
| | | return request({ |
| | | url: '/areaInf/getAllAreaInf', |
| | | url: 'areaInf/getAllAreaInfInPaltForm', |
| | | method: 'get' |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 添加区域 |
| | | * areaName, areaDescript, parentId |
| | | * [{uid, uname}] |
| | | */ |
| | | export function addArea(params, data) { |
| | | return request({ |
| | | url: "areaInf/addArea", |
| | | method: "POST", |
| | | params, |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 删除区域 |
| | | * id |
| | | */ |
| | | export function delArea(id) { |
| | | return request({ |
| | | url: "areaInf/delArea", |
| | | method: "GET", |
| | | params: { id } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 修改区域 |
| | | * areaId, areaName, areaDescript, parentId |
| | | * [{uid, uname}] |
| | | */ |
| | | export function updateArea(params, data) { |
| | | return request({ |
| | | url: "areaInf/updateArea", |
| | | method: "POST", |
| | | params, |
| | | data |
| | | }); |
| | | } |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | /** |
| | | * 查询所有授权信息 |
| | | * areaId, pageNum, pageSize, state, uname |
| | | */ |
| | | export function getAllAuthInf(params) { |
| | | return request({ |
| | | url: 'authInf/getAllAuthInf', |
| | | method: 'GET', |
| | | params |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 添加授权(批量) |
| | | */ |
| | | export function addAuth(data) { |
| | | return request({ |
| | | url: 'authInf/addAuth', |
| | | method: 'POST', |
| | | data |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 修改授权 |
| | | */ |
| | | export function updateAuth(id, data) { |
| | | return request({ |
| | | url: 'authInf/updateAuth', |
| | | method: 'POST', |
| | | params: { id }, |
| | | data |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 删除授权(批量) |
| | | */ |
| | | export function delAuth(ids) { |
| | | return request({ |
| | | url: 'authInf/delAuth', |
| | | method: 'POST', |
| | | data: ids |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 根据mac检测蓝牙锁是否有权限 |
| | | */ |
| | | export function checkAuth(mac) { |
| | | return request({ |
| | | url: 'authInf/getAuthByUidAndMac', |
| | | method: 'GET', |
| | | params: { mac } |
| | | }); |
| | | } |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | /* |
| | | *用户人脸查询 |
| | | *传参:null |
| | | *参数: data = 传参 str=请求方式 |
| | | */ |
| | | export const faceInfo = function (data, str) { |
| | | return request({ |
| | | method: str, |
| | | url: 'face/info', |
| | | params: data |
| | | }); |
| | | } |
| | | /* |
| | | *用户人脸管理 新增 |
| | | *传参:- |
| | | * |
| | | * |
| | | */ |
| | | export const faceMagerAdd = function (data) { |
| | | return request({ |
| | | method: "POST", |
| | | url: 'face', |
| | | headers: { 'content-type': 'application/json' }, |
| | | data: data |
| | | }); |
| | | } |
| | | |
| | | /* |
| | | *用户人脸管理 更新 |
| | | *传参:- |
| | | * |
| | | * |
| | | */ |
| | | export const faceMagerChange = function (data) { |
| | | return request({ |
| | | method: "POST", |
| | | url: 'face/update', |
| | | headers: { 'content-type': 'application/json' }, |
| | | params: { |
| | | uName: data.uName |
| | | }, |
| | | data: data.fileData |
| | | }); |
| | | } |
| | | /* |
| | | *用户人脸管理 删除 |
| | | *传参:- |
| | | * |
| | | * |
| | | */ |
| | | export const faceMagerDelete = function (data) { |
| | | return request({ |
| | | method: "POST", |
| | | url: 'face/delete', |
| | | params: data |
| | | }); |
| | | } |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | /** |
| | | * 添加钥匙 |
| | | */ |
| | | export function addKey(data) { |
| | | return request({ |
| | | url: 'lockInf/addKey', |
| | | method: 'POST', |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 删除钥匙 |
| | | */ |
| | | export function delKey(keyId) { |
| | | return request({ |
| | | url: 'lockInf/delKey', |
| | | method: 'GET', |
| | | params: { keyId }, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询所有钥匙信息 |
| | | * { keyName, pageNum, pageSize, uname |
| | | * } |
| | | * @returns |
| | | */ |
| | | export function getAllKeyList(params) { |
| | | return request({ |
| | | url: 'lockInf/getAllKeyInf', |
| | | method: 'GET', |
| | | params |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 授权时查询所有钥匙信息(不分页) |
| | | * |
| | | * @returns |
| | | */ |
| | | export function getKeyInfAuth() { |
| | | return request({ |
| | | url: 'lockInf/getKeyInfAuth', |
| | | method: 'GET', |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询所有钥匙名信息(用于下拉) |
| | | */ |
| | | export function authKey() { |
| | | return request({ |
| | | url: 'lockInf/getkinf', |
| | | method: 'GET', |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 更新钥匙信息 |
| | | */ |
| | | export function updateKey(data) { |
| | | return request({ |
| | | url: 'lockInf/updateKey', |
| | | method: 'POST', |
| | | data, |
| | | }); |
| | | } |
New file |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | /** |
| | | * 查询所有锁信息 |
| | | * areaId lockName lockState lockType pageNum pageSize |
| | | */ |
| | | export function getAllLockInf(params) { |
| | | return request({ |
| | | url: "lockInf/getAllLockInf", |
| | | method: "GET", |
| | | params, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 编辑 |
| | | * lockId lockName areaId lockType |
| | | */ |
| | | export function updateLock(params) { |
| | | return request({ |
| | | url: "lockInf/updateLock", |
| | | method: "GET", |
| | | params, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 添加锁 包含批量 |
| | | * areaId lockName lockType num |
| | | */ |
| | | export function addLock(params) { |
| | | return request({ |
| | | url: "lockInf/addLock", |
| | | method: "GET", |
| | | params, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 删除锁 |
| | | * lockId |
| | | */ |
| | | export function delLock(lockId) { |
| | | return request({ |
| | | url: "lockInf/delLock", |
| | | method: "GET", |
| | | params: { lockId }, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询所有锁信息 |
| | | * |
| | | */ |
| | | export function getLockInfAuth() { |
| | | return request({ |
| | | url: "lockInf/getLockInfAuth", |
| | | method: "GET", |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 远程开锁 |
| | | * lockId |
| | | */ |
| | | export function lockOpen(lockId) { |
| | | return request({ |
| | | url: "lockRt/lockOpen", |
| | | method: "GET", |
| | | params: { lockId }, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前管理员 所管理区域下的所有锁具 下拉 |
| | | */ |
| | | export function getAreaUserLock() { |
| | | return request({ |
| | | url: "lockInf/getAreaUserLock", |
| | | method: "GET", |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询指定区域下的所有锁具 下拉用 |
| | | * id |
| | | */ |
| | | export function getLinfById(id) { |
| | | return request({ |
| | | url: "areaInf/getLinfById", |
| | | method: "GET", |
| | | params: { id }, |
| | | }); |
| | | } |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | /** |
| | | * 查询操作日志 锁相关 |
| | | */ |
| | | export function getLockLog(pageNum, pageSize, data) { |
| | | return request({ |
| | | url: 'areaInf/getLockLog', |
| | | method: 'POST', |
| | | params: { pageNum, pageSize }, |
| | | data |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询系统日志 |
| | | */ |
| | | export function getSysLog(data) { |
| | | return request({ |
| | | url: 'operationLog/getPage', |
| | | method: 'POST', |
| | | data |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 事件列表 下拉 |
| | | */ |
| | | export function getTypes() { |
| | | return request({ |
| | | url: 'operationLog/getTypes', |
| | | method: 'GET' |
| | | }); |
| | | } |
| | |
| | | export function login(uname, usnId) { |
| | | return request({ |
| | | method: 'GET', |
| | | url: '/login/login', |
| | | url: 'login/login', |
| | | params: { |
| | | uname, |
| | | usnId: encodeURIComponent(formatPassword(usnId)) |
| | | usnId: encodeURIComponent(formatPassword(usnId)), |
| | | platFrom: 1, |
| | | } |
| | | }); |
| | | } |
| | |
| | | export function getInfo(uname, usnId) { |
| | | return request({ |
| | | method: 'GET', |
| | | url: '/login/login', |
| | | url: 'login/login', |
| | | params: { |
| | | uname, |
| | | usnId: encodeURIComponent(formatPassword(usnId)) |
| | |
| | | |
| | | export function logout(token) { |
| | | return request({ |
| | | url: '/login/logout', |
| | | method: 'post' |
| | | url: 'login/logout', |
| | | method: 'GET' |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 空接口 用于重置会话有效期 |
| | | */ |
| | | export const pingpong = () => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "heart/getCookie", |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询所有用户信息 |
| | | * @param {*} areaId, pageCurr, pageSize |
| | | * @returns |
| | | */ |
| | | export const getAllUser = (areaId, pageCurr, pageSize) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/getAllUser", |
| | | params: { areaId, pageCurr, pageSize }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询区域管理员下所有的用户名 只能是管理员才能查询 |
| | | */ |
| | | export const getAllUserName = () => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "areaUser/getUserNameByAreaIds", |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前管理员下所有用户对象 只能是管理员才能查询 (不包含管理员自己) |
| | | */ |
| | | export const getUinfByAreaIds = () => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "areaUser/getUinfByAreaIds", |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 编辑用户信息 |
| | | * 不能改用户名 |
| | | * @returns |
| | | */ |
| | | export const updateUser = (data) => { |
| | | return request({ |
| | | method: "POST", |
| | | url: "userInf/updateUinf", |
| | | data |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 新添加用户信息 |
| | | * |
| | | */ |
| | | export const addUser = (data) => { |
| | | return request({ |
| | | method: "POST", |
| | | url: "userInf/addUser", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 删除用户信息 |
| | | * |
| | | */ |
| | | export const deleteUser = (uname) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/deleteUser", |
| | | params: { uname }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 将管理员变成普通用户 |
| | | * |
| | | */ |
| | | export const dropRole = (uid) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/dropRole", |
| | | params: { uid }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 将普通用户变成管理员 |
| | | * |
| | | */ |
| | | export const improveRole = (uid) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/improveRole", |
| | | params: { uid }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 重置用户密码 |
| | | * |
| | | */ |
| | | export const resetSnId = (uid) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/resetSnId", |
| | | params: { uid }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询所有包机组信息 |
| | | */ |
| | | export const getBaojiInfo = () => { |
| | | return request({ |
| | | method: "POST", |
| | | url: "baoji/getBaojiInfo", |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询所有设备 |
| | | */ |
| | | export const getAllDevs = () => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "devInf/getDinf", |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询所有用户信息(不分页除内置用户外用于下拉) |
| | | */ |
| | | export const getAllUsers = () => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/getUinf", |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 查询指定区域下的所有用户名 下拉用 |
| | | */ |
| | | export const getUinfById = (id) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "areaInf/getUinfById", |
| | | params: { id }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 根据用户名查询绑定的ukey |
| | | * @returns {AxiosPromise} |
| | | */ |
| | | export const getUKeyByUName = (uname) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/searchUNameToUKey", |
| | | params: { |
| | | uname, |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 根据uKey的id查询已绑定的用户名 |
| | | */ |
| | | export const getUNameByUKey = (ukeyId) => { |
| | | return request({ |
| | | method: "GET", |
| | | url: "userInf/searchUKeyToUName", |
| | | params: { |
| | | ukeyId |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 绑定UKey |
| | | */ |
| | | export const bindUKey = (UName, UKeyId, upubKeyX, upubKeyY) => { |
| | | return request({ |
| | | method: "POST", |
| | | url: "userInf/bindUkey", |
| | | data: { |
| | | uname: UName, |
| | | ukeyId: UKeyId, |
| | | upubKeyX, |
| | | upubKeyY, |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * uKeyLogin登录 |
| | | */ |
| | | export const uKeyLogin = (uname, password, ukeyId) => { |
| | | |
| | | return request({ |
| | | method: "POST", |
| | | url: `login/loginWithUKey`, |
| | | params: { |
| | | uname, |
| | | usnId: encodeURIComponent(formatPassword(password)), |
| | | ukeyId, |
| | | }, |
| | | }); |
| | | }; |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import { getAreaTreeApi } from '@/api/area'; |
| | | import { formatAreaTree } from '@/utils/tree'; |
| | | <script setup> |
| | | import { ref, onMounted, reactive, nextTick } from "vue"; |
| | | import { getAreaTreeApi } from "@/api/area"; |
| | | import { formatAreaTree } from "@/utils/tree"; |
| | | |
| | | export default defineComponent({ |
| | | name: 'HdwTree', |
| | | data() { |
| | | return { |
| | | defaultProps: { |
| | | children: 'children', |
| | | label: 'label' |
| | | }, |
| | | data: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleNodeClick(data) { |
| | | console.log(data); |
| | | }, |
| | | async getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let data = []; |
| | | if (res.code === 1 && res.data) { |
| | | data = res.data2; |
| | | } |
| | | const treeList = []; |
| | | for (let i = 0; i < data.length; i++) { |
| | | formatAreaTree(data[i], treeList); |
| | | } |
| | | console.log(data); |
| | | console.log(treeList); |
| | | this.data = treeList; |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getAreaTree(); |
| | | } |
| | | }); |
| | | const emit = defineEmits(["itemClick"]); |
| | | const defaultProps = reactive({ |
| | | children: "children", |
| | | label: "label", |
| | | }); |
| | | |
| | | const treeRef = ref(); |
| | | const data = ref([]); |
| | | const defaultSelect = ref([1]); |
| | | |
| | | onMounted(() => { |
| | | getAreaTree(); |
| | | }); |
| | | |
| | | function handleNodeClick(data) { |
| | | console.log(data); |
| | | emit("itemClick", data); |
| | | } |
| | | |
| | | async function getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let _data = []; |
| | | if (res.code === 1 && res.data) { |
| | | _data = res.data2; |
| | | } |
| | | console.log('_data', _data, '============='); |
| | | |
| | | const treeList = []; |
| | | let ids = _data.map((v) => v.id); |
| | | for (let i = 0; i < _data.length; i++) { |
| | | formatAreaTree(_data[i], ids, treeList); |
| | | } |
| | | // console.log(_data, 'data'); |
| | | console.log(treeList, "treeList"); |
| | | data.value = treeList; |
| | | await nextTick(); |
| | | // defaultSelect.value = [treeList[0].id] |
| | | handleNodeClick(treeList[0]); |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | |
| | | const collapseAll = () => { |
| | | const nodes = treeRef.value.store.nodesMap; |
| | | Object.values(nodes).forEach((node) => { |
| | | if (node.level > 0) { |
| | | // 排除根节点 |
| | | node.expanded = false; |
| | | } |
| | | }); |
| | | treeRef.value.store.updateExpandedKeys(); // 更新展开状态 |
| | | }; |
| | | |
| | | const expandAll = () => { |
| | | const nodes = treeRef.value.store.nodesMap; |
| | | Object.values(nodes).forEach((node) => { |
| | | if (node.level > 0) { |
| | | // 排除根节点 |
| | | node.expanded = true; |
| | | } |
| | | }); |
| | | treeRef.value.store.updateExpandedKeys(); // 更新展开状态 |
| | | }; |
| | | </script> |
| | | |
| | | <template> |
| | | <el-scrollbar> |
| | | <el-tree |
| | | style="max-width: 600px" |
| | | :data="data" |
| | | :props="defaultProps" |
| | | :expand-on-click-node="false" |
| | | @node-click="handleNodeClick" |
| | | /> |
| | | </el-scrollbar> |
| | | <el-scrollbar> |
| | | <el-button type="warning" size="small" @click="collapseAll">折叠全部</el-button> |
| | | <el-button type="primary" size="small" @click="expandAll">展开全部</el-button> |
| | | <el-tree |
| | | style="max-width: 600px" |
| | | ref="treeRef" |
| | | :data="data" |
| | | :props="defaultProps" |
| | | node-key="id" |
| | | :expand-on-click-node="false" |
| | | :default-checked-keys="defaultSelect" |
| | | @node-click="handleNodeClick" |
| | | /> |
| | | </el-scrollbar> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/styles/mixin.scss"; |
| | | @use "@/styles/mixin.scss"; |
| | | .upload-container { |
| | | width: 100%; |
| | | position: relative; |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/styles/mixin.scss"; |
| | | @use "@/styles/mixin.scss"; |
| | | .upload-container { |
| | | width: 100%; |
| | | position: relative; |
New file |
| | |
| | | import { ref, reactive } from "vue"; |
| | | import { ElMessageBox, ElMessage, ElLoading } from "element-plus"; |
| | | |
| | | export default () => { |
| | | const $message = ElMessage; |
| | | function $alert(title, fnCancel = () => {}) { |
| | | ElMessageBox.confirm(title, "系统提示", { |
| | | confirmButtonText: "确定", |
| | | type: "warning", |
| | | showCancelButton: false, |
| | | center: true, |
| | | }) |
| | | .then(() => { |
| | | fnCancel(); |
| | | }) |
| | | .catch(() => { |
| | | fnCancel(); |
| | | }); |
| | | } |
| | | |
| | | function $confirm(operate, fnOk, fnCancel = () => {}) { |
| | | ElMessageBox.confirm(`请确认是否${operate}?`, "系统提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | center: true, |
| | | }) |
| | | .then(() => { |
| | | fnOk(); |
| | | }) |
| | | .catch(() => { |
| | | fnCancel(); |
| | | }); |
| | | } |
| | | |
| | | function $loading(customOptions = {}) { |
| | | const defaultOptions = { |
| | | lock: true, |
| | | text: "Loading", |
| | | background: "rgba(0, 0, 0, 0.7)", |
| | | target: document.body, |
| | | // 可以添加更多默认配置 |
| | | }; |
| | | |
| | | // 合并默认配置和自定义配置 |
| | | const options = { ...defaultOptions, ...customOptions }; |
| | | |
| | | // 调用Element UI的加载服务 |
| | | const loadingInstance = ElLoading.service(options); |
| | | return loadingInstance; |
| | | // return () => { |
| | | // console.log('?', 'close', '============='); |
| | | |
| | | // loadingInstance.close(); |
| | | // }; |
| | | } |
| | | |
| | | return { $alert, $confirm, $message, $loading }; |
| | | }; |
New file |
| | |
| | | // useWebSocket.js |
| | | import { |
| | | ref, |
| | | reactive, |
| | | onMounted, |
| | | onUnmounted, |
| | | onActivated, |
| | | onDeactivated, |
| | | } from "vue"; |
| | | import getWsUrl from "@/utils/getWsUrl"; |
| | | |
| | | export default function (url) { |
| | | url = getWsUrl(url); |
| | | // 重连时间间隔 默认5秒 |
| | | const reConnectDelay = 5 * 1000; |
| | | |
| | | const socket = ref(null); |
| | | const isConnected = ref(false); |
| | | const message = ref(""); |
| | | let timer = null; |
| | | |
| | | const sendCallback = reactive([]); |
| | | |
| | | const connect = () => { |
| | | if (socket.value) { |
| | | socket.value.close(); |
| | | } |
| | | socket.value = new WebSocket(url); |
| | | |
| | | socket.value.onopen = () => { |
| | | isConnected.value = true; |
| | | console.log("WebSocket Connected, url: ", url); |
| | | sendCallback.forEach((v) => v()); |
| | | sendCallback.length = 0; |
| | | }; |
| | | |
| | | socket.value.onmessage = (event) => { |
| | | // 处理接收到的消息 |
| | | // console.log("Received:", event.data); |
| | | // 可以在这里通过 emit 发送消息到组件 |
| | | message.value = event.data; |
| | | }; |
| | | |
| | | socket.value.onerror = (Event) => { |
| | | console.error("WebSocket Error:", Event, url); |
| | | WSClose(Event); |
| | | }; |
| | | |
| | | socket.value.onclose = WSClose; |
| | | |
| | | }; |
| | | |
| | | // 发送数据 |
| | | const sendData = (data) => { |
| | | if (socket.value && socket.value.readyState === socket.value.OPEN) { |
| | | // console.log('send', data, '============='); |
| | | socket.value.send(data); |
| | | } else { |
| | | sendCallback.push(() => sendData(data)); |
| | | } |
| | | }; |
| | | |
| | | function WSClose(Event) { |
| | | isConnected.value = false; |
| | | if (socket.value) { |
| | | switch (socket.value.readyState) { |
| | | case 0: |
| | | socket.value.onopen = () => { |
| | | socket.value.close(); |
| | | console.log('链接关闭', url, 'close事件对象:', Event); |
| | | socket.value = null; |
| | | // 没有event对象 则为手动关闭 |
| | | if (Event) { |
| | | reConnect(); |
| | | } |
| | | } |
| | | break; |
| | | case 1: |
| | | socket.value.close(); |
| | | console.log('链接关闭', url, 'close事件对象:', Event); |
| | | socket.value = null; |
| | | // 没有event对象 则为手动关闭 |
| | | if (Event) { |
| | | reConnect(); |
| | | } |
| | | break; |
| | | case 2: |
| | | socket.value.onclose = () => { |
| | | console.log('链接关闭', url, 'close事件对象:', Event); |
| | | socket.value = null; |
| | | // 没有event对象 则为手动关闭 |
| | | if (Event) { |
| | | reConnect(); |
| | | } |
| | | } |
| | | break; |
| | | case 3: |
| | | console.log('链接关闭', url, 'close事件对象:', Event); |
| | | socket.value = null; |
| | | // 没有event对象 则为手动关闭 |
| | | if (Event) { |
| | | reConnect(); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 重连 |
| | | function reConnect() { |
| | | if (timer) { |
| | | return false; |
| | | } |
| | | timer = setTimeout(() => { |
| | | timer = null; |
| | | connect(); |
| | | }, reConnectDelay); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // console.log('socket mount', Date.now(), '============='); |
| | | console.log("on socket mount", url, "============="); |
| | | |
| | | connect(); |
| | | }); |
| | | |
| | | onActivated(() => { |
| | | if (!socket.value) { |
| | | console.log("on socket active", url, "============="); |
| | | connect(); |
| | | } |
| | | }); |
| | | |
| | | onDeactivated(() => { |
| | | if (socket.value) { |
| | | WSClose(); |
| | | } |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | if (socket.value) { |
| | | WSClose(); |
| | | } |
| | | }); |
| | | |
| | | // 返回 socket 对象和状态 |
| | | return { socket, isConnected, message, sendData }; |
| | | } |
| | |
| | | <template> |
| | | <div class="navbar"> |
| | | <div class="sys-name-wrapper"> |
| | | <div class="sys-icon"> |
| | | <svg-icon icon-class="lock-hdw"></svg-icon> |
| | | </div> |
| | | <div class="sys-name">{{ title }}</div> |
| | | </div> |
| | | <div class="right-menu"> |
| | | <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> |
| | | <div class="avatar-wrapper"> |
| | | <img :src="avatar + '?imageView2/1/w/80/h/80'" class="user-avatar" alt="" /> |
| | | <el-icon class="el-icon-caret-bottom" size="small"> |
| | | <CaretBottom /> |
| | | </el-icon> |
| | | </div> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <router-link to="/"> |
| | | <el-dropdown-item>首页</el-dropdown-item> |
| | | </router-link> |
| | | <el-dropdown-item @click="logout"> |
| | | <span style="display:block;">退出登录</span> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | <div class="navbar"> |
| | | <div class="sys-name-wrapper"> |
| | | <div class="sys-icon"> |
| | | <svg-icon icon-class="lock-hdw"></svg-icon> |
| | | </div> |
| | | <div class="sys-name">{{ title }}</div> |
| | | </div> |
| | | <div class="right-menu"> |
| | | <el-dropdown |
| | | class="avatar-container right-menu-item hover-effect" |
| | | trigger="click" |
| | | > |
| | | <div class="avatar-wrapper"> |
| | | <img |
| | | :src="avatar + '?imageView2/1/w/80/h/80'" |
| | | class="user-avatar" |
| | | alt="" |
| | | /> |
| | | <span>{{ uname }}</span> |
| | | <el-icon class="el-icon-caret-bottom" size="small"> |
| | | <CaretBottom /> |
| | | </el-icon> |
| | | </div> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <router-link to="/"> |
| | | <el-dropdown-item>首页</el-dropdown-item> |
| | | </router-link> |
| | | <el-dropdown-item @click="logout"> |
| | | <span style="display: block">退出登录</span> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { mapState } from 'pinia'; |
| | | import store from '@/store'; |
| | | import { defineComponent } from 'vue'; |
| | | import { CaretBottom } from '@element-plus/icons-vue'; |
| | | import SvgIcon from '@/components/SvgIcon/index.vue'; |
| | | <script setup name="Navbar"> |
| | | import store from "@/store"; |
| | | import { computed, ref, watchEffect } from "vue"; |
| | | import { useRoute, useRouter } from "vue-router"; |
| | | import { CaretBottom } from "@element-plus/icons-vue"; |
| | | import SvgIcon from "@/components/SvgIcon/index.vue"; |
| | | import useWebSocket from "@/hooks/useWebSocket"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | const { message } = useWebSocket("loginCheck"); |
| | | |
| | | const { $alert, $loading, $message, $confirm } = useElement(); |
| | | |
| | | export default defineComponent({ |
| | | components: { |
| | | SvgIcon, |
| | | CaretBottom |
| | | }, |
| | | data() { |
| | | return { |
| | | title: '鸿蒙智能电子锁管理平台' |
| | | }; |
| | | }, |
| | | computed: { |
| | | ...mapState(store.app, [ |
| | | 'sidebar', |
| | | 'device' |
| | | ]), |
| | | ...mapState(store.user, [ |
| | | 'avatar' |
| | | ]) |
| | | }, |
| | | methods: { |
| | | toggleSidebar() { |
| | | store.app().toggleSidebar(); |
| | | }, |
| | | async logout() { |
| | | await store.user().logout(); |
| | | this.$router.push(`/login?redirect=${this.$route.fullPath}`); |
| | | const router = useRouter(); |
| | | const route = useRoute(); |
| | | |
| | | const title = ref("鸿蒙智能电子锁管理平台"); |
| | | const sidebar = computed(() => store.app().sidebar); |
| | | const device = computed(() => store.app().device); |
| | | const avatar = computed(() => store.user().avatar); |
| | | const uname = computed(() => store.user().name); |
| | | |
| | | watchEffect(() => { |
| | | if (message.value) { |
| | | const { |
| | | code, |
| | | data: { checkLogin }, |
| | | } = JSON.parse(message.value); |
| | | if (!checkLogin.data) { |
| | | $message(checkLogin.msg); |
| | | logout(); |
| | | // localStorage.removeItem("uname"); |
| | | // localStorage.removeItem("uid"); |
| | | // setTimeout(() => { |
| | | // $router.push("/login"); |
| | | // location.reload(); |
| | | // }, 2000); |
| | | } |
| | | } |
| | | |
| | | }); |
| | | |
| | | function toggleSidebar() { |
| | | store.app().toggleSidebar(); |
| | | } |
| | | async function logout() { |
| | | await store.user().logout(); |
| | | // console.log('logout', '============='); |
| | | |
| | | router.push(`/login?redirect=${route.fullPath}`); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .navbar { |
| | | height: 64px; |
| | | overflow: hidden; |
| | | position: relative; |
| | | background: #fff; |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, .08); |
| | | .sys-name-wrapper { |
| | | display: inline-block; |
| | | line-height: 64px; |
| | | color: var(--light-color); |
| | | font-size: 24px; |
| | | width: 894px; |
| | | .sys-icon { |
| | | display: inline-block; |
| | | font-weight: 700; |
| | | margin-left: 16px; |
| | | margin-right: 8px; |
| | | } |
| | | .sys-name { |
| | | font-weight: 700; |
| | | display: inline-block; |
| | | } |
| | | } |
| | | .hamburger-container { |
| | | line-height: 46px; |
| | | height: 100%; |
| | | float: left; |
| | | cursor: pointer; |
| | | transition: background .3s; |
| | | -webkit-tap-highlight-color: transparent; |
| | | .navbar { |
| | | height: 64px; |
| | | overflow: hidden; |
| | | position: relative; |
| | | background: #fff; |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | .sys-name-wrapper { |
| | | display: inline-block; |
| | | line-height: 64px; |
| | | color: var(--light-color); |
| | | font-size: 24px; |
| | | width: 894px; |
| | | .sys-icon { |
| | | display: inline-block; |
| | | font-weight: 700; |
| | | margin-left: 16px; |
| | | margin-right: 8px; |
| | | } |
| | | .sys-name { |
| | | font-weight: 700; |
| | | display: inline-block; |
| | | } |
| | | } |
| | | .hamburger-container { |
| | | line-height: 46px; |
| | | height: 100%; |
| | | float: left; |
| | | cursor: pointer; |
| | | transition: background 0.3s; |
| | | -webkit-tap-highlight-color: transparent; |
| | | |
| | | &:hover { |
| | | background: rgba(0, 0, 0, .025) |
| | | } |
| | | } |
| | | &:hover { |
| | | background: rgba(0, 0, 0, 0.025); |
| | | } |
| | | } |
| | | |
| | | .breadcrumb-container { |
| | | float: left; |
| | | } |
| | | .breadcrumb-container { |
| | | float: left; |
| | | } |
| | | |
| | | .errLog-container { |
| | | display: inline-block; |
| | | vertical-align: top; |
| | | } |
| | | .errLog-container { |
| | | display: inline-block; |
| | | vertical-align: top; |
| | | } |
| | | |
| | | .right-menu { |
| | | float: right; |
| | | height: 100%; |
| | | line-height: 64px; |
| | | .right-menu { |
| | | float: right; |
| | | height: 100%; |
| | | line-height: 64px; |
| | | |
| | | &:focus { |
| | | outline: none; |
| | | } |
| | | &:focus { |
| | | outline: none; |
| | | } |
| | | |
| | | .right-menu-item { |
| | | display: inline-block; |
| | | padding: 0 8px; |
| | | height: 100%; |
| | | line-height: 64px; |
| | | font-size: 18px; |
| | | color: #5a5e66; |
| | | vertical-align: text-bottom; |
| | | .right-menu-item { |
| | | display: inline-block; |
| | | padding: 0 8px; |
| | | height: 100%; |
| | | line-height: 64px; |
| | | font-size: 18px; |
| | | color: #5a5e66; |
| | | vertical-align: text-bottom; |
| | | |
| | | &.hover-effect { |
| | | cursor: pointer; |
| | | transition: background .3s; |
| | | &.hover-effect { |
| | | cursor: pointer; |
| | | transition: background 0.3s; |
| | | |
| | | &:hover { |
| | | background: rgba(0, 0, 0, .025) |
| | | } |
| | | } |
| | | } |
| | | &:hover { |
| | | background: rgba(0, 0, 0, 0.025); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .avatar-container { |
| | | margin-right: 30px; |
| | | .avatar-container { |
| | | margin-right: 30px; |
| | | |
| | | .avatar-wrapper { |
| | | margin-top: 10px; |
| | | position: relative; |
| | | height: 45px; |
| | | .avatar-wrapper { |
| | | margin-top: 10px; |
| | | position: relative; |
| | | height: 45px; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #fff; |
| | | |
| | | .user-avatar { |
| | | cursor: pointer; |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 10px; |
| | | } |
| | | .user-avatar { |
| | | cursor: pointer; |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 10px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .el-icon-caret-bottom { |
| | | cursor: pointer; |
| | | position: absolute; |
| | | right: -20px; |
| | | top: 25px; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .el-icon-caret-bottom { |
| | | cursor: pointer; |
| | | position: absolute; |
| | | right: -20px; |
| | | // top: 25px; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div :class="classObj" class="app-wrapper"> |
| | | <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> |
| | | <!-- <sidebar class="sidebar-container" />--> |
| | | <!-- <sidebar class="sidebar-container" />--> |
| | | <div :class="{ hasTagsView: needTagsView }" class="main-container"> |
| | | <div :class="{ 'fixed-header': fixedHeader }"> |
| | | <navbar /> |
| | |
| | | </right-panel> |
| | | </div> |
| | | </div> |
| | | <el-drawer |
| | | v-model="isCollapse" |
| | | title="I am the title" |
| | | direction="ltr" |
| | | size="300px" |
| | | :with-header="false" |
| | | :before-close="handleClose"> |
| | | <el-drawer v-model="isCollapseM" title="I am the title" direction="ltr" size="300px" :with-header="false" |
| | | :before-close="handleClose"> |
| | | <sidebar class="sidebar-container" /> |
| | | </el-drawer> |
| | | </template> |
| | | |
| | | <script> |
| | | import RightPanel from '@/components/RightPanel'; |
| | | import { AppMain, Navbar, Settings, TagsView, Sidebar } from './components'; |
| | | import ResizeMixin from './mixin/ResizeHandler'; |
| | | import { mapState } from 'pinia'; |
| | | import store from '@/store'; |
| | | import { defineComponent } from 'vue'; |
| | | import changeTheme from '@/utils/changeTheme.js'; |
| | | import RightPanel from "@/components/RightPanel"; |
| | | import { AppMain, Navbar, Settings, TagsView, Sidebar } from "./components"; |
| | | import ResizeMixin from "./mixin/ResizeHandler"; |
| | | import { mapState } from "pinia"; |
| | | import store from "@/store"; |
| | | import { defineComponent } from "vue"; |
| | | import changeTheme from "@/utils/changeTheme.js"; |
| | | import { throttle } from "@/utils/throttle.js"; |
| | | import { pingpong } from "@/api/user"; |
| | | import config from '@/utils/config.js'; |
| | | const { ukey, face } = config; |
| | | |
| | | export default defineComponent({ |
| | | name: 'LayoutIndex', |
| | | components: { |
| | | AppMain, |
| | | Navbar, |
| | | RightPanel, |
| | | Settings, |
| | | TagsView, |
| | | Sidebar |
| | | }, |
| | | watch: { |
| | | theme() { |
| | | changeTheme(this.theme); |
| | | } |
| | | }, |
| | | mixins: [ResizeMixin], |
| | | computed: { |
| | | ...mapState(store.app, ['sidebar']), |
| | | ...mapState(store.app, ['sidebar', 'device']), |
| | | ...mapState(store.settings, { |
| | | theme: 'theme', |
| | | showSettings: 'showSettings', |
| | | needTagsView: 'tagsView', |
| | | fixedHeader: 'fixedHeader', |
| | | secondMenuPopup: 'secondMenuPopup' |
| | | }), |
| | | classObj() { |
| | | return { |
| | | hideSidebar: !this.sidebar.opened, |
| | | openSidebar: this.sidebar.opened, |
| | | withoutAnimation: this.sidebar.withoutAnimation, |
| | | mobile: this.device === 'mobile' |
| | | }; |
| | | }, |
| | | isCollapse() { |
| | | if (this.secondMenuPopup) { |
| | | return true; |
| | | const throttleConect = throttle(pingpong, 1000); |
| | | |
| | | export default defineComponent({ |
| | | name: "LayoutIndex", |
| | | components: { |
| | | AppMain, |
| | | Navbar, |
| | | RightPanel, |
| | | Settings, |
| | | TagsView, |
| | | Sidebar, |
| | | }, |
| | | watch: { |
| | | theme() { |
| | | changeTheme(this.theme); |
| | | }, |
| | | isCollapse: { |
| | | handler(val) { |
| | | this.isCollapseM = val; |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | isIn: { |
| | | async handler(val) { |
| | | if (ukey && !val) { |
| | | await store.user().logout(); |
| | | // console.log('logout', '============='); |
| | | |
| | | router.push(`/login?redirect=${route.fullPath}`); |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | return !this.sidebar.opened; |
| | | } |
| | | }, |
| | | methods: { |
| | | handleClickOutside() { |
| | | store.app().closeSidebar({ withoutAnimation: false }); |
| | | }, |
| | | handleClose() { |
| | | store.app().toggleSidebar(); |
| | | } |
| | | }, |
| | | beforeMount() { |
| | | changeTheme(this.theme); |
| | | }, |
| | | mounted() { |
| | | |
| | | } |
| | | }); |
| | | }, |
| | | mixins: [ResizeMixin], |
| | | computed: { |
| | | ...mapState(store.app, ["sidebar"]), |
| | | ...mapState(store.app, ["sidebar", "device"]), |
| | | ...mapState(store.ukey, ["isIn"]), |
| | | ...mapState(store.settings, { |
| | | theme: "theme", |
| | | showSettings: "showSettings", |
| | | needTagsView: "tagsView", |
| | | fixedHeader: "fixedHeader", |
| | | secondMenuPopup: "secondMenuPopup", |
| | | }), |
| | | classObj() { |
| | | return { |
| | | hideSidebar: !this.sidebar.opened, |
| | | openSidebar: this.sidebar.opened, |
| | | withoutAnimation: this.sidebar.withoutAnimation, |
| | | mobile: this.device === "mobile", |
| | | }; |
| | | }, |
| | | isCollapse() { |
| | | if (this.secondMenuPopup) { |
| | | return true; |
| | | } |
| | | return !this.sidebar.opened; |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | isCollapseM: false, |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleClickOutside() { |
| | | store.app().closeSidebar({ withoutAnimation: false }); |
| | | }, |
| | | handleClose() { |
| | | store.app().toggleSidebar(); |
| | | }, |
| | | }, |
| | | beforeMount() { |
| | | changeTheme(this.theme); |
| | | }, |
| | | mounted() { |
| | | document.addEventListener("click", throttleConect); |
| | | document.addEventListener("mousemove", throttleConect); |
| | | document.addEventListener("keydown", throttleConect); |
| | | }, |
| | | unMounted() { |
| | | document.removeEventListener("click", throttleConect); |
| | | document.removeEventListener("mousemove", throttleConect); |
| | | document.removeEventListener("keydown", throttleConect); |
| | | }, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/styles/mixin.scss"; |
| | | @use "@/styles/mixin.scss"; |
| | | |
| | | .app-wrapper { |
| | | @include clearfix; |
| | | // @include clearfix; |
| | | position: relative; |
| | | height: 100%; |
| | | width: 100%; |
| | |
| | | } |
| | | |
| | | .hideSidebar .fixed-header { |
| | | width: calc(100%) |
| | | width: calc(100%); |
| | | } |
| | | |
| | | .mobile .fixed-header { |
| | |
| | | import 'element-plus/dist/index.css'; |
| | | import router from './router'; |
| | | import { setupStore } from './store'; |
| | | import ElementPlus from "element-plus"; |
| | | import * as ElementPlusIconsVue from '@element-plus/icons-vue' |
| | | |
| | | import zhCn from "element-plus/es/locale/lang/zh-cn"; |
| | | |
| | | import '@/styles/index.scss'; |
| | | import SvgIcon from './icons'; // icon |
| | |
| | | const app = createApp(App); |
| | | setupStore(app); |
| | | app.use(router); |
| | | app.use(ElementPlus, { locale: zhCn }); |
| | | |
| | | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { |
| | | app.component(key, component) |
| | | } |
| | | |
| | | app.component('svg-icon', SvgIcon); |
| | | app.directive('permission', vPermission); |
| | | checkEnableLogs(app); |
| | |
| | | } else { |
| | | // determine whether the user has obtained his permission roles through getInfo |
| | | const hasRoles = userStore().roles && userStore().roles.length > 0; |
| | | // console.log('hasRoles=', hasRoles); |
| | | console.log('hasRoles=', hasRoles, userStore().roles , userStore().roles && userStore().roles.length); |
| | | if (hasRoles) { |
| | | next(); |
| | | } else { |
| | |
| | | |
| | | // generate accessible routes map based on roles |
| | | const accessRoutes = await permissionStore().generateRoutes(roles); |
| | | // console.log('accessRoutes=', accessRoutes) |
| | | console.log('accessRoutes=', accessRoutes); |
| | | |
| | | // dynamically add accessible routes |
| | | // router.addRoutes(accessRoutes); |
| | | accessRoutes.forEach(item => { |
| | | router.addRoute(item); |
| | | }); |
| | | // console.log('next=', accessRoutes); |
| | | console.log('next=', accessRoutes, to); |
| | | |
| | | // hack method to ensure that addRoutes is complete |
| | | // set the replace: true, so the navigation will not leave a history record |
File was renamed from src/router/index.ts |
| | |
| | | import { createRouter, createWebHashHistory } from 'vue-router'; // createWebHashHistory, createWebHistory |
| | | import type { Router, RouteRecordRaw, RouteComponent } from 'vue-router'; |
| | | // import type { Router, RouteRecordRaw, RouteComponent } from 'vue-router'; |
| | | |
| | | import devicesRouter from './modules/devices'; |
| | | import generalRouter from './modules/general'; |
| | | import systemRouter from './modules/system'; |
| | | /* Layout */ |
| | | const Layout = ():RouteComponent => import('@/layout/index.vue'); |
| | | const Layout = () => import('@/layout/index.vue'); |
| | | |
| | | /** |
| | | * constantRoutes |
| | |
| | | * |
| | | * 注意:hidden、alwaysShow 属性配置移动到了meta中!!! |
| | | */ |
| | | export const constantRoutes:RouteRecordRaw[] = [ |
| | | export const constantRoutes = [ |
| | | { |
| | | path: '/redirect', |
| | | component: Layout, |
| | |
| | | { |
| | | path: '/', |
| | | component: Layout, |
| | | redirect: '/dashboard', |
| | | children: [ |
| | | { |
| | | path: 'dashboard', |
| | | component: () => import('@/views/dashboard/index.vue'), |
| | | name: 'Dashboard', |
| | | meta: { title: '首页', icon: 'home-hdw', affix: true } |
| | | } |
| | | ] |
| | | // redirect: '/dashboard', |
| | | redirect: '/device/lock', |
| | | // children: [ |
| | | // { |
| | | // path: 'dashboard', |
| | | // component: () => import('@/views/dashboard/index.vue'), |
| | | // name: 'Dashboard', |
| | | // meta: { title: '首页', icon: 'home-hdw', affix: true } |
| | | // } |
| | | // ] |
| | | } |
| | | ]; |
| | | |
| | |
| | | * |
| | | * 注意:hidden、alwaysShow 属性配置移动到了meta中!!! |
| | | */ |
| | | export const asyncRoutes:RouteRecordRaw[] = [ |
| | | export const asyncRoutes = [ |
| | | devicesRouter, |
| | | generalRouter, |
| | | systemRouter, |
| | |
| | | { path: '/:pathMatch(.*)*', redirect: '/404', meta: { hidden: true }} |
| | | ]; |
| | | |
| | | // console.log('asyncRoutes=', asyncRoutes, '============='); |
| | | |
| | | console.log('BASE_URL=', import.meta.env); |
| | | |
| | | const createTheRouter = ():Router => createRouter({ |
| | | const createTheRouter = () => createRouter({ |
| | | history: createWebHashHistory(import.meta.env.BASE_URL), |
| | | // 注意,如果要配置 HTML5 模式,则需要修改nginx配置,参考资料: |
| | | // https://router.vuejs.org/zh/guide/essentials/history-mode.html |
| | |
| | | routes: constantRoutes |
| | | }); |
| | | |
| | | interface RouterPro extends Router { |
| | | matcher: unknown; |
| | | } |
| | | // interface RouterPro extends Router { |
| | | // matcher: unknown; |
| | | // } |
| | | |
| | | const router = createTheRouter() as RouterPro; |
| | | const router = createTheRouter() ; |
| | | |
| | | // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465 |
| | | export function resetRouter() { |
| | | const newRouter = createTheRouter() as RouterPro; |
| | | const newRouter = createTheRouter(); |
| | | router.matcher = newRouter.matcher; // reset router |
| | | } |
| | | |
File was renamed from src/router/modules/devices.ts |
| | |
| | | children: [ |
| | | { |
| | | path: 'lock', |
| | | component: () => import('@/views/device/lock/index.vue'), |
| | | component: () => import('@/views/device/locks/index.vue'), |
| | | name: 'LockManage', |
| | | meta: { title: '锁具管理', icon: 'lock-hdw', noCache: false } |
| | | meta: { title: '锁具管理', icon: 'lock-hdw', affix: true, noCache: false } |
| | | }, |
| | | { |
| | | path: 'key', |
| | | component: () => import('@/views/device/key/index.vue'), |
| | | component: () => import('@/views/device/keys/index.vue'), |
| | | // component: () => import('@/views/test/index2.vue'), |
| | | name: 'KeyManage', |
| | | meta: { title: '钥匙管理', icon: 'key-hdw', noCache: false } |
| | | } |
File was renamed from src/router/modules/general.ts |
| | |
| | | name: 'General', |
| | | meta: { |
| | | title: '通用管理', |
| | | icon: 'general-hdw' |
| | | icon: 'general-hdw', |
| | | }, |
| | | children: [ |
| | | { |
| | |
| | | path: 'log', |
| | | component: () => import('@/views/general/log/index.vue'), |
| | | name: 'LogManage', |
| | | meta: { title: '日志管理', icon: 'log-hdw', noCache: false } |
| | | meta: { title: '锁具日志', icon: 'log-hdw', noCache: false } |
| | | }, |
| | | { |
| | | path: 'map', |
| | | component: () => import('@/views/general/map/index.vue'), |
| | | name: 'MapManage', |
| | | meta: { title: '地图定位', icon: 'map-hdw', noCache: false } |
| | | } |
| | | // { |
| | | // path: 'map', |
| | | // component: () => import('@/views/general/map/index.vue'), |
| | | // name: 'MapManage', |
| | | // meta: { title: '地图定位', icon: 'map-hdw', noCache: false, } |
| | | // } |
| | | ] |
| | | }; |
| | | |
File was renamed from src/router/modules/system.ts |
| | |
| | | component: () => import('@/views/system/user/index.vue'), |
| | | name: 'UserManage', |
| | | meta: { title: '用户管理', icon: 'people-hdw', noCache: false } |
| | | }, |
| | | { |
| | | path: 'face', |
| | | component: () => import('@/views/system/user/userFaceManager.vue'), |
| | | name: 'UserFaceManage', |
| | | meta: { title: '用户人脸管理', icon: 'people-hdw', noCache: false } |
| | | }, |
| | | { |
| | | path: 'logs', |
| | | component: () => import('@/views/system/logs.vue'), |
| | | name: 'sysLogs', |
| | | meta: { title: '系统日志', icon: 'log-hdw', noCache: false } |
| | | } |
| | | ] |
| | | }; |
| | |
| | | * @param route |
| | | */ |
| | | function hasPermission(roles:string[], route:RouteRecordRaw):boolean { |
| | | console.trace('hasPermission'); |
| | | console.log('hasPermission', roles, route, '============='); |
| | | |
| | | if (route.meta && route.meta.roles) { |
| | | const rolesArr = route.meta.roles as string[]; |
| | | return roles.some(role => rolesArr.includes(role)); |
| | |
| | | setRoutes(routes: RouteRecordRaw[]) { |
| | | this.addRoutes = routes; |
| | | this.routes = constantRoutes.concat(routes); |
| | | console.log('this.routes=', this.routes, '=============', constantRoutes); |
| | | }, |
| | | generateRoutes(roles: string[]) { |
| | | let accessedRoutes; |
| | | if (roles.includes('admin')) { |
| | | console.log('1', '============='); |
| | | |
| | | accessedRoutes = asyncRoutes || []; |
| | | } else { |
| | | console.log('2', '============='); |
| | | |
| | | accessedRoutes = filterAsyncRoutes(asyncRoutes, roles); |
| | | } |
| | | this.setRoutes(accessedRoutes); |
| | | console.log('accessedRoutes=', accessedRoutes, '============='); |
| | | |
| | | return accessedRoutes; |
| | | } |
| | | } |
New file |
| | |
| | | import SoftKey3W from "@/utils/Syunew3"; |
| | | import { defineStore } from 'pinia'; |
| | | |
| | | export default defineStore({ |
| | | id: 'ukey', |
| | | state() { |
| | | return { |
| | | connect: 0, // 判断是否安装了客户端服务,0未安装,1已安装 |
| | | isIn: 0, // uKey的插拔状态 |
| | | id: "", // uKey的唯一编号 |
| | | } |
| | | }, |
| | | getters: { |
| | | getId(state) { |
| | | if (state.isIn) { |
| | | return state.id; |
| | | } else { |
| | | return ""; |
| | | } |
| | | } |
| | | }, |
| | | actions: { |
| | | changeIsIn(isIn) { |
| | | this.isIn = isIn; |
| | | }, |
| | | changeConnect(isConnect) { |
| | | this.connect = isConnect; |
| | | }, |
| | | changeUKeyId(id) { |
| | | this.id = id; |
| | | }, |
| | | /** |
| | | * 监控uKey的插拔事件 |
| | | * @param context |
| | | * @returns {boolean} |
| | | */ |
| | | load(isLoad) { |
| | | //如果是IE10及以下浏览器,则跳过不处理, |
| | | if (navigator.userAgent.indexOf("MSIE") > 0 && !navigator.userAgent.indexOf("opera") > -1) { |
| | | //该例子只支持HTM5的浏览器 |
| | | return; |
| | | } |
| | | try { |
| | | let s_pnp = new SoftKey3W();//创建UK类 |
| | | // context.commit('changeConnect', 0); //客户端服务安装状态 |
| | | this.changeConnect(0); |
| | | s_pnp.Socket_UK.onopen = () => { |
| | | // context.commit('changeConnect', 1);//代表已经连接,用于判断是否安装了客户端服务 |
| | | this.changeConnect(1); |
| | | } |
| | | |
| | | // uKey插拔事件监听 |
| | | s_pnp.Socket_UK.onmessage = (Msg) => { |
| | | let PnpData = JSON.parse(Msg.data); |
| | | console.log('PnpData', PnpData) |
| | | if (PnpData.type == "PnpEvent")//如果是插拨事件处理消息 |
| | | { |
| | | if (PnpData.IsIn) { |
| | | // context.commit('changeIsIn', 1); // 已插入uKey |
| | | this.changeIsIn(1); |
| | | } else { |
| | | // context.commit('changeIsIn', 0); // 未插入uKey |
| | | this.changeIsIn(0); |
| | | // context.commit('changeId', ""); // 初始化uKeyId为空 |
| | | this.changeUKeyId(""); |
| | | } |
| | | } |
| | | } |
| | | |
| | | s_pnp.Socket_UK.onclose = () => { |
| | | console.log('关闭监控插拔监控'); |
| | | } |
| | | } catch (error) { |
| | | console.log(error.name + ": " + error.message); |
| | | return false; |
| | | } |
| | | }, |
| | | /** |
| | | * 检测是否插入uKey |
| | | * @param context |
| | | * @param isConnent 客户端服务安装状态 |
| | | */ |
| | | checkIsIn(isConnent) { |
| | | if (isConnent) { |
| | | try { |
| | | let s_simnew1 = new SoftKey3W(); //创建UK类 |
| | | let DevicePath, version; |
| | | s_simnew1.Socket_UK.onopen = () => { |
| | | s_simnew1.ResetOrder();//这里调用ResetOrder将计数清零,这样,消息处理处就会收到0序号的消息,通过计数及序号的方式,从而生产流程 |
| | | } |
| | | |
| | | s_simnew1.Socket_UK.onmessage = (Msg) => { |
| | | let UK_Data = JSON.parse(Msg.data); |
| | | if (UK_Data.type != "Process") return;//如果不是流程处理消息,则跳过 |
| | | switch (UK_Data.order) { |
| | | case 0: |
| | | { |
| | | s_simnew1.FindPort(0); //发送命令取UK的路径 |
| | | } |
| | | break; |
| | | case 1: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | // context.commit('changeIsIn', 0); // 未插入 |
| | | this.changeIsIn(0); |
| | | // context.commit('changeId', ""); // 初始化uKeyId为空 |
| | | this.changeUKeyId(""); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | // context.commit('changeIsIn', 1); // 已插入 |
| | | this.changeIsIn(1); |
| | | DevicePath = UK_Data.return_value;//获得返回的UK的路径 |
| | | s_simnew1.GetVersion(DevicePath); //发送命令取UK的版本 |
| | | } |
| | | break; |
| | | case 2: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | console.log("返回版本号错误,错误码为:" + UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | version = UK_Data.return_value;//获得返回的UK的版本 |
| | | if (version > 10) { |
| | | //取得锁的出厂编码 |
| | | s_simnew1.GetProduceDate(DevicePath);//发送命令取UK的出厂编码 |
| | | } else { |
| | | console.log("锁的版本少于11,不支持返回锁的出厂编码功能\n2013年9月15号以后出厂的锁都支持这个功能。"); |
| | | } |
| | | } |
| | | break; |
| | | case 3: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | console.log("取得锁的出厂编码错误,错误码为:" + UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | let id = UK_Data.return_value;//获得返回的UK的出厂编码 |
| | | // context.commit('changeId', id); |
| | | this.changeUKeyId(id); |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | } |
| | | break; |
| | | default: |
| | | { |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | s_simnew1.Socket_UK.onclose = () => { |
| | | console.log('初始化设置uKey插拔状态和uKey唯一编号监控程序关闭'); |
| | | } |
| | | return true; |
| | | } catch (e) { |
| | | console.log('设置uKey插拔状态和uKey唯一编号监控程序报错'); |
| | | console.log(error.name + ": " + error.message); |
| | | return false; |
| | | } |
| | | } else { |
| | | // context.commit('changeIsIn', 0); |
| | | this.changeIsIn(0); |
| | | } |
| | | }, |
| | | changeId(isIn) { |
| | | if (isIn) { |
| | | try { |
| | | let s_simnew1 = new SoftKey3W(); //创建UK类 |
| | | let DevicePath, version; |
| | | s_simnew1.Socket_UK.onopen = () => { |
| | | s_simnew1.ResetOrder();//这里调用ResetOrder将计数清零,这样,消息处理处就会收到0序号的消息,通过计数及序号的方式,从而生产流程 |
| | | } |
| | | |
| | | s_simnew1.Socket_UK.onmessage = (Msg) => { |
| | | let UK_Data = JSON.parse(Msg.data); |
| | | if (UK_Data.type != "Process") return;//如果不是流程处理消息,则跳过 |
| | | switch (UK_Data.order) { |
| | | case 0: |
| | | { |
| | | s_simnew1.FindPort(0); //发送命令取UK的路径 |
| | | } |
| | | break; |
| | | case 1: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | // context.commit('changeId', ""); // 初始化uKeyId为空 |
| | | this.changeUKeyId(""); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | DevicePath = UK_Data.return_value;//获得返回的UK的路径 |
| | | s_simnew1.GetVersion(DevicePath); //发送命令取UK的版本 |
| | | } |
| | | break; |
| | | case 2: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | console.log("返回版本号错误,错误码为:" + UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | version = UK_Data.return_value;//获得返回的UK的版本 |
| | | if (version > 10) { |
| | | //取得锁的出厂编码 |
| | | s_simnew1.GetProduceDate(DevicePath);//发送命令取UK的出厂编码 |
| | | } else { |
| | | console.log("锁的版本少于11,不支持返回锁的出厂编码功能\n2013年9月15号以后出厂的锁都支持这个功能。"); |
| | | } |
| | | } |
| | | break; |
| | | case 3: |
| | | { |
| | | if (UK_Data.LastError != 0) { |
| | | console.log("取得锁的出厂编码错误,错误码为:" + UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | let id = UK_Data.return_value;//获得返回的UK的出厂编码 |
| | | // context.commit('changeId', id); |
| | | this.changeUKeyId(id); |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | } |
| | | break; |
| | | default: |
| | | { |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | s_simnew1.Socket_UK.onclose = () => { |
| | | console.log('设置uKey唯一编号监控程序关闭'); |
| | | } |
| | | return true; |
| | | } catch (e) { |
| | | console.log('设置uKey唯一编号监控程序报错'); |
| | | console.log(error.name + ": " + error.message); |
| | | return false; |
| | | } |
| | | } else { |
| | | // context.commit("changeId", ""); |
| | | this.changeUKeyId(""); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | |
| | | import { defineStore } from 'pinia'; |
| | | import { login as apiLogin, logout as apiLogout } from '@/api/user'; |
| | | import { getToken, removeToken, setToken } from '@/utils/auth'; |
| | | import { getToken, removeToken, setToken, getUname, setUname, removeUname, getUrole, setUrole, removeUrole } from '@/utils/auth'; |
| | | import router, { resetRouter } from '@/router'; |
| | | import tagsViewStore from './tagsView'; |
| | | import permissionStore from './permission'; |
| | |
| | | state: () => ({ |
| | | token: getToken(), |
| | | userId: '', |
| | | name: '', |
| | | name: getUname(), |
| | | avatar: '', |
| | | urole: getUrole(), |
| | | introduction: '', |
| | | roles: [] |
| | | }), |
| | |
| | | return new Promise((resolve, reject) => { |
| | | apiLogin(username.trim(), password).then((response) => { |
| | | if (response.code === 1 && response.data) { |
| | | let name = response.data2.uname; |
| | | let role = response.data2.urole; |
| | | this.name = name; |
| | | setUname(name); |
| | | this.token = 'admin'; |
| | | setToken('admin'); |
| | | this.urole = role; |
| | | setUrole(role); |
| | | resolve(response); |
| | | } else { |
| | | reject('用户名/密码错误'); |
| | | // reject('用户名/密码错误'); |
| | | reject(response.msg); |
| | | } |
| | | }).catch(error => { |
| | | reject(error); |
| | | }); |
| | | }); |
| | | });u |
| | | }, |
| | | |
| | | // get user info |
| | |
| | | roles: ['admin'], |
| | | introduction: 'I am a super administrator', |
| | | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', |
| | | name: 'Super Admin' |
| | | // name: 'Super Admin' |
| | | name: getUname() |
| | | }; |
| | | const { roles, name, avatar, introduction } = data; |
| | | const { roles, name, avatar, introduction } = data; |
| | | this.roles = roles; |
| | | this.name = name; |
| | | this.avatar = avatar; |
| | |
| | | this.token = ''; |
| | | this.roles = []; |
| | | removeToken(); |
| | | removeUname(); |
| | | removeUrole(); |
| | | resetRouter(); |
| | | |
| | | // reset visited views and cached views |
New file |
| | |
| | | function SoftUKey(SoftKey3W) { |
| | | this.SoftKey3W = SoftKey3W; |
| | | } |
| | | |
| | | /** |
| | | * uKey写入用户名 |
| | | * @param userName 用户名 |
| | | * @param callback 回调函数 |
| | | */ |
| | | SoftUKey.prototype.setUserName = function (userName, callback) { |
| | | try { |
| | | let s_simnew1 = new this.SoftKey3W(); //创建UK类 |
| | | let DevicePath, PriKey, PubKeyX, PubKeyY; |
| | | // 开启监听 |
| | | s_simnew1.Socket_UK.onopen = function() { |
| | | s_simnew1.ResetOrder();//这里调用ResetOrder将计数清零,这样,消息处理处就会收到0序号的消息,通过计数及序号的方式,从而生产流程 |
| | | } |
| | | |
| | | // 监听获取到的信息 |
| | | s_simnew1.Socket_UK.onmessage = function(Msg) { |
| | | let UK_Data = JSON.parse(Msg.data); |
| | | if(UK_Data.type!="Process")return ;//如果不是流程处理消息,则跳过 |
| | | |
| | | // 根据收到的序号执行函数 |
| | | switch(UK_Data.order) { |
| | | case 0: |
| | | s_simnew1.FindPort(0); //发送命令取UK的路径 |
| | | break; |
| | | case 1: |
| | | if(UK_Data.LastError!=0) { |
| | | window.alert ( "未发现加密锁,请插入加密锁"); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | // 设置路径 |
| | | DevicePath=UK_Data.return_value;//获得返回的UK的路径 |
| | | |
| | | //产生密钥对 |
| | | s_simnew1.StarGenKeyPair(DevicePath); |
| | | break; |
| | | case 2: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("产生密钥对出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | |
| | | //获取生成的私钥 |
| | | s_simnew1.GenPriKey(); |
| | | break; |
| | | case 3: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("获取生成的私钥时错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | PriKey = UK_Data.return_value; |
| | | //获取生成的公钥X |
| | | s_simnew1.GenPubKeyX(); |
| | | break; |
| | | case 4: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("获取生成的公钥X时错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | PubKeyX = UK_Data.return_value; |
| | | |
| | | //获取生成的公钥Y |
| | | s_simnew1.GenPubKeyY(); |
| | | break; |
| | | case 5: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("获取生成的公钥Y时错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | PubKeyY = UK_Data.return_value; |
| | | |
| | | //设置密钥对及用户身份到锁中 |
| | | s_simnew1.Set_SM2_KeyPair(PriKey,PubKeyX,PubKeyY,userName,DevicePath); |
| | | break; |
| | | case 6: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("设置密钥对及用户身份时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | // 执行回调函数 |
| | | if(typeof callback == 'function') { |
| | | callback({ |
| | | PriKey, |
| | | PubKeyX, |
| | | PubKeyY, |
| | | userName, |
| | | DevicePath |
| | | }); |
| | | } |
| | | |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 关闭监听 |
| | | s_simnew1.Socket_UK.onclose = function() { |
| | | console.log("关闭设置用户名称") |
| | | } |
| | | return true; |
| | | }catch(e) { |
| | | console.log("设置用户名称异常:"+e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读取uKey中的用户名 |
| | | * @param callback |
| | | * @return {boolean} |
| | | */ |
| | | SoftUKey.prototype.getUserName = function(callback) { |
| | | try { |
| | | let s_simnew1 = new this.SoftKey3W(); //创建UK类 |
| | | let DevicePath, userName; |
| | | // 开启监听 |
| | | s_simnew1.Socket_UK.onopen = function() { |
| | | s_simnew1.ResetOrder();//这里调用ResetOrder将计数清零,这样,消息处理处就会收到0序号的消息,通过计数及序号的方式,从而生产流程 |
| | | } |
| | | |
| | | // 监听获取到的信息 |
| | | s_simnew1.Socket_UK.onmessage = function(Msg) { |
| | | let UK_Data = JSON.parse(Msg.data); |
| | | if(UK_Data.type!="Process")return ;//如果不是流程处理消息,则跳过 |
| | | |
| | | // 根据收到的序号执行函数 |
| | | switch(UK_Data.order) { |
| | | case 0: |
| | | s_simnew1.FindPort(0); //发送命令取UK的路径 |
| | | break; |
| | | case 1: |
| | | if(UK_Data.LastError!=0) { |
| | | window.alert ( "未发现加密锁,请插入加密锁"); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | // 设置路径 |
| | | DevicePath=UK_Data.return_value;//获得返回的UK的路径 |
| | | |
| | | //返回设置在锁中的身份 |
| | | s_simnew1.GetSm2UserName(DevicePath); |
| | | break; |
| | | case 2: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("返回设置在锁中的用户身份时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | userName = UK_Data.return_value; |
| | | |
| | | // 执行回调函数 |
| | | if(typeof callback == 'function') { |
| | | callback({ |
| | | userName, |
| | | }); |
| | | } |
| | | |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 关闭监听 |
| | | s_simnew1.Socket_UK.onclose = function() { |
| | | console.log("关闭读取用户名称") |
| | | } |
| | | return true; |
| | | }catch (e) { |
| | | console.log("读取用户名称异常:"+e); |
| | | } |
| | | } |
| | | /** |
| | | * 获取ukey的签名 |
| | | * @param randomNumber |
| | | * @param callback |
| | | */ |
| | | SoftUKey.prototype.getSign = function(randomNumber, callback) { |
| | | try { |
| | | let s_simnew1 = new this.SoftKey3W(); //创建UK类 |
| | | let inPath, sign, uKeyId, publicX, publicY; |
| | | // 开启监听 |
| | | s_simnew1.Socket_UK.onopen = function() { |
| | | s_simnew1.ResetOrder();//这里调用ResetOrder将计数清零,这样,消息处理处就会收到0序号的消息,通过计数及序号的方式,从而生产流程 |
| | | } |
| | | |
| | | // 监听获取到的信息 |
| | | s_simnew1.Socket_UK.onmessage = function(Msg) { |
| | | let UK_Data = JSON.parse(Msg.data); |
| | | if(UK_Data.type!="Process")return ;//如果不是流程处理消息,则跳过 |
| | | |
| | | // 根据收到的序号执行函数 |
| | | switch(UK_Data.order) { |
| | | case 0: |
| | | s_simnew1.FindPort(0); //发送命令取UK的路径 |
| | | break; |
| | | case 1: |
| | | if(UK_Data.LastError!=0) { |
| | | window.alert ( "未发现加密锁,请插入加密锁"); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | // 设置路径 |
| | | inPath=UK_Data.return_value;//获得返回的UK的路径 |
| | | |
| | | s_simnew1.GetProduceDate(inPath);//返回芯片唯一ID |
| | | break; |
| | | case 2: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("返回芯片唯一ID时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | uKeyId = UK_Data.return_value; |
| | | |
| | | //返回设置在锁中的公钥X |
| | | s_simnew1.GetPubKeyX(inPath); |
| | | break; |
| | | case 3: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("返回设置在锁中的公钥X时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | publicX = UK_Data.return_value; |
| | | |
| | | // 返回设置在锁中的公钥Y |
| | | s_simnew1.GetPubKeyY(inPath); |
| | | break; |
| | | case 4: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("返回设置在锁中的公钥Y时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | publicY = UK_Data.return_value; |
| | | |
| | | // 对数据进行签名 |
| | | s_simnew1.YtSign(randomNumber,"123", inPath); |
| | | break; |
| | | case 5: |
| | | if(UK_Data.LastError!=0){ |
| | | window.alert("对数据进行签名时出现错误,错误码为:"+UK_Data.LastError.toString()); |
| | | s_simnew1.Socket_UK.close(); |
| | | return false; |
| | | } |
| | | sign = UK_Data.return_value; |
| | | |
| | | // 执行回调函数 |
| | | if(typeof callback == 'function') { |
| | | callback({ |
| | | inPath, |
| | | sign, |
| | | uKeyId, |
| | | publicX, |
| | | publicY, |
| | | }); |
| | | } |
| | | |
| | | //所有工作处理完成后,关掉Socket |
| | | s_simnew1.Socket_UK.close(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 关闭监听 |
| | | s_simnew1.Socket_UK.onclose = function() { |
| | | console.log("关闭获取签名") |
| | | } |
| | | }catch (e) { |
| | | console.log("获取签名异常:"+e) |
| | | } |
| | | } |
| | | |
| | | export default SoftUKey; |
New file |
| | |
| | | function SoftKey3W() { |
| | | var isIE11 = |
| | | navigator.userAgent.indexOf("Trident") > -1 && |
| | | navigator.userAgent.indexOf("rv:11.0") > -1; |
| | | var isEDGE = navigator.userAgent.indexOf("Edge") > -1; |
| | | var u = document.URL; |
| | | var url; |
| | | if (u.substring(0, 5) == "https") { |
| | | if (isIE11 || isEDGE) { |
| | | if (isIE11) url = "wss://127.0.0.1:4006/xxx"; |
| | | else url = "ws://127.0.0.1:4006/xxx"; |
| | | } else { |
| | | url = "ws://localhost:4006/xxx"; |
| | | } |
| | | } else { |
| | | url = "ws://127.0.0.1:4006/xxx"; |
| | | } |
| | | |
| | | var Socket_UK; |
| | | |
| | | if (typeof MozWebSocket != "undefined") { |
| | | Socket_UK = new MozWebSocket(url, "usbkey-protocol"); |
| | | } else { |
| | | this.Socket_UK = new WebSocket(url, "usbkey-protocol"); |
| | | } |
| | | |
| | | this.FindPort = function (start) { |
| | | var msg = { |
| | | FunName: "FindPort", |
| | | start: start, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.FindPort_2 = function (start, in_data, verf_data) { |
| | | var msg = { |
| | | FunName: "FindPort_2", |
| | | start: start, |
| | | in_data: in_data, |
| | | verf_data: verf_data, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.FindPort_3 = function (start, in_data, verf_data) { |
| | | var msg = { |
| | | FunName: "FindPort_3", |
| | | start: start, |
| | | in_data: in_data, |
| | | verf_data: verf_data, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetVersion = function (Path) { |
| | | var msg = { |
| | | FunName: "GetVersion", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetVersionEx = function (Path) { |
| | | var msg = { |
| | | FunName: "GetVersionEx", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetID_1 = function (Path) { |
| | | var msg = { |
| | | FunName: "GetID_1", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetID_2 = function (Path) { |
| | | var msg = { |
| | | FunName: "GetID_2", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sRead = function (Path) { |
| | | var msg = { |
| | | FunName: "sRead", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWrite = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWrite", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWrite_2 = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWrite_2", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWrite_2Ex = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWrite_2Ex", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWriteEx = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWriteEx", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWriteEx_New = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWriteEx_New", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.sWrite_2Ex_New = function (InData, Path) { |
| | | var msg = { |
| | | FunName: "sWrite_2Ex_New", |
| | | InData: InData, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetCal = function (Hkey, Lkey, new_Hkey, new_Lkey, Path) { |
| | | var msg = { |
| | | FunName: "SetCal", |
| | | Hkey: Hkey, |
| | | Lkey: Lkey, |
| | | new_Hkey: new_Hkey, |
| | | new_Lkey: new_Lkey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetBuf = function (InData, pos) { |
| | | var msg = { |
| | | FunName: "SetBuf", |
| | | InData: InData, |
| | | pos: pos, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetBuf = function (pos) { |
| | | var msg = { |
| | | FunName: "GetBuf", |
| | | pos: pos, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YRead = function (Address, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YRead", |
| | | Address: Address, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YWrite = function (InData, Address, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YWrite", |
| | | InData: InData, |
| | | Address: Address, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YReadEx = function (Address, len, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YReadEx", |
| | | Address: Address, |
| | | len: len, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YWriteEx = function (Address, len, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YWriteEx", |
| | | Address: Address, |
| | | len: len, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YReadString = function (Address, len, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YReadString", |
| | | Address: Address, |
| | | len: len, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YWriteString = function (InString, Address, HKey, LKey, Path) { |
| | | var msg = { |
| | | FunName: "YWriteString", |
| | | InString: InString, |
| | | Address: Address, |
| | | HKey: HKey, |
| | | LKey: LKey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetWritePassword = function (W_Hkey, W_Lkey, new_Hkey, new_Lkey, Path) { |
| | | var msg = { |
| | | FunName: "SetWritePassword", |
| | | W_Hkey: W_Hkey, |
| | | W_Lkey: W_Lkey, |
| | | new_Hkey: new_Hkey, |
| | | new_Lkey: new_Lkey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetReadPassword = function (W_Hkey, W_Lkey, new_Hkey, new_Lkey, Path) { |
| | | var msg = { |
| | | FunName: "SetReadPassword", |
| | | W_Hkey: W_Hkey, |
| | | W_Lkey: W_Lkey, |
| | | new_Hkey: new_Hkey, |
| | | new_Lkey: new_Lkey, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.DecString = function (InString, Key) { |
| | | var msg = { |
| | | FunName: "DecString", |
| | | InString: InString, |
| | | Key: Key, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.EncString = function (InString, Path) { |
| | | var msg = { |
| | | FunName: "EncString", |
| | | InString: InString, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.EncString_New = function (InString, Path) { |
| | | var msg = { |
| | | FunName: "EncString_New", |
| | | InString: InString, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.Cal = function (Path) { |
| | | var msg = { |
| | | FunName: "Cal", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.Cal_New = function (Path) { |
| | | var msg = { |
| | | FunName: "Cal_New", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetCal_2 = function (Key, Path) { |
| | | var msg = { |
| | | FunName: "SetCal_2", |
| | | Key: Key, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetCal_New = function (Key, Path) { |
| | | var msg = { |
| | | FunName: "SetCal_New", |
| | | Key: Key, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetEncBuf = function (InData, pos) { |
| | | var msg = { |
| | | FunName: "SetEncBuf", |
| | | InData: InData, |
| | | pos: pos, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetEncBuf = function (pos) { |
| | | var msg = { |
| | | FunName: "GetEncBuf", |
| | | pos: pos, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.ReSet = function (Path) { |
| | | var msg = { |
| | | FunName: "ReSet", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetID = function (Seed, Path) { |
| | | var msg = { |
| | | FunName: "SetID", |
| | | Seed: Seed, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetProduceDate = function (Path) { |
| | | var msg = { |
| | | FunName: "GetProduceDate", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.MacAddr = function () { |
| | | var msg = { |
| | | FunName: "MacAddr", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetChipID = function (Path) { |
| | | var msg = { |
| | | FunName: "GetChipID", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.StarGenKeyPair = function (Path) { |
| | | var msg = { |
| | | FunName: "StarGenKeyPair", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GenPubKeyY = function () { |
| | | var msg = { |
| | | FunName: "GenPubKeyY", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GenPubKeyX = function () { |
| | | var msg = { |
| | | FunName: "GenPubKeyX", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GenPriKey = function () { |
| | | var msg = { |
| | | FunName: "GenPriKey", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetPubKeyY = function (Path) { |
| | | var msg = { |
| | | FunName: "GetPubKeyY", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetPubKeyX = function (Path) { |
| | | var msg = { |
| | | FunName: "GetPubKeyX", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.GetSm2UserName = function (Path) { |
| | | var msg = { |
| | | FunName: "GetSm2UserName", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.Set_SM2_KeyPair = function ( |
| | | PriKey, |
| | | PubKeyX, |
| | | PubKeyY, |
| | | sm2UserName, |
| | | Path |
| | | ) { |
| | | var msg = { |
| | | FunName: "Set_SM2_KeyPair", |
| | | PriKey: PriKey, |
| | | PubKeyX: PubKeyX, |
| | | PubKeyY: PubKeyY, |
| | | sm2UserName: sm2UserName, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YtSign = function (SignMsg, Pin, Path) { |
| | | var msg = { |
| | | FunName: "YtSign", |
| | | SignMsg: SignMsg, |
| | | Pin: Pin, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YtSign_2 = function (SignMsg, Pin, Path) { |
| | | var msg = { |
| | | FunName: "YtSign_2", |
| | | SignMsg: SignMsg, |
| | | Pin: Pin, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YtVerfiy = function (id, SignMsg, PubKeyX, PubKeyY, VerfiySign, Path) { |
| | | var msg = { |
| | | FunName: "YtVerfiy", |
| | | id: id, |
| | | SignMsg: SignMsg, |
| | | PubKeyX: PubKeyX, |
| | | PubKeyY: PubKeyY, |
| | | VerfiySign: VerfiySign, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SM2_DecString = function (InString, Pin, Path) { |
| | | var msg = { |
| | | FunName: "SM2_DecString", |
| | | InString: InString, |
| | | Pin: Pin, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SM2_EncString = function (InString, Path) { |
| | | var msg = { |
| | | FunName: "SM2_EncString", |
| | | InString: InString, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.YtSetPin = function (OldPin, NewPin, Path) { |
| | | var msg = { |
| | | FunName: "YtSetPin", |
| | | OldPin: OldPin, |
| | | NewPin: NewPin, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.FindU = function (start) { |
| | | var msg = { |
| | | FunName: "FindU", |
| | | start: start, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.FindU_2 = function (start, in_data, verf_data) { |
| | | var msg = { |
| | | FunName: "FindU_2", |
| | | start: start, |
| | | in_data: in_data, |
| | | verf_data: verf_data, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.FindU_3 = function (start, in_data, verf_data) { |
| | | var msg = { |
| | | FunName: "FindU_3", |
| | | start: start, |
| | | in_data: in_data, |
| | | verf_data: verf_data, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.IsUReadOnly = function (Path) { |
| | | var msg = { |
| | | FunName: "IsUReadOnly", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetUReadOnly = function (Path) { |
| | | var msg = { |
| | | FunName: "SetUReadOnly", |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.SetHidOnly = function (IsHidOnly, Path) { |
| | | var msg = { |
| | | FunName: "SetHidOnly", |
| | | IsHidOnly: IsHidOnly, |
| | | Path: Path, |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.ResetOrder = function () { |
| | | var msg = { |
| | | FunName: "ResetOrder", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | |
| | | this.ContinueOrder = function () { |
| | | var msg = { |
| | | FunName: "ContinueOrder", |
| | | }; |
| | | this.Socket_UK.send(JSON.stringify(msg)); |
| | | }; |
| | | } |
| | | |
| | | export default SoftKey3W; |
| | |
| | | export function removeToken() { |
| | | return Cookies.remove(TokenKey); |
| | | } |
| | | |
| | | export function getUname() { |
| | | return Cookies.get('uname'); |
| | | } |
| | | |
| | | export function setUname(uname) { |
| | | return Cookies.set('uname', uname); |
| | | } |
| | | |
| | | export function removeUname() { |
| | | return Cookies.remove('uname'); |
| | | } |
| | | |
| | | export function getUrole() { |
| | | return Cookies.get('urole'); |
| | | } |
| | | |
| | | export function setUrole(urole) { |
| | | return Cookies.set('urole', urole); |
| | | } |
| | | |
| | | export function removeUrole() { |
| | | return Cookies.remove('urole'); |
| | | } |
New file |
| | |
| | | export default { |
| | | // 平台是否需要ukey 才能登录 |
| | | ukey: true, |
| | | // ukey: false, |
| | | // 是否需要人脸识别 |
| | | face: true, |
| | | } |
New file |
| | |
| | | /** |
| | | * 获取Websocket的连接 |
| | | * @param action |
| | | * @returns {string} |
| | | */ |
| | | function getWsUrl(action, port) { |
| | | let _port = port ? port : 8100; |
| | | let hostname = window.location.hostname; |
| | | let wsProtocol = "ws://"; |
| | | if (window.location.protocol == "https:") { |
| | | wsProtocol = "wss://"; |
| | | } |
| | | if (process.env.NODE_ENV == "development") { |
| | | hostname = "localhost"; |
| | | } else { |
| | | _port = window.location.port; |
| | | } |
| | | // 处理端口为80 |
| | | _port = _port == 80 ? "" : ":" + _port; |
| | | return wsProtocol + hostname + _port + "/bl/" + action; |
| | | } |
| | | |
| | | export default getWsUrl; |
| | |
| | | const service = axios.create({ |
| | | baseURL: baseURL, // url = base url + request url |
| | | withCredentials: true, // send cookies when cross-domain requests |
| | | timeout: 10000 // request timeout |
| | | // timeout: 20000 // request timeout |
| | | }); |
| | | |
| | | // request interceptor |
New file |
| | |
| | | // 节流 |
| | | export const throttle = function (fn, delay = 300) { |
| | | var lastTime, timer; |
| | | return function () { |
| | | var _this = this; |
| | | var args = arguments; |
| | | var nowTime = Date.now(); |
| | | if (lastTime && nowTime - lastTime < delay) { |
| | | if (timer) clearTimeout(timer); |
| | | timer = setTimeout(function () { |
| | | lastTime = nowTime; |
| | | fn.apply(_this, args); |
| | | }, delay); |
| | | } else { |
| | | lastTime = nowTime; |
| | | fn.apply(_this, args); |
| | | } |
| | | }; |
| | | }; |
| | |
| | | export function formatAreaTree(item, list) { |
| | | if (item.parentId === 0) { |
| | | export function formatAreaTree(item, ids, list) { |
| | | // parentId 不在id列表中; |
| | | // if (item.parentId === 0) { |
| | | if (ids.indexOf(item.parentId) === -1) { |
| | | list.push({ |
| | | label: item.areaName, |
| | | id: item.id, |
| | | data: item, |
| | | children: [] |
| | | areaDescript: item.areaDescript, |
| | | charger: item.areaUsers.map((v) => v.uname).join(","), |
| | | children: [], |
| | | }); |
| | | } else { |
| | | let isCurrentChild = false; |
| | |
| | | label: item.areaName, |
| | | id: item.id, |
| | | data: item, |
| | | children: [] |
| | | areaDescript: item.areaDescript, |
| | | charger: item.areaUsers.map((v) => v.uname).join(","), |
| | | children: [], |
| | | }); |
| | | } |
| | | } |
| | |
| | | for (let i = 0; i < list.length; i++) { |
| | | const listItem = list[i]; |
| | | if (!isCurrentChild && listItem.children !== 0) { |
| | | formatAreaTree(item, listItem.children); |
| | | formatAreaTree(item, ids, listItem.children); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { addKey, updateKey } from "@/api/keys"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import { getAllUserName } from "@/api/user"; |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object, |
| | | }, |
| | | }); |
| | | const formRef = ref(); |
| | | const areaList = ref([]); |
| | | const userList = ref([]); |
| | | |
| | | const form1 = reactive({ |
| | | uname: "", |
| | | keyType: "", |
| | | uid: "", |
| | | keyNumber: "", |
| | | keyName: "", |
| | | }); |
| | | |
| | | const rules = { |
| | | uname: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | keyType: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | keyName: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | keyNumber: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const isEdit = computed(() => !!props.info?.keyName); |
| | | const $emit = defineEmits(["cancel", "success"]); |
| | | function close() { |
| | | $emit("cancel"); |
| | | } |
| | | |
| | | // 查询所有用户 |
| | | async function getAllUser() { |
| | | let res = await getAllUserName(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | userList.value = _list; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | async function update() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | // uid: form1.uid, |
| | | uname: form1.uname, |
| | | keyName: form1.keyName?.trim(), |
| | | keyNumber: form1.keyNumber?.trim() || undefined, |
| | | keyId: props.info.keyId, |
| | | keyType: form1.keyType |
| | | }; |
| | | console.log("params update", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | updateKey(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | async function onSubmit() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | // uid: form1.uid, |
| | | uname: form1.uname, |
| | | keyName: form1.keyName?.trim(), |
| | | keyNumber: form1.keyNumber?.trim() || undefined, |
| | | keyType: form1.keyType |
| | | }; |
| | | console.log("params", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | addKey(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | |
| | | |
| | | onMounted(() => { |
| | | let info = props.info; |
| | | if (info) { |
| | | form1.uname = info.uname; |
| | | form1.uid = info.uid; |
| | | form1.keyType = info.keyType; |
| | | form1.keyName = info.keyName; |
| | | form1.keyNumber = info.keyNumber; |
| | | } |
| | | getAllUser(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class=""> |
| | | <el-form ref="formRef" :model="form1" label-width="80px" :rules="rules"> |
| | | <el-form-item label="归属人" prop="uname"> |
| | | <el-select v-model="form1.uname"> |
| | | <el-option v-for="(item, idx) in userList" :key="'key_' + idx" :label="item" :value="item" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="钥匙类型" prop="keyType"> |
| | | <el-select v-model="form1.keyType"> |
| | | <el-option label="ID钥匙" :value="1" /> |
| | | <el-option label="机械钥匙" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="钥匙名称" prop="keyName"> |
| | | <el-input v-model="form1.keyName"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="钥匙编号" prop="keyNumber" v-if="form1.keyType == 1"> |
| | | <el-input v-model="form1.keyNumber"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button v-if="isEdit" type="primary" @click="update">修改</el-button> |
| | | <el-button v-else type="primary" @click="onSubmit">新增</el-button> |
| | | <el-button @click="close">取消</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup name="KeyManage"> |
| | | import { ref, onMounted, reactive, computed } from 'vue'; |
| | | import addEdit from './addEdit.vue'; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import store from '@/store'; |
| | | |
| | | import { Search, Plus } from "@element-plus/icons-vue"; |
| | | |
| | | import { |
| | | getAllKeyList, |
| | | addKey, |
| | | delKey, |
| | | } from '@/api/keys.js'; |
| | | |
| | | const dialogTitle = ref('添加钥匙'); |
| | | const addEditVisible = ref(false); |
| | | const background = ref(true); |
| | | const disabled = ref(false); |
| | | |
| | | const isAdd = ref(false); |
| | | |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | |
| | | const pageCurr = ref(1); |
| | | const pageSize = ref(10); |
| | | const total = ref(0); |
| | | |
| | | const datas = reactive({ |
| | | tableData: [], |
| | | keyInfo: {}, |
| | | }); |
| | | |
| | | const urole = computed(() => { |
| | | return store.user().urole; |
| | | }); |
| | | |
| | | function onOk() { |
| | | addEditVisible.value = false; |
| | | getList(); |
| | | } |
| | | |
| | | function onCanel() { |
| | | addEditVisible.value = false; |
| | | } |
| | | |
| | | |
| | | const filter = reactive({ |
| | | keyName: '', |
| | | userName: '' |
| | | }); |
| | | |
| | | function add() { |
| | | dialogTitle.value = '添加钥匙'; |
| | | datas.keyInfo = {}; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function del(scope) { |
| | | $confirm('删除该钥匙', () => { |
| | | let loading = $loading(); |
| | | delKey(scope.row.keyId).then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $message({ |
| | | type: 'success', |
| | | message: '删除成功!' |
| | | }); |
| | | getList(); |
| | | } else { |
| | | $message({ |
| | | type: 'error', |
| | | message: '删除失败!' |
| | | }); |
| | | } |
| | | loading.close(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function edit(scope) { |
| | | dialogTitle.value = '编辑钥匙'; |
| | | datas.keyInfo = scope.row; |
| | | // console.log('edit', scope.row, '============='); |
| | | |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function getList() { |
| | | // keyName, pageNum, pageSize, uname |
| | | let params = { |
| | | pageNum: pageCurr.value, |
| | | pageSize: pageSize.value, |
| | | keyName: filter.keyName || undefined, |
| | | uname: filter.userName || undefined |
| | | }; |
| | | |
| | | let loading = $loading(); |
| | | getAllKeyList(params).then((res) => { |
| | | let { code, data, data2 } = res; |
| | | let _total = 0; |
| | | let _list = []; |
| | | if (code && data) { |
| | | let { list, total } = data2; |
| | | _list = list.map(v => { |
| | | v.type = { 1: 'ID钥匙', 2: '机械钥匙' }[v.keyType]; |
| | | return v; |
| | | }); |
| | | _total = total; |
| | | } |
| | | datas.tableData = _list; |
| | | total.value = _total; |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | |
| | | } |
| | | |
| | | function handleSizeChange(val) { |
| | | } |
| | | |
| | | function handleCurrentChange(val) { |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="page-wrapper"> |
| | | <div class="page-header"> |
| | | </div> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <el-button type="primary" size="small" :icon="Plus" @click="add">添加钥匙</el-button> |
| | | | |
| | | <div class="tools-filter"> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">钥匙名称:</div> |
| | | <div class="filter-content"> |
| | | <el-input v-model="filter.keyName" size="small" @input="getList"></el-input> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">员工名称:</div> |
| | | <div class="filter-content"> |
| | | <el-input v-model="filter.userName" size="small" @input="getList"></el-input> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" size="small" :icon="Search" @click="getList">查询</el-button> |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table :data="datas.tableData" border style="width: 100%; height: 100%"> |
| | | <el-table-column type="index" width="50" /> |
| | | <el-table-column prop="type" align="center" label="钥匙类型" width="120" /> |
| | | <el-table-column prop="keyName" align="center" label="钥匙名称" width="180" /> |
| | | <el-table-column prop="keyNumber" align="center" label="钥匙编号" width="180" /> |
| | | <el-table-column prop="uname" align="center" label="保管人" width="180" /> |
| | | <el-table-column prop="createTime" label="创建时间" /> |
| | | <el-table-column align="center" fixed="right" label="操作" width="180" v-if="urole > 0"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="edit(scope)">编辑</el-button> |
| | | <el-button type="danger" size="small" @click="del(scope)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination v-model:current-page="pageCurr" v-model:page-size="pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" :disabled="disabled" |
| | | :background="background" layout="total, sizes, prev, pager, next, jumper" :total="total" |
| | | @size-change="handleSizeChange" @current-change="handleCurrentChange" /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 弹窗 --> |
| | | <el-dialog :title="dialogTitle" v-model="addEditVisible" top="0" :close-on-click-modal="false" class="dialog-center" |
| | | width="700px" center> |
| | | <add-edit v-if="addEditVisible" @success="onOk" :info="datas.keyInfo" @cancel="onCanel"></add-edit> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { getAreaTreeApi } from "@/api/area"; |
| | | import { formatAreaTree } from "@/utils/tree"; |
| | | import { updateLock, addLock } from "@/api/lockManager.js"; |
| | | const areaList = ref([]); |
| | | const emit = defineEmits(["close", "ok"]); |
| | | const rules = { |
| | | count: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | const reg = /^\d+$/; |
| | | if (!reg.test(value)) { |
| | | callback(new Error("只能为数字")); |
| | | } else { |
| | | if (value > 1000) { |
| | | callback(new Error("最大支持批量新增1000套")); |
| | | } else if (value < 1) { |
| | | callback(new Error("输入不能小于1")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | } |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | areaId: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value.length) { |
| | | callback(new Error("请选择区域")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | lockName: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | }; |
| | | const formLock = ref({ |
| | | areaId: "", |
| | | lockId: "", |
| | | lockType: 3, |
| | | lockName: "", |
| | | count: 1, |
| | | }); |
| | | |
| | | const lockTypes = ref([ |
| | | { |
| | | label: "实体锁", |
| | | value: 3, |
| | | }, |
| | | ]); |
| | | |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object, |
| | | }, |
| | | isAdd: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | isBatch: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }); |
| | | |
| | | function ok() { |
| | | if (props.isAdd) { |
| | | add(); |
| | | } else { |
| | | update(); |
| | | } |
| | | } |
| | | |
| | | function add() { |
| | | let areaId; |
| | | if (formLock.value.areaId && formLock.value.areaId.length) { |
| | | areaId = formLock.value.areaId[formLock.value.areaId.length - 1]; |
| | | } |
| | | let params = { |
| | | lockName: formLock.value.lockName, |
| | | areaId, |
| | | // 目前固定 |
| | | lockType: formLock.value.lockType, |
| | | }; |
| | | if (props.isBatch) { |
| | | params["num"] = formLock.value.count; |
| | | } |
| | | addLock(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | emit("ok"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | }); |
| | | } |
| | | |
| | | function update() { |
| | | // lockId lockName areaId lockType |
| | | let areaId; |
| | | if (formLock.value.areaId && formLock.value.areaId.length) { |
| | | areaId = formLock.value.areaId[formLock.value.areaId.length - 1]; |
| | | } |
| | | let params = { |
| | | lockId: formLock.value.lockId, |
| | | lockName: formLock.value.lockName, |
| | | areaId, |
| | | // 目前固定 |
| | | lockType: formLock.value.lockType, |
| | | }; |
| | | updateLock(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | emit("ok"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | }); |
| | | } |
| | | |
| | | function close() { |
| | | emit("close"); |
| | | } |
| | | |
| | | async function getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let _data = []; |
| | | if (res.code === 1 && res.data) { |
| | | _data = res.data2; |
| | | } |
| | | const treeList = []; |
| | | let ids = _data.map((v) => v.id); |
| | | for (let i = 0; i < _data.length; i++) { |
| | | formatAreaTree(_data[i], ids, treeList); |
| | | } |
| | | // console.log(_data, 'data'); |
| | | // console.log(treeList, 'treeList'); |
| | | areaList.value = treeList; |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (!props.isAdd) { |
| | | console.log("info ", props.info, "============="); |
| | | |
| | | formLock.value = props.info; |
| | | } |
| | | getAreaTree(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <el-form |
| | | label-position="left" |
| | | label-width="auto" |
| | | :model="formLock" |
| | | :rules="rules" |
| | | style="max-width: 600px" |
| | | > |
| | | <!-- 所属区域 --> |
| | | <el-form-item label="所属区域" label-position="right" prop="areaId"> |
| | | <el-cascader |
| | | class="select" |
| | | filterable |
| | | clearable |
| | | v-model="formLock.areaId" |
| | | :props="{ value: 'id', checkStrictly: true }" |
| | | :options="areaList" |
| | | ><template #default="{ node, data }"> |
| | | <span>{{ data.label }}</span> |
| | | <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> |
| | | </template></el-cascader |
| | | > |
| | | </el-form-item> |
| | | <!-- 类型 --> |
| | | <el-form-item label="类型" label-position="right" prop="lockType"> |
| | | <el-select |
| | | v-model="formLock.lockType" |
| | | placeholder="Select" |
| | | style="width: 240px" |
| | | > |
| | | <el-option |
| | | v-for="item in lockTypes" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- 锁具名称 --> |
| | | <el-form-item label="锁具名称" label-position="right" prop="lockName"> |
| | | <el-input v-model="formLock.lockName" /> |
| | | </el-form-item> |
| | | <!-- 批量添加数量 --> |
| | | <el-form-item |
| | | label="批量添加数量" |
| | | label-position="right" |
| | | prop="count" |
| | | v-if="isBatch" |
| | | > |
| | | <el-input v-model="formLock.count" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="footer"> |
| | | <el-button size="small" @click="close">取消</el-button> |
| | | <el-button type="primary" size="small" @click="ok">确定</el-button> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.select) { |
| | | width: 100%; |
| | | } |
| | | .footer { |
| | | text-align: right; |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup name="LockManage"> |
| | | import { ref, onMounted, reactive, computed, watchEffect } from "vue"; |
| | | // import const_theme from "@/utils/const/const_theme"; |
| | | import store from "@/store"; |
| | | |
| | | import { Search, Plus } from "@element-plus/icons-vue"; |
| | | // import HdwTree from "@/components/HdwTree/index.vue"; |
| | | import { |
| | | getAllLockInf, |
| | | delLock, |
| | | lockOpen, |
| | | } from '@/api/lockManager.js'; |
| | | |
| | | import useWebSocket from "@/hooks/useWebsocket.js"; |
| | | |
| | | import addEdit from './addEdit.vue'; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | const { sendData, message: listMessage } = useWebSocket("lockRt"); |
| | | |
| | | const disabled = ref(false); |
| | | const background = ref(false); |
| | | const addEditVisible = ref(false); |
| | | const isAdd = ref(false); |
| | | const isBatch = ref(false); |
| | | |
| | | const currentAreaId = ref(); |
| | | |
| | | // const themes = ref(const_theme); |
| | | // const theme = store.settings().theme; |
| | | const tableData = ref([]); |
| | | |
| | | const addEditTitle = ref(''); |
| | | |
| | | const filter = reactive({ |
| | | name: "", |
| | | state: undefined, |
| | | type: undefined, |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 当前编辑的锁对象 |
| | | const editLock = ref(); |
| | | |
| | | const isAdmin = computed(() => store.user().urole > 0); |
| | | |
| | | onMounted(() => { |
| | | |
| | | }); |
| | | |
| | | // function handleChangeTheme(val) { |
| | | // console.log(val); |
| | | // store.settings().changeSetting({ |
| | | // key: "theme", |
| | | // value: val, |
| | | // }); |
| | | // } |
| | | |
| | | function sendMessage() { |
| | | let params = { |
| | | areaId: currentAreaId.value, |
| | | lockName: filter.name.trim() || undefined, |
| | | lockState: filter.state, |
| | | lockType: filter.type, |
| | | pageNum: page.pageNum, |
| | | pageSize: page.pageSize, |
| | | }; |
| | | sendData( |
| | | JSON.stringify(params) |
| | | ); |
| | | } |
| | | |
| | | function itemClickHandler(item) { |
| | | console.log(item, '====item', item.data); |
| | | // areaId lockName lockState lockType pageNum pageSize |
| | | currentAreaId.value = item.data.id; |
| | | sendMessage(); |
| | | } |
| | | |
| | | watchEffect(() => { |
| | | let _total = 0; |
| | | let _list = []; |
| | | if (listMessage.value) { |
| | | const { |
| | | code, |
| | | data, |
| | | data2 |
| | | } = JSON.parse(listMessage.value); |
| | | |
| | | if (code && data) { |
| | | let { list, total } = data2; |
| | | _list = list.map(v => { |
| | | v.state = { '-1': '未安装', 0: '闭锁', 1: '开锁' }[v.lockState]; |
| | | v.onlineState = { 0: '离线', 1: '在线' }[v.lockOnline]; |
| | | v.type = { 1: '蓝牙锁', 2: 'ID锁', 3: '实体锁' }[v.lockType]; |
| | | return v; |
| | | }); |
| | | _total = total; |
| | | } |
| | | } |
| | | tableData.value = _list; |
| | | page.total = _total; |
| | | }); |
| | | |
| | | |
| | | function handleSizeChange(val) { |
| | | page.pageSize = val; |
| | | sendMessage(); |
| | | } |
| | | |
| | | function handleCurrentChange(val) { |
| | | page.pageNum = val; |
| | | sendMessage(); |
| | | } |
| | | |
| | | function edit(scope) { |
| | | console.log('scope', scope, '============='); |
| | | let { |
| | | row |
| | | } = scope; |
| | | editLock.value = row; |
| | | addEditTitle.value = '修改锁具'; |
| | | isBatch.value = false; |
| | | isAdd.value = false; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function okHandle() { |
| | | addEditVisible.value = false; |
| | | sendMessage(); |
| | | } |
| | | |
| | | function add() { |
| | | isAdd.value = true; |
| | | isBatch.value = false; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function batchAdd() { |
| | | isAdd.value = true; |
| | | isBatch.value = true; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function confirmDel(params) { |
| | | $confirm("删除该锁具", () => { |
| | | del(params.row.lockId); |
| | | }); |
| | | } |
| | | |
| | | function open(scope) { |
| | | console.log('scope', scope, '============='); |
| | | let { |
| | | row |
| | | } = scope; |
| | | $confirm("远程打开该锁具", () => { |
| | | let loading = $loading(); |
| | | lockOpen(scope.row.lockId).then((res) => { |
| | | let { code, data } = res; |
| | | loading.close(); |
| | | if (code && data) { |
| | | $message.success("操作成功"); |
| | | sendMessage(); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | |
| | | }); |
| | | } |
| | | |
| | | function del(id) { |
| | | let loading = $loading(); |
| | | delLock(id).then((res) => { |
| | | let { code, data } = res; |
| | | loading.close(); |
| | | if (code && data) { |
| | | $message.success("操作成功"); |
| | | sendMessage(); |
| | | } else { |
| | | $message.success("操作失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="page-wrapper"> |
| | | <div class="page-header"> |
| | | <div class="hdw-card-container"> |
| | | <hdw-card title="区域列表" is-full> |
| | | <hdw-tree @item-click="itemClickHandler"></hdw-tree> |
| | | </hdw-card> |
| | | </div> |
| | | </div> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <el-button type="primary" size="small" :icon="Plus" @click="add">添加</el-button> |
| | | <el-button type="primary" size="small" :icon="Plus" @click="batchAdd">批量添加</el-button> |
| | | | |
| | | <div class="tools-filter"> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">锁具名称:</div> |
| | | <div class="filter-content"> |
| | | <el-input @input="sendMessage" placeholder="请输入锁具名称..." v-model="filter.name" size="small"></el-input> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">锁具状态:</div> |
| | | <div class="filter-content"> |
| | | <el-select v-model="filter.state" placeholder="请选择" @change="sendMessage" size="small" |
| | | style="width: 180px"> |
| | | <el-option label="--请选择--" value="" /> |
| | | <el-option label="未安装" :value="-1" /> |
| | | <el-option label="闭锁" :value="0" /> |
| | | <el-option label="开锁" :value="1" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">锁具类型:</div> |
| | | <div class="filter-content"> |
| | | <el-select v-model="filter.type" @change="sendMessage" placeholder="请选择" size="small" |
| | | style="width: 180px"> |
| | | <el-option label="--请选择--" value="" /> |
| | | <el-option label="蓝牙锁" :value="1" /> |
| | | <el-option label="ID锁" :value="2" /> |
| | | <el-option label="实体锁" :value="3" /> |
| | | </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" @click="sendMessage">查询</el-button> |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table stripe :data="tableData" border style="width: 100%; height: 100%"> |
| | | <el-table-column type="index" width="50" /> |
| | | <el-table-column prop="type" label="类型" width="180" /> |
| | | <el-table-column prop="lockName" label="锁具名称" width="180" /> |
| | | <el-table-column prop="areaPath" label="关联区域" /> |
| | | <el-table-column prop="onlineState" label="在线状态" width="180" /> |
| | | <el-table-column prop="state" label="安装状态" width="180" /> |
| | | <!-- <el-table-column prop="lockImg" label="锁具图片" width="180" /> --> |
| | | <!-- <el-table-column prop="address" label="地址" /> --> |
| | | <el-table-column align="center" fixed="right" label="操作" width="240"> |
| | | <template #default="scope"> |
| | | <el-button type="danger" size="small" |
| | | v-if="isAdmin && scope.row.lockOnline == 1 && scope.row.lockState == 0" |
| | | @click="open(scope)">远程开锁</el-button> |
| | | <el-button type="primary" size="small" @click="edit(scope)">编辑</el-button> |
| | | <el-button type="danger" size="small" @click="confirmDel(scope)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination v-model:current-page="page.pageNum" v-model:page-size="page.pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" :disabled="disabled" |
| | | :background="background" layout="total, sizes, prev, pager, next, jumper" :total="page.total" |
| | | @size-change="handleSizeChange" @current-change="handleCurrentChange" /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 编辑 新建 --> |
| | | <el-dialog v-model="addEditVisible" :title="addEditTitle" width="500" align-center :close-on-click-modal="false"> |
| | | <add-edit v-if="addEditVisible" :isBatch="isBatch" :info="editLock" :isAdd="isAdd" @close="addEditVisible = false" |
| | | @ok="okHandle"></add-edit> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | border-top: 1px solid var(--border-light-color); |
| | | box-sizing: border-box; |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { getAllUserName } from "@/api/user"; |
| | | import { addAuth, updateAuth } from "@/api/auth"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import { getKeyInfAuth } from '@/api/keys.js'; |
| | | import { getAreaUserLock } from '@/api/lockManager.js'; |
| | | |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object, |
| | | }, |
| | | }); |
| | | const formRef = ref(); |
| | | const userList = ref([]); |
| | | const keyList = ref([]); |
| | | const lockList = ref([]); |
| | | const form1 = reactive({ |
| | | uname: "", |
| | | uid: "", |
| | | keyId: "", |
| | | lockIds: [], |
| | | descript: "", |
| | | }); |
| | | |
| | | const rules = { |
| | | uname: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | keyId: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | lockIds: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value.length) { |
| | | callback(new Error("请选择锁具")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const isEdit = computed(() => !!props.info?.uname); |
| | | const $emit = defineEmits(["close", "ok"]); |
| | | function close() { |
| | | $emit("close"); |
| | | } |
| | | // 查询所有用户 |
| | | async function getAllUser() { |
| | | let res = await getAllUserName(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | userList.value = _list; |
| | | } |
| | | |
| | | // 查询所有钥匙 |
| | | async function getKeyList() { |
| | | let res = await getKeyInfAuth(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | // _list.unshift({ keyId: 0, keyName: "蓝牙钥匙" }); |
| | | keyList.value = _list; |
| | | } |
| | | |
| | | // 查询所有锁具 |
| | | async function getLockList() { |
| | | let res = await getAreaUserLock(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | lockList.value = _list; |
| | | } |
| | | |
| | | async function update() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | // uname: form1.uname.trim(), |
| | | uname: form1.uname, |
| | | keyId: form1.keyId, |
| | | keyName: keyList.value.find(item => item.keyId === form1.keyId)?.keyName, |
| | | lockInfs: form1.lockIds.map(v => ({ lockId: v, lockName: lockList.value.find(item => item.lockId === v)?.lockName })), |
| | | descript: form1.descript.trim(), |
| | | }; |
| | | console.log("params update", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | updateAuth(props.info.id, params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("ok"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | async function onSubmit() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | // uname: form1.uname.trim(), |
| | | uname: form1.uname, |
| | | keyId: form1.keyId, |
| | | keyName: keyList.value.find(item => item.keyId === form1.keyId)?.keyName, |
| | | lockInfs: form1.lockIds.map(v => ({ lockId: v, lockName: lockList.value.find(item => item.lockId === v)?.lockName })), |
| | | descript: form1.descript.trim(), |
| | | }; |
| | | console.log("params", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | addAuth(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("ok"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | |
| | | |
| | | onMounted(() => { |
| | | let info = props.info; |
| | | console.log('info', info, '============='); |
| | | |
| | | if (info) { |
| | | form1.uname = info.uname; |
| | | // form1.uid = info.uid; |
| | | form1.keyId = info.keyId; |
| | | form1.lockIds = [info.lockId]; |
| | | form1.descript = info.descript; |
| | | } |
| | | getAllUser(); |
| | | getKeyList(); |
| | | getLockList(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class=""> |
| | | <el-form ref="formRef" :model="form1" label-width="80px" :rules="rules"> |
| | | <el-form-item label="授权人员" prop="uname"> |
| | | <el-select v-model="form1.uname"> |
| | | <el-option v-for="(item, idx) in userList" :key="'user_' + idx" :label="item" :value="item" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="授权钥匙" prop="keyId"> |
| | | <el-select v-model="form1.keyId"> |
| | | <el-option v-for="item in keyList" :key="'key_' + item.keyId" :label="item.keyName" :value="item.keyId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="授权锁具" prop="lockIds"> |
| | | <el-select v-model="form1.lockIds" clearable multiple collapse-tags collapse-tags-tooltip> |
| | | <el-option v-for="item in lockList" :key="'lock_' + item.lockId" :label="item.lockName" :value="item.lockId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务说明" prop="descript"> |
| | | <el-input v-model="form1.descript" :rows="2" type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button v-if="isEdit" type="primary" @click="update">修改</el-button> |
| | | <el-button v-else type="primary" @click="onSubmit">新增</el-button> |
| | | <el-button @click="close">取消</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import HdwCard from '@/components/HdwCard/index.vue'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'AuthManage', |
| | | components: { HdwCard }, |
| | | data() { |
| | | return { |
| | | tableData: [ |
| | | { |
| | | userName: 'whyc', |
| | | authKey: '四楼蓝牙锁1', |
| | | authLock: '机柜蓝牙锁', |
| | | authTimeStart: '2024-10-11 14:25:51', |
| | | authTimeEnd: '2024-10-12 14:25:51', |
| | | jobDes: '测试', |
| | | state: '通过' |
| | | } |
| | | ], |
| | | filter: { |
| | | name: '', |
| | | state: 0, |
| | | type: 0 |
| | | }, |
| | | page: { |
| | | currentPage: 1, |
| | | pageSize: 20, |
| | | total: 0 |
| | | } |
| | | }; |
| | | }, |
| | | methods: { |
| | | |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <script lang="ts" setup> |
| | | <script lang="js" setup name="AuthManage"> |
| | | import { reactive, ref, onMounted } from 'vue'; |
| | | import addEdit from './addEdit.vue'; |
| | | import { |
| | | Search, |
| | | Plus |
| | | } from '@element-plus/icons-vue'; |
| | | import HdwTree from '@/components/HdwTree/index.vue'; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | |
| | | import { |
| | | getAllAuthInf, |
| | | delAuth, |
| | | |
| | | } from '@/api/auth.js'; |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | |
| | | const currentAreaId = ref(); |
| | | |
| | | const tableData = reactive([]); |
| | | |
| | | const filter = reactive({ |
| | | name: '', |
| | | state: 0, |
| | | type: 0 |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 20, |
| | | total: 0 |
| | | }); |
| | | |
| | | const info = ref({}); |
| | | |
| | | const disabled = ref(false); |
| | | const background = ref(false); |
| | | |
| | | const addEditVisible = ref(false); |
| | | const addEditTitle = ref(''); |
| | | |
| | | function itemClickHandler(item) { |
| | | console.log(item, '====item', item.data); |
| | | // areaId lockName lockState lockType pageNum pageSize |
| | | currentAreaId.value = item.data.id; |
| | | getList(); |
| | | } |
| | | |
| | | function okHandle() { |
| | | addEditVisible.value = false; |
| | | getList(); |
| | | } |
| | | |
| | | function handleSizeChange(val) { |
| | | page.pageSize = val; |
| | | getList(); |
| | | } |
| | | |
| | | function handleCurrentChange(val) { |
| | | page.currentPage = val; |
| | | getList(); |
| | | } |
| | | |
| | | function edit(scope) { |
| | | addEditTitle.value = '编辑授权'; |
| | | info.value = scope.row; |
| | | console.log('edit', scope.row, '============='); |
| | | |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function add() { |
| | | addEditTitle.value = '添加授权'; |
| | | info.value = undefined; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function del(scope) { |
| | | $confirm('删除该授权', () => { |
| | | let loading = $loading(); |
| | | delAuth([scope.row.id]).then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $message({ |
| | | type: 'success', |
| | | message: '删除成功!' |
| | | }); |
| | | getList(); |
| | | } else { |
| | | $message({ |
| | | type: 'error', |
| | | message: '删除失败!' |
| | | }); |
| | | } |
| | | loading.close(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function getList() { |
| | | // areaId, pageNum, pageSize, state, uname |
| | | let params = { |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | state: filter.state, |
| | | uname: filter.name, |
| | | areaId: currentAreaId.value, |
| | | } |
| | | |
| | | getAllAuthInf(params).then((res) => { |
| | | let { code, data, data2 } = res; |
| | | let _total = 0; |
| | | let _list = []; |
| | | if (code && data) { |
| | | let { list, total } = data2; |
| | | _list = list; |
| | | _total = total; |
| | | } |
| | | tableData.length = 0; |
| | | tableData.push(..._list); |
| | | page.total = _total; |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | |
| | | <div class="page-header"> |
| | | <div class="hdw-card-container"> |
| | | <hdw-card title="区域列表" is-full> |
| | | <hdw-tree></hdw-tree> |
| | | <hdw-tree @item-click="itemClickHandler"></hdw-tree> |
| | | </hdw-card> |
| | | </div> |
| | | </div> |
| | |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <el-button type="primary" size="small" :icon="Plus">添加授权</el-button> |
| | | <el-button type="primary" size="small" :icon="Plus" @click="add" |
| | | >添加授权</el-button |
| | | > |
| | | | |
| | | <div class="tools-filter"> |
| | | <div class="tools-filter-item"> |
| | |
| | | <el-input v-model="filter.name" size="small"></el-input> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <!-- <div class="tools-filter-item"> |
| | | <div class="filter-label">授权状态:</div> |
| | | <div class="filter-content"> |
| | | <el-select |
| | | v-model="filter.state" |
| | | placeholder="请选择" |
| | | size="small" |
| | | style="width: 180px" |
| | | v-model="filter.state" |
| | | placeholder="请选择" |
| | | size="small" |
| | | style="width: 180px" |
| | | > |
| | | <el-option label="--请选择--" :value="0"/> |
| | | <el-option label="未安装" :value="1"/> |
| | | <el-option label="已安装" :value="2"/> |
| | | <el-option label="--请选择--" :value="0" /> |
| | | <el-option label="未安装" :value="1" /> |
| | | <el-option label="已安装" :value="2" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | </div> --> |
| | | </div> |
| | | <el-button type="primary" size="small" :icon="Search">查询</el-button> |
| | | <el-button type="primary" size="small" :icon="Search" |
| | | >查询</el-button |
| | | > |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table :data="tableData" border style="width: 100%; height: 100%"> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | style="width: 100%; height: 100%" |
| | | > |
| | | <el-table-column type="index" width="50" /> |
| | | <el-table-column prop="userName" align="center" label="授权人员" width="120" /> |
| | | <el-table-column prop="authKey" align="center" label="授权钥匙" width="120" /> |
| | | <el-table-column prop="authLock" align="center" label="授权锁具" width="120" /> |
| | | <el-table-column prop="authTimeStart" align="center" label="授权时限开始" width="180" /> |
| | | <el-table-column prop="authTimeEnd" align="center" label="授权时限结束" width="180" /> |
| | | <el-table-column prop="jobDes" align="center" min-width="180" label="任务说明" /> |
| | | <el-table-column prop="state" align="center" label="状态" width="80" /> |
| | | <el-table-column align="center" fixed="right" label="操作" width="180"> |
| | | <template #default> |
| | | <el-button type="primary" size="small">编辑</el-button> |
| | | <el-button type="danger" size="small">删除</el-button> |
| | | <el-table-column |
| | | prop="uname" |
| | | align="center" |
| | | label="授权人员" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | prop="keyName" |
| | | align="center" |
| | | label="授权钥匙" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | prop="lockName" |
| | | align="center" |
| | | label="授权锁具" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | prop="descript" |
| | | align="center" |
| | | min-width="180" |
| | | label="任务说明" |
| | | /> |
| | | <el-table-column |
| | | prop="state" |
| | | align="center" |
| | | label="状态" |
| | | width="80" |
| | | /> |
| | | <el-table-column |
| | | align="center" |
| | | fixed="right" |
| | | label="操作" |
| | | width="180" |
| | | > |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="edit(scope)">编辑</el-button> |
| | | <el-button type="danger" size="small" @click="del(scope)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination |
| | | v-model:current-page="page.currentPage" |
| | | v-model:page-size="page.pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" |
| | | size="small" |
| | | :disabled="disabled" |
| | | :background="background" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="page.total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | v-model:current-page="page.currentPage" |
| | | v-model:page-size="page.pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" |
| | | size="small" |
| | | :disabled="disabled" |
| | | :background="background" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="page.total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 编辑 新建 --> |
| | | <el-dialog |
| | | v-model="addEditVisible" |
| | | :title="addEditTitle" |
| | | width="500" |
| | | align-center |
| | | :close-on-click-modal="false" |
| | | > |
| | | <add-edit |
| | | v-if="addEditVisible" |
| | | :info="info" |
| | | @close="addEditVisible = false" |
| | | @ok="okHandle" |
| | | ></add-edit> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import HdwCard from '@/components/HdwCard/index.vue'; |
| | | <script setup name="LogManage"> |
| | | import { ref, onMounted } from 'vue'; |
| | | import { getLockLog } from "@/api/loginfo"; |
| | | import { getLinfById } from '@/api/lockManager.js'; |
| | | import { getUinfById } from '@/api/user'; |
| | | import { |
| | | Search |
| | | } from '@element-plus/icons-vue'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'LogManage', |
| | | components: { HdwCard }, |
| | | data() { |
| | | return { |
| | | tableData: [ |
| | | { |
| | | areaName: '武汉源畅科技', |
| | | userName: '源畅科技', |
| | | keyName: '测试', |
| | | lockName: '机柜蓝牙锁', |
| | | type: '开锁操作', |
| | | state: '成功', |
| | | openType: '蓝牙', |
| | | time: '2024-08-14 17:13:09' |
| | | } |
| | | ], |
| | | filter: { |
| | | userName: '', |
| | | timeRange: '', |
| | | type: 0 |
| | | }, |
| | | page: { |
| | | currentPage: 1, |
| | | pageSize: 20, |
| | | total: 0 |
| | | } |
| | | }; |
| | | }, |
| | | methods: { |
| | | import useElement from "@/hooks/useElement.js"; |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | const tableData = ref([]); |
| | | const ctlUname = ref(''); |
| | | const ctlResult = ref(''); |
| | | const startTime = ref(''); |
| | | const endTime = ref(''); |
| | | const lockId = ref(''); |
| | | const ctlType = ref(''); |
| | | const pageNum = ref(1); |
| | | const pageSize = ref(10); |
| | | const total = ref(0); |
| | | const currentAreaId = ref(); |
| | | |
| | | } |
| | | }); |
| | | </script> |
| | | const lockList = ref([]); |
| | | |
| | | <script lang="ts" setup> |
| | | import { |
| | | Search |
| | | } from '@element-plus/icons-vue'; |
| | | import HdwTree from '@/components/HdwTree/index.vue'; |
| | | const userList = ref([]); |
| | | const logList = ref([]); |
| | | // 操作类型[1-清空所有授权ID卡 2-远程开锁 3-远程重启 4-设置锁具地址 5-添加授权ID 6-移除授权ID 7-蓝牙开锁 8-ID开锁] |
| | | const ctlTypeList = [ |
| | | '', |
| | | '清空所有授权ID卡', |
| | | '远程开锁', |
| | | '远程重启', |
| | | '设置锁具地址', |
| | | '添加授权ID', |
| | | '移除授权ID', |
| | | '蓝牙开锁', |
| | | 'ID开锁' |
| | | ]; |
| | | |
| | | function itemClickHandler(item) { |
| | | console.log(item, '====item', item.data); |
| | | // areaId lockName lockState lockType pageNum pageSize |
| | | currentAreaId.value = item.data.id; |
| | | ctlUname.value = ''; |
| | | lockId.value = ''; |
| | | getUsers(); |
| | | getLockList(); |
| | | getList(); |
| | | } |
| | | |
| | | async function getLockList() { |
| | | let res = await getLinfById(currentAreaId.value); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | lockList.value = _list; |
| | | } |
| | | |
| | | async function getList() { |
| | | let params = { |
| | | areaId: currentAreaId.value, |
| | | ctlUname: ctlUname.value || undefined, |
| | | ctlResult: ctlResult.value || undefined, |
| | | startTime: startTime.value || undefined, |
| | | endTime: endTime.value || undefined, |
| | | ctlType: ctlType.value || undefined, |
| | | lockId: lockId.value || undefined |
| | | |
| | | }; |
| | | let res = await getLockLog(pageNum.value, pageSize.value, params); |
| | | let { code, data, data2 } = res; |
| | | let _total = 0; |
| | | let _list = []; |
| | | if (code && data) { |
| | | let { list, total } = data2; |
| | | _total = total; |
| | | _list = list.map(v => ({ |
| | | ...v, |
| | | ctlResultStr: v.ctlResult ? '成功' : '失败', |
| | | ctlTypeStr: ctlTypeList[v.ctlType] || '未知', |
| | | openTypeStr: [2, 7, 8].includes(v.ctlType) ? ctlTypeList[v.ctlType] : '--', |
| | | })); |
| | | } |
| | | total.value = _total; |
| | | logList.value = _list; |
| | | } |
| | | |
| | | async function getUsers() { |
| | | let res = await getUinfById(currentAreaId.value); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | userList.value = _list; |
| | | } |
| | | |
| | | function handleSizeChange(params) { |
| | | pageSize.value = params |
| | | getList(); |
| | | } |
| | | |
| | | function handleCurrentChange(params) { |
| | | pageNum.value = params |
| | | getList(); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | |
| | | }); |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | |
| | | <div class="page-header"> |
| | | <div class="hdw-card-container"> |
| | | <hdw-card title="区域列表" is-full> |
| | | <hdw-tree></hdw-tree> |
| | | <hdw-tree @item-click="itemClickHandler"></hdw-tree> |
| | | </hdw-card> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="page-content-tools"> |
| | | <div class="tools-filter"> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作人:</div> |
| | | <div class="filter-label">操作人</div> |
| | | <div class="filter-content"> |
| | | <el-input v-model="filter.userName" size="small"></el-input> |
| | | <el-select v-model="ctlUname" clearable placeholder="请选择" size="small" filterable style="width: 180px" |
| | | @change="getList"> |
| | | <el-option v-for="(item, idx) in userList" size="small" :key="'user_' + idx" :label="item" |
| | | :value="item" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作时间:</div> |
| | | <div class="filter-label">操作时间</div> |
| | | <div class="filter-content"> |
| | | <el-date-picker |
| | | v-model="filter.timeRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始时间" |
| | | end-placeholder="结束时间" |
| | | size="small" |
| | | /> |
| | | <el-date-picker v-model="startTime" @change="getList" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" |
| | | size="small" placeholder="" />至<el-date-picker v-model="endTime" type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" size="small" @change="getList" placeholder="" /> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作类型:</div> |
| | | <div class="filter-label">操作类型</div> |
| | | <div class="filter-content"> |
| | | <el-select |
| | | v-model="filter.type" |
| | | placeholder="请选择" |
| | | size="small" |
| | | style="width: 180px" |
| | | > |
| | | <el-option label="--请选择--" :value="0"/> |
| | | <el-option label="开关门日志" :value="1"/> |
| | | <el-option label="报警日志" :value="2"/> |
| | | <el-select v-model="ctlType" @change="getList" placeholder="请选择" size="small" style="width: 180px"> |
| | | <el-option v-for="(item, idx) in ctlTypeList" :key="'type_' + idx" :label="item || '全部'" |
| | | :value="idx" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">锁具</div> |
| | | <div class="filter-content"> |
| | | <el-select v-model="lockId" @change="getList" clearable filterable placeholder="请选择" size="small" |
| | | style="width: 180px"> |
| | | <el-option v-for="item in lockList" :key="'lock_' + item.lockId" :label="item.lockName" |
| | | :value="item.lockId" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" size="small" :icon="Search">查询</el-button> |
| | | <el-button type="primary" size="small" :icon="Search" @click="getList">查询</el-button> |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table :data="tableData" border style="width: 100%; height: 100%"> |
| | | <el-table :data="logList" border style="width: 100%; height: 100%"> |
| | | <el-table-column type="index" width="50" /> |
| | | <el-table-column prop="areaName" align="center" label="区域名称" width="180" /> |
| | | <el-table-column prop="userName" align="center" label="操作人" width="120" /> |
| | | <el-table-column prop="keyName" align="center" label="钥匙名称" width="120" /> |
| | | <!-- <el-table-column prop="areaName" align="center" label="区域名称" width="180" /> --> |
| | | <el-table-column prop="ctlUname" align="center" label="操作人" width="120" /> |
| | | <!-- <el-table-column prop="keyName" align="center" label="钥匙名称" width="120" /> --> |
| | | <el-table-column prop="lockName" align="center" label="锁具名称" min-width="180" /> |
| | | <el-table-column prop="type" align="center" label="操作类型" width="180" /> |
| | | <el-table-column prop="state" align="center" width="120" label="状态" /> |
| | | <el-table-column prop="openType" align="center" label="开锁方式" width="120" /> |
| | | <el-table-column prop="time" align="center" label="操作时间" width="180" /> |
| | | <el-table-column prop="ctlTypeStr" align="center" label="操作类型" width="180" /> |
| | | <el-table-column prop="ctlResultStr" align="center" width="120" label="状态" /> |
| | | <el-table-column prop="openTypeStr" align="center" label="开锁方式" width="120" /> |
| | | <el-table-column prop="ctlTime" align="center" label="操作时间" width="180" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination |
| | | v-model:current-page="page.currentPage" |
| | | v-model:page-size="page.pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" |
| | | size="small" |
| | | :disabled="disabled" |
| | | :background="background" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="page.total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" |
| | | layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | |
| | | &::after { |
| | | content: ":"; |
| | | } |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
New file |
| | |
| | | <template> |
| | | <div class="params-dialog"> |
| | | <div class="form-content"> |
| | | {{ message }} |
| | | </div> |
| | | <div class="form-footer"> |
| | | <el-button type="primary" :disabled="bindState" @click="next">下一步</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getUNameByUKey } from "@/api/user"; |
| | | import useElement from '@/hooks/useElement.js'; |
| | | |
| | | const { $loading } = useElement(); |
| | | export default { |
| | | name: "BindStep2", |
| | | props: { |
| | | id: { |
| | | type: String, |
| | | default: "" |
| | | } |
| | | }, |
| | | watch: { |
| | | id(id) { |
| | | this.checkUKey(id); |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | bindState: false, // uKey绑定的状态 |
| | | userName: "", // 绑定的用户名 |
| | | state: 0 |
| | | }; |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 检测uKey是否已经绑定用户 |
| | | */ |
| | | checkUKey(id) { |
| | | if (id) { |
| | | let loading = $loading(); |
| | | getUNameByUKey(id.trim()) |
| | | .then(res => { |
| | | let { code, data, data2 } = res; |
| | | if (code && data) { |
| | | this.state = 1; |
| | | this.bindState = true; |
| | | this.userName = data2.uname; |
| | | } else { |
| | | this.state = 0; |
| | | this.bindState = false; |
| | | } |
| | | // 关闭等待框 |
| | | loading.close(); |
| | | }) |
| | | .catch(error => { |
| | | // 请求网络失败 |
| | | this.state = -1; |
| | | this.bindState = true; |
| | | // 关闭等待框 |
| | | loading.close(); |
| | | console.log(error); |
| | | }); |
| | | } else { |
| | | this.state = -2; |
| | | this.bindState = true; |
| | | } |
| | | }, |
| | | next() { |
| | | this.$emit("next"); |
| | | } |
| | | }, |
| | | computed: { |
| | | message() { |
| | | let msg = ""; |
| | | switch (this.state) { |
| | | case -2: |
| | | msg = "未获取到ukey的信息"; |
| | | break; |
| | | case -1: |
| | | msg = "请求网络失败,无法检测ukey绑定状态!"; |
| | | break; |
| | | case 0: |
| | | msg = "ukey未绑定用户"; |
| | | break; |
| | | case 1: |
| | | msg = "ukey已绑定" + this.userName + "用户"; |
| | | break; |
| | | } |
| | | return msg; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.checkUKey(this.id); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .form-content { |
| | | padding: 8px; |
| | | font-size: 18px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .form-footer { |
| | | padding: 8px; |
| | | text-align: right; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <el-form label-position="top" class="params-dialog"> |
| | | <el-row> |
| | | <el-col :span="6"> |
| | | <div style="visibility: hidden">1</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item class="label" label="用户名"> |
| | | <el-input type="text" placeholder="请输入用户名" resize="none" v-model="userName"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"></el-col> |
| | | </el-row> |
| | | <div class="form-footer"> |
| | | <el-button type="primary" @click="confirmBindUser">绑定用户</el-button> |
| | | </div> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script> |
| | | import SoftUKey from "@/utils/SoftUKey"; |
| | | import SoftKey3W from "@/utils/Syunew3"; |
| | | import useElement from '@/hooks/useElement.js'; |
| | | |
| | | const { $loading, $confirm, $message } = useElement(); |
| | | import { |
| | | getUKeyByUName, |
| | | bindUKey, |
| | | } from "@/api/user"; |
| | | export default { |
| | | name: "BindStep3", |
| | | props: { |
| | | id: { |
| | | type: String, |
| | | default: "" |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | userName: "", |
| | | softUKey: new SoftUKey(SoftKey3W) |
| | | } |
| | | }, |
| | | methods: { |
| | | confirmBindUser() { |
| | | let userName = this.userName.trim(); |
| | | let id = this.id.trim(); |
| | | if (!userName) { |
| | | $message("用户名不能为空"); |
| | | return; |
| | | } |
| | | if (!id) { |
| | | $message("uKey的信息不能为空"); |
| | | return; |
| | | } |
| | | $confirm('绑定' + this.userName, () => { |
| | | this.checkUser(userName, id); |
| | | }); |
| | | }, |
| | | /** |
| | | * 校验用户是否已经绑定用户 |
| | | * @param name 用户名 |
| | | * @param id ukey的信息 |
| | | */ |
| | | checkUser(name, id) { |
| | | let loading = $loading(); |
| | | getUKeyByUName(name).then(res => { |
| | | // 1:已经绑定ukey,0:用户不存在 -1:可以绑定 |
| | | |
| | | let { code, msg } = res; |
| | | loading.close(); |
| | | if (code == 1) { |
| | | $message(msg); |
| | | } else if (code == 0) { |
| | | $message(msg); |
| | | } else { |
| | | this.softUKey.setUserName(name, this.setUserNameRs); |
| | | } |
| | | |
| | | }).catch(error => { |
| | | // 关闭等待框 |
| | | loading.close(); |
| | | console.log(error); |
| | | }); |
| | | }, |
| | | setUserNameRs(result) { |
| | | let name = result.userName; |
| | | let id = this.id.trim(); |
| | | let publicX = result.PubKeyX; |
| | | let publicY = result.PubKeyY; |
| | | let loading = $loading(); |
| | | this.bindUkey(name, id, publicX, publicY, loading); |
| | | }, |
| | | /** |
| | | * 绑定用户 |
| | | * @param name 用户名 |
| | | * @param id ukey的信息 |
| | | * @param loading 加载等待框 |
| | | */ |
| | | bindUkey(name, id, publicX, publicY, loading) { |
| | | if (!loading) { |
| | | loading = $loading(); |
| | | } |
| | | bindUKey(name, id, publicX, publicY).then(res => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $message('绑定成功'); |
| | | this.$emit('next'); |
| | | } else { |
| | | $message('绑定失败'); |
| | | } |
| | | // 关闭等待框 |
| | | loading.close(); |
| | | }).catch(error => { |
| | | // 关闭等待框 |
| | | loading.close(); |
| | | console.log(error); |
| | | }); |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .label { |
| | | padding: 4px; |
| | | color: #153953; |
| | | background: transparent; |
| | | font-size: 12px; |
| | | font-weight: bold; |
| | | |
| | | :deep(.el-input) { |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper) { |
| | | padding: 0; |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | border-color: #dcdfe6; |
| | | color: #153953; |
| | | background-color: #cccccc; |
| | | } |
| | | } |
| | | |
| | | |
| | | .form-footer { |
| | | text-align: right; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="params-container"> |
| | | <el-steps :active="active" finish-status="success" simple> |
| | | <el-step title="插入ukey">123</el-step> |
| | | <el-step title="ukey验证"></el-step> |
| | | <el-step title="用户验证"></el-step> |
| | | <el-step title="绑定状态"></el-step> |
| | | </el-steps> |
| | | <div class="el-step" v-if="active == 1"> |
| | | <div class="el-step-text-content">未插入ukey,请插入ukey</div> |
| | | </div> |
| | | <bind-step2 :id="id" @next="next" v-if="active == 2"></bind-step2> |
| | | <bind-step3 :id="id" @next="next" v-if="active == 3"></bind-step3> |
| | | <div class="params-dialog" v-if="active == 4"> |
| | | <div class="el-step-text-content">已完成绑定</div> |
| | | <div class="form-footer"> |
| | | <el-button type="primary" @click="close">关闭</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import BindStep2 from "./BindStep2"; |
| | | import BindStep3 from "./BindStep3"; |
| | | import store from "@/store"; |
| | | import { mapState } from 'pinia'; |
| | | |
| | | export default { |
| | | name: "UkeyBind", |
| | | components: { BindStep3, BindStep2 }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | computed: { |
| | | ...mapState(store.ukey, ['id', 'isIn']), |
| | | }, |
| | | watch: { |
| | | id: { |
| | | handler(id) { |
| | | if (id) { |
| | | this.active = 2; |
| | | } else { |
| | | this.active = 1; |
| | | } |
| | | }, |
| | | immediate: true |
| | | }, |
| | | }, |
| | | data() { |
| | | let active = this.isIn ? 2 : 1; |
| | | return { |
| | | active: active, |
| | | // id: "", |
| | | }; |
| | | }, |
| | | methods: { |
| | | next() { |
| | | this.active++; |
| | | }, |
| | | close() { |
| | | this.$emit("update:visible", false); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | // this.id = this.$store.state.ukey.id; |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .params-container { |
| | | padding: 8px 8px 0 8px; |
| | | background-color: #ececec; |
| | | } |
| | | .form-footer { |
| | | text-align: right; |
| | | } |
| | | .el-step-text-content { |
| | | padding: 8px; |
| | | text-align: center; |
| | | font-size: 16px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <!-- 人脸登陆弹窗 --> |
| | | <div> |
| | | <video ref="video" width="480" height="320" style="display: none"></video> |
| | | <canvas ref="canvas" width="480" height="320"></canvas> |
| | | <p class="text">{{ faceDetect }}</p> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import faceManager from "./faceManager.js"; |
| | | import { uKeyLogin } from "@/api/user"; |
| | | import store from '@/store'; |
| | | import { mapState } from 'pinia'; |
| | | import useElement from '@/hooks/useElement.js'; |
| | | import { getToken, removeToken, setToken, getUname, setUname, removeUname, getUrole, setUrole, removeUrole } from '@/utils/auth'; |
| | | |
| | | const { $loading, $confirm, $message } = useElement(); |
| | | // import const_num from "@/assets/js/const/const_num"; |
| | | // import RSA from "@/assets/js/tools/RSA"; |
| | | export default { |
| | | props: { |
| | | faceShow: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | status: true, |
| | | faceDetect: "请将正脸对准摄像头", |
| | | imageBase64: "", |
| | | newstream: "", |
| | | intTime: null, |
| | | postTime: null, |
| | | setTime: null, |
| | | redirect: undefined, |
| | | otherQuery: {} |
| | | }; |
| | | }, |
| | | watch: { |
| | | $route: { |
| | | handler: function (route) { |
| | | const query = route.query; |
| | | if (query) { |
| | | this.redirect = query.redirect; |
| | | this.otherQuery = this.getOtherQuery(query); |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | computed: { |
| | | ...mapState(store.ukey, ['isIn', 'connect', 'id']), |
| | | }, |
| | | mounted() { |
| | | this.faceChange(); |
| | | }, |
| | | beforeUnmount() { |
| | | // console.log('beforeUnmount ', '============='); |
| | | |
| | | this.status = false; |
| | | this.clearVideo(); |
| | | }, |
| | | methods: { |
| | | getOtherQuery(query) { |
| | | return Object.keys(query).reduce((acc, cur) => { |
| | | if (cur !== 'redirect') { |
| | | acc[cur] = query[cur]; |
| | | } |
| | | return acc; |
| | | }, {}); |
| | | }, |
| | | // 关闭摄像头 |
| | | clearVideo: function () { |
| | | // 关闭定时器 |
| | | clearInterval(this.intTime); |
| | | clearInterval(this.postTime); |
| | | clearTimeout(this.setTime); |
| | | // 关闭摄像头 |
| | | for (let track of this.newstream.getTracks()) { |
| | | track.stop(); |
| | | } |
| | | }, |
| | | // 获取图片 |
| | | getImg: function () { |
| | | let vm = this; |
| | | let video = vm.$refs.video; |
| | | let canvas = vm.$refs.canvas; |
| | | let context = canvas.getContext("2d"); |
| | | context.drawImage(video, 0, 0, 480, 320); |
| | | // 获取图片base64链接 |
| | | vm.imageBase64 = canvas.toDataURL("image/png"); |
| | | }, |
| | | // 人脸检测 |
| | | faceChange: function () { |
| | | let vm = this; |
| | | // 恢复提示语 |
| | | vm.faceDetect = "请将正脸对准摄像头"; |
| | | // vm.faceShow = true; |
| | | if ( |
| | | navigator.mediaDevices.getUserMedia || |
| | | navigator.getUserMedia || |
| | | navigator.webkitGetUserMedia || |
| | | navigator.mozGetUserMedia |
| | | ) { |
| | | //调用用户媒体设备, 访问摄像头 |
| | | this.getUserMedia( |
| | | { video: { width: 480, height: 320 } }, |
| | | this.success, |
| | | this.error |
| | | ); |
| | | } else { |
| | | alert("不支持访问用户媒体"); |
| | | } |
| | | }, |
| | | //访问用户媒体设备的兼容方法 |
| | | getUserMedia: function (constraints, success, error) { |
| | | if (navigator.mediaDevices.getUserMedia) { |
| | | //最新的标准API |
| | | navigator.mediaDevices |
| | | .getUserMedia(constraints) |
| | | .then(success) |
| | | .catch(error); |
| | | } else if (navigator.webkitGetUserMedia) { |
| | | //webkit核心浏览器 |
| | | navigator.webkitGetUserMedia(constraints, success, error); |
| | | } else if (navigator.mozGetUserMedia) { |
| | | //firfox浏览器 |
| | | navigator.mozGetUserMedia(constraints, success, error); |
| | | } else if (navigator.getUserMedia) { |
| | | //旧版API |
| | | navigator.getUserMedia(constraints, success, error); |
| | | } |
| | | }, |
| | | // 成功回调 |
| | | success: function (stream) { |
| | | let vm = this; |
| | | //兼容webkit核心浏览器 |
| | | let CompatibleURL = window.URL || window.webkitURL; |
| | | //将视频流设置为video元素的源 |
| | | // console.log(stream); |
| | | // stream = stream; |
| | | this.newstream = stream; |
| | | //video.src = CompatibleURL.createObjectURL(stream); |
| | | let video = this.$refs.video; |
| | | video.srcObject = stream; |
| | | video.play(); |
| | | this.intTime = setInterval(() => { |
| | | vm.getImg(); |
| | | }, 0); |
| | | setTimeout(function () { |
| | | vm.facePost(); |
| | | }, 0); |
| | | }, |
| | | error: function (error) { |
| | | console.log(error); |
| | | console.log(`访问用户媒体设备失败${error.name}, ${error.message}`); |
| | | }, |
| | | // 请求后台验证人脸 |
| | | facePost: function () { |
| | | if (!this.isIn) { |
| | | this.faceDetect = "请先插入ukey"; |
| | | this.setTime = setTimeout(() => { |
| | | this.facePost(); |
| | | }, 500); |
| | | } else if (!this.imageBase64) { |
| | | this.faceDetect = "人脸识别中..."; |
| | | this.setTime = setTimeout(() => { |
| | | this.facePost(); |
| | | }, 500); |
| | | } else { |
| | | let vm = this; |
| | | faceManager |
| | | .faceVerify('"' + vm.imageBase64 + '"', this.id) |
| | | .then((result) => { |
| | | let res = result; |
| | | console.log(res); |
| | | if (res.code === 1 && res.data) { |
| | | vm.faceDetect = "匹配成功"; |
| | | let user = res.data2[0]; |
| | | setTimeout(() => { |
| | | // vm.onLogin(); |
| | | // $message.success("登录成功"); |
| | | setUname(user.uname); |
| | | setToken('admin'); |
| | | setUrole(user.urole); |
| | | this.$router.push({ path: this.redirect || '/', query: this.otherQuery }); |
| | | // this.$router.push("/home"); |
| | | // // // 设置用户的权限 |
| | | // // this.$store.dispatch("user/getPermits"); |
| | | }, 1000); |
| | | } else { |
| | | vm.faceDetect = res.msg; |
| | | if (vm.status == true) { |
| | | this.setTime = setTimeout(() => { |
| | | this.facePost(); |
| | | }, 3000); |
| | | } |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | vm.faceDetect = "网络链接失败"; |
| | | if (vm.status == true) { |
| | | this.setTime = setTimeout(() => { |
| | | this.facePost(); |
| | | }, 3000); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | // 登陆设置sessionStorage |
| | | onLogin: function () { |
| | | faceManager |
| | | .getUserName() |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code == 1) { |
| | | this.uKeyLogin(data.uname, data.usnid); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | }); |
| | | }, |
| | | uKeyLogin(username, password) { |
| | | // ukey登录 |
| | | uKeyLogin(username, password, this.id, true) |
| | | .then((res) => { |
| | | console.log('res', res, '============='); |
| | | |
| | | // 对结果进行处理 |
| | | this.handleLogin(res, username); |
| | | }) |
| | | .catch((error) => { |
| | | // 关闭等待 |
| | | this.loading = false; |
| | | this.faceDetect = "网络异常"; |
| | | this.facePost(); |
| | | }); |
| | | }, |
| | | handleLogin(res, username) { |
| | | let rs = res.data; |
| | | if (rs.code == 1) { |
| | | this.$message.success("登录成功"); |
| | | sessionStorage.setItem("username", username); |
| | | sessionStorage.setItem("userId", rs.data); |
| | | this.$router.push("/home"); |
| | | // 设置用户的权限 |
| | | this.$store.dispatch("user/getPermits"); |
| | | } else { |
| | | this.faceDetect = rs.msg; |
| | | this.facePost(); |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .text { |
| | | text-align: center; |
| | | padding: 10px 0; |
| | | } |
| | | </style> |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | export default { |
| | | /** |
| | | * 人脸验证 |
| | | * @param json:base64Image |
| | | * @returns {AxiosPromise} |
| | | */ |
| | | faceVerify(data, param) { |
| | | return request({ |
| | | method: 'post', |
| | | url: `/face/faceCompare2N?ukeyId=${param}`, |
| | | headers: { 'content-type': 'application/json' }, |
| | | data |
| | | }); |
| | | }, |
| | | /** |
| | | * 获取用户名 |
| | | * @param 无参 |
| | | * @returns {AxiosPromise} |
| | | */ |
| | | getUserName() { |
| | | return request({ |
| | | method: 'GET', |
| | | url: '/face/info', |
| | | data: null |
| | | }); |
| | | }, |
| | | } |
| | |
| | | <div class="login-container"> |
| | | <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" |
| | | label-position="left"> |
| | | |
| | | |
| | | <div class="title-container"> |
| | | <h3 class="title">鸿蒙智能电子锁管理平台</h3> |
| | | </div> |
| | | |
| | | |
| | | <el-form-item prop="username"> |
| | | <span class="svg-container"> |
| | | <svg-icon icon-class="user" /> |
| | |
| | | <el-input ref="username" v-model="loginForm.username" placeholder="Username" name="username" type="text" |
| | | tabindex="1" autocomplete="on" /> |
| | | </el-form-item> |
| | | |
| | | |
| | | <el-tooltip v-model="capsTooltip" :content="passwordType === 'password' ?'显示密码':'隐藏密码'" placement="right" manual> |
| | | <el-form-item prop="password"> |
| | | <span class="svg-container"> |
| | |
| | | </span> |
| | | </el-form-item> |
| | | </el-tooltip> |
| | | |
| | | <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:40px;" @click.prevent="handleLogin">登录</el-button> |
| | | |
| | | <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:40px;" |
| | | @click.prevent="handleLogin">登录</el-button> |
| | | </el-form> |
| | | <div class="tools-container"> |
| | | <div class="tools-item" :class="uKeyState" v-if="uKey" @click="uKeyVisible = true"> |
| | | <span class="ukey"></span> |
| | | </div> |
| | | <div class="tools-item" v-if="faceCfg" @click="faceVisible = true"> |
| | | <span class="face"></span> |
| | | </div> |
| | | </div> |
| | | <!-- uKey的验证 --> |
| | | <el-dialog title="uKey绑定" width="750px" v-model="uKeyVisible" :close-on-click-modal="false" top="0" |
| | | class="dialog-center" :modal-append-to-body="false"> |
| | | <ukey-bind v-if="uKeyVisible" v-model:visible="uKeyVisible"></ukey-bind> |
| | | </el-dialog> |
| | | |
| | | <!-- 人脸登陆 --> |
| | | <el-dialog title="人脸登陆" width="480px" v-model="faceVisible" :close-on-click-modal="false" top="0" |
| | | class="dialog-center" :modal-append-to-body="false"> |
| | | <face-login v-if="faceVisible" ></face-login> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import { ElMessage, type FormItemRule } from 'element-plus'; |
| | | import type { IForm } from '@/types/element-plus'; |
| | | import store from '@/store'; |
| | | import { defineComponent } from 'vue'; |
| | | import { ElMessage, type FormItemRule } from 'element-plus'; |
| | | import type { IForm } from '@/types/element-plus'; |
| | | import store from '@/store'; |
| | | import { mapState } from 'pinia'; |
| | | import config from '@/utils/config.js'; |
| | | import UkeyBind from './components/UKeyBind/index.vue'; |
| | | import useElement from '@/hooks/useElement.js'; |
| | | import { uKeyLogin } from '@/api/user'; |
| | | import FaceLogin from './components/face/FaceLogin.vue'; |
| | | import { getToken, removeToken, setToken, getUname, setUname, removeUname, getUrole, setUrole, removeUrole } from '@/utils/auth'; |
| | | |
| | | interface QueryType { |
| | | // 自定义key 任意字符串 |
| | | [propname:string]:string |
| | | } |
| | | const { $loading, $confirm, $message } = useElement(); |
| | | const { ukey, face } = config; |
| | | |
| | | export default defineComponent({ |
| | | name: 'Login', |
| | | data() { |
| | | const validateUsername: FormItemRule['validator'] = (_rule, value, callback) => { |
| | | if (!value.trim()) { |
| | | callback(new Error('请输入用户名')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | const validatePassword: FormItemRule['validator'] = (_rule, value, callback) => { |
| | | if (value.length < 1) { |
| | | callback(new Error('请输入密码,至少1位')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | return { |
| | | loginForm: { |
| | | username: 'admin', |
| | | password: '1' |
| | | }, |
| | | loginRules: { |
| | | username: [{ required: true, trigger: 'blur', validator: validateUsername }], |
| | | password: [{ required: true, trigger: 'blur', validator: validatePassword }] |
| | | }, |
| | | passwordType: 'password', |
| | | capsTooltip: false, |
| | | loading: false, |
| | | showDialog: false, |
| | | redirect: undefined, |
| | | otherQuery: {} |
| | | }; |
| | | }, |
| | | watch: { |
| | | $route: { |
| | | handler: function(route) { |
| | | const query = route.query; |
| | | if (query) { |
| | | this.redirect = query.redirect; |
| | | this.otherQuery = this.getOtherQuery(query); |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | created() { |
| | | // window.addEventListener('storage', this.afterQRScan) |
| | | }, |
| | | mounted() { |
| | | if (this.loginForm.username === '') { |
| | | (this.$refs.username as HTMLElement).focus(); |
| | | } else if (this.loginForm.password === '') { |
| | | (this.$refs.password as HTMLElement).focus(); |
| | | } |
| | | this.themeChange('blue-theme'); |
| | | }, |
| | | 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'); |
| | | }, |
| | | showPwd() { |
| | | if (this.passwordType === 'password') { |
| | | this.passwordType = ''; |
| | | } else { |
| | | this.passwordType = 'password'; |
| | | } |
| | | this.$nextTick(() => { |
| | | (this.$refs.password as HTMLElement).focus(); |
| | | }); |
| | | }, |
| | | handleLogin() { |
| | | (this.$refs.loginForm as IForm).validate(valid => { |
| | | return new Promise((resolve, reject) => { |
| | | if (valid) { |
| | | this.loading = true; |
| | | store.user().login(this.loginForm) |
| | | .then(() => { |
| | | this.loading = false; |
| | | this.$router.push({ path: this.redirect || '/', query: this.otherQuery }); |
| | | }).catch((error) => { |
| | | this.loading = false; |
| | | // 请求失败,处理错误 |
| | | if (error.message === 'Network Error') { |
| | | // 如果是网络错误,显示中文消息 |
| | | ElMessage({ |
| | | message: '网络错误,请检查您的网络连接或服务器状态。', |
| | | type: 'error' |
| | | }); |
| | | } else { |
| | | // 其他类型的错误,可以根据需要处理 |
| | | ElMessage({ |
| | | message: error, |
| | | type: 'warning' |
| | | }); |
| | | } |
| | | }).finally(() => { |
| | | resolve(); |
| | | }); |
| | | } else { |
| | | console.log('error submit!!'); |
| | | reject(); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | getOtherQuery(query:QueryType) { |
| | | return Object.keys(query).reduce((acc:QueryType, cur) => { |
| | | if (cur !== 'redirect') { |
| | | acc[cur] = query[cur]; |
| | | } |
| | | return acc; |
| | | }, {}); |
| | | } |
| | | // afterQRScan() { |
| | | // if (e.key === 'x-admin-oauth-code') { |
| | | // const code = getQueryObject(e.newValue) |
| | | // const codeMap = { |
| | | // wechat: 'code', |
| | | // tencent: 'code' |
| | | // } |
| | | // const type = codeMap[this.auth_type] |
| | | // const codeName = code[type] |
| | | // if (codeName) { |
| | | // store.user().LoginByThirdparty(codeName).then(() => { |
| | | // this.$router.push({ path: this.redirect || '/' }) |
| | | // }) |
| | | // } else { |
| | | // alert('第三方登录失败') |
| | | // } |
| | | // } |
| | | // } |
| | | } |
| | | }); |
| | | interface QueryType { |
| | | // 自定义key 任意字符串 |
| | | [propname: string]: string |
| | | } |
| | | |
| | | export default defineComponent({ |
| | | name: 'Login', |
| | | data() { |
| | | const validateUsername: FormItemRule['validator'] = (_rule, value, callback) => { |
| | | if (!value.trim()) { |
| | | callback(new Error('请输入用户名')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | const validatePassword: FormItemRule['validator'] = (_rule, value, callback) => { |
| | | if (value.length < 1) { |
| | | callback(new Error('请输入密码,至少1位')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | return { |
| | | uKey: ukey, |
| | | faceCfg: face, |
| | | uKeyVisible: false, |
| | | faceVisible: false, |
| | | loginForm: { |
| | | username: '', |
| | | password: '' |
| | | }, |
| | | loginRules: { |
| | | username: [{ required: true, trigger: 'blur', validator: validateUsername }], |
| | | password: [{ required: true, trigger: 'blur', validator: validatePassword }] |
| | | }, |
| | | passwordType: 'password', |
| | | capsTooltip: false, |
| | | loading: false, |
| | | showDialog: false, |
| | | redirect: undefined, |
| | | otherQuery: {} |
| | | }; |
| | | }, |
| | | components: { |
| | | UkeyBind, |
| | | FaceLogin, |
| | | }, |
| | | computed: { |
| | | |
| | | uKeyState() { |
| | | let state = -1; |
| | | let uKey = store.ukey(); |
| | | let cls = "state-error"; |
| | | // 设置uKey的状态 |
| | | if (uKey.connect) { |
| | | if (uKey.isIn) { |
| | | state = 1; |
| | | } else { |
| | | state = 0; |
| | | } |
| | | } else { |
| | | state = -1; |
| | | } |
| | | // 根据状态确定uKey图表的颜色 |
| | | switch (state) { |
| | | case 0: |
| | | cls = "state-default"; |
| | | break; |
| | | case 1: |
| | | cls = ""; |
| | | break; |
| | | default: |
| | | cls = "state-error"; |
| | | break; |
| | | } |
| | | return cls; |
| | | }, |
| | | ...mapState(store.ukey, ['isIn', 'connect', 'id']) |
| | | }, |
| | | watch: { |
| | | $route: { |
| | | handler: function (route) { |
| | | const query = route.query; |
| | | if (query) { |
| | | this.redirect = query.redirect; |
| | | this.otherQuery = this.getOtherQuery(query); |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | created() { |
| | | // window.addEventListener('storage', this.afterQRScan) |
| | | }, |
| | | mounted() { |
| | | if (this.loginForm.username === '') { |
| | | (this.$refs.username as HTMLElement).focus(); |
| | | } else if (this.loginForm.password === '') { |
| | | (this.$refs.password as HTMLElement).focus(); |
| | | } |
| | | this.themeChange('blue-theme'); |
| | | }, |
| | | 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'); |
| | | }, |
| | | showPwd() { |
| | | if (this.passwordType === 'password') { |
| | | this.passwordType = ''; |
| | | } else { |
| | | this.passwordType = 'password'; |
| | | } |
| | | this.$nextTick(() => { |
| | | (this.$refs.password as HTMLElement).focus(); |
| | | }); |
| | | }, |
| | | handleLogin() { |
| | | if (ukey) { |
| | | this.uKeyLoginFn(); |
| | | } else { |
| | | this.normalLogin(); |
| | | } |
| | | }, |
| | | uKeyLoginFn() { |
| | | // |
| | | if (!this.connect) { |
| | | $message.error("请先安装uKey客户端服务"); |
| | | return; |
| | | } |
| | | if (!this.isIn) { |
| | | $message.warning("请先插入uKey"); |
| | | return; |
| | | } |
| | | |
| | | // 校验用户 |
| | | if (this.loginForm.username && this.loginForm.password) { |
| | | // 开启等待框 |
| | | this.loading = true; |
| | | uKeyLogin( |
| | | this.loginForm.username, |
| | | this.loginForm.password, |
| | | this.id |
| | | ) |
| | | .then((res) => { |
| | | // 对结果进行处理 |
| | | console.log('res', res, '============='); |
| | | let { code, data, data2, msg } = res; |
| | | this.loading = false; |
| | | if (code && data) { |
| | | setUname(data2.uname); |
| | | setToken('admin'); |
| | | setUrole(data2.urole); |
| | | ElMessage({ |
| | | message: msg, |
| | | type: 'success' |
| | | }); |
| | | this.$router.push({ path: this.redirect || '/', query: this.otherQuery }); |
| | | } else { |
| | | ElMessage({ |
| | | message: msg, |
| | | type: 'error' |
| | | }); |
| | | } |
| | | |
| | | }) |
| | | .catch((error) => { |
| | | // 关闭等待 |
| | | this.loading = false; |
| | | console.log(error); |
| | | $message.error("网络异常"); |
| | | }); |
| | | } else { |
| | | $message.error("用户名或密码不能为空"); |
| | | } |
| | | }, |
| | | normalLogin() { |
| | | (this.$refs.loginForm as IForm).validate(valid => { |
| | | return new Promise((resolve, reject) => { |
| | | if (valid) { |
| | | this.loading = true; |
| | | store.user().login(this.loginForm) |
| | | .then((res) => { |
| | | this.loading = false; |
| | | let { code, data, msg } = res; |
| | | if (code && data) { |
| | | ElMessage({ |
| | | message: msg, |
| | | type: 'success' |
| | | }); |
| | | this.$router.push({ path: this.redirect || '/', query: this.otherQuery }); |
| | | } else { |
| | | ElMessage({ |
| | | message: msg, |
| | | type: 'error' |
| | | }); |
| | | } |
| | | }).catch((error) => { |
| | | this.loading = false; |
| | | // 请求失败,处理错误 |
| | | if (error.message === 'Network Error') { |
| | | // 如果是网络错误,显示中文消息 |
| | | ElMessage({ |
| | | message: '网络错误,请检查您的网络连接或服务器状态。', |
| | | type: 'error' |
| | | }); |
| | | } else { |
| | | // 其他类型的错误,可以根据需要处理 |
| | | ElMessage({ |
| | | message: error, |
| | | type: 'warning' |
| | | }); |
| | | } |
| | | }).finally(() => { |
| | | resolve(); |
| | | }); |
| | | } else { |
| | | console.log('error submit!!'); |
| | | reject(); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | getOtherQuery(query: QueryType) { |
| | | return Object.keys(query).reduce((acc: QueryType, cur) => { |
| | | if (cur !== 'redirect') { |
| | | acc[cur] = query[cur]; |
| | | } |
| | | return acc; |
| | | }, {}); |
| | | } |
| | | // afterQRScan() { |
| | | // if (e.key === 'x-admin-oauth-code') { |
| | | // const code = getQueryObject(e.newValue) |
| | | // const codeMap = { |
| | | // wechat: 'code', |
| | | // tencent: 'code' |
| | | // } |
| | | // const type = codeMap[this.auth_type] |
| | | // const codeName = code[type] |
| | | // if (codeName) { |
| | | // store.user().LoginByThirdparty(codeName).then(() => { |
| | | // this.$router.push({ path: this.redirect || '/' }) |
| | | // }) |
| | | // } else { |
| | | // alert('第三方登录失败') |
| | | // } |
| | | // } |
| | | // } |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | |
| | | |
| | | &:-webkit-autofill { |
| | | box-shadow: 0 0 0px 1000px $bg inset !important; |
| | | -webkit-text-fill-color: $cursor !important; |
| | | -webkit-text-fill-color: $cursor !important; |
| | | } |
| | | } |
| | | } |
| | |
| | | bottom: 6px; |
| | | } |
| | | |
| | | .tools-container { |
| | | position: absolute; |
| | | bottom: 0; |
| | | right: 0; |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .tools-container .tools-item { |
| | | padding: 8px; |
| | | width: 40px; |
| | | height: 40px; |
| | | cursor: pointer; |
| | | |
| | | .face { |
| | | display: inline-block; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: url("data:image/svg+xml,%3csvg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' %3e%3cpath d='M161.6 153.1h128.7V73.3H99.7c-8.3 0-15.1 6.7-15.1 15.1V286h76.9V153.1z m692.7 132.8h76.9V88.3c0-8.3-6.7-15.1-15.1-15.1H725.9V153h128.3v132.9zM605 449.2s140.1 88.3 161.6 22.2c0-148.1-115.8-268-258.5-268s-258.5 119.9-258.5 268C386.9 521.9 605 449.2 605 449.2z m161.6 134.1h-43.2s1 59.4-53.8 78C668.4 693.9 615 829 508.7 829c-106.2 0-160.9-135.1-162.2-167.7-55-18.9-52.5-78-52.5-78h-44.5s-1.6 78 64.6 100.6c1.6 38.2 66.2 189.9 193.9 189.9s192.6-151.4 193.9-189.9c66.3-22.5 64.7-100.6 64.7-100.6zM161.9 738.1H84.6v197.6c0 8.3 6.7 15.1 15.1 15.1h190.2V871h-128V738.1z m692.4 132.8H725.9v79.8h190.2c8.3 0 15.1-6.7 15.1-15.1V738.1h-76.9v132.8zM945 520H79c-8.2 0-15 6.7-15 15v2.2c0 8.2 6.7 15 15 15h866c8.2 0 15-6.7 15-15V535c0-8.3-6.7-15-15-15z' fill='%23333333'%3e%3c/path%3e%3c/svg%3e") center center / contain no-repeat; |
| | | } |
| | | |
| | | .ukey { |
| | | display: inline-block; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: url("data:image/svg+xml,%3csvg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' %3e%3cpath d='M456.26 247.11a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m160 0a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m72-64h-352v248h352z m79.9 357.5h-53.7a8 8 0 0 0-6.6 3.5l-81 118.2a157.35 157.35 0 0 0-8.2 15.6h-0.9v-129.2a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v274.4a8 8 0 0 0 8 8h45.9a8 8 0 0 0 8-8V689h0.9a90.25 90.25 0 0 0 7.7 15.2L712 827.71a8.19 8.19 0 0 0 6.6 3.4h58.3a7.84 7.84 0 0 0 4.7-1.6 8 8 0 0 0 1.7-11.2l-103-139.1 94.3-125.8a8.37 8.37 0 0 0 1.6-4.8 8 8 0 0 0-8.04-8z m-459.3 0.1h-46.1a8 8 0 0 0-8 8v160.8q0 126.6 116.6 126.6 120.9 0 120.8-129.9v-157.5a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v164q0 69.9-56.2 69.9-57.15 0-57.2-72.6v-161.3a8 8 0 0 0-8-8z m419.4-429.6a32 32 0 0 1 32 31.47v288.53c65.54 0 118.93 51.06 120 114.09v357.91a8 8 0 0 1-7.75 8H152.26a8 8 0 0 1-8-7.75V547.11c0-63.26 52.73-115 118-116h2v-288a32 32 0 0 1 31.47-32h432.53z' fill='%230000ff'%3e%3c/path%3e%3c/svg%3e") center center / contain no-repeat; |
| | | } |
| | | |
| | | &.state-default .ukey { |
| | | background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' %3e%3cpath d='M456.26 247.11a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m160 0a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m72-64h-352v248h352z m79.9 357.5h-53.7a8 8 0 0 0-6.6 3.5l-81 118.2a157.35 157.35 0 0 0-8.2 15.6h-0.9v-129.2a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v274.4a8 8 0 0 0 8 8h45.9a8 8 0 0 0 8-8V689h0.9a90.25 90.25 0 0 0 7.7 15.2L712 827.71a8.19 8.19 0 0 0 6.6 3.4h58.3a7.84 7.84 0 0 0 4.7-1.6 8 8 0 0 0 1.7-11.2l-103-139.1 94.3-125.8a8.37 8.37 0 0 0 1.6-4.8 8 8 0 0 0-8.04-8z m-459.3 0.1h-46.1a8 8 0 0 0-8 8v160.8q0 126.6 116.6 126.6 120.9 0 120.8-129.9v-157.5a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v164q0 69.9-56.2 69.9-57.15 0-57.2-72.6v-161.3a8 8 0 0 0-8-8z m419.4-429.6a32 32 0 0 1 32 31.47v288.53c65.54 0 118.93 51.06 120 114.09v357.91a8 8 0 0 1-7.75 8H152.26a8 8 0 0 1-8-7.75V547.11c0-63.26 52.73-115 118-116h2v-288a32 32 0 0 1 31.47-32h432.53z' fill='%23808080'%3e%3c/path%3e%3c/svg%3e") |
| | | } |
| | | |
| | | &.state-error .ukey { |
| | | background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' %3e%3cpath d='M456.26 247.11a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m160 0a8 8 0 0 1 8 7.75v48.25a8 8 0 0 1-7.75 8h-48.25a8 8 0 0 1-8-7.75v-48.25a8 8 0 0 1 7.76-8h48.24z m72-64h-352v248h352z m79.9 357.5h-53.7a8 8 0 0 0-6.6 3.5l-81 118.2a157.35 157.35 0 0 0-8.2 15.6h-0.9v-129.2a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v274.4a8 8 0 0 0 8 8h45.9a8 8 0 0 0 8-8V689h0.9a90.25 90.25 0 0 0 7.7 15.2L712 827.71a8.19 8.19 0 0 0 6.6 3.4h58.3a7.84 7.84 0 0 0 4.7-1.6 8 8 0 0 0 1.7-11.2l-103-139.1 94.3-125.8a8.37 8.37 0 0 0 1.6-4.8 8 8 0 0 0-8.04-8z m-459.3 0.1h-46.1a8 8 0 0 0-8 8v160.8q0 126.6 116.6 126.6 120.9 0 120.8-129.9v-157.5a8 8 0 0 0-8-8h-45.9a8 8 0 0 0-8 8v164q0 69.9-56.2 69.9-57.15 0-57.2-72.6v-161.3a8 8 0 0 0-8-8z m419.4-429.6a32 32 0 0 1 32 31.47v288.53c65.54 0 118.93 51.06 120 114.09v357.91a8 8 0 0 1-7.75 8H152.26a8 8 0 0 1-8-7.75V547.11c0-63.26 52.73-115 118-116h2v-288a32 32 0 0 1 31.47-32h432.53z' fill='%23ff0000'%3e%3c/path%3e%3c/svg%3e"); |
| | | } |
| | | } |
| | | |
| | | .tools-container .tools-item:hover { |
| | | background-color: #e4e4e4; |
| | | } |
| | | |
| | | .tools-container .iconfont { |
| | | font-size: 22px; |
| | | color: #0080ff; |
| | | } |
| | | |
| | | .tools-container .state-default .iconfont { |
| | | color: #808080; |
| | | } |
| | | |
| | | .tools-container .state-error .iconfont { |
| | | color: #ff0000; |
| | | } |
| | | :deep(.dialog-center) { |
| | | box-sizing: content-box; |
| | | } |
| | | |
| | | |
| | | @media only screen and (max-width: 470px) { |
| | | .thirdparty-button { |
| | | display: none; |
New file |
| | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { getAllUserName } from "@/api/user"; |
| | | import { getAreaUserLock } from '@/api/lockManager.js'; |
| | | |
| | | import { getSysLog, getTypes } from '@/api/loginfo.js'; |
| | | const userName = ref(''); |
| | | const startTime = ref(''); |
| | | const endTime = ref(''); |
| | | const userList = ref([]); |
| | | const logList = ref([]); |
| | | const lockList = ref([]); |
| | | const pageCurr = ref(1); |
| | | const pageSize = ref(10); |
| | | const total = ref(0); |
| | | const typeList = ref([]); |
| | | |
| | | async function getList() { |
| | | let params = { |
| | | pageNum: pageCurr.value, |
| | | pageSize: pageSize.value, |
| | | startTime: startTime.value || undefined, |
| | | endTime: endTime.value || undefined, |
| | | userName: userName.value || undefined, |
| | | }; |
| | | |
| | | let res = await getSysLog(params); |
| | | let { code, data } = res; |
| | | let _total = 0; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data.list; |
| | | _total = data.total |
| | | } |
| | | logList.value = _list; |
| | | } |
| | | |
| | | const handleSizeChange = (params) => { |
| | | pageSize.value = params; |
| | | getList(); |
| | | } |
| | | |
| | | function handleCurrentChange(params) { |
| | | pageCurr.value = params; |
| | | getList(); |
| | | } |
| | | |
| | | async function getTypeList() { |
| | | let res = await getTypes(); |
| | | let { code, data } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | // console.log(data); |
| | | Object.keys(data).forEach((v) => { |
| | | data[v].forEach((vv) => { |
| | | _list.push({ label: vv.type2Name, value: vv.type2 }); |
| | | }); |
| | | }); |
| | | } |
| | | typeList.value = _list; |
| | | } |
| | | |
| | | async function getLockList() { |
| | | let res = await getAreaUserLock(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | lockList.value = _list; |
| | | } |
| | | async function getUsers() { |
| | | let res = await getAllUserName(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | userList.value = _list; |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getUsers(); |
| | | getLockList(); |
| | | getTypeList(); |
| | | getList(); |
| | | }); |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="page-wrapper"> |
| | | <div class="page-header"> |
| | | </div> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <div class="tools-filter"> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作人</div> |
| | | <div class="filter-content"> |
| | | <el-select v-model="userName" clearable placeholder="请选择" size="small" filterable style="width: 180px" |
| | | @change="getList"> |
| | | <el-option v-for="(item, idx) in userList" size="small" :key="'user_' + idx" :label="item" |
| | | :value="item" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作时间</div> |
| | | <div class="filter-content"> |
| | | <el-date-picker v-model="startTime" @change="getList" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" |
| | | size="small" placeholder="" />至<el-date-picker v-model="endTime" type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" size="small" @change="getList" placeholder="" /> |
| | | </div> |
| | | </div> |
| | | <div class="tools-filter-item"> |
| | | <div class="filter-label">操作类型</div> |
| | | <div class="filter-content"> |
| | | <el-select v-model="ctlType" @change="getList" placeholder="请选择" size="small" style="width: 180px"> |
| | | <el-option v-for="(item, idx) in typeList" :key="'type_' + idx" :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" size="small" :icon="Search" @click="getList">查询</el-button> |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table :data="logList" border style="width: 100%; height: 100%"> |
| | | <el-table-column type="index" width="50" /> |
| | | <el-table-column prop="userName" align="center" label="操作人" width="120" /> |
| | | <el-table-column prop="msg" align="center" label="操作类型" width="180" /> |
| | | <el-table-column prop="detail" align="center" width="" label="详情" /> |
| | | <el-table-column prop="ip" align="center" label="ip" width="120" /> |
| | | <el-table-column prop="createTime" align="center" label="操作时间" width="180" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination v-model:current-page="pageCurr" v-model:page-size="pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" |
| | | layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | |
| | | &::after { |
| | | content: ":"; |
| | | } |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { getUinfByAreaIds } from "@/api/user"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import { getAreaTreeApi, addArea, updateArea } from "@/api/area"; |
| | | import { formatAreaTree } from "@/utils/tree"; |
| | | import store from "@/store"; |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | |
| | | const uname = computed(() => store.user().name); |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object, |
| | | }, |
| | | isEdit: { |
| | | type: Boolean, |
| | | required: true |
| | | }, |
| | | }); |
| | | const props1 = { value: 'id', checkStrictly: true, multiple: true }; |
| | | const formRef = ref(); |
| | | const areaList = ref([]); |
| | | const userList = ref([]); |
| | | const form1 = reactive({ |
| | | areaName: "", |
| | | areaId: '', |
| | | parentId: "", |
| | | unames: "", |
| | | areaDescript: "", |
| | | }); |
| | | |
| | | const otherIdList = ref([]); |
| | | |
| | | const rules = { |
| | | areaName: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const $emit = defineEmits(["cancel", "success"]); |
| | | function close() { |
| | | $emit("cancel"); |
| | | } |
| | | |
| | | // 查询所有用户 |
| | | async function getAllUser() { |
| | | let res = await getUinfByAreaIds(); |
| | | let { code, data, data2 } = res; |
| | | let _list = []; |
| | | if (code && data) { |
| | | _list = data2; |
| | | } |
| | | userList.value = _list; |
| | | } |
| | | |
| | | async function update() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | areaName: form1.areaName.trim(), |
| | | areaDescript: form1.areaDescript.trim(), |
| | | id: form1.areaId, |
| | | }; |
| | | |
| | | // 编辑用户时, 区域中不在管理员管理内的区域要挑出来 最后更新时再追加进去 |
| | | console.log("params update", params, "============="); |
| | | let list = []; |
| | | form1.chargers.forEach((v) => { |
| | | list.push({ |
| | | uid: v, |
| | | uname: userList.value.find(item => item.uid === v)?.uname |
| | | }); |
| | | }); |
| | | |
| | | let loading = $loading(); |
| | | updateArea(params, list) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | async function onSubmit() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | areaName: form1.areaName.trim(), |
| | | areaDescript: form1.areaDescript.trim(), |
| | | parentId: form1.parentId, |
| | | }; |
| | | console.log("params", params, "============="); |
| | | |
| | | let list = []; |
| | | form1.chargers.forEach((v) => { |
| | | list.push({ |
| | | uid: v, |
| | | uname: userList.value.find(item => item.uid === v)?.uname |
| | | }); |
| | | }); |
| | | |
| | | let loading = $loading(); |
| | | addArea(params, list) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | |
| | | async function getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let _data = []; |
| | | if (res.code === 1 && res.data) { |
| | | _data = res.data2; |
| | | } |
| | | const treeList = []; |
| | | let ids = _data.map((v) => v.id); |
| | | for (let i = 0; i < _data.length; i++) { |
| | | formatAreaTree(_data[i], ids, treeList); |
| | | } |
| | | // console.log(_data, 'data'); |
| | | console.log(treeList, 'treeList'); |
| | | areaList.value = treeList; |
| | | formatAreaSelected(treeList); |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | |
| | | // 区域树 根节点 |
| | | // const areaRoots = computed(() => { |
| | | // if (!areaList.value) { |
| | | // return []; |
| | | // } else { |
| | | // return areaList.value.map(v => v.id); |
| | | // } |
| | | // }); |
| | | |
| | | function formatAreaSelected(treeList) { |
| | | let roots = treeList.map(v => v.id); |
| | | let otherAreas = form1.areaId.filter(v=>!v.some((vv) => roots.includes(vv))); |
| | | let otherIds = otherAreas.map(v => v[v.length - 1]); |
| | | |
| | | otherIdList.value = otherIds; |
| | | |
| | | form1.areaId = form1.areaId.filter(v=>v.some((vv) => roots.includes(vv))).map(v => { |
| | | let idx = 0; |
| | | for (let i = 0; i < roots.length; i++) { |
| | | if (v.includes(roots[i])) { |
| | | idx = v.indexOf(roots[i]); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return v.slice(idx); |
| | | }); |
| | | console.log('form1.areaId', form1.areaId, '============='); |
| | | |
| | | } |
| | | |
| | | function handleChange(value) { |
| | | let oldV = value.slice(0, value.length - 1); |
| | | let newV = value[value.length - 1]; |
| | | console.log('value', value, '=============', oldV, newV); |
| | | |
| | | // 检查新选中的项是否与已选中的项有包含关系 |
| | | const hasInclusion = checkInclusion(newV, oldV); |
| | | if (hasInclusion) { |
| | | // 弹出对话框询问用户是否取消之前的项 |
| | | $message.error('取消之前的项(新选中的项与已选中的项存在包含关系)'); |
| | | form1.areaId = value.slice(0, value.length - 1); |
| | | // $confirm('取消之前的项(新选中的项与已选中的项存在包含关系)', () => { |
| | | // form1.areaId = value; |
| | | // }); |
| | | } |
| | | }; |
| | | |
| | | function checkInclusion(newValue, oldValue) { |
| | | // 遍历新选中的项 |
| | | for (let j = 0; j < oldValue.length; j++) { |
| | | const oldItem = oldValue[j]; |
| | | if (isIncluded(newValue, oldItem) || isIncluded(oldItem, newValue)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | function isIncluded(item1, item2) { |
| | | // 新元素是一个选项 取数组的最后一个元素 |
| | | const id = item1[item1.length - 1]; |
| | | return item2.includes(id); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | let info = props.info.value; |
| | | console.log('info', info, '===0000', props, '============='); |
| | | |
| | | if (!props.isEdit) { |
| | | form1.parentId = info.id; |
| | | form1.parentName = info.areaName; |
| | | } else { |
| | | let path = info.areaPath.split("_"); |
| | | |
| | | let pName = path.length > 1 ? path[path.length - 2] : '--'; |
| | | form1.parentId = info.parentId; |
| | | form1.areaName = info.areaName; |
| | | form1.areaId = info.id; |
| | | form1.parentName = pName; |
| | | form1.chargers = info.areaUsers.map(v => v.uid); |
| | | form1.areaDescript = info.areaDescript; |
| | | } |
| | | // getAreaTree(); |
| | | getAllUser(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class=""> |
| | | <el-form ref="formRef" :model="form1" label-width="100px" :rules="rules"> |
| | | <el-form-item label="上级区域"> |
| | | <el-input v-model="form1.parentName" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="区域名称" prop="areaName"> |
| | | <el-input v-model="form1.areaName"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="区域负责人" prop="chargers"> |
| | | <el-select v-model="form1.chargers" multiple clearable> |
| | | <el-option v-for="(item, idx) in userList" :disabled="item.uname == uname" :key="'key_' + idx" :label="item.uname" :value="item.uid" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="区域描述" prop="areaDescript"> |
| | | <el-input v-model="form1.areaDescript" :rows="2" type="textarea"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button v-if="isEdit" type="primary" @click="update">修改</el-button> |
| | | <el-button v-else type="primary" @click="onSubmit">新增</el-button> |
| | | <el-button @click="close">取消</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | <script setup name="RegionManage"> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { getAreaTreeApi } from "@/api/area"; |
| | | import { formatAreaTree } from "@/utils/tree"; |
| | | import { Search, Plus } from "@element-plus/icons-vue"; |
| | | import { delArea } from "@/api/area"; |
| | | import addEdit from "./addEdit.vue"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | const tableData = ref([]); |
| | | const tableRef = ref(); |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | |
| | | export default defineComponent({ |
| | | name: 'RegionManage' |
| | | }); |
| | | onMounted(() => { |
| | | getAreaTree(); |
| | | }); |
| | | |
| | | const dialogTitle = ref('添加区域'); |
| | | const addEditVisible = ref(false); |
| | | const areaInfo = reactive({}); |
| | | const isEdit = ref(false); |
| | | |
| | | function onOk () { |
| | | addEditVisible.value = false; |
| | | getAreaTree(); |
| | | } |
| | | |
| | | function onCanel () { |
| | | addEditVisible.value = false; |
| | | } |
| | | |
| | | // 递归函数,用于展开或折叠所有行及其子行 |
| | | const toggleRowsExpansion = (rows, expand, ref) => { |
| | | rows.forEach((row) => { |
| | | ref.toggleRowExpansion(row, expand); |
| | | if (row.children && row.children.length) { |
| | | // 如果当前行有子行,则递归调用 |
| | | toggleRowsExpansion(row.children, expand, ref); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const expandAll = (expand) => { |
| | | toggleRowsExpansion(tableData.value, expand, tableRef.value); |
| | | }; |
| | | |
| | | async function getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let _data = []; |
| | | if (res.code === 1 && res.data) { |
| | | _data = res.data2; |
| | | } |
| | | const treeList = []; |
| | | let ids = _data.map((v) => v.id); |
| | | for (let i = 0; i < _data.length; i++) { |
| | | formatAreaTree(_data[i], ids, treeList); |
| | | } |
| | | // console.log(_data, 'data'); |
| | | console.log(treeList, "treeList"); |
| | | tableData.value = treeList; |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | // 添加 |
| | | function add(scope) { |
| | | dialogTitle.value = '添加区域'; |
| | | areaInfo.value = scope.row.data; |
| | | isEdit.value = false; |
| | | addEditVisible.value = true; |
| | | |
| | | // addArea().then((res) => { |
| | | // let { code, data } = res.data; |
| | | // if (code && data) { |
| | | // console.log(data); |
| | | // } |
| | | // }) |
| | | // .catch((err) => { |
| | | // console.log(err); |
| | | // }); |
| | | |
| | | } |
| | | |
| | | function edit(scope) { |
| | | dialogTitle.value = '编辑区域'; |
| | | areaInfo.value = scope.row.data; |
| | | isEdit.value = true; |
| | | addEditVisible.value = true; |
| | | } |
| | | |
| | | function del(scope) { |
| | | $confirm('删除该区域', () =>{ |
| | | let loading = $loading(); |
| | | delArea(scope.row.id).then((res) => { |
| | | let { code, data, msg } = res; |
| | | if (code && data) { |
| | | $message({ |
| | | type: 'success', |
| | | message: '删除成功!' |
| | | }); |
| | | getAreaTree(); |
| | | } else { |
| | | $message.error(msg); |
| | | } |
| | | loading.close(); |
| | | }); |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div>区域管理</div> |
| | | <div class="page-wrapper"> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <!-- <el-button type="primary" size="small" :icon="Plus" @click="add" |
| | | >添加</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | :icon="Plus" |
| | | @click="test" |
| | | >修改</el-button |
| | | > |
| | | <el-button type="danger" size="small" icon="del" @click="test" |
| | | >删除</el-button |
| | | > --> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | :icon="Plus" |
| | | @click="expandAll(true)" |
| | | >全部展开</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | :icon="Search" |
| | | @click="expandAll(false)" |
| | | >全部折叠</el-button |
| | | > |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table |
| | | stripe |
| | | ref="tableRef" |
| | | :data="tableData" |
| | | :tree-props="{ children: 'children', checkStrictly: true }" |
| | | row-key="id" |
| | | default-expand-all |
| | | > |
| | | <!-- <el-table-column type="selection" width="55" /> --> |
| | | <el-table-column prop="label" label="区域名称" /> |
| | | <el-table-column prop="charger" label="区域负责人" /> |
| | | <el-table-column prop="areaDescript" label="区域描述" /> |
| | | <el-table-column align="center" fixed="right" label="操作" width="240"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" :disabled="scope.row.data.areaLevel >= 4" @click="add(scope)">添加</el-button> |
| | | <el-button type="primary" size="small" @click="edit(scope)">编辑</el-button> |
| | | <el-button type="danger" size="small" @click="del(scope)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 弹窗 --> |
| | | <el-dialog :title="dialogTitle" v-model="addEditVisible" top="0" :close-on-click-modal="false" class="dialog-center" |
| | | width="700px" center> |
| | | <add-edit v-if="addEditVisible" @success="onOk" :info="areaInfo" :is-edit="isEdit" @cancel="onCanel"></add-edit> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | .page-content-table { |
| | | border-top: 1px solid var(--border-light-color); |
| | | box-sizing: border-box; |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | .filter-label { |
| | | display: inline-block; |
| | | } |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { addUser, updateUser } from "@/api/user"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import { getAreaTreeApi } from "@/api/area"; |
| | | import { formatAreaTree } from "@/utils/tree"; |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object, |
| | | }, |
| | | }); |
| | | const props1 = { value: 'id', checkStrictly: true, multiple: true }; |
| | | const formRef = ref(); |
| | | const areaList = ref([]); |
| | | const form1 = reactive({ |
| | | uname: "", |
| | | uid: "", |
| | | urole: "", |
| | | realName: "", |
| | | phoneNumber: "", |
| | | address: "", |
| | | areaId: 0, |
| | | permission: false, |
| | | }); |
| | | |
| | | const otherIdList = ref([]); |
| | | |
| | | const rules = { |
| | | uname: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | realName: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | urole: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["blur", "change"], |
| | | }, |
| | | ], |
| | | areaId: [ |
| | | { |
| | | required: true, |
| | | message: "不能为空", |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value.length) { |
| | | callback(new Error("请选择区域")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const isEdit = computed(() => !!props.info?.uid); |
| | | const $emit = defineEmits(["cancel", "success"]); |
| | | function close() { |
| | | $emit("cancel"); |
| | | } |
| | | async function update() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | uname: form1.uname.trim(), |
| | | uid: form1.uid || undefined, |
| | | realName: form1.realName.trim(), |
| | | phoneNumber: form1.phoneNumber?.trim(), |
| | | address: form1.address?.trim(), |
| | | idList: form1.areaId.map(v => v[v.length - 1]).concat(otherIdList.value), |
| | | urole: form1.urole, |
| | | }; |
| | | |
| | | // 编辑用户时, 区域中不在管理员管理内的区域要挑出来 最后更新时再追加进去 |
| | | console.log("params update", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | updateUser(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | async function onSubmit() { |
| | | let valid = await formRef.value.validate(() => { }); |
| | | // console.log('valid', valid, '============='); |
| | | |
| | | if (!valid) { |
| | | $message.error("表单验证失败"); |
| | | return false; |
| | | } |
| | | let params = { |
| | | uname: form1.uname.trim(), |
| | | uid: form1.uid || undefined, |
| | | realName: form1.realName.trim(), |
| | | phoneNumber: form1.phoneNumber?.trim(), |
| | | address: form1.address?.trim(), |
| | | idList: form1.areaId.map(v => v[v.length - 1]), |
| | | urole: form1.urole, |
| | | }; |
| | | console.log("params", params, "============="); |
| | | |
| | | let loading = $loading(); |
| | | addUser(params) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | if (code && data) { |
| | | $emit("success"); |
| | | $message.success("操作成功"); |
| | | } else { |
| | | $message.error("操作失败"); |
| | | } |
| | | loading.close(); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | |
| | | async function getAreaTree() { |
| | | try { |
| | | const res = await getAreaTreeApi(); |
| | | let _data = []; |
| | | if (res.code === 1 && res.data) { |
| | | _data = res.data2; |
| | | } |
| | | const treeList = []; |
| | | let ids = _data.map((v) => v.id); |
| | | for (let i = 0; i < _data.length; i++) { |
| | | formatAreaTree(_data[i], ids, treeList); |
| | | } |
| | | // console.log(_data, 'data'); |
| | | console.log(treeList, 'treeList'); |
| | | areaList.value = treeList; |
| | | formatAreaSelected(treeList); |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | } |
| | | |
| | | // 区域树 根节点 |
| | | // const areaRoots = computed(() => { |
| | | // if (!areaList.value) { |
| | | // return []; |
| | | // } else { |
| | | // return areaList.value.map(v => v.id); |
| | | // } |
| | | // }); |
| | | |
| | | function formatAreaSelected(treeList) { |
| | | let roots = treeList.map(v => v.id); |
| | | let otherAreas = form1.areaId.filter(v=>!v.some((vv) => roots.includes(vv))); |
| | | let otherIds = otherAreas.map(v => v[v.length - 1]); |
| | | |
| | | otherIdList.value = otherIds; |
| | | |
| | | form1.areaId = form1.areaId.filter(v=>v.some((vv) => roots.includes(vv))).map(v => { |
| | | let idx = 0; |
| | | for (let i = 0; i < roots.length; i++) { |
| | | if (v.includes(roots[i])) { |
| | | idx = v.indexOf(roots[i]); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return v.slice(idx); |
| | | }); |
| | | console.log('form1.areaId', form1.areaId, '============='); |
| | | |
| | | } |
| | | |
| | | function handleChange(value) { |
| | | let oldV = value.slice(0, value.length - 1); |
| | | let newV = value[value.length - 1]; |
| | | console.log('value', value, '=============', oldV, newV); |
| | | |
| | | // 检查新选中的项是否与已选中的项有包含关系 |
| | | const hasInclusion = checkInclusion(newV, oldV); |
| | | if (hasInclusion) { |
| | | // 弹出对话框询问用户是否取消之前的项 |
| | | $message.error('取消之前的项(新选中的项与已选中的项存在包含关系)'); |
| | | form1.areaId = value.slice(0, value.length - 1); |
| | | // $confirm('取消之前的项(新选中的项与已选中的项存在包含关系)', () => { |
| | | // form1.areaId = value; |
| | | // }); |
| | | } |
| | | }; |
| | | |
| | | function checkInclusion(newValue, oldValue) { |
| | | // 遍历新选中的项 |
| | | for (let j = 0; j < oldValue.length; j++) { |
| | | const oldItem = oldValue[j]; |
| | | if (isIncluded(newValue, oldItem) || isIncluded(oldItem, newValue)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | function isIncluded(item1, item2) { |
| | | // 新元素是一个选项 取数组的最后一个元素 |
| | | const id = item1[item1.length - 1]; |
| | | return item2.includes(id); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | let info = props.info; |
| | | if (info) { |
| | | form1.uname = info.uname; |
| | | form1.uid = info.uid; |
| | | form1.realName = info.realName; |
| | | form1.phoneNumber = info.phoneNumber; |
| | | form1.address = info.address; |
| | | form1.areaId = info.areaId; |
| | | form1.urole = info.urole; |
| | | } |
| | | getAreaTree(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class=""> |
| | | <el-form ref="formRef" :model="form1" label-width="80px" :rules="rules"> |
| | | <el-form-item label="用户名" prop="uname"> |
| | | <el-input v-model="form1.uname" :disabled="isEdit"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="真实姓名" prop="realName"> |
| | | <el-input v-model="form1.realName"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="手机号" prop="phoneNumber"> |
| | | <el-input v-model="form1.phoneNumber"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="所属区域" prop="areaId"> |
| | | <el-cascader class="select" filterable clearable v-model="form1.areaId" :props="props1" @change="handleChange" |
| | | :options="areaList"><template #default="{ node, data }"> |
| | | <span>{{ data.label }}</span> |
| | | <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> |
| | | </template></el-cascader> |
| | | </el-form-item> |
| | | <el-form-item label="所属角色" prop="urole"> |
| | | <el-select v-model="form1.urole"> |
| | | <el-option label="普通用户" :value="0" /> |
| | | <el-option label="区域管理员" :value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="通讯地址" prop="address"> |
| | | <el-input v-model="form1.address"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button v-if="isEdit" type="primary" @click="update">修改</el-button> |
| | | <el-button v-else type="primary" @click="onSubmit">新增</el-button> |
| | | <el-button @click="close">取消</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | <script setup name="UserManage"> |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import { storeToRefs } from "pinia"; |
| | | import { Search, Plus } from "@element-plus/icons-vue"; |
| | | import HdwCard from "@/components/HdwCard/index.vue"; |
| | | import addEdit from "./addEdit.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | import store from "@/store"; |
| | | import { |
| | | getAllUser, |
| | | deleteUser, |
| | | dropRole, |
| | | improveRole, |
| | | resetSnId, |
| | | } from "@/api/user"; |
| | | |
| | | export default defineComponent({ |
| | | name: 'UserManage' |
| | | }); |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | // const $message = ElMessage; |
| | | const headers = [ |
| | | { |
| | | prop: "uname", |
| | | label: "姓名", |
| | | width: "", |
| | | }, |
| | | { |
| | | prop: "createTime", |
| | | label: "创建时间", |
| | | width: "", |
| | | }, |
| | | // { |
| | | // prop: "canDownload", |
| | | // label: "控制权限", |
| | | // width: "", |
| | | // }, |
| | | ]; |
| | | const background = ref(true); |
| | | const disabled = ref(false); |
| | | const pageCurr = ref(1); |
| | | const pageSize = ref(10); |
| | | const total = ref(0); |
| | | const addEditVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const currentAreaId = ref(); |
| | | const currentAreaIds = ref([]); |
| | | const datas = reactive({ |
| | | tableData: [], |
| | | userInfo: {}, |
| | | }); |
| | | |
| | | const uname = computed(() => store.user().name); |
| | | // const tableData = reactive([]); |
| | | // const userInfo = reactive({}); |
| | | |
| | | // const userStore = useUserStore(); |
| | | // const { uid, uname } = storeToRefs(userStore); |
| | | |
| | | function getList() { |
| | | let loading = $loading(); |
| | | getAllUser(currentAreaId.value, pageCurr.value, pageSize.value) |
| | | .then((res) => { |
| | | let { code, data, data2 } = res; |
| | | let list = []; |
| | | let _total = 0; |
| | | if (code && data) { |
| | | // console.log(data); |
| | | list = data2.list; |
| | | _total = data2.total; |
| | | } |
| | | loading.close(); |
| | | // tableData.length = 0; |
| | | // tableData.push(...list); |
| | | datas.tableData = list; |
| | | total.value = _total; |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | |
| | | // 展示数据数量 |
| | | function handleSizeChange(val) { |
| | | pageSize.value = val; |
| | | getList(); |
| | | } |
| | | // 翻页 |
| | | function handleCurrentChange(val) { |
| | | pageCurr.value = val; |
| | | getList(); |
| | | } |
| | | function addUser() { |
| | | dialogTitle.value = "添加用户"; |
| | | datas.userInfo = { areaId: currentAreaIds.value }; |
| | | addEditVisible.value = true; |
| | | } |
| | | function edit(record) { |
| | | dialogTitle.value = "编辑用户"; |
| | | addEditVisible.value = true; |
| | | console.log(record); |
| | | let ids = record.ainfList.map(v => { |
| | | let res = v.idPath.split("_").map((vv) => vv * 1); |
| | | res.push(v.id); |
| | | return res |
| | | }); |
| | | // if (record.ainfList.idPath) { |
| | | // ids = record.ainfList.idPath.split("_").map((v) => v * 1); |
| | | // } |
| | | // ids.push(record.areaId); |
| | | console.log('ids', ids, '============='); |
| | | |
| | | datas.userInfo = { ...record, areaId: ids }; |
| | | } |
| | | function confirmRemove(record) { |
| | | $confirm("删除该用户", () => { |
| | | remove(record.uname); |
| | | }); |
| | | } |
| | | function remove(uname) { |
| | | let loading = $loading(); |
| | | deleteUser(uname) |
| | | .then((res) => { |
| | | let { code, data } = res; |
| | | loading.close(); |
| | | if (code && data) { |
| | | $message.success("操作成功"); |
| | | handleCurrentChange(1); |
| | | } else { |
| | | $message.success("操作失败"); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | loading.close(); |
| | | console.log(err); |
| | | }); |
| | | } |
| | | function onOk() { |
| | | addEditVisible.value = false; |
| | | handleCurrentChange(1); |
| | | } |
| | | function onCanel() { |
| | | addEditVisible.value = false; |
| | | } |
| | | function improveRolefn(record) { |
| | | let loading = $loading(); |
| | | improveRole(record.uid) |
| | | .then((res) => { |
| | | let { code, data, msg } = res; |
| | | loading.close(); |
| | | if (code && data) { |
| | | $message.success(msg); |
| | | getList(); |
| | | } else { |
| | | $message.error(msg); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | loading.close(); |
| | | }); |
| | | } |
| | | function dropRolefn(record) { |
| | | let loading = $loading(); |
| | | dropRole(record.uid) |
| | | .then((res) => { |
| | | let { code, data, msg } = res; |
| | | loading.close(); |
| | | if (code && data) { |
| | | $message.success(msg); |
| | | getList(); |
| | | } else { |
| | | $message.error(msg); |
| | | } |
| | | }) |
| | | .catch((err) => { |
| | | loading.close(); |
| | | console.log(err); |
| | | }); |
| | | } |
| | | function resetSnIdfn(record) { |
| | | $confirm("重置该用户密码", () => { |
| | | let loading = $loading(); |
| | | resetSnId(record.uid).then((res) => { |
| | | let { code, data, msg } = res; |
| | | if (code && data) { |
| | | $message.success(msg); |
| | | } else { |
| | | $message.error(msg); |
| | | } |
| | | loading.close(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function itemClickHandler(item) { |
| | | console.log(item, "====item", item.data); |
| | | // areaId lockName lockState lockType pageNum pageSize |
| | | currentAreaId.value = item.data.id; |
| | | currentAreaIds.value = item.data.idPath |
| | | ? item.data.idPath.split("_").map((v) => v * 1) |
| | | : []; |
| | | currentAreaIds.value.push(item.data.id); |
| | | |
| | | getList(); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div>用户管理</div> |
| | | <div class="page-wrapper"> |
| | | <div class="page-header"> |
| | | <div class="hdw-card-container"> |
| | | <hdw-card title="区域列表" is-full> |
| | | <hdw-tree @item-click="itemClickHandler"></hdw-tree> |
| | | </hdw-card> |
| | | </div> |
| | | </div> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-tools"> |
| | | <el-button type="primary" round size="small" @click="addUser" :icon="Plus">添加</el-button> |
| | | <el-button type="primary" round size="small" @click="getList" :icon="Search">查询</el-button> |
| | | </div> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table class="yc-table" stripe height="100%" size="small" :data="datas.tableData" style="width: 100%"> |
| | | <el-table-column type="index" label="序号" width="80"></el-table-column> |
| | | <el-table-column v-for="header in headers" :key="header.prop" :prop="header.prop" :label="header.label" |
| | | :min-width="header.width" align="center"></el-table-column> |
| | | <el-table-column label="操作" width="360" align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" :disabled="scope.row.uname == uname" |
| | | @click="edit(scope.row)">编辑</el-button> |
| | | <el-button type="primary" size="small" :disabled="scope.row.uname == uname" |
| | | @click="resetSnIdfn(scope.row)">重置密码</el-button> |
| | | <el-button type="danger" size="small" :disabled="scope.row.uname == uname" |
| | | @click="confirmRemove(scope.row)">删除</el-button> |
| | | <!-- <el-button |
| | | type="success" |
| | | v-if="scope.row.uid > 1000" |
| | | size="small" |
| | | @click="improveRolefn(scope.row)" |
| | | >加入管理员组</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | v-else |
| | | :disabled="scope.row.uid == uid" |
| | | size="small" |
| | | @click="dropRolefn(scope.row)" |
| | | >移出管理员组</el-button |
| | | > --> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | <div class="el-page-container"> |
| | | <el-pagination v-model:current-page="pageCurr" v-model:page-size="pageSize" |
| | | :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" :disabled="disabled" |
| | | :background="background" layout="total, sizes, prev, pager, next, jumper" :total="total" |
| | | @size-change="handleSizeChange" @current-change="handleCurrentChange" /> |
| | | </div> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 弹窗 --> |
| | | <el-dialog :title="dialogTitle" v-model="addEditVisible" top="0" :close-on-click-modal="false" class="dialog-center" |
| | | width="700px" center> |
| | | <add-edit v-if="addEditVisible" @success="onOk" :info="datas.userInfo" @cancel="onCanel"></add-edit> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | border-top: 1px solid var(--border-light-color); |
| | | box-sizing: border-box; |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <script setup name="userFaceManager"> |
| | | // import userInfo from '@/assets/js/userMager/userInfo'; |
| | | // import faceManager from '../login/components/face/faceManager'; |
| | | // import faceManager from '../../assets/js/apis/faceManager/faceManager.js' |
| | | import { faceInfo, faceMagerAdd, faceMagerChange, faceMagerDelete } from '@/api/face'; |
| | | import { ref, onMounted } from 'vue'; |
| | | import useElement from "@/hooks/useElement.js"; |
| | | |
| | | const { $loading, $message, $confirm } = useElement(); |
| | | |
| | | const faceVisible = ref(false); |
| | | const dataList = ref([]); |
| | | const imageUrl = ref(''); |
| | | const updateFace = ref({ |
| | | id: 0, |
| | | uid: '', |
| | | uname: '', |
| | | msg: '只能上传jpg/png文件,且不超过2M' |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | queryList(); |
| | | }); |
| | | |
| | | // 查询用户列表 |
| | | function queryList() { |
| | | let obj = null; |
| | | faceInfo(obj, "GET").then(result => { |
| | | console.log(result) |
| | | let params = []; |
| | | if (result.code == 1) { |
| | | params.push(result.data); |
| | | } |
| | | console.log('params', params, '============='); |
| | | |
| | | dataList.value = params; |
| | | }).catch(err => { |
| | | |
| | | }) |
| | | } |
| | | // 添加/更新 |
| | | function handleClick(row) { |
| | | listObj(row); |
| | | faceVisible.value = true; |
| | | } |
| | | // 删除 |
| | | function deleteData(row) { |
| | | listObj(row); |
| | | if (!row.face) { |
| | | $message.success('用户未上传人脸!'); |
| | | return false; |
| | | } |
| | | let obj = { |
| | | uId: updateFace.uid, |
| | | uName: updateFace.uname, |
| | | faceId: updateFace.id |
| | | } |
| | | $confirm('删除人脸?', { icon: 3 }, index => { |
| | | faceMagerDelete(obj).then(res => { |
| | | let result = res.data; |
| | | if (result.code == 1) { |
| | | $message.success('删除人脸成功!'); |
| | | queryList(); |
| | | } else { |
| | | $message.error('删除人脸失败!'); |
| | | } |
| | | }).catch(err => { |
| | | $message.error('删除人脸失败!'); |
| | | }) |
| | | // 关闭弹出框 |
| | | $layer.close(index); |
| | | }) |
| | | } |
| | | // 处理参数 |
| | | function listObj(row) { |
| | | updateFace.uid = row.uid; |
| | | updateFace.uname = row.uname; |
| | | updateFace.id = row.face ? row.face.id : null; |
| | | } |
| | | // 上传图片前 |
| | | function uploadImg(file) { |
| | | const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'; |
| | | const isLt2M = file.size / 1024 / 1024 < 2; |
| | | if (!isJPG) { |
| | | $message.error('上传头像图片只能是 JPG或PNG 格式!'); |
| | | return false; |
| | | } |
| | | if (!isLt2M) { |
| | | $message.error('上传头像图片大小不能超过 2MB!'); |
| | | return false; |
| | | } |
| | | // 图片转base64 |
| | | getBase64(file).then(res => { |
| | | imageUrl.value = res; |
| | | // //上传图片 |
| | | let uname = updateFace.uname; |
| | | let jsontemp = { |
| | | fileData: res, |
| | | uName: uname |
| | | } |
| | | // let imgData ='"' + res + '"'; |
| | | if (!updateFace.id) {//新增 |
| | | jsontemp.uId = updateFace.uid.toString(); |
| | | faceMagerAdd(jsontemp, "POST").then(res => { |
| | | let result = res.data; |
| | | if (result.code == 1) { |
| | | //隐藏弹窗 |
| | | updateFace.show = false; |
| | | if (result.data === false) { |
| | | $message.error(result.msg); |
| | | } else { |
| | | // let text = updateFace.faceId ==0?'新增人脸成功!':'更新人脸成功!'; |
| | | $message.success("新增人脸成功!"); |
| | | queryList(); |
| | | } |
| | | } else { |
| | | $message.error('上传失败,请重新上传!'); |
| | | } |
| | | }).catch(err => { |
| | | $message.error('上传失败,请重新上传!'); |
| | | }) |
| | | } else { |
| | | jsontemp.fileData = '"' + jsontemp.fileData + '"'; |
| | | faceMagerChange(jsontemp).then(res => { |
| | | let result = res.data; |
| | | if (result.code == 1) { |
| | | //隐藏弹窗 |
| | | updateFace.show = false; |
| | | // let text = updateFace.faceId ==0?'新增人脸成功!':'更新人脸成功!'; |
| | | if (result.data === false) { |
| | | $message.error(result.msg); |
| | | } else { |
| | | $message.success("更新人脸成功!"); |
| | | queryList(); |
| | | } |
| | | } else { |
| | | $message.error('上传失败,请重新上传!'); |
| | | } |
| | | }).catch(err => { |
| | | $message.error('上传失败,请重新上传!'); |
| | | }) |
| | | } |
| | | |
| | | }) |
| | | return false; |
| | | } |
| | | // 图片转base64 |
| | | function getBase64(file) { |
| | | return new Promise(function (resolve, reject) { |
| | | let reader = new FileReader(); |
| | | let imgResult = ""; |
| | | reader.readAsDataURL(file); |
| | | reader.onload = function () { |
| | | imgResult = reader.result; |
| | | }; |
| | | reader.onerror = function (error) { |
| | | reject(error); |
| | | }; |
| | | reader.onloadend = function () { |
| | | resolve(imgResult); |
| | | }; |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="page-wrapper"> |
| | | <div class="page-header"> |
| | | </div> |
| | | <div class="page-content"> |
| | | <hdw-card is-full> |
| | | <div class="page-content-wrapper"> |
| | | <div class="page-content-table"> |
| | | <div class="pos-rel"> |
| | | <div class="pos-abs"> |
| | | <el-table class="yc-table" stripe height="100%" size="small" :data="dataList" style="width: 100%"> |
| | | <el-table-column type="index" label="编号" min-width="90" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="uname" label="用户名称" min-width="160" align="center"></el-table-column> |
| | | <el-table-column label="状态" min-width="160" align="center"> |
| | | <template #default="scope"> |
| | | <span v-if="!scope.row.face">未上传人脸</span> |
| | | <span v-else>已上传人脸</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="250" align="center"> |
| | | <template #default="scope"> |
| | | <el-button @click="handleClick(scope.row)" type="primary" size="small">{{ |
| | | !scope.row.face?'添加人脸':'更新人脸' }}</el-button> |
| | | <el-button type="danger" size="small" @click="deleteData(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="page-content-page"> |
| | | <div class="page-tool"></div> |
| | | </div> |
| | | </div> |
| | | </hdw-card> |
| | | </div> |
| | | <div class="page-footer"></div> |
| | | <!-- 人脸上传 --> |
| | | <el-dialog title="人脸上传" v-model="faceVisible" top="0" :close-on-click-modal="false" class="dialog-center" |
| | | width="700px" center> |
| | | <el-upload :before-upload="uploadImg" class="upload-demo" action="#" drag multiple> |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip">{{ updateFace.msg }} |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrapper { |
| | | display: flex; |
| | | flex-direction: row; |
| | | padding: 8px; |
| | | height: 100%; |
| | | |
| | | .page-content { |
| | | flex: 1; |
| | | } |
| | | } |
| | | |
| | | .page-content-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | |
| | | .page-content-tools { |
| | | padding-bottom: 8px; |
| | | } |
| | | |
| | | .page-content-table { |
| | | border-top: 1px solid var(--border-light-color); |
| | | box-sizing: border-box; |
| | | flex: 1; |
| | | margin-left: -8px; |
| | | margin-right: -8px; |
| | | } |
| | | |
| | | .page-content-page { |
| | | padding: 8px 8px 0 8px; |
| | | text-align: center; |
| | | |
| | | .el-page-container { |
| | | display: inline-block; |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .page-tool { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .hdw-card-container { |
| | | width: 240px; |
| | | padding-right: 8px; |
| | | height: 100%; |
| | | } |
| | | |
| | | .pos-rel { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .pos-abs { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .tools-filter { |
| | | display: inline-block; |
| | | font-size: 14px; |
| | | |
| | | .tools-filter-item { |
| | | display: inline-block; |
| | | margin-right: 8px; |
| | | |
| | | .filter-label { |
| | | display: inline-block; |
| | | } |
| | | |
| | | .filter-content { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .face_manager { |
| | | .upload-demo { |
| | | text-align: center; |
| | | padding: 10px 0; |
| | | |
| | | .el-upload { |
| | | width: 100%; |
| | | |
| | | .el-upload-dragger { |
| | | width: 100%; |
| | | border: none; |
| | | } |
| | | } |
| | | |
| | | .el-upload__tip { |
| | | color: red; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | |
| | | import { defineConfig, loadEnv } from 'vite'; |
| | | import vue from '@vitejs/plugin-vue'; |
| | | |
| | | import VueSetupExtend from 'vite-plugin-vue-setup-extend'; |
| | | import Inspect from 'vite-plugin-inspect'; |
| | | |
| | | // element plus 样式自动按需导入 |
| | |
| | | const prodMock = true; |
| | | |
| | | return { |
| | | base: '/', // 注意,必须以"/"结尾,BASE_URL配置 |
| | | base: './', // 注意,必须以"/"结尾,BASE_URL配置 |
| | | build: { |
| | | outDir: '../hm-lock-sys/public' |
| | | }, |
| | |
| | | plugins: [ |
| | | vue(), |
| | | Inspect(), |
| | | VueSetupExtend(), |
| | | AutoImport({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | |
| | | }) |
| | | ], |
| | | server: { |
| | | // https: true, |
| | | // key: './key.pem', |
| | | // cert: './cert.pem', |
| | | host: 'localhost', |
| | | port: 8001 |
| | | } |
New file |
| | |
| | | // vite.config.ts |
| | | import { fileURLToPath, URL } from "node:url"; |
| | | import path from "node:path"; |
| | | import { defineConfig, loadEnv } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite@5.4.11_@types+node@20.17.10_sass@1.83.0/node_modules/vite/dist/node/index.js"; |
| | | import vue from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/@vitejs+plugin-vue@5.2.1_vite@5.4.11_vue@3.5.13/node_modules/@vitejs/plugin-vue/dist/index.mjs"; |
| | | import VueSetupExtend from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-vue-setup-extend@0.4.0_vite@5.4.11/node_modules/vite-plugin-vue-setup-extend/dist/index.mjs"; |
| | | import Inspect from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-inspect@0.8.9_vite@5.4.11/node_modules/vite-plugin-inspect/dist/index.mjs"; |
| | | import AutoImport from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-auto-import@0.17.8/node_modules/unplugin-auto-import/dist/vite.js"; |
| | | import Components from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/vite.js"; |
| | | import { ElementPlusResolver } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/resolvers.js"; |
| | | import svgSprites from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/rollup-plugin-svg-sprites@1.2.5_@vue+compiler-sfc@3.5.13/node_modules/rollup-plugin-svg-sprites/lib/index.js"; |
| | | import { viteMockServe } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-mock@2.9.8_mockjs@1.1.0_vite@5.4.11/node_modules/vite-plugin-mock/dist/index.js"; |
| | | var __vite_injected_original_import_meta_url = "file:///D:/GitWorkSpace/hm-lock/vite.config.ts"; |
| | | var vite_config_default = defineConfig(({ command, mode }) => { |
| | | console.log("vite.config defineConfig", command, mode); |
| | | const env = loadEnv(mode, process.cwd(), ""); |
| | | console.log("vite.config env.NODE_ENV=", env.NODE_ENV); |
| | | const prodMock = true; |
| | | return { |
| | | base: "./", |
| | | // 注意,必须以"/"结尾,BASE_URL配置 |
| | | build: { |
| | | outDir: "../hm-lock-sys/public" |
| | | }, |
| | | define: { |
| | | "process.env": env |
| | | }, |
| | | resolve: { |
| | | alias: { |
| | | "@": fileURLToPath(new URL("./src", __vite_injected_original_import_meta_url)) |
| | | }, |
| | | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] |
| | | }, |
| | | plugins: [ |
| | | vue(), |
| | | Inspect(), |
| | | VueSetupExtend(), |
| | | AutoImport({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | Components({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | svgSprites({ |
| | | vueComponent: true, |
| | | exclude: ["node_modules/**"], |
| | | symbolId(filePath) { |
| | | const filename = path.basename(filePath); |
| | | return "icon-" + filename.substring(0, filename.lastIndexOf(".")); |
| | | } |
| | | }), |
| | | // https://openbase.com/js/vite-plugin-mock |
| | | viteMockServe({ |
| | | ignore: /^_/, |
| | | mockPath: "./mock/", |
| | | supportTs: true, |
| | | watchFiles: true, |
| | | localEnabled: command === "serve", |
| | | prodEnabled: command !== "serve" && prodMock, |
| | | // configPath: './mock/index.js', |
| | | logger: false, |
| | | injectCode: `import { setupProdMockServer } from '../mock/_createProductionServer.js'; |
| | | setupProdMockServer();` |
| | | }) |
| | | ], |
| | | server: { |
| | | host: "localhost", |
| | | port: 8001 |
| | | } |
| | | }; |
| | | }); |
| | | export { |
| | | vite_config_default as default |
| | | }; |
| | | //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxHaXRXb3JrU3BhY2VcXFxcaG0tbG9ja1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRDpcXFxcR2l0V29ya1NwYWNlXFxcXGhtLWxvY2tcXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Q6L0dpdFdvcmtTcGFjZS9obS1sb2NrL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSAnbm9kZTp1cmwnO1xyXG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xyXG5cclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSc7XHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJztcclxuaW1wb3J0IFZ1ZVNldHVwRXh0ZW5kIGZyb20gJ3ZpdGUtcGx1Z2luLXZ1ZS1zZXR1cC1leHRlbmQnO1xyXG5pbXBvcnQgSW5zcGVjdCBmcm9tICd2aXRlLXBsdWdpbi1pbnNwZWN0JztcclxuXHJcbi8vIGVsZW1lbnQgcGx1cyBcdTY4MzdcdTVGMEZcdTgxRUFcdTUyQThcdTYzMDlcdTk3MDBcdTVCRkNcdTUxNjVcclxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSAndW5wbHVnaW4tYXV0by1pbXBvcnQvdml0ZSc7XHJcbmltcG9ydCBDb21wb25lbnRzIGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3ZpdGUnO1xyXG5pbXBvcnQgeyBFbGVtZW50UGx1c1Jlc29sdmVyIH0gZnJvbSAndW5wbHVnaW4tdnVlLWNvbXBvbmVudHMvcmVzb2x2ZXJzJztcclxuXHJcbmltcG9ydCBzdmdTcHJpdGVzIGZyb20gJ3JvbGx1cC1wbHVnaW4tc3ZnLXNwcml0ZXMnO1xyXG5pbXBvcnQgeyB2aXRlTW9ja1NlcnZlIH0gZnJvbSAndml0ZS1wbHVnaW4tbW9jayc7XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgY29tbWFuZCwgbW9kZSB9KSA9PiB7XHJcbiAgY29uc29sZS5sb2coJ3ZpdGUuY29uZmlnIGRlZmluZUNvbmZpZycsIGNvbW1hbmQsIG1vZGUpO1xyXG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSwgJycpO1xyXG4gIGNvbnNvbGUubG9nKCd2aXRlLmNvbmZpZyBlbnYuTk9ERV9FTlY9JywgZW52Lk5PREVfRU5WKTtcclxuICAvLyBBY2NvcmRpbmcgdG8gdGhlIHByb2plY3QgY29uZmlndXJhdGlvbi4gQ2FuIGJlIGNvbmZpZ3VyZWQgaW4gdGhlIC5lbnYgZmlsZVxyXG4gIGNvbnN0IHByb2RNb2NrID0gdHJ1ZTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGJhc2U6ICcuLycsIC8vIFx1NkNFOFx1NjEwRlx1RkYwQ1x1NUZDNVx1OTg3Qlx1NEVFNVwiL1wiXHU3RUQzXHU1QzNFXHVGRjBDQkFTRV9VUkxcdTkxNERcdTdGNkVcclxuICAgIGJ1aWxkOiB7XHJcbiAgICAgIG91dERpcjogJy4uL2htLWxvY2stc3lzL3B1YmxpYydcclxuICAgIH0sXHJcbiAgICBkZWZpbmU6IHtcclxuICAgICAgJ3Byb2Nlc3MuZW52JzogZW52XHJcbiAgICB9LFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICBhbGlhczoge1xyXG4gICAgICAgICdAJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYycsIGltcG9ydC5tZXRhLnVybCkpXHJcbiAgICAgIH0sXHJcbiAgICAgIGV4dGVuc2lvbnM6IFsnLm1qcycsICcuanMnLCAnLnRzJywgJy5qc3gnLCAnLnRzeCcsICcuanNvbicsICcudnVlJ11cclxuICAgIH0sXHJcbiAgICBwbHVnaW5zOiBbXHJcbiAgICAgIHZ1ZSgpLFxyXG4gICAgICBJbnNwZWN0KCksXHJcbiAgICAgIFZ1ZVNldHVwRXh0ZW5kKCksXHJcbiAgICAgIEF1dG9JbXBvcnQoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIENvbXBvbmVudHMoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIHN2Z1Nwcml0ZXMoe1xyXG4gICAgICAgIHZ1ZUNvbXBvbmVudDogdHJ1ZSxcclxuICAgICAgICBleGNsdWRlOiBbJ25vZGVfbW9kdWxlcy8qKiddLFxyXG4gICAgICAgIHN5bWJvbElkKGZpbGVQYXRoKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgcmV0dXJuICdpY29uLScgKyBmaWxlbmFtZS5zdWJzdHJpbmcoMCwgZmlsZW5hbWUubGFzdEluZGV4T2YoJy4nKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KSxcclxuICAgICAgLy8gaHR0cHM6Ly9vcGVuYmFzZS5jb20vanMvdml0ZS1wbHVnaW4tbW9ja1xyXG4gICAgICB2aXRlTW9ja1NlcnZlKHtcclxuICAgICAgICBpZ25vcmU6IC9eXy8sXHJcbiAgICAgICAgbW9ja1BhdGg6ICcuL21vY2svJyxcclxuICAgICAgICBzdXBwb3J0VHM6IHRydWUsXHJcbiAgICAgICAgd2F0Y2hGaWxlczogdHJ1ZSxcclxuICAgICAgICBsb2NhbEVuYWJsZWQ6IGNvbW1hbmQgPT09ICdzZXJ2ZScsXHJcbiAgICAgICAgcHJvZEVuYWJsZWQ6IGNvbW1hbmQgIT09ICdzZXJ2ZScgJiYgcHJvZE1vY2ssXHJcbiAgICAgICAgLy8gY29uZmlnUGF0aDogJy4vbW9jay9pbmRleC5qcycsXHJcbiAgICAgICAgbG9nZ2VyOiBmYWxzZSxcclxuICAgICAgICBpbmplY3RDb2RlOiBgaW1wb3J0IHsgc2V0dXBQcm9kTW9ja1NlcnZlciB9IGZyb20gJy4uL21vY2svX2NyZWF0ZVByb2R1Y3Rpb25TZXJ2ZXIuanMnO1xyXG4gICAgICBzZXR1cFByb2RNb2NrU2VydmVyKCk7YFxyXG4gICAgICB9KVxyXG4gICAgXSxcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICBob3N0OiAnbG9jYWxob3N0JyxcclxuICAgICAgcG9ydDogODAwMVxyXG4gICAgfVxyXG4gIH07XHJcbn0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTZQLFNBQVMsZUFBZSxXQUFXO0FBQ2hTLE9BQU8sVUFBVTtBQUVqQixTQUFTLGNBQWMsZUFBZTtBQUN0QyxPQUFPLFNBQVM7QUFDaEIsT0FBTyxvQkFBb0I7QUFDM0IsT0FBTyxhQUFhO0FBR3BCLE9BQU8sZ0JBQWdCO0FBQ3ZCLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMsMkJBQTJCO0FBRXBDLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMscUJBQXFCO0FBZDZILElBQU0sMkNBQTJDO0FBaUI1TSxJQUFPLHNCQUFRLGFBQWEsQ0FBQyxFQUFFLFNBQVMsS0FBSyxNQUFNO0FBQ2pELFVBQVEsSUFBSSw0QkFBNEIsU0FBUyxJQUFJO0FBQ3JELFFBQU0sTUFBTSxRQUFRLE1BQU0sUUFBUSxJQUFJLEdBQUcsRUFBRTtBQUMzQyxVQUFRLElBQUksNkJBQTZCLElBQUksUUFBUTtBQUVyRCxRQUFNLFdBQVc7QUFFakIsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBO0FBQUEsSUFDTixPQUFPO0FBQUEsTUFDTCxRQUFRO0FBQUEsSUFDVjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sZUFBZTtBQUFBLElBQ2pCO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPO0FBQUEsUUFDTCxLQUFLLGNBQWMsSUFBSSxJQUFJLFNBQVMsd0NBQWUsQ0FBQztBQUFBLE1BQ3REO0FBQUEsTUFDQSxZQUFZLENBQUMsUUFBUSxPQUFPLE9BQU8sUUFBUSxRQUFRLFNBQVMsTUFBTTtBQUFBLElBQ3BFO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixRQUFRO0FBQUEsTUFDUixlQUFlO0FBQUEsTUFDZixXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxjQUFjO0FBQUEsUUFDZCxTQUFTLENBQUMsaUJBQWlCO0FBQUEsUUFDM0IsU0FBUyxVQUFVO0FBQ2pCLGdCQUFNLFdBQVcsS0FBSyxTQUFTLFFBQVE7QUFDdkMsaUJBQU8sVUFBVSxTQUFTLFVBQVUsR0FBRyxTQUFTLFlBQVksR0FBRyxDQUFDO0FBQUEsUUFDbEU7QUFBQSxNQUNGLENBQUM7QUFBQTtBQUFBLE1BRUQsY0FBYztBQUFBLFFBQ1osUUFBUTtBQUFBLFFBQ1IsVUFBVTtBQUFBLFFBQ1YsV0FBVztBQUFBLFFBQ1gsWUFBWTtBQUFBLFFBQ1osY0FBYyxZQUFZO0FBQUEsUUFDMUIsYUFBYSxZQUFZLFdBQVc7QUFBQTtBQUFBLFFBRXBDLFFBQVE7QUFBQSxRQUNSLFlBQVk7QUFBQTtBQUFBLE1BRWQsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxJQUNSO0FBQUEsRUFDRjtBQUNGLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg== |
New file |
| | |
| | | // vite.config.ts |
| | | import { fileURLToPath, URL } from "node:url"; |
| | | import path from "node:path"; |
| | | import { defineConfig, loadEnv } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite@5.4.11_@types+node@20.17.10_sass@1.83.0/node_modules/vite/dist/node/index.js"; |
| | | import vue from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/@vitejs+plugin-vue@5.2.1_vite@5.4.11_vue@3.5.13/node_modules/@vitejs/plugin-vue/dist/index.mjs"; |
| | | import VueSetupExtend from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-vue-setup-extend@0.4.0_vite@5.4.11/node_modules/vite-plugin-vue-setup-extend/dist/index.mjs"; |
| | | import Inspect from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-inspect@0.8.9_vite@5.4.11/node_modules/vite-plugin-inspect/dist/index.mjs"; |
| | | import AutoImport from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-auto-import@0.17.8/node_modules/unplugin-auto-import/dist/vite.js"; |
| | | import Components from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/vite.js"; |
| | | import { ElementPlusResolver } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/resolvers.js"; |
| | | import svgSprites from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/rollup-plugin-svg-sprites@1.2.5_@vue+compiler-sfc@3.5.13/node_modules/rollup-plugin-svg-sprites/lib/index.js"; |
| | | import { viteMockServe } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-mock@2.9.8_mockjs@1.1.0_vite@5.4.11/node_modules/vite-plugin-mock/dist/index.js"; |
| | | var __vite_injected_original_import_meta_url = "file:///D:/GitWorkSpace/hm-lock/vite.config.ts"; |
| | | var vite_config_default = defineConfig(({ command, mode }) => { |
| | | console.log("vite.config defineConfig", command, mode); |
| | | const env = loadEnv(mode, process.cwd(), ""); |
| | | console.log("vite.config env.NODE_ENV=", env.NODE_ENV); |
| | | const prodMock = true; |
| | | return { |
| | | base: "./", |
| | | // 注意,必须以"/"结尾,BASE_URL配置 |
| | | build: { |
| | | outDir: "../hm-lock-sys/public" |
| | | }, |
| | | define: { |
| | | "process.env": env |
| | | }, |
| | | resolve: { |
| | | alias: { |
| | | "@": fileURLToPath(new URL("./src", __vite_injected_original_import_meta_url)) |
| | | }, |
| | | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] |
| | | }, |
| | | plugins: [ |
| | | vue(), |
| | | Inspect(), |
| | | VueSetupExtend(), |
| | | AutoImport({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | Components({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | svgSprites({ |
| | | vueComponent: true, |
| | | exclude: ["node_modules/**"], |
| | | symbolId(filePath) { |
| | | const filename = path.basename(filePath); |
| | | return "icon-" + filename.substring(0, filename.lastIndexOf(".")); |
| | | } |
| | | }), |
| | | // https://openbase.com/js/vite-plugin-mock |
| | | viteMockServe({ |
| | | ignore: /^_/, |
| | | mockPath: "./mock/", |
| | | supportTs: true, |
| | | watchFiles: true, |
| | | localEnabled: command === "serve", |
| | | prodEnabled: command !== "serve" && prodMock, |
| | | // configPath: './mock/index.js', |
| | | logger: false, |
| | | injectCode: `import { setupProdMockServer } from '../mock/_createProductionServer.js'; |
| | | setupProdMockServer();` |
| | | }) |
| | | ], |
| | | server: { |
| | | host: "localhost", |
| | | port: 8001 |
| | | } |
| | | }; |
| | | }); |
| | | export { |
| | | vite_config_default as default |
| | | }; |
| | | //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxHaXRXb3JrU3BhY2VcXFxcaG0tbG9ja1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRDpcXFxcR2l0V29ya1NwYWNlXFxcXGhtLWxvY2tcXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Q6L0dpdFdvcmtTcGFjZS9obS1sb2NrL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSAnbm9kZTp1cmwnO1xyXG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xyXG5cclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSc7XHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJztcclxuaW1wb3J0IFZ1ZVNldHVwRXh0ZW5kIGZyb20gJ3ZpdGUtcGx1Z2luLXZ1ZS1zZXR1cC1leHRlbmQnO1xyXG5pbXBvcnQgSW5zcGVjdCBmcm9tICd2aXRlLXBsdWdpbi1pbnNwZWN0JztcclxuXHJcbi8vIGVsZW1lbnQgcGx1cyBcdTY4MzdcdTVGMEZcdTgxRUFcdTUyQThcdTYzMDlcdTk3MDBcdTVCRkNcdTUxNjVcclxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSAndW5wbHVnaW4tYXV0by1pbXBvcnQvdml0ZSc7XHJcbmltcG9ydCBDb21wb25lbnRzIGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3ZpdGUnO1xyXG5pbXBvcnQgeyBFbGVtZW50UGx1c1Jlc29sdmVyIH0gZnJvbSAndW5wbHVnaW4tdnVlLWNvbXBvbmVudHMvcmVzb2x2ZXJzJztcclxuXHJcbmltcG9ydCBzdmdTcHJpdGVzIGZyb20gJ3JvbGx1cC1wbHVnaW4tc3ZnLXNwcml0ZXMnO1xyXG5pbXBvcnQgeyB2aXRlTW9ja1NlcnZlIH0gZnJvbSAndml0ZS1wbHVnaW4tbW9jayc7XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgY29tbWFuZCwgbW9kZSB9KSA9PiB7XHJcbiAgY29uc29sZS5sb2coJ3ZpdGUuY29uZmlnIGRlZmluZUNvbmZpZycsIGNvbW1hbmQsIG1vZGUpO1xyXG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSwgJycpO1xyXG4gIGNvbnNvbGUubG9nKCd2aXRlLmNvbmZpZyBlbnYuTk9ERV9FTlY9JywgZW52Lk5PREVfRU5WKTtcclxuICAvLyBBY2NvcmRpbmcgdG8gdGhlIHByb2plY3QgY29uZmlndXJhdGlvbi4gQ2FuIGJlIGNvbmZpZ3VyZWQgaW4gdGhlIC5lbnYgZmlsZVxyXG4gIGNvbnN0IHByb2RNb2NrID0gdHJ1ZTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGJhc2U6ICcuLycsIC8vIFx1NkNFOFx1NjEwRlx1RkYwQ1x1NUZDNVx1OTg3Qlx1NEVFNVwiL1wiXHU3RUQzXHU1QzNFXHVGRjBDQkFTRV9VUkxcdTkxNERcdTdGNkVcclxuICAgIGJ1aWxkOiB7XHJcbiAgICAgIG91dERpcjogJy4uL2htLWxvY2stc3lzL3B1YmxpYydcclxuICAgIH0sXHJcbiAgICBkZWZpbmU6IHtcclxuICAgICAgJ3Byb2Nlc3MuZW52JzogZW52XHJcbiAgICB9LFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICBhbGlhczoge1xyXG4gICAgICAgICdAJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYycsIGltcG9ydC5tZXRhLnVybCkpXHJcbiAgICAgIH0sXHJcbiAgICAgIGV4dGVuc2lvbnM6IFsnLm1qcycsICcuanMnLCAnLnRzJywgJy5qc3gnLCAnLnRzeCcsICcuanNvbicsICcudnVlJ11cclxuICAgIH0sXHJcbiAgICBwbHVnaW5zOiBbXHJcbiAgICAgIHZ1ZSgpLFxyXG4gICAgICBJbnNwZWN0KCksXHJcbiAgICAgIFZ1ZVNldHVwRXh0ZW5kKCksXHJcbiAgICAgIEF1dG9JbXBvcnQoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIENvbXBvbmVudHMoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIHN2Z1Nwcml0ZXMoe1xyXG4gICAgICAgIHZ1ZUNvbXBvbmVudDogdHJ1ZSxcclxuICAgICAgICBleGNsdWRlOiBbJ25vZGVfbW9kdWxlcy8qKiddLFxyXG4gICAgICAgIHN5bWJvbElkKGZpbGVQYXRoKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgcmV0dXJuICdpY29uLScgKyBmaWxlbmFtZS5zdWJzdHJpbmcoMCwgZmlsZW5hbWUubGFzdEluZGV4T2YoJy4nKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KSxcclxuICAgICAgLy8gaHR0cHM6Ly9vcGVuYmFzZS5jb20vanMvdml0ZS1wbHVnaW4tbW9ja1xyXG4gICAgICB2aXRlTW9ja1NlcnZlKHtcclxuICAgICAgICBpZ25vcmU6IC9eXy8sXHJcbiAgICAgICAgbW9ja1BhdGg6ICcuL21vY2svJyxcclxuICAgICAgICBzdXBwb3J0VHM6IHRydWUsXHJcbiAgICAgICAgd2F0Y2hGaWxlczogdHJ1ZSxcclxuICAgICAgICBsb2NhbEVuYWJsZWQ6IGNvbW1hbmQgPT09ICdzZXJ2ZScsXHJcbiAgICAgICAgcHJvZEVuYWJsZWQ6IGNvbW1hbmQgIT09ICdzZXJ2ZScgJiYgcHJvZE1vY2ssXHJcbiAgICAgICAgLy8gY29uZmlnUGF0aDogJy4vbW9jay9pbmRleC5qcycsXHJcbiAgICAgICAgbG9nZ2VyOiBmYWxzZSxcclxuICAgICAgICBpbmplY3RDb2RlOiBgaW1wb3J0IHsgc2V0dXBQcm9kTW9ja1NlcnZlciB9IGZyb20gJy4uL21vY2svX2NyZWF0ZVByb2R1Y3Rpb25TZXJ2ZXIuanMnO1xyXG4gICAgICBzZXR1cFByb2RNb2NrU2VydmVyKCk7YFxyXG4gICAgICB9KVxyXG4gICAgXSxcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICBob3N0OiAnbG9jYWxob3N0JyxcclxuICAgICAgcG9ydDogODAwMVxyXG4gICAgfVxyXG4gIH07XHJcbn0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTZQLFNBQVMsZUFBZSxXQUFXO0FBQ2hTLE9BQU8sVUFBVTtBQUVqQixTQUFTLGNBQWMsZUFBZTtBQUN0QyxPQUFPLFNBQVM7QUFDaEIsT0FBTyxvQkFBb0I7QUFDM0IsT0FBTyxhQUFhO0FBR3BCLE9BQU8sZ0JBQWdCO0FBQ3ZCLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMsMkJBQTJCO0FBRXBDLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMscUJBQXFCO0FBZDZILElBQU0sMkNBQTJDO0FBaUI1TSxJQUFPLHNCQUFRLGFBQWEsQ0FBQyxFQUFFLFNBQVMsS0FBSyxNQUFNO0FBQ2pELFVBQVEsSUFBSSw0QkFBNEIsU0FBUyxJQUFJO0FBQ3JELFFBQU0sTUFBTSxRQUFRLE1BQU0sUUFBUSxJQUFJLEdBQUcsRUFBRTtBQUMzQyxVQUFRLElBQUksNkJBQTZCLElBQUksUUFBUTtBQUVyRCxRQUFNLFdBQVc7QUFFakIsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBO0FBQUEsSUFDTixPQUFPO0FBQUEsTUFDTCxRQUFRO0FBQUEsSUFDVjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sZUFBZTtBQUFBLElBQ2pCO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPO0FBQUEsUUFDTCxLQUFLLGNBQWMsSUFBSSxJQUFJLFNBQVMsd0NBQWUsQ0FBQztBQUFBLE1BQ3REO0FBQUEsTUFDQSxZQUFZLENBQUMsUUFBUSxPQUFPLE9BQU8sUUFBUSxRQUFRLFNBQVMsTUFBTTtBQUFBLElBQ3BFO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixRQUFRO0FBQUEsTUFDUixlQUFlO0FBQUEsTUFDZixXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxjQUFjO0FBQUEsUUFDZCxTQUFTLENBQUMsaUJBQWlCO0FBQUEsUUFDM0IsU0FBUyxVQUFVO0FBQ2pCLGdCQUFNLFdBQVcsS0FBSyxTQUFTLFFBQVE7QUFDdkMsaUJBQU8sVUFBVSxTQUFTLFVBQVUsR0FBRyxTQUFTLFlBQVksR0FBRyxDQUFDO0FBQUEsUUFDbEU7QUFBQSxNQUNGLENBQUM7QUFBQTtBQUFBLE1BRUQsY0FBYztBQUFBLFFBQ1osUUFBUTtBQUFBLFFBQ1IsVUFBVTtBQUFBLFFBQ1YsV0FBVztBQUFBLFFBQ1gsWUFBWTtBQUFBLFFBQ1osY0FBYyxZQUFZO0FBQUEsUUFDMUIsYUFBYSxZQUFZLFdBQVc7QUFBQTtBQUFBLFFBRXBDLFFBQVE7QUFBQSxRQUNSLFlBQVk7QUFBQTtBQUFBLE1BRWQsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxJQUNSO0FBQUEsRUFDRjtBQUNGLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg== |
New file |
| | |
| | | // vite.config.ts |
| | | import { fileURLToPath, URL } from "node:url"; |
| | | import path from "node:path"; |
| | | import { defineConfig, loadEnv } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite@5.4.11_@types+node@20.17.10_sass@1.83.0/node_modules/vite/dist/node/index.js"; |
| | | import vue from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/@vitejs+plugin-vue@5.2.1_vite@5.4.11_vue@3.5.13/node_modules/@vitejs/plugin-vue/dist/index.mjs"; |
| | | import VueSetupExtend from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-vue-setup-extend@0.4.0_vite@5.4.11/node_modules/vite-plugin-vue-setup-extend/dist/index.mjs"; |
| | | import Inspect from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-inspect@0.8.9_vite@5.4.11/node_modules/vite-plugin-inspect/dist/index.mjs"; |
| | | import AutoImport from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-auto-import@0.17.8/node_modules/unplugin-auto-import/dist/vite.js"; |
| | | import Components from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/vite.js"; |
| | | import { ElementPlusResolver } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/unplugin-vue-components@0.27.5_vue@3.5.13/node_modules/unplugin-vue-components/dist/resolvers.js"; |
| | | import svgSprites from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/rollup-plugin-svg-sprites@1.2.5_@vue+compiler-sfc@3.5.13/node_modules/rollup-plugin-svg-sprites/lib/index.js"; |
| | | import { viteMockServe } from "file:///D:/GitWorkSpace/hm-lock/node_modules/.pnpm/vite-plugin-mock@2.9.8_mockjs@1.1.0_vite@5.4.11/node_modules/vite-plugin-mock/dist/index.js"; |
| | | var __vite_injected_original_import_meta_url = "file:///D:/GitWorkSpace/hm-lock/vite.config.ts"; |
| | | var vite_config_default = defineConfig(({ command, mode }) => { |
| | | console.log("vite.config defineConfig", command, mode); |
| | | const env = loadEnv(mode, process.cwd(), ""); |
| | | console.log("vite.config env.NODE_ENV=", env.NODE_ENV); |
| | | const prodMock = true; |
| | | return { |
| | | base: "./", |
| | | // 注意,必须以"/"结尾,BASE_URL配置 |
| | | build: { |
| | | outDir: "../hm-lock-sys/public" |
| | | }, |
| | | define: { |
| | | "process.env": env |
| | | }, |
| | | resolve: { |
| | | alias: { |
| | | "@": fileURLToPath(new URL("./src", __vite_injected_original_import_meta_url)) |
| | | }, |
| | | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] |
| | | }, |
| | | plugins: [ |
| | | vue(), |
| | | Inspect(), |
| | | VueSetupExtend(), |
| | | AutoImport({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | Components({ |
| | | resolvers: [ElementPlusResolver()] |
| | | }), |
| | | svgSprites({ |
| | | vueComponent: true, |
| | | exclude: ["node_modules/**"], |
| | | symbolId(filePath) { |
| | | const filename = path.basename(filePath); |
| | | return "icon-" + filename.substring(0, filename.lastIndexOf(".")); |
| | | } |
| | | }), |
| | | // https://openbase.com/js/vite-plugin-mock |
| | | viteMockServe({ |
| | | ignore: /^_/, |
| | | mockPath: "./mock/", |
| | | supportTs: true, |
| | | watchFiles: true, |
| | | localEnabled: command === "serve", |
| | | prodEnabled: command !== "serve" && prodMock, |
| | | // configPath: './mock/index.js', |
| | | logger: false, |
| | | injectCode: `import { setupProdMockServer } from '../mock/_createProductionServer.js'; |
| | | setupProdMockServer();` |
| | | }) |
| | | ], |
| | | server: { |
| | | // https: true, |
| | | // key: './key.pem', |
| | | // cert: './cert.pem', |
| | | host: "localhost", |
| | | port: 8001 |
| | | } |
| | | }; |
| | | }); |
| | | export { |
| | | vite_config_default as default |
| | | }; |
| | | //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxHaXRXb3JrU3BhY2VcXFxcaG0tbG9ja1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRDpcXFxcR2l0V29ya1NwYWNlXFxcXGhtLWxvY2tcXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Q6L0dpdFdvcmtTcGFjZS9obS1sb2NrL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSAnbm9kZTp1cmwnO1xyXG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xyXG5cclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSc7XHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJztcclxuaW1wb3J0IFZ1ZVNldHVwRXh0ZW5kIGZyb20gJ3ZpdGUtcGx1Z2luLXZ1ZS1zZXR1cC1leHRlbmQnO1xyXG5pbXBvcnQgSW5zcGVjdCBmcm9tICd2aXRlLXBsdWdpbi1pbnNwZWN0JztcclxuXHJcbi8vIGVsZW1lbnQgcGx1cyBcdTY4MzdcdTVGMEZcdTgxRUFcdTUyQThcdTYzMDlcdTk3MDBcdTVCRkNcdTUxNjVcclxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSAndW5wbHVnaW4tYXV0by1pbXBvcnQvdml0ZSc7XHJcbmltcG9ydCBDb21wb25lbnRzIGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3ZpdGUnO1xyXG5pbXBvcnQgeyBFbGVtZW50UGx1c1Jlc29sdmVyIH0gZnJvbSAndW5wbHVnaW4tdnVlLWNvbXBvbmVudHMvcmVzb2x2ZXJzJztcclxuXHJcbmltcG9ydCBzdmdTcHJpdGVzIGZyb20gJ3JvbGx1cC1wbHVnaW4tc3ZnLXNwcml0ZXMnO1xyXG5pbXBvcnQgeyB2aXRlTW9ja1NlcnZlIH0gZnJvbSAndml0ZS1wbHVnaW4tbW9jayc7XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgY29tbWFuZCwgbW9kZSB9KSA9PiB7XHJcbiAgY29uc29sZS5sb2coJ3ZpdGUuY29uZmlnIGRlZmluZUNvbmZpZycsIGNvbW1hbmQsIG1vZGUpO1xyXG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSwgJycpO1xyXG4gIGNvbnNvbGUubG9nKCd2aXRlLmNvbmZpZyBlbnYuTk9ERV9FTlY9JywgZW52Lk5PREVfRU5WKTtcclxuICAvLyBBY2NvcmRpbmcgdG8gdGhlIHByb2plY3QgY29uZmlndXJhdGlvbi4gQ2FuIGJlIGNvbmZpZ3VyZWQgaW4gdGhlIC5lbnYgZmlsZVxyXG4gIGNvbnN0IHByb2RNb2NrID0gdHJ1ZTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGJhc2U6ICcuLycsIC8vIFx1NkNFOFx1NjEwRlx1RkYwQ1x1NUZDNVx1OTg3Qlx1NEVFNVwiL1wiXHU3RUQzXHU1QzNFXHVGRjBDQkFTRV9VUkxcdTkxNERcdTdGNkVcclxuICAgIGJ1aWxkOiB7XHJcbiAgICAgIG91dERpcjogJy4uL2htLWxvY2stc3lzL3B1YmxpYydcclxuICAgIH0sXHJcbiAgICBkZWZpbmU6IHtcclxuICAgICAgJ3Byb2Nlc3MuZW52JzogZW52XHJcbiAgICB9LFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICBhbGlhczoge1xyXG4gICAgICAgICdAJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYycsIGltcG9ydC5tZXRhLnVybCkpXHJcbiAgICAgIH0sXHJcbiAgICAgIGV4dGVuc2lvbnM6IFsnLm1qcycsICcuanMnLCAnLnRzJywgJy5qc3gnLCAnLnRzeCcsICcuanNvbicsICcudnVlJ11cclxuICAgIH0sXHJcbiAgICBwbHVnaW5zOiBbXHJcbiAgICAgIHZ1ZSgpLFxyXG4gICAgICBJbnNwZWN0KCksXHJcbiAgICAgIFZ1ZVNldHVwRXh0ZW5kKCksXHJcbiAgICAgIEF1dG9JbXBvcnQoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIENvbXBvbmVudHMoe1xyXG4gICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgfSksXHJcbiAgICAgIHN2Z1Nwcml0ZXMoe1xyXG4gICAgICAgIHZ1ZUNvbXBvbmVudDogdHJ1ZSxcclxuICAgICAgICBleGNsdWRlOiBbJ25vZGVfbW9kdWxlcy8qKiddLFxyXG4gICAgICAgIHN5bWJvbElkKGZpbGVQYXRoKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgcmV0dXJuICdpY29uLScgKyBmaWxlbmFtZS5zdWJzdHJpbmcoMCwgZmlsZW5hbWUubGFzdEluZGV4T2YoJy4nKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KSxcclxuICAgICAgLy8gaHR0cHM6Ly9vcGVuYmFzZS5jb20vanMvdml0ZS1wbHVnaW4tbW9ja1xyXG4gICAgICB2aXRlTW9ja1NlcnZlKHtcclxuICAgICAgICBpZ25vcmU6IC9eXy8sXHJcbiAgICAgICAgbW9ja1BhdGg6ICcuL21vY2svJyxcclxuICAgICAgICBzdXBwb3J0VHM6IHRydWUsXHJcbiAgICAgICAgd2F0Y2hGaWxlczogdHJ1ZSxcclxuICAgICAgICBsb2NhbEVuYWJsZWQ6IGNvbW1hbmQgPT09ICdzZXJ2ZScsXHJcbiAgICAgICAgcHJvZEVuYWJsZWQ6IGNvbW1hbmQgIT09ICdzZXJ2ZScgJiYgcHJvZE1vY2ssXHJcbiAgICAgICAgLy8gY29uZmlnUGF0aDogJy4vbW9jay9pbmRleC5qcycsXHJcbiAgICAgICAgbG9nZ2VyOiBmYWxzZSxcclxuICAgICAgICBpbmplY3RDb2RlOiBgaW1wb3J0IHsgc2V0dXBQcm9kTW9ja1NlcnZlciB9IGZyb20gJy4uL21vY2svX2NyZWF0ZVByb2R1Y3Rpb25TZXJ2ZXIuanMnO1xyXG4gICAgICBzZXR1cFByb2RNb2NrU2VydmVyKCk7YFxyXG4gICAgICB9KVxyXG4gICAgXSxcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICAvLyBodHRwczogdHJ1ZSxcclxuICAgICAgLy8ga2V5OiAnLi9rZXkucGVtJyxcclxuICAgICAgLy8gY2VydDogJy4vY2VydC5wZW0nLFxyXG4gICAgICBob3N0OiAnbG9jYWxob3N0JyxcclxuICAgICAgcG9ydDogODAwMVxyXG4gICAgfVxyXG4gIH07XHJcbn0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTZQLFNBQVMsZUFBZSxXQUFXO0FBQ2hTLE9BQU8sVUFBVTtBQUVqQixTQUFTLGNBQWMsZUFBZTtBQUN0QyxPQUFPLFNBQVM7QUFDaEIsT0FBTyxvQkFBb0I7QUFDM0IsT0FBTyxhQUFhO0FBR3BCLE9BQU8sZ0JBQWdCO0FBQ3ZCLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMsMkJBQTJCO0FBRXBDLE9BQU8sZ0JBQWdCO0FBQ3ZCLFNBQVMscUJBQXFCO0FBZDZILElBQU0sMkNBQTJDO0FBaUI1TSxJQUFPLHNCQUFRLGFBQWEsQ0FBQyxFQUFFLFNBQVMsS0FBSyxNQUFNO0FBQ2pELFVBQVEsSUFBSSw0QkFBNEIsU0FBUyxJQUFJO0FBQ3JELFFBQU0sTUFBTSxRQUFRLE1BQU0sUUFBUSxJQUFJLEdBQUcsRUFBRTtBQUMzQyxVQUFRLElBQUksNkJBQTZCLElBQUksUUFBUTtBQUVyRCxRQUFNLFdBQVc7QUFFakIsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBO0FBQUEsSUFDTixPQUFPO0FBQUEsTUFDTCxRQUFRO0FBQUEsSUFDVjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sZUFBZTtBQUFBLElBQ2pCO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPO0FBQUEsUUFDTCxLQUFLLGNBQWMsSUFBSSxJQUFJLFNBQVMsd0NBQWUsQ0FBQztBQUFBLE1BQ3REO0FBQUEsTUFDQSxZQUFZLENBQUMsUUFBUSxPQUFPLE9BQU8sUUFBUSxRQUFRLFNBQVMsTUFBTTtBQUFBLElBQ3BFO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixRQUFRO0FBQUEsTUFDUixlQUFlO0FBQUEsTUFDZixXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxXQUFXLENBQUMsb0JBQW9CLENBQUM7QUFBQSxNQUNuQyxDQUFDO0FBQUEsTUFDRCxXQUFXO0FBQUEsUUFDVCxjQUFjO0FBQUEsUUFDZCxTQUFTLENBQUMsaUJBQWlCO0FBQUEsUUFDM0IsU0FBUyxVQUFVO0FBQ2pCLGdCQUFNLFdBQVcsS0FBSyxTQUFTLFFBQVE7QUFDdkMsaUJBQU8sVUFBVSxTQUFTLFVBQVUsR0FBRyxTQUFTLFlBQVksR0FBRyxDQUFDO0FBQUEsUUFDbEU7QUFBQSxNQUNGLENBQUM7QUFBQTtBQUFBLE1BRUQsY0FBYztBQUFBLFFBQ1osUUFBUTtBQUFBLFFBQ1IsVUFBVTtBQUFBLFFBQ1YsV0FBVztBQUFBLFFBQ1gsWUFBWTtBQUFBLFFBQ1osY0FBYyxZQUFZO0FBQUEsUUFDMUIsYUFBYSxZQUFZLFdBQVc7QUFBQTtBQUFBLFFBRXBDLFFBQVE7QUFBQSxRQUNSLFlBQVk7QUFBQTtBQUFBLE1BRWQsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBLFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQUlOLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxJQUNSO0FBQUEsRUFDRjtBQUNGLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg== |