Browse Source

add login

master
秋田弘 5 months ago
parent
commit
acd11f1ba2
  1. 2
      frontend/package.json
  2. 231
      frontend/pnpm-lock.yaml
  3. 101
      frontend/public/ref/clientid.js
  4. 167
      frontend/public/ref/config.js
  5. 111
      frontend/public/ref/ding.html
  6. 566
      frontend/src/components/desktop/LockDesktop.vue
  7. 5
      frontend/src/stores/login.ts
  8. 2
      frontend/src/system/index.ts
  9. 2
      frontend/src/system/router.ts
  10. 0
      frontend/src/util/thirdlogin.ts

2
frontend/package.json

@ -14,6 +14,7 @@
"@onlyoffice/document-editor-vue": "^1.4.0",
"cherry-markdown": "^0.8.52",
"dexie": "^4.0.8",
"dingtalk-jsapi": "^3.0.42",
"element-plus": "^2.7.7",
"file-saver": "^2.0.5",
"js-md5": "^0.8.3",
@ -22,6 +23,7 @@
"moment": "^2.30.1",
"pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0",
"qrcode": "^1.5.4",
"swiper": "^11.1.15",
"vant": "^4.9.15",
"vue": "^3.4.31",

231
frontend/pnpm-lock.yaml

@ -23,6 +23,9 @@ importers:
dexie:
specifier: ^4.0.8
version: 4.0.8
dingtalk-jsapi:
specifier: ^3.0.42
version: 3.0.42
element-plus:
specifier: ^2.7.7
version: 2.8.6(vue@3.5.12(typescript@5.6.3))
@ -47,6 +50,9 @@ importers:
pinia-plugin-persist:
specifier: ^1.0.0
version: 1.0.0(pinia@2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
qrcode:
specifier: ^1.5.4
version: 1.5.4
swiper:
specifier: ^11.1.15
version: 11.2.0
@ -631,6 +637,14 @@ packages:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
@ -665,6 +679,10 @@ packages:
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
camelcase@5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
cherry-markdown@0.8.52:
resolution: {integrity: sha512-Bo9TN/ajPWPVbfF0wCKS2z9ILcaT50khZ0eJ4fYTD/hbNqjg7wCM9FqVZCcOWa0Rb34G6AqfIbHTjEUSIhNWoQ==}
engines: {node: '>=14'}
@ -677,6 +695,16 @@ packages:
resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
engines: {node: '>= 14.16.0'}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@ -879,6 +907,10 @@ packages:
supports-color:
optional: true
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
decimal.js@10.4.3:
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
@ -897,6 +929,12 @@ packages:
dexie@4.0.8:
resolution: {integrity: sha512-1G6cJevS17KMDK847V3OHvK2zei899GwpDiqfEXHP1ASvme6eWJmAp9AU4s1son2TeGkWmC0g3y8ezOBPnalgQ==}
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
dingtalk-jsapi@3.0.42:
resolution: {integrity: sha512-cIJ+3HUnSRVAanCip5yT1rEoLPrj97BxjYKpB33sgwUDStmfPgyEzG8Hux/Sq2zYJNH6riEA9PflsDnevr1f/g==}
domexception@4.0.0:
resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==}
engines: {node: '>=12'}
@ -913,6 +951,9 @@ packages:
elkjs@0.8.2:
resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@ -970,6 +1011,10 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
form-data@4.0.1:
resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
engines: {node: '>= 6'}
@ -979,6 +1024,10 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@ -1024,6 +1073,10 @@ packages:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@ -1076,6 +1129,10 @@ packages:
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
engines: {node: '>=14'}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
@ -1154,12 +1211,28 @@ packages:
nwsapi@2.2.13:
resolution: {integrity: sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==}
p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
parse5@6.0.1:
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
@ -1195,6 +1268,10 @@ packages:
pkg-types@1.2.1:
resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==}
pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
postcss@8.4.47:
resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
engines: {node: ^10 || ^12 || >=14}
@ -1202,6 +1279,9 @@ packages:
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
promise-polyfill@7.1.2:
resolution: {integrity: sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==}
psl@1.13.0:
resolution: {integrity: sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw==}
@ -1209,6 +1289,11 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'}
hasBin: true
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@ -1226,6 +1311,13 @@ packages:
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
engines: {node: '>= 14.16.0'}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
@ -1272,6 +1364,9 @@ packages:
sdp@2.12.0:
resolution: {integrity: sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw==}
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
@ -1286,9 +1381,17 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
strip-literal@2.1.0:
resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
@ -1522,6 +1625,13 @@ packages:
resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==}
engines: {node: '>=12'}
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
ws@8.18.0:
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
engines: {node: '>=10.0.0'}
@ -1541,6 +1651,17 @@ packages:
xmlchars@2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
snapshots:
'@antfu/utils@0.7.10': {}
@ -1958,6 +2079,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
ansi-regex@5.0.1: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
@ -1985,6 +2112,8 @@ snapshots:
buffer-from@1.1.2: {}
camelcase@5.3.1: {}
cherry-markdown@0.8.52:
dependencies:
'@types/codemirror': 0.0.108
@ -2014,6 +2143,18 @@ snapshots:
dependencies:
readdirp: 4.0.2
cliui@6.0.0:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
@ -2269,6 +2410,8 @@ snapshots:
dependencies:
ms: 2.1.3
decamelize@1.2.0: {}
decimal.js@10.4.3: {}
delaunator@5.0.1:
@ -2282,6 +2425,12 @@ snapshots:
dexie@4.0.8: {}
dijkstrajs@1.0.3: {}
dingtalk-jsapi@3.0.42:
dependencies:
promise-polyfill: 7.1.2
domexception@4.0.0:
dependencies:
webidl-conversions: 7.0.0
@ -2313,6 +2462,8 @@ snapshots:
elkjs@0.8.2:
optional: true
emoji-regex@8.0.0: {}
entities@4.5.0: {}
esbuild@0.21.5:
@ -2385,6 +2536,11 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
path-exists: 4.0.0
form-data@4.0.1:
dependencies:
asynckit: 0.4.0
@ -2394,6 +2550,8 @@ snapshots:
fsevents@2.3.3:
optional: true
get-caller-file@2.0.5: {}
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@ -2441,6 +2599,8 @@ snapshots:
is-extglob@2.1.1: {}
is-fullwidth-code-point@3.0.0: {}
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
@ -2516,6 +2676,10 @@ snapshots:
mlly: 1.7.2
pkg-types: 1.2.1
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
lodash-es@4.17.21: {}
lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21):
@ -2597,10 +2761,22 @@ snapshots:
nwsapi@2.2.13: {}
p-limit@2.3.0:
dependencies:
p-try: 2.2.0
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
p-try@2.2.0: {}
pako@1.0.11: {}
parse5@6.0.1: {}
path-exists@4.0.0: {}
pathe@1.1.2: {}
picocolors@1.1.1: {}
@ -2627,6 +2803,8 @@ snapshots:
mlly: 1.7.2
pathe: 1.1.2
pngjs@5.0.0: {}
postcss@8.4.47:
dependencies:
nanoid: 3.3.7
@ -2635,12 +2813,20 @@ snapshots:
process-nextick-args@2.0.1: {}
promise-polyfill@7.1.2: {}
psl@1.13.0:
dependencies:
punycode: 2.3.1
punycode@2.3.1: {}
qrcode@1.5.4:
dependencies:
dijkstrajs: 1.0.3
pngjs: 5.0.0
yargs: 15.4.1
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}
@ -2661,6 +2847,10 @@ snapshots:
readdirp@4.0.2: {}
require-directory@2.1.1: {}
require-main-filename@2.0.0: {}
requires-port@1.0.0: {}
reusify@1.0.4: {}
@ -2720,6 +2910,8 @@ snapshots:
sdp@2.12.0: {}
set-blocking@2.0.0: {}
setimmediate@1.0.5: {}
source-map-js@1.2.1: {}
@ -2731,10 +2923,20 @@ snapshots:
source-map@0.6.1: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
string_decoder@1.1.1:
dependencies:
safe-buffer: 5.1.2
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
strip-literal@2.1.0:
dependencies:
js-tokens: 9.0.0
@ -2957,8 +3159,37 @@ snapshots:
tr46: 3.0.0
webidl-conversions: 7.0.0
which-module@2.0.1: {}
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
ws@8.18.0: {}
xml-name-validator@4.0.0: {}
xmlchars@2.2.0: {}
y18n@4.0.3: {}
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
decamelize: 1.2.0
yargs@15.4.1:
dependencies:
cliui: 6.0.0
decamelize: 1.2.0
find-up: 4.1.0
get-caller-file: 2.0.5
require-directory: 2.1.1
require-main-filename: 2.0.0
set-blocking: 2.0.0
string-width: 4.2.3
which-module: 2.0.1
y18n: 4.0.3
yargs-parser: 18.1.3

