mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-08-21 21:47:00 +08:00
@@ -683,7 +683,7 @@ export class KeyService {
|
||||
if (loginRequired) {
|
||||
return {
|
||||
success: false,
|
||||
error: '微信已启动但尚未完成登录,请先在微信客户端完成登录后再重试自动获取密钥。',
|
||||
error: '微信可能已经启动并登录,请先在微信客户端保持未登录状态,具体点击上方“查看5分钟上手教程” ',
|
||||
logs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export function AIProviderEditor({
|
||||
)
|
||||
|
||||
return (
|
||||
<section className="settings-card ai-provider-editor">
|
||||
<section id="ai-provider-editor" className="settings-card ai-provider-editor">
|
||||
<header>
|
||||
<div>
|
||||
<h2>{editing ? '编辑供应商' : '新增供应商'}</h2>
|
||||
@@ -66,7 +66,11 @@ export function AIProviderEditor({
|
||||
<div className="ai-provider-form-grid">
|
||||
<label>
|
||||
供应商名称
|
||||
<input value={provider.name} onChange={(event) => patch({ name: event.target.value })} />
|
||||
<input
|
||||
id="ai-provider-name"
|
||||
value={provider.name}
|
||||
onChange={(event) => patch({ name: event.target.value })}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
供应商 ID
|
||||
@@ -148,16 +152,22 @@ export function AIProviderEditor({
|
||||
<div className="ai-model-table">
|
||||
{provider.models.map((model, index) => (
|
||||
<div className="ai-model-row" key={`${index}-${model.id}`}>
|
||||
<input
|
||||
value={model.name}
|
||||
onChange={(event) => patchModel(index, { name: event.target.value })}
|
||||
placeholder="显示名称"
|
||||
/>
|
||||
<input
|
||||
value={model.id}
|
||||
onChange={(event) => patchModel(index, { id: event.target.value })}
|
||||
placeholder="实际模型 ID"
|
||||
/>
|
||||
<label className="ai-model-identity-field">
|
||||
<span>模型名称</span>
|
||||
<input
|
||||
value={model.name}
|
||||
onChange={(event) => patchModel(index, { name: event.target.value })}
|
||||
placeholder="例如:DeepSeek Chat"
|
||||
/>
|
||||
</label>
|
||||
<label className="ai-model-identity-field">
|
||||
<span>模型 ID</span>
|
||||
<input
|
||||
value={model.id}
|
||||
onChange={(event) => patchModel(index, { id: event.target.value })}
|
||||
placeholder="例如:deepseek-chat"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -314,5 +324,9 @@ export function AIProviderEditor({
|
||||
}
|
||||
|
||||
function emptyModel(): AIModelDefinition {
|
||||
return { name: '', id: '', capabilities: { chat: true, vision: false, ocr: false, longContext: false } }
|
||||
return {
|
||||
name: '',
|
||||
id: '',
|
||||
capabilities: { chat: true, vision: false, ocr: false, longContext: false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useReducer } from 'react'
|
||||
import { useCallback, useEffect, useReducer, useRef } from 'react'
|
||||
import type {
|
||||
AIProviderConfig,
|
||||
AIProviderSummary,
|
||||
@@ -16,6 +16,11 @@ export function useAIModelSettingsController({
|
||||
onNotice: (message: string) => void
|
||||
}): AIModelSettingsController {
|
||||
const [state, dispatch] = useReducer(aiModelSettingsReducer, initialAIModelSettingsState)
|
||||
const onRuntimeChangeRef = useRef(onRuntimeChange)
|
||||
|
||||
useEffect(() => {
|
||||
onRuntimeChangeRef.current = onRuntimeChange
|
||||
}, [onRuntimeChange])
|
||||
|
||||
const refresh = useCallback(async (): Promise<void> => {
|
||||
const [list, runtime] = await Promise.all([
|
||||
@@ -24,8 +29,8 @@ export function useAIModelSettingsController({
|
||||
])
|
||||
if (!list.success) return dispatch({ type: 'ERROR', error: list.error || '供应商配置读取失败' })
|
||||
dispatch({ type: 'LOADED', providers: list.providers, runtime })
|
||||
onRuntimeChange(runtime)
|
||||
}, [onRuntimeChange])
|
||||
onRuntimeChangeRef.current(runtime)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
void refresh()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import type { AIRuntimeModelConfig } from '../../../../../shared/ai-provider'
|
||||
import { AIProviderCard } from '../ai-model/AIProviderCard'
|
||||
import { AIProviderEditor } from '../ai-model/AIProviderEditor'
|
||||
@@ -12,10 +13,25 @@ export function AIModelPage({
|
||||
onNotice: (message: string) => void
|
||||
}): React.ReactElement {
|
||||
const controller = useAIModelSettingsController({ onRuntimeChange, onNotice })
|
||||
const shouldRevealNewEditor = useRef(false)
|
||||
const runtime = controller.state.runtime
|
||||
const defaultProvider = controller.state.providers.find(
|
||||
(provider) => provider.id === runtime?.providerId
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!controller.state.editor || !shouldRevealNewEditor.current) return
|
||||
shouldRevealNewEditor.current = false
|
||||
const editor = document.getElementById('ai-provider-editor')
|
||||
editor?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
editor?.querySelector<HTMLInputElement>('#ai-provider-name')?.focus({ preventScroll: true })
|
||||
}, [controller.state.editor])
|
||||
|
||||
const openNewProvider = (): void => {
|
||||
shouldRevealNewEditor.current = true
|
||||
controller.openNew()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="settings-page ai-model-page">
|
||||
<header className="settings-page-header">
|
||||
@@ -23,7 +39,7 @@ export function AIModelPage({
|
||||
<h1>AI 模型</h1>
|
||||
<p>管理模型供应商、连接信息和默认模型</p>
|
||||
</div>
|
||||
<button className="database-key-primary" onClick={controller.openNew}>
|
||||
<button className="database-key-primary" onClick={openNewProvider}>
|
||||
添加供应商
|
||||
</button>
|
||||
</header>
|
||||
|
||||
@@ -1777,6 +1777,16 @@
|
||||
white-space: nowrap;
|
||||
font-weight: 400;
|
||||
}
|
||||
.ai-model-row .ai-model-identity-field {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 5px;
|
||||
justify-self: stretch;
|
||||
color: #66706b;
|
||||
font-family: inherit;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.ai-provider-advanced,
|
||||
.ai-provider-preview {
|
||||
border: 1px solid #e3e8e5;
|
||||
|
||||
Reference in New Issue
Block a user