fix: fix bugs

This commit is contained in:
2025-11-30 21:40:41 +08:00
parent 6ff8d7acde
commit 01c7a59e02
7 changed files with 118 additions and 56 deletions

View File

@@ -21,6 +21,7 @@
"@astrojs/sitemap": "^3.6.0",
"@floating-ui/dom": "^1.7.4",
"@kevisual/context": "^0.0.4",
"@kevisual/kv-login": "^0.0.1",
"@kevisual/query": "0.0.29",
"@kevisual/query-login": "^0.0.6",
"@kevisual/registry": "^0.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@kevisual/kv-login",
"version": "0.0.1",
"version": "0.0.2",
"description": "",
"main": "src/main.ts",
"scripts": {
@@ -8,7 +8,7 @@
"build": "vite build --config vite-lib.config.ts",
"build:test": "vite build",
"prepub": "rm -rf ./dist && pnpm run build:test",
"pub": "ev deploy ./dist -k kv-login-test -v 0.0.1 -u -y yes"
"pub": "ev deploy ./dist -k kv-login-test -v 0.0.2 -u -y yes"
},
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",

View File

@@ -3,7 +3,7 @@ import { createMessage } from '../pages/kv-message.ts';
import { WX_MP_APP_ID } from '../pages/kv-login.ts';
export const message = createMessage();
type LoginOpts = {
loginMethod: 'password' | 'phone' | 'wechat' | 'wechat-mp',
loginMethod: 'password' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket',
data: any,
el: HTMLElement
}
@@ -38,7 +38,11 @@ export const loginHandle = async (opts: LoginOpts) => {
console.warn('未知的登录方式:', loginMethod)
}
}
/**
* 使用用户名和密码登录
* @param data
* @returns
*/
const loginByPassword = async (data: { username: string, password: string }) => {
console.log('使用用户名密码登录:', data)
let needLogin = true; // 这里可以根据实际情况决定是否需要登录, 只能判断密码登录和手机号登录
@@ -185,4 +189,49 @@ const checkMpWechatInWx = async () => {
setTimeout(() => {
checkMpWechat();
}, 100);
}, 100);
export const getQrCode = async () => {
const res = await query.post({
path: 'wx',
key: 'get-qrcode-ticket'
})
if (res.code !== 200) {
message.error('获取二维码失败');
return null;
}
return res?.data as { ticket: string, url: string }
}
export const checkMpQrCodeLogin = (ticket: string) => {
let run = true;
const fetchLoginStatus = async () => {
const res = await query.post({
path: 'wx',
key: 'check-qrcode-login',
payload: { ticket }
})
if (res.code === 200) {
message.success('登录成功');
clearTimeout(timer);
redirectHome();
} else {
// message.error(res.message || '登录失败');
if (res.code === 401) {
console.log('等待扫码登录...');
} else {
console.log('扫码登录状态:', res);
}
if (run) {
setTimeout(fetchLoginStatus, 2000);
}
}
}
const timer = setTimeout(fetchLoginStatus, 2000);
const close = () => {
console.log('停止检测扫码登录状态');
clearTimeout(timer);
run = false
}
return close;
}

View File