101
frontend/public/ref/clientid.js

@ -0,0 +1,101 @@
function getOSInfo() {
const userAgent = navigator.userAgent;
if (/windows phone/i.test(userAgent)) {
return 'Windows Phone';
}
if (/win/i.test(userAgent)) {
return 'Windows';
}
if (/mac/i.test(userAgent)) {
return 'Mac';
}
if (/x11/i.test(userAgent)) {
return 'UNIX';
}
if (/android/i.test(userAgent)) {
return 'Android';
}
if (/iphone|ipad|ipod/i.test(userAgent)) {
return 'iOS';
}
return 'Unknown';
}
function bin2hex(s) {
s = encodeURI(s); // 只会有0-127的ascii不转化
let m = s.match(/%[\dA-F]{2}/g), a = s.split(/%[\dA-F]{2}/), i, j, n, t;
m.push("");
for (i in a) {
if (a[i] === "") { a[i] = m[i]; continue; }
n = "";
for (j in a[i]) {
t = a[i][j].charCodeAt().toString(16).toUpperCase();
if (t.length === 1) t = "0" + t;
n += "%" + t;
}
a[i] = n + m[i];
}
return a.join("").split("%").join("");
}
function getBrowserFingerprint() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d'); // 移除类型声明
const txt = window.location.hostname;
ctx.textBaseline = 'top';
ctx.font = '14px \'Arial\'';
ctx.textBaseline = 'alphabetic';
ctx.fillStyle = '#f60';
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = '#069';
ctx.fillText(txt, 2, 15);
ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
ctx.fillText(txt, 4, 17);
const b64 = canvas.toDataURL().replace("data:image/png;base64,", "");
const bin = window.atob(b64);
const hash = bin2hex(bin.slice(-16, -12));
const fingerprint = [
navigator.platform,
navigator.product,
navigator.productSub,
navigator.appName,
navigator.appVersion,
navigator.javaEnabled(),
navigator.userAgent,
screen.width,
screen.height,
new Date().getTimezoneOffset(),
hash,
screen.colorDepth,
navigator.language,
navigator.hardwareConcurrency,
getOSInfo(),
navigator.maxTouchPoints,
navigator.doNotTrack,
navigator.cookieEnabled
].join('|');
return fingerprint;
}
function djb2Hash(str) {
let hash = 5381;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) + hash) + char; /* hash * 33 + c */
}
return hash.toString(36); // Convert to base 36 for shorter string
}
function GetClientId() {
let uuid = localStorage.getItem("ClientID");
if (!uuid) {
const fingerprint = getBrowserFingerprint();
uuid = djb2Hash(fingerprint).slice(0, 36);
localStorage.setItem("ClientID", uuid);
}
return uuid;
}

