diff --git a/packages/kv-login/package.json b/packages/kv-login/package.json index 51a7b64..c3d31d7 100644 --- a/packages/kv-login/package.json +++ b/packages/kv-login/package.json @@ -19,7 +19,7 @@ ], "author": "abearxiong (https://www.xiongxiao.me)", "license": "MIT", - "packageManager": "pnpm@10.24.0", + "packageManager": "pnpm@10.26.2", "publishConfig": { "access": "public" }, @@ -27,7 +27,8 @@ "dependencies": { "@kevisual/context": "^0.0.4", "@kevisual/query-login": "^0.0.7", - "lit-html": "^3.3.1", + "crypto-js": "^4.2.0", + "lit-html": "^3.3.2", "qrcode": "^1.5.4" }, "exports": { @@ -36,6 +37,7 @@ }, "types": "./types/index.d.ts", "devDependencies": { + "@kevisual/api": "^0.0.8", "@types/bun": "^1.3.5" } } \ No newline at end of file diff --git a/packages/kv-login/src/modules/login-handle.ts b/packages/kv-login/src/modules/login-handle.ts index b5ac59f..359ecab 100644 --- a/packages/kv-login/src/modules/login-handle.ts +++ b/packages/kv-login/src/modules/login-handle.ts @@ -2,9 +2,11 @@ import { query } from './query.ts'; import { createMessage } from '../pages/kv-message.ts'; import { WX_MP_APP_ID } from '../pages/kv-login.ts'; import { emit } from './mitt.ts'; +import { Query } from '@kevisual/query'; +import { QueryLoginBrowser } from '@kevisual/api/login' export const message = createMessage(); type LoginOpts = { - loginMethod: 'password' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket', + loginMethod: 'password' | 'web' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket', data: any, el: HTMLElement } @@ -40,10 +42,28 @@ export const loginHandle = async (opts: LoginOpts) => { case 'wechat': await loginByWeChat(data) break + case 'web': + await loginByWeb(data) + break default: console.warn('未知的登录方式:', loginMethod) } } +const loginByWeb = async (data: {}) => { + const url = new URL("https://kevisual.cn/api/router"); + const query = new Query({ url: "https://kevisual.cn/api/router" }) + const login = new QueryLoginBrowser({ query }) + // @ts-ignore + const res = login.loginWithWeb(url.origin, {}) + console.log('打开网页登录:', res) + window.open(res.url, '_blank'); + const status = await login.pollLoginStatus(res); + if (status) { + redirectHome() + } else { + message.error('网页登录失败,请重试') + } +} /** * 使用用户名和密码登录 * @param data diff --git a/packages/kv-login/src/pages/kv-login.ts b/packages/kv-login/src/pages/kv-login.ts index 4044627..2632e14 100644 --- a/packages/kv-login/src/pages/kv-login.ts +++ b/packages/kv-login/src/pages/kv-login.ts @@ -1,10 +1,11 @@ import { render, html } from 'lit-html' import { unsafeHTML } from 'lit-html/directives/unsafe-html.js' -import { loginHandle, checkWechat, getQrCode, checkMpQrCodeLogin } from '../modules/login-handle.ts' +import { loginHandle, checkWechat, getQrCode, checkMpQrCodeLogin, redirectHome } from '../modules/login-handle.ts' import { setWxerwma } from '../modules/wx/ws-login.ts'; import { useCreateLoginQRCode } from '../modules/wx-mp/qr.ts'; import { eventEmitter } from '../modules/mitt.ts'; import { useContextKey } from '@kevisual/context' + export const loginEmitter = useContextKey('login-emitter', eventEmitter); export const WX_MP_APP_ID = "wxff97d569b1db16b6"; interface LoginMethod { @@ -17,29 +18,31 @@ const wxmpSvg = `` const phone = `` const pwd = `` - +const web = `` const icons: any = { pwd, + web, phone, wxmpSvg, wxOpenSvg } const DefaultLoginMethods: LoginMethod[] = [ { id: 'password', name: '密码登录', icon: 'pwd' }, + { id: 'web', name: '网页登录', icon: 'web' }, { id: 'wechat', name: '微信登录', icon: 'wxmpSvg', appid: "wx9378885c8390e09b" }, { id: 'wechat-mp', name: '微信公众号', icon: 'wxOpenSvg', appid: WX_MP_APP_ID }, { id: 'wechat-mp-ticket', name: '微信公众号', icon: 'wxOpenSvg' }, { id: 'phone', name: '手机号登录', icon: 'phone' } ] -const LoginMethods = ['password', 'phone', 'wechat', 'wechat-mp', 'wechat-mp-ticket'] as const; -type LoginMethods = 'password' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket'; +const LoginMethods = ['password', 'web', 'phone', 'wechat', 'wechat-mp', 'wechat-mp-ticket'] as const; +type LoginMethods = 'password' | 'web' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket'; const getLoginMethodByDomain = (): LoginMethod[] => { let domain = window.location.host let methods: LoginMethods[] = [] - const has51015 = domain.includes('51015'); - if (has51015) { - domain = 'localhost:51015' + const has51 = domain.includes('localhost') && (domain.endsWith('51515') || domain.endsWith('51015')); + if (has51) { + domain = 'localhost' } switch (domain) { case 'kevisual.xiongxiao.me': @@ -48,11 +51,11 @@ const getLoginMethodByDomain = (): LoginMethod[] => { case 'kevisual.cn': methods = ['password', 'wechat-mp-ticket', 'wechat',] break; - case 'localhost:51015': - methods = ['password'] + case 'localhost': + methods = ['password', 'web'] break default: - methods = ['password', 'phone', 'wechat', 'wechat-mp', 'wechat-mp-ticket'] + methods = ['password', 'web', 'phone', 'wechat', 'wechat-mp', 'wechat-mp-ticket'] break; } return DefaultLoginMethods.filter(method => methods.includes(method.id)) @@ -161,7 +164,8 @@ class KvLogin extends HTMLElement { username: username?.value || '', password: password?.value || '' } - + case 'web': + return {} case 'phone': const phone = this.shadowRoot.querySelector('#phone') as HTMLInputElement const code = this.shadowRoot.querySelector('#code') as HTMLInputElement @@ -210,7 +214,14 @@ class KvLogin extends HTMLElement { ` } - + private renderWebForm() { + return html` +
+ + +
+ ` + } private renderPhoneForm() { return html`
@@ -308,6 +319,8 @@ class KvLogin extends HTMLElement { switch (this.selectedMethod) { case 'password': return this.renderPasswordForm() + case 'web': + return this.renderWebForm() case 'phone': return this.renderPhoneForm() case 'wechat': diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ccf8096..51f8401 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,6 +130,31 @@ importers: specifier: ^7.3.0 version: 7.3.0(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0) + packages/kv-login: + dependencies: + '@kevisual/context': + specifier: ^0.0.4 + version: 0.0.4 + '@kevisual/query-login': + specifier: ^0.0.7 + version: 0.0.7(@kevisual/query@0.0.33) + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + lit-html: + specifier: ^3.3.2 + version: 3.3.2 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 + devDependencies: + '@kevisual/api': + specifier: ^0.0.8 + version: 0.0.8 + '@types/bun': + specifier: ^1.3.5 + version: 1.3.5 + packages/user-login: dependencies: '@floating-ui/dom': @@ -904,6 +929,9 @@ packages: '@kevisual/ai@0.0.19': resolution: {integrity: sha512-AFc8m6OcHZNxCb88bvzhvwWTZ4EVYyPupBzPUsLKLpdNBvsqm9TRboKCM2brJj2cqHnm+H+RbAk9AcGJkYhRCA==} + '@kevisual/api@0.0.8': + resolution: {integrity: sha512-dHF0zUuepccmmTrt1Yh2xfM5zWrpOR7cdTxiyu/ikA+6uK1kkA+Y79vE6PeyI+XuSp+6g3GiuBzisNIeWGO45Q==} + '@kevisual/cache@0.0.2': resolution: {integrity: sha512-2Cl5KF2Gi27uLfhO6CdTMFnRzx9vYnqevAo7d9ab3rOaqTgF8tLeAXglXyRbaWW3WUbHU2XaOb4r98uUsqIQQw==} @@ -916,6 +944,9 @@ packages: '@kevisual/kv-login@0.1.3': resolution: {integrity: sha512-ASl8Y4mapW7bI8CXhx/gkAYUVpFwgQP0YnWzZ6rXG46Bba2yW2F2mEQnIWNvqRGx1YYCZtft1kIJicXHSC6UOw==} + '@kevisual/load@0.0.6': + resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==} + '@kevisual/logger@0.0.4': resolution: {integrity: sha512-+fpr92eokSxoGOW1SIRl/27lPuO+zyY+feR5o2Q4YCNlAdt2x64NwC/w8r/3NEC5QenLgd4K0azyKTI2mHbARw==} @@ -1906,6 +1937,9 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/bun@1.3.5': + resolution: {integrity: sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==} + '@types/d3-array@3.2.2': resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} @@ -2197,6 +2231,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bun-types@1.3.5: + resolution: {integrity: sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==} + bytestreamjs@2.0.1: resolution: {integrity: sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==} engines: {node: '>=6.0.0'} @@ -2339,6 +2376,9 @@ packages: crossws@0.3.5: resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -3082,6 +3122,9 @@ packages: lit-html@3.3.1: resolution: {integrity: sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==} + lit-html@3.3.2: + resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -5044,6 +5087,12 @@ snapshots: '@kevisual/permission': 0.0.3 '@kevisual/query': 0.0.31 + '@kevisual/api@0.0.8': + dependencies: + '@kevisual/load': 0.0.6 + es-toolkit: 1.43.0 + nanoid: 5.1.6 + '@kevisual/cache@0.0.2(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)': dependencies: '@rollup/plugin-commonjs': 28.0.3(rollup@4.52.5) @@ -5071,6 +5120,10 @@ snapshots: transitivePeerDependencies: - '@kevisual/query' + '@kevisual/load@0.0.6': + dependencies: + eventemitter3: 5.0.1 + '@kevisual/logger@0.0.4': {} '@kevisual/permission@0.0.3': {} @@ -6139,6 +6192,10 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@types/bun@1.3.5': + dependencies: + bun-types: 1.3.5 + '@types/d3-array@3.2.2': {} '@types/d3-axis@3.0.6': @@ -6603,6 +6660,10 @@ snapshots: buffer-from@1.1.2: optional: true + bun-types@1.3.5: + dependencies: + '@types/node': 22.10.3 + bytestreamjs@2.0.1: {} camelcase@5.3.1: {} @@ -6723,6 +6784,8 @@ snapshots: dependencies: uncrypto: 0.1.3 + crypto-js@4.2.0: {} + css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -7557,6 +7620,10 @@ snapshots: dependencies: '@types/trusted-types': 2.0.7 + lit-html@3.3.2: + dependencies: + '@types/trusted-types': 2.0.7 + locate-path@5.0.0: dependencies: p-locate: 4.1.0