@@ -1,5 +1,5 @@
import { render, html } from 'lit-html'
import { loginHandle, checkWechat } from '../modules/login-handle.ts'
import { loginHandle, checkWechat, getQrCode, checkMpQrCodeLogin } from '../modules/login-handle.ts'
import { setWxerwma } from '../modules/wx/ws-login.ts';
import { useCreateLoginQRCode } from '../modules/wx-mp/qr.ts';
export const WX_MP_APP_ID = "wxff97d569b1db16b6";
@@ -13,9 +13,10 @@ const DefaultLoginMethods: LoginMethod[] = [
{ id: 'password', name: '密码登录', icon: '🔒' },
{ id: 'wechat', name: '微信登录', icon: '💬', appid: "wx9378885c8390e09b" },
{ id: 'wechat-mp', name: '微信公众号登录', icon: '💬', appid: WX_MP_APP_ID },
{ id: 'wechat-mp-ticket', name: '微信公众号登录', icon: '💬' },
{ id: 'phone', name: '手机号登录', icon: '📱' }
]
type LoginMethods = 'password' | 'phone' | 'wechat' | 'wechat-mp'
type LoginMethods = 'password' | 'phone' | 'wechat' | 'wechat-mp' | 'wechat-mp-ticket';
const getLoginMethodByDomain = (): LoginMethod[] => {
const domain = window.location.hostname
let methods: LoginMethods[] = []
@@ -24,10 +25,10 @@ const getLoginMethodByDomain = (): LoginMethod[] => {
methods = ['password', 'wechat-mp']
break;
case 'kevisual.cn':
methods = ['password', 'wechat']
methods = ['password', 'wechat', 'wechat-mp-ticket']
break;
default:
methods = ['password', 'phone', 'wechat', 'wechat-mp']
methods = ['password', 'phone', 'wechat', 'wechat-mp', 'wechat-mp-ticket']
break;
}
return DefaultLoginMethods.filter(method => methods.includes(method.id))
@@ -224,6 +225,31 @@ class KvLogin extends HTMLElement {
</div>
`
}
private renderWechatMpTicketForm() {
const that = this;
setTimeout(async () => {
const data = await getQrCode();
if (!data) return;
const imgEl = that.shadowRoot!.querySelector('.qrcode') as HTMLImageElement;
if (data.url) {
imgEl.src = data.url;
// TODO: 轮询检测登录状态
const clear = checkMpQrCodeLogin(data.ticket)
// 当切换登录方式时,停止轮询
that.#clearTimer = clear
}
}, 0)
return html`
<div class="wechat-login">
<div class="qr-container">
<div class="qr-placeholder">
<img class="qrcode" width="300" height="300" data-appid="" data-size="200" data-ticket=""></img>
<p class="qr-desc">请使用微信扫描二维码登录</p>
</div>
</div>
</div>
`
}
private sendVerificationCode() {
console.log('发送验证码')
@@ -248,6 +274,8 @@ class KvLogin extends HTMLElement {
return this.renderWechatForm()
case 'wechat-mp':
return this.renderWechatMpForm()
case 'wechat-mp-ticket':
return this.renderWechatMpTicketForm()
default:
return this.renderPasswordForm()
}

View File

@@ -19,7 +19,6 @@
"@kevisual/query": "0.0.29",
"@kevisual/query-login": "^0.0.6",
"@kevisual/system-lib": "^0.0.22",
"@kevisual/system-ui": "^0.0.3",
"clsx": "^2.1.1",
"dayjs": "^1.11.19",
"lodash-es": "^4.17.21",

63
pnpm-lock.yaml generated
View File

@@ -23,6 +23,9 @@ importers:
'@kevisual/context':
specifier: ^0.0.4
version: 0.0.4
'@kevisual/kv-login':
specifier: ^0.0.1
version: 0.0.1(@kevisual/query@0.0.29(ws@8.18.0)(zod@3.25.76))(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)
'@kevisual/query':
specifier: 0.0.29
version: 0.0.29(ws@8.18.0)(zod@3.25.76)
@@ -141,9 +144,6 @@ importers:
'@kevisual/system-lib':
specifier: ^0.0.22
version: 0.0.22
'@kevisual/system-ui':
specifier: ^0.0.3
version: 0.0.3
clsx:
specifier: ^2.1.1
version: 2.1.1
@@ -701,92 +701,78 @@ packages:
resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.3':
resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.2.3':
resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.2.3':
resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.3':
resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.3':
resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.3':
resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.34.4':
resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.34.4':
resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-ppc64@0.34.4':
resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-s390x@0.34.4':
resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.34.4':
resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.4':
resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.4':
resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-wasm32@0.34.4':
resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==}
@@ -850,6 +836,9 @@ packages:
'@kevisual/context@0.0.4':
resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==}
'@kevisual/kv-login@0.0.1':
resolution: {integrity: sha512-xbZ0jcVOdgu8YngoqjL4C3QJ9lkWjwkRTVQc4Nk3R90iCfoBoQEUIjpC2YSUDZ1WdLpEVMP2NNsYIHpEN2+X6Q==}
'@kevisual/query-login@0.0.6':
resolution: {integrity: sha512-ZdX+sxeQaM3PV9fZXofMlxFz1RmpYIkoi47exzUgw6DADjEryBAQKRXe2/oL20NsBTV8owqaagRqffAVjq5c5g==}
peerDependencies:
@@ -876,9 +865,6 @@ packages:
'@kevisual/system-lib@0.0.22':
resolution: {integrity: sha512-kdzYlWLH+TGnNe4BfzB4Lk7jRdQE/KMQnMguWvPXdOb/aRiwJFVjlfYoNtA6BXgNC9MOpJ59CzFRc+EsMx1HRw==}
'@kevisual/system-ui@0.0.3':
resolution: {integrity: sha512-zRtUnL6wNe6R1W7X6eirDADZWeTmxZCNpLwxCLu30yeNuIhpFJdxHyOg0nX9aOZn6F0Kb6lB3Li2fZpKwdpk0w==}
'@kevisual/types@0.0.10':
resolution: {integrity: sha512-Q73uzzjk9UidumnmCvOpgzqDDvQxsblz22bIFuoiioUFJWwaparx8bpd8ArRyFojicYL1YJoFDzDZ9j9NN8grA==}
@@ -1142,28 +1128,24 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.1.17':
resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.1.17':
resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.1.17':
resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.1.17':
resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==}
@@ -1825,9 +1807,6 @@ packages:
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
inline-style-parser@0.2.6:
resolution: {integrity: sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg==}
iron-webcrypto@1.2.1:
resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
@@ -1938,28 +1917,24 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.30.2:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
@@ -2621,9 +2596,6 @@ packages:
style-to-object@1.0.11:
resolution: {integrity: sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==}
style-to-object@1.0.12:
resolution: {integrity: sha512-ddJqYnoT4t97QvN2C95bCgt+m7AAgXjVnkk/jxAfmp7EAB8nnqqZYEbMd3em7/vEomDb2LAQKAy1RFfv41mdNw==}
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -3561,6 +3533,17 @@ snapshots:
'@kevisual/context@0.0.4': {}
'@kevisual/kv-login@0.0.1(@kevisual/query@0.0.29(ws@8.18.0)(zod@3.25.76))(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)':
dependencies:
'@kevisual/query-login': 0.0.6(@kevisual/query@0.0.29(ws@8.18.0)(zod@3.25.76))(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)
lit-html: 3.3.1
qrcode: 1.5.4
transitivePeerDependencies:
- '@kevisual/query'
- rollup
- tslib
- typescript
'@kevisual/query-login@0.0.6(@kevisual/query@0.0.29(ws@8.18.0)(zod@3.25.76))(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)':
dependencies:
'@kevisual/cache': 0.0.2(rollup@4.52.5)(tslib@2.8.1)(typescript@5.8.3)
@@ -3618,12 +3601,6 @@ snapshots:
'@kevisual/system-lib@0.0.22': {}
'@kevisual/system-ui@0.0.3':
dependencies:
dayjs: 1.11.19
lodash-es: 4.17.21
style-to-object: 1.0.12
'@kevisual/types@0.0.10': {}
'@mdx-js/mdx@3.1.1':
@@ -4730,8 +4707,6 @@ snapshots:
inline-style-parser@0.2.4: {}
inline-style-parser@0.2.6: {}
iron-webcrypto@1.2.1: {}
is-alphabetical@2.0.1: {}
@@ -5846,10 +5821,6 @@ snapshots:
dependencies:
inline-style-parser: 0.2.4
style-to-object@1.0.12:
dependencies:
inline-style-parser: 0.2.6
supports-preserve-symlinks-flag@1.0.0: {}
tailwind-merge@3.4.0: {}

View File

@@ -1,6 +1,7 @@
import { app } from '../ai';
import { useEffect, useState } from 'react';
import { local } from '@/modules/query';
import '@kevisual/kv-login'
const getAppRoutes = () => {
const appRoutes = app.routes.map((route) => {
return {
@@ -52,5 +53,18 @@ export const App = () => {
setAppRoutes(getAppRoutes());
}
}>{JSON.stringify(appRoutes, null, 2)}</pre>
<kv-login>
<div id="weixinLogin"></div>
</kv-login>
</div >;
}
// Add custom element to JSX namespace for TypeScript
declare global {
namespace JSX {
interface IntrinsicElements {
'kv-login': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
}
}
}