167
frontend/public/ref/config.js

@ -0,0 +1,167 @@
const getSystemConfig = (ifset = false) => {
const configSetting = localStorage.getItem('GodoOS-config') || '{}';
let config = JSON.parse(configSetting);
config.version ??= '1.0.4';
config.isFirstRun ??= false;
config.lang ??= '';
config.apiUrl ??= `${window.location.protocol}//${window.location.hostname}:56780`;
config.userType ??= 'person';
config.editorType ??= 'local';
config.onlyoffice ??= { url: '', secret: '' };
config.file ??= { isPwd: 0, pwd: '' };
config.fileInputPwd ??= [];
config.userInfo ??= {
url: '',
username: '',
password: '',
id: 0,
nickname: '',
avatar: '',
email: '',
phone: '',
desc: '',
job_number: '',
work_place: '',
hired_date: '',
ding_id: '',
role_id: 0,
roleName: '',
dept_id: 0,
deptName: '',
token: '',
user_auths: '',
user_shares: '',
isPwd: false
};
config.isApp = window.go ? true : false;
config.systemInfo ??= {};
config.theme ??= 'light';
config.storeType ??= localStorage.getItem('GodoOS-storeType') || 'local';
config.storePath ??= '';
config.netPath ??= '';
config.netPort ??= '56780';
config.background ??= {
url: '/image/bg/bg6.jpg',
type: 'image',
color: 'rgba(30, 144, 255, 1)',
imageList: [
'/image/bg/bg1.jpg',
'/image/bg/bg2.jpg',
'/image/bg/bg3.jpg',
'/image/bg/bg4.jpg',
'/image/bg/bg5.jpg',
'/image/bg/bg6.jpg',
'/image/bg/bg7.jpg',
'/image/bg/bg8.jpg',
'/image/bg/bg9.jpg',
]
};
config.account ??= { ad: false, username: '', password: '' };
if (config.userType === 'member') {
config.account.ad = false;
}
config.storenet ??= { url: '', username: '', password: '', isCors: '' };
config.webdavClient ??= { url: '', username: '', password: '' };
config.dbInfo ??= { url: '', username: '', password: '', dbname: '' };
config.chatConf ??= {
checkTime: '15',
first: '192',
second: '168',
thirdStart: '1',
thirdEnd: '1',
fourthStart: '2',
fourthEnd: '254'
};
config.desktopList ??= [];
config.menuList ??= [];
config.token ??= generateRandomString(16);
config = parseAiConfig(config);
if (ifset) {
setSystemConfig(config);
}
return config;
};
const setSystemConfig = (config) => {
localStorage.setItem('GodoOS-config', JSON.stringify(config));
localStorage.setItem('GodoOS-storeType', config.storeType);
};
function generateRandomString(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
const parseAiConfig = (config) => {
if (!config.ollamaUrl) {
config.ollamaUrl = `${window.location.protocol}//${window.location.hostname}:11434`
}
if (!config.ollamaDir) {
config.ollamaDir = ''
}
if (!config.aiDir) {
config.aiDir = ''
}
if (!config.aiUrl) {
config.aiUrl = config.apiUrl
}
//openai
if (!config.openaiUrl) {
config.openaiUrl = 'https://api.openai.com/v1'
}
if (!config.openaiSecret) {
config.openaiSecret = ""
}
//gitee
if (!config.giteeSecret) {
config.giteeSecret = ""
}
//cloudflare
if (!config.cloudflareUserId) {
config.cloudflareUserId = ""
}
if (!config.cloudflareSecret) {
config.cloudflareSecret = ""
}
if (!config.deepseekSecret) {
config.deepseekSecret = ""
}
if (!config.bigmodelSecret) {
config.bigmodelSecret = ""
}
if (!config.volcesSecret) {
config.volcesSecret = ""
}
if (!config.alibabaSecret) {
config.alibabaSecret = ""
}
if (!config.groqSecret) {
config.groqSecret = ""
}
if (!config.mistralSecret) {
config.mistralSecret = ""
}
if (!config.anthropicSecret) {
config.anthropicSecret = ""
}
if (!config.llamafamilySecret) {
config.llamafamilySecret = ""
}
if (!config.siliconflowSecret) {
config.siliconflowSecret = ""
}
return config
};

111
frontend/public/ref/ding.html

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>钉钉授权页面</title>
<meta
name="renderer"
content="webkit"
/>
<meta
http-equiv="X-UA-Compatible"
content="IE=edge,chrome=1"
/>
<meta
http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
</head>
<script src="https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.12/dingtalk.open.js"></script>
<script src="./clientid.js"></script>
<script src="./config.js"></script>
<body>
<div id="ding"></div>
<script>
// 页面加载完成后执行登录
window.onload = function () {
getCropId();
};
async function getCropId() {
try {
const res = await fetch(
"http://server001.godoos.com/user/ding/conf"
);
const data = await res.json();
if (data.success) {
await getCode(data.data.id);
} else {
ElMessage.error("获取钉钉配置失败");
}
} catch (e) {
throw e;
}
}
// 获取code登录
async function getCode(corpId) {
dd.runtime.permission.requestAuthCode({
corpId: corpId,
onSuccess: async function (result) {
await toLogin(result.code);
},
onFail: function (err) {
document.getElementById("ding").innerHTML =
JSON.stringify(err);
},
});
}
// 登录接口
async function toLogin(code) {
const data = {
login_type: "dingtalk_workbench",
client_id: GetClientId(),
param: {
code,
},
};
document.getElementById("ding").innerHTML =
JSON.stringify(data);
const res = await fetch(
"http://server001.godoos.com/user/login",
{
method: "POST",
body: JSON.stringify(data),
}
);
const jsondata = await res.json();
if (jsondata.success) {
document.getElementById("ding").innerHTML =
JSON.stringify(jsondata);
// 从本地存储中尝试获取配置信息,若不存在则使用默认空对象
const config = getSystemConfig();
jsondata.data.url = config.userInfo.url;
config.userInfo = jsondata.data;
document.getElementById("ding").innerHTML =
JSON.stringify(config);
setSystemConfig(config);
window.location.href = "http://osadmin.godoos.com/";
// setStorage("Authorization", resData.data.token);
// setStorage("ClientID", resData.data.client_id);
// 缓存用户数据
// const userData = {
// userDept: resData.data.dept,
// userInfo: resData.data.user,
// };
// setStorage("userData", userData);
ElMessage.success("登录成功");
// router.push("/knowledge/#/home");
} else {
ElMessage.error("登录失败");
}
}
</script>
</body>
</html>

566
frontend/src/components/desktop/LockDesktop.vue

@ -15,152 +15,199 @@
/>
</el-avatar>
</div>
<div v-if="store.page == 'login'">
<el-form
v-if="!isRegisterMode"
label-position="left"
label-width="0px"
<el-form
v-if="ThirdPartyLoginMethod === 'login'"
label-position="left"
label-width="0px"
>
<el-form-item>
<el-input
v-model="userName"
placeholder="请输入用户名"
autofocus
prefix-icon="UserFilled"
></el-input>
</el-form-item>
<el-form-item v-if="!sys._options.noPassword">
<el-input
v-model="userPassword"
type="password"
placeholder="请输入登录密码"
show-password
prefix-icon="Key"
@keyup.enter="onLogin()"
></el-input>
</el-form-item>
<el-button
type="primary"
@click="onLogin()"
>登录</el-button
>
<el-form-item>
<el-input
v-model="userName"
placeholder="请输入用户名"
autofocus
prefix-icon="UserFilled"
></el-input>
</el-form-item>
<el-form-item v-if="!sys._options.noPassword">
<el-input
v-model="userPassword"
type="password"
placeholder="请输入登录密码"
show-password
prefix-icon="Key"
@keyup.enter="onLogin"
></el-input>
</el-form-item>
<el-button
type="primary"
@click="onLogin"
>登录</el-button
<div class="divider">
<span>第三方登录</span>
</div>
<div class="third-party-login">
<img
v-for="platform in thirdPartyPlatforms"
:key="platform.name"
:src="platform.icon"
:alt="platform.name"
style="
width: 25px;
height: 25px;
cursor: pointer;
color: #409eff;
"
@click="onThirdPartyLogin(platform.name)"
/>
</div>
<div class="actions">
<!-- <a
href="#"
@click.prevent="toggleRegister"
>注册新用户</a
> -->
<a
href="#"
@click.prevent="toggleUserSwitch"
>切换角色</a
>
<div class="divider">
<span>第三方登录</span>
</div>
<div class="third-party-login">
<img
v-for="platform in thirdPartyPlatforms"
:key="platform.name"
:src="platform.icon"
:alt="platform.name"
style="
width: 25px;
height: 25px;
cursor: pointer;
color: #409eff;
"
@click="onThirdPartyLogin(platform.name)"
/>
</div>
<div class="actions">
<a
href="#"
@click.prevent="toggleRegister"
>注册新用户</a
>
<a
href="#"
@click.prevent="toggleUserSwitch"
>切换角色</a
>
</div>
</el-form>
<el-form
v-else
label-position="left"
label-width="0px"
:model="regForm"
ref="regFormRef"
:rules="rules"
</div>
</el-form>
<el-form
v-else-if="ThirdPartyLoginMethod === 'register'"
label-position="left"
label-width="0px"
:model="regForm"
ref="regFormRef"
:rules="rules"
>
<el-form-item prop="username">
<el-input
v-model="regForm.username"
placeholder="请输入用户名"
prefix-icon="UserFilled"
></el-input>
</el-form-item>
<el-form-item prop="nickname">
<el-input
v-model="regForm.nickname"
placeholder="请输入真实姓名"
prefix-icon="Avatar"
></el-input>
</el-form-item>
<el-form-item prop="email">
<el-input
v-model="regForm.email"
placeholder="请输入邮箱"
prefix-icon="Message"
></el-input>
</el-form-item>
<el-form-item prop="phone">
<el-input
v-model="regForm.phone"
placeholder="请输入手机号"
prefix-icon="Iphone"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="regForm.password"
type="password"
placeholder="请输入密码"
show-password
prefix-icon="Key"
></el-input>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
v-model="regForm.confirmPassword"
type="password"
placeholder="请再次输入密码"
show-password
prefix-icon="Lock"
></el-input>
</el-form-item>
<el-button
type="primary"
@click="onRegister"
>注册</el-button
>
<el-form-item prop="username">
<el-input
v-model="regForm.username"
placeholder="请输入用户名"
prefix-icon="UserFilled"
></el-input>
</el-form-item>
<el-form-item prop="nickname">
<el-input
v-model="regForm.nickname"
placeholder="请输入真实姓名"
prefix-icon="Avatar"
></el-input>
</el-form-item>
<el-form-item prop="email">
<el-input
v-model="regForm.email"
placeholder="请输入邮箱"
prefix-icon="Message"
></el-input>
</el-form-item>
<el-form-item prop="phone">
<el-input
v-model="regForm.phone"
placeholder="请输入手机号"
prefix-icon="Iphone"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="regForm.password"
type="password"
placeholder="请输入密码"
show-password
prefix-icon="Key"
></el-input>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
v-model="regForm.confirmPassword"
type="password"
placeholder="请再次输入密码"
show-password
prefix-icon="Lock"
></el-input>
</el-form-item>
<el-button
type="primary"
@click="onRegister"
>注册</el-button
>
<div class="actions">
<a
href="#"
@click.prevent="toggleRegister"
>返回登录</a
</el-form>
<div v-else-if="ThirdPartyLoginMethod === 'dingding'">
<el-row>
<el-col :span="24">
<div class="qr-code">
<div id="dd-qr-code"></div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-button @click="ThirdPartyLoginMethod = 'login'"
>返回</el-button
>
</div>
</el-form>
</el-col>
</el-row>
</div>
<div v-else-if="store.page == 'setphone'">
<el-form>
<el-form-item>
<el-input
v-model="userName"
placeholder="请输入手机号"
autofocus
prefix-icon="Iphone"
></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="setPhone"
>确定</el-button
<!-- 企业微信 -->
<div v-else-if="ThirdPartyLoginMethod === 'qywechat'">
<el-row>
<el-col :span="24">
<div class="qr-code">
<div id="qywechat-qr-code"></div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-button @click="ThirdPartyLoginMethod = 'login'"
>返回</el-button
>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
<!-- 手机登录 -->
<div v-else-if="ThirdPartyLoginMethod === 'phone'">
<el-row>
<el-col :span="24">
<el-form>
<el-form-item>
<el-input
v-model="phoneForm.phone"
placeholder="请输入手机号"
/>
</el-form-item>
<!-- 验证码 -->
<el-form-item>
<el-row :gutter="10">
<el-col :span="16">
<el-input
v-model="phoneForm.code"
placeholder="请输入验证码"
/>
</el-col>
<el-col :span="8">
<button
class="send-code-btn"
@click.prevent="onSendCode"
>
发送验证码
</button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-button @click="ThirdPartyLoginMethod = 'login'"
>返回</el-button
>
</el-col>
</el-row>
</div>
</el-card>
</div>
@ -172,7 +219,8 @@
import { getSystemConfig, setSystemConfig } from "@/system/config";
import router from "@/system/router";
import { RestartApp } from "@/util/goutil";
import { notifyError, notifySuccess } from "@/util/msg";
import { notifyError } from "@/util/msg";
import QRCode from "qrcode";
import { onMounted, ref, watchEffect } from "vue";
import { useRoute } from "vue-router";
const route = useRoute();
@ -181,7 +229,46 @@
const loginCallback = sys._options.loginCallback;
const config = getSystemConfig();
const lockClassName = ref("screen-show");
const isRegisterMode = ref(false);
const ThirdPartyLoginMethod = ref("login");
const phoneForm = ref({
phone: "",
code: "",
});
// DTFrameLogin
declare global {
interface Window {
DTFrameLogin: (
frameParams: IDTLoginFrameParams,
loginParams: IDTLoginLoginParams,
successCbk: (result: IDTLoginSuccess) => void,
errorCbk?: (error: any) => void
) => void;
}
}
// 使css
interface IDTLoginFrameParams {
id: string; // ID'#'
width?: number; // iframe280300
height?: number; // iframe280300
}
// isPre
interface IDTLoginLoginParams {
redirect_uri: string; // urlencode
response_type: string; // code
client_id: string; //
scope: string; // openid+corpidorg_typecorpId
prompt: string; // consent
state?: string; //
org_type?: string; // scopeopenid+corpid
corpId?: string; // scopeopenid+corpid
exclusiveLogin?: string; // true
exclusiveCorpId?: string; // exclusiveLogintruecorpId
}
interface IDTLoginSuccess {
redirectUrl: string; // 使
authCode: string; // authCode
state?: string; // state
}
onMounted(() => {
getThirdpartyList();
@ -192,30 +279,69 @@
config.userInfo.url + "/user/thirdparty/list"
);
if (result.ok) {
const data = await result.json();
console.log(data, "data");
await result.json();
}
};
const setPhone = async () => {
console.log("123");
const res = await fetch(config.userInfo.url + "/user/editdata", {
method: "POST",
body: JSON.stringify({
phone: userName.value,
}),
headers: {
ClientID: store.tempClientId,
Authorization: store.tempToken,
},
});
if (res.ok) {
notifySuccess("手机号设置成功");
} else {
notifyError("手机号设置失败");
const onDingDingScan = () => {
ThirdPartyLoginMethod.value = "dingding";
initDingDingScan();
};
const initDingDingScan = async () => {
try {
//
await loadScript(
"https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"
);
const res = await fetch("http://192.168.1.10:8816/user/ding/conf");
const data = await res.json();
// DTFrameLogin
window.DTFrameLogin(
{
id: "dd-qr-code",
width: 200,
height: 300,
},
{
redirect_uri: encodeURIComponent(data.data.host),
client_id: data.data.client_id,
scope: "openid",
response_type: "code",
state: "xxxxxxxxx",
prompt: "consent",
},
(loginResult: any) => {
const { authCode } = loginResult;
onLogin(authCode);
},
(errorMsg: any) => {
console.log("二维码获取错误", errorMsg);
}
);
} catch (error) {
console.error(error);
}
};
// JS
function loadScript(url: string): Promise<void> {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = url;
script.onload = () => resolve();
script.onerror = () =>
reject(new Error(`Failed to load script ${url}`));
document.head.appendChild(script);
});
}
const onSendCode = () => {
console.log("发送验证码");
};
const thirdPartyPlatforms = [
{
name: "qywechat",
@ -268,18 +394,19 @@
}
});
async function onLogin() {
async function onLogin(authCode?: string) {
if (loginCallback) {
const platform = localStorage.getItem("ThirdPartyPlatform");
const code = router.currentRoute.value.query.code as string;
const code =
authCode || (router.currentRoute.value.query.code as string);
console.log(platform, "platform");
// 使
const platformCodeMap: Record<string, string> = {
github: "github",
gitee: "gitee",
wechat: "wechat",
qywechat: "qywechat",
qq: "qq",
dingding: "dingtalk_scan",
};
//
@ -287,7 +414,6 @@
//
const login_type = codeParam ? codeParam : "password";
console.log(login_type, "login_type");
const param = codeParam
? { code: code }
@ -304,10 +430,6 @@
}
}
const toggleRegister = () => {
isRegisterMode.value = !isRegisterMode.value;
};
const toggleUserSwitch = () => {
config.userType = "person";
setSystemConfig(config);
@ -397,7 +519,7 @@
const res = await comp.json();
if (res.success) {
notifyError("注册成功");
toggleRegister();
// toggleRegister();
} else {
notifyError(res.message);
return;
@ -405,6 +527,23 @@
} catch (error) {
console.error(error);
}
// console.log("123");
// const res = await fetch(config.userInfo.url + "/user/editdata", {
// method: "POST",
// body: JSON.stringify({
// phone: userName.value,
// }),
// headers: {
// ClientID: store.tempClientId,
// Authorization: store.tempToken,
// },
// });
// if (res.ok) {
// notifySuccess("");
// } else {
// notifyError("");
// }
};
const onThirdPartyLogin = async (platform: string) => {
@ -422,7 +561,21 @@
return await authWithGitee();
};
break;
//
case "dingding":
loginFunction = async function () {
return await authWithDingDing();
};
break;
case "qywechat":
loginFunction = async function () {
return await authWithWechat();
};
break;
case "phone":
loginFunction = async function () {
return await authWithPhone();
};
break;
default:
notifyError("不支持的第三方登录平台");
return;
@ -436,6 +589,16 @@
}
};
const authWithPhone = async (): Promise<boolean> => {
ThirdPartyLoginMethod.value = "phone";
return true;
};
const authWithDingDing = async (): Promise<boolean> => {
onDingDingScan();
return true;
};
const authWithGithub = async (): Promise<boolean> => {
// stateCSRF,使
const state = Date.now() + Math.random().toString(36).substring(2, 15);
@ -472,16 +635,30 @@
}
};
const authWithWechat = (): boolean | PromiseLike<boolean> => {
throw new Error("Function not implemented.");
};
const authWithQQ = (): boolean | PromiseLike<boolean> => {
throw new Error("Function not implemented.");
};
const authWithSina = (): boolean | PromiseLike<boolean> => {
throw new Error("Function not implemented.");
const authWithWechat = async (): Promise<boolean> => {
ThirdPartyLoginMethod.value = "qywechat";
const res = await fetch(
"http://server001.godoos.com/user/qyweixin/qrcode"
);
if (res.ok) {
const data = await res.json();
if (data.success && data.data.url) {
//
QRCode.toCanvas(
document.getElementById("qywechat-qr-code"),
data.data.url,
function (error: any) {
if (error) console.error(error);
console.log("二维码生成成功");
}
);
} else {
notifyError("获取授权URL失败");
}
} else {
notifyError("网络错误,无法获取二维码");
}
return true;
};
const authWithGitee = async (): Promise<boolean> => {
@ -646,6 +823,23 @@
}
}
.qr-code {
width: 200px;
height: 200px;
padding: 10px;
margin: 0 auto;
overflow: hidden;
border: 1px solid rgb(203, 203, 203);
border-radius: 10px;
:deep(#dd-qr-code) {
width: 200px;
height: 200px;
iframe {
margin-top: -50px;
}
}
}
@keyframes outan {
0% {
opacity: 1;
@ -660,4 +854,14 @@
opacity: 0;
}
}
.send-code-btn {
border: none;
height: 40px;
background: #409eff;
color: #fff;
border-radius: 4px;
line-height: 40px;
cursor: pointer;
}
</style>

5
frontend/src/stores/login.ts

@ -9,12 +9,11 @@ export const useLoginStore = defineStore("login", () => {
const tempToken = ref<string>("");
// 临时clientId
const tempClientId = ref<string>("");
const page = ref("login");
const ThirdPartyLoginMethod = ref("login");
return {
ThirdPartyPlatform,
State,
page,
ThirdPartyLoginMethod,
tempToken,
tempClientId,
};

2
frontend/src/system/index.ts

@ -226,7 +226,7 @@ export class System {
const loginStore = useLoginStore();
loginStore.tempToken = jsondata.data.token;
loginStore.tempClientId = jsondata.data.client_id;
loginStore.page = "setphone";
loginStore.ThirdPartyLoginMethod = "register";
return true;
}

2
frontend/src/system/router.ts

@ -19,7 +19,7 @@ const routes = [
path: "/:pathMatch(.*)*",
name: "not-found",
component: () => import('../components/window/NotFound.vue')
}
},
]
const router = createRouter({

0
frontend/src/util/thirdlogin.ts

Loading…
Cancel
Save