mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
feat: 支持配置每次拉取消息数
This commit is contained in:
1 parent
352a071a21
commit
c97e2e7098
13 files changed
+92
-22
No files matched your search
@@ -30,6 +30,7 @@ export interface DataSource {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit: number
|
||||
enabled: boolean
|
||||
createdAt: number
|
||||
sessions: ImportSession[]
|
||||
@@ -62,6 +63,9 @@ export function loadDataSources(): DataSource[] {
|
||||
return []
|
||||
}
|
||||
|
||||
for (const ds of parsed) {
|
||||
if (!ds.pullLimit) ds.pullLimit = 1000
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -101,6 +105,7 @@ export function addDataSource(partial: {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit?: number
|
||||
}): DataSource {
|
||||
const sources = loadDataSources()
|
||||
const ds: DataSource = {
|
||||
@@ -109,6 +114,7 @@ export function addDataSource(partial: {
|
||||
baseUrl: normalizeBaseUrl(partial.baseUrl),
|
||||
token: partial.token,
|
||||
intervalMinutes: partial.intervalMinutes,
|
||||
pullLimit: partial.pullLimit || 1000,
|
||||
enabled: true,
|
||||
createdAt: Math.floor(Date.now() / 1000),
|
||||
sessions: [],
|
||||
@@ -120,7 +126,7 @@ export function addDataSource(partial: {
|
||||
|
||||
export function updateDataSource(
|
||||
id: string,
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'enabled'>>
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'pullLimit' | 'enabled'>>
|
||||
): DataSource | null {
|
||||
const sources = loadDataSources()
|
||||
const idx = sources.findIndex((s) => s.id === id)
|
||||
@@ -130,6 +136,7 @@ export function updateDataSource(
|
||||
if (updates.baseUrl !== undefined) ds.baseUrl = normalizeBaseUrl(updates.baseUrl)
|
||||
if (updates.token !== undefined) ds.token = updates.token
|
||||
if (updates.intervalMinutes !== undefined) ds.intervalMinutes = updates.intervalMinutes
|
||||
if (updates.pullLimit !== undefined) ds.pullLimit = updates.pullLimit
|
||||
if (updates.enabled !== undefined) ds.enabled = updates.enabled
|
||||
saveDataSources(sources)
|
||||
return ds
|
||||
|
||||
@@ -233,7 +233,6 @@ async function importTempFile(baseUrl: string, sess: ImportSession, tempFile: st
|
||||
// ==================== Core pull loop (per ImportSession) ====================
|
||||
|
||||
const MAX_PAGES_PER_PULL = 50
|
||||
const DEFAULT_PULL_LIMIT = 1000
|
||||
const PULL_OVERLAP_SECONDS = 60
|
||||
|
||||
interface PullSessionResult {
|
||||
@@ -264,7 +263,7 @@ async function executePullSession(sourceId: string, ds: DataSource, sess: Import
|
||||
since,
|
||||
offset,
|
||||
end,
|
||||
limit: DEFAULT_PULL_LIMIT,
|
||||
limit: ds.pullLimit,
|
||||
})
|
||||
|
||||
try {
|
||||
|
||||
@@ -59,7 +59,10 @@ export function registerApiHandlers(_ctx: IpcContext): void {
|
||||
|
||||
ipcMain.handle(
|
||||
'api:addDataSource',
|
||||
(_event, partial: { name?: string; baseUrl: string; token: string; intervalMinutes: number }) => {
|
||||
(
|
||||
_event,
|
||||
partial: { name?: string; baseUrl: string; token: string; intervalMinutes: number; pullLimit?: number }
|
||||
) => {
|
||||
const ds = addDataSource(partial)
|
||||
return ds
|
||||
}
|
||||
@@ -70,7 +73,7 @@ export function registerApiHandlers(_ctx: IpcContext): void {
|
||||
(
|
||||
_event,
|
||||
id: string,
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'enabled'>>
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'pullLimit' | 'enabled'>>
|
||||
) => {
|
||||
const ds = updateDataSource(id, updates)
|
||||
if (ds) {
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface DataSource {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit: number
|
||||
enabled: boolean
|
||||
createdAt: number
|
||||
sessions: ImportSession[]
|
||||
@@ -100,13 +101,14 @@ export const apiServerApi = {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit?: number
|
||||
}): Promise<DataSource> => {
|
||||
return ipcRenderer.invoke('api:addDataSource', partial)
|
||||
},
|
||||
|
||||
updateDataSource: (
|
||||
id: string,
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'enabled'>>
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'pullLimit' | 'enabled'>>
|
||||
): Promise<DataSource | null> => {
|
||||
return ipcRenderer.invoke('api:updateDataSource', id, updates)
|
||||
},
|
||||
|
||||
Vendored
+3
-1
@@ -1019,6 +1019,7 @@ interface DataSource {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit: number
|
||||
enabled: boolean
|
||||
createdAt: number
|
||||
sessions: ImportSession[]
|
||||
@@ -1057,10 +1058,11 @@ interface ApiServerApi {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit?: number
|
||||
}) => Promise<DataSource>
|
||||
updateDataSource: (
|
||||
id: string,
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'enabled'>>
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'pullLimit' | 'enabled'>>
|
||||
) => Promise<DataSource | null>
|
||||
deleteDataSource: (id: string) => Promise<boolean>
|
||||
addImportSessions: (
|
||||
|
||||
@@ -26,6 +26,7 @@ const formData = ref({
|
||||
baseUrl: '',
|
||||
token: '',
|
||||
intervalMinutes: 60,
|
||||
pullLimit: 1000,
|
||||
})
|
||||
|
||||
const remoteSessions = ref<RemoteSession[]>([])
|
||||
@@ -53,9 +54,10 @@ watch(
|
||||
baseUrl: props.manageSource.baseUrl,
|
||||
token: props.manageSource.token,
|
||||
intervalMinutes: props.manageSource.intervalMinutes,
|
||||
pullLimit: props.manageSource.pullLimit,
|
||||
}
|
||||
} else {
|
||||
formData.value = { name: '', baseUrl: '', token: '', intervalMinutes: 60 }
|
||||
formData.value = { name: '', baseUrl: '', token: '', intervalMinutes: 60, pullLimit: 1000 }
|
||||
}
|
||||
remoteSessions.value = []
|
||||
selectedSessionIds.value = new Set()
|
||||
@@ -205,6 +207,7 @@ async function handleSubmit() {
|
||||
baseUrl: formData.value.baseUrl,
|
||||
token: formData.value.token,
|
||||
intervalMinutes: formData.value.intervalMinutes,
|
||||
pullLimit: formData.value.pullLimit || undefined,
|
||||
})
|
||||
if (ds && selectedSessionIds.value.size > 0) {
|
||||
const sessions = remoteSessions.value
|
||||
@@ -273,11 +276,26 @@ function formatMessageCount(count?: number): string {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.interval') }}
|
||||
</label>
|
||||
<UInput v-model.number="formData.intervalMinutes" type="number" :min="1" class="w-full" />
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.interval') }}
|
||||
</label>
|
||||
<UInput v-model.number="formData.intervalMinutes" type="number" :min="1" class="w-full" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.pullLimit') }}
|
||||
</label>
|
||||
<UInput
|
||||
v-model.number="formData.pullLimit"
|
||||
type="number"
|
||||
:min="100"
|
||||
:max="10000"
|
||||
class="w-full"
|
||||
:placeholder="t('settings.api.dataSources.form.pullLimitPlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
|
||||
@@ -10,7 +10,7 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:open': [value: boolean]
|
||||
saved: [updates: { name: string; baseUrl: string; token: string; intervalMinutes: number }]
|
||||
saved: [updates: { name: string; baseUrl: string; token: string; intervalMinutes: number; pullLimit: number }]
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -20,6 +20,7 @@ const form = ref({
|
||||
baseUrl: '',
|
||||
token: '',
|
||||
intervalMinutes: 60,
|
||||
pullLimit: 1000,
|
||||
})
|
||||
|
||||
watch(
|
||||
@@ -31,6 +32,7 @@ watch(
|
||||
baseUrl: props.dataSource.baseUrl,
|
||||
token: props.dataSource.token,
|
||||
intervalMinutes: props.dataSource.intervalMinutes,
|
||||
pullLimit: props.dataSource.pullLimit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +44,7 @@ function save() {
|
||||
baseUrl: form.value.baseUrl,
|
||||
token: form.value.token,
|
||||
intervalMinutes: form.value.intervalMinutes,
|
||||
pullLimit: form.value.pullLimit,
|
||||
})
|
||||
emit('update:open', false)
|
||||
}
|
||||
@@ -85,11 +88,26 @@ function save() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.interval') }}
|
||||
</label>
|
||||
<UInput v-model.number="form.intervalMinutes" type="number" :min="1" class="w-full" />
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.interval') }}
|
||||
</label>
|
||||
<UInput v-model.number="form.intervalMinutes" type="number" :min="1" class="w-full" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('settings.api.dataSources.form.pullLimit') }}
|
||||
</label>
|
||||
<UInput
|
||||
v-model.number="form.pullLimit"
|
||||
type="number"
|
||||
:min="100"
|
||||
:max="10000"
|
||||
class="w-full"
|
||||
:placeholder="t('settings.api.dataSources.form.pullLimitPlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-2 pt-2">
|
||||
|
||||
@@ -128,7 +128,13 @@ function openEditSource(ds: DataSource) {
|
||||
showEditModal.value = true
|
||||
}
|
||||
|
||||
async function handleEditSaved(updates: { name: string; baseUrl: string; token: string; intervalMinutes: number }) {
|
||||
async function handleEditSaved(updates: {
|
||||
name: string
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit: number
|
||||
}) {
|
||||
if (!editingDataSource.value) return
|
||||
await store.updateDataSource(editingDataSource.value.id, updates)
|
||||
}
|
||||
|
||||
@@ -498,6 +498,8 @@
|
||||
"token": "Access Token (optional)",
|
||||
"tokenPlaceholder": "Bearer Token for the remote API",
|
||||
"interval": "Pull Interval (minutes)",
|
||||
"pullLimit": "Messages per Pull",
|
||||
"pullLimitPlaceholder": "Default 1000",
|
||||
"targetSession": "Target Session ID (optional)",
|
||||
"targetSessionPlaceholder": "Leave empty to create new session each time",
|
||||
"add": "Add"
|
||||
|
||||
@@ -497,6 +497,8 @@
|
||||
"token": "アクセストークン(任意)",
|
||||
"tokenPlaceholder": "リモート API の Bearer Token",
|
||||
"interval": "取得間隔(分)",
|
||||
"pullLimit": "1回の取得メッセージ数",
|
||||
"pullLimitPlaceholder": "デフォルト 1000",
|
||||
"targetSession": "ターゲットセッション ID(任意)",
|
||||
"targetSessionPlaceholder": "空欄の場合、毎回新規セッションを作成",
|
||||
"add": "追加"
|
||||
|
||||
@@ -498,6 +498,8 @@
|
||||
"token": "访问令牌(可选)",
|
||||
"tokenPlaceholder": "远程 API 的 Bearer Token",
|
||||
"interval": "拉取间隔(分钟)",
|
||||
"pullLimit": "每次拉取消息数",
|
||||
"pullLimitPlaceholder": "默认 1000",
|
||||
"targetSession": "目标会话 ID(可选)",
|
||||
"targetSessionPlaceholder": "留空则每次新建会话",
|
||||
"add": "添加"
|
||||
|
||||
@@ -497,6 +497,8 @@
|
||||
"token": "存取權杖(可選)",
|
||||
"tokenPlaceholder": "遠端 API 的 Bearer Token",
|
||||
"interval": "拉取間隔(分鐘)",
|
||||
"pullLimit": "每次拉取訊息數",
|
||||
"pullLimitPlaceholder": "預設 1000",
|
||||
"targetSession": "目標會話 ID(可選)",
|
||||
"targetSessionPlaceholder": "留空則每次新建會話",
|
||||
"add": "新增"
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface DataSource {
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit: number
|
||||
enabled: boolean
|
||||
createdAt: number
|
||||
sessions: ImportSession[]
|
||||
@@ -153,7 +154,13 @@ export const useApiServerStore = defineStore('apiServer', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function addDataSource(partial: { name?: string; baseUrl: string; token: string; intervalMinutes: number }) {
|
||||
async function addDataSource(partial: {
|
||||
name?: string
|
||||
baseUrl: string
|
||||
token: string
|
||||
intervalMinutes: number
|
||||
pullLimit?: number
|
||||
}) {
|
||||
try {
|
||||
const ds = await window.apiServerApi.addDataSource(partial)
|
||||
dataSources.value.push(ds)
|
||||
@@ -166,7 +173,7 @@ export const useApiServerStore = defineStore('apiServer', () => {
|
||||
|
||||
async function updateDataSource(
|
||||
id: string,
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'enabled'>>
|
||||
updates: Partial<Pick<DataSource, 'name' | 'baseUrl' | 'token' | 'intervalMinutes' | 'pullLimit' | 'enabled'>>
|
||||
) {
|
||||
try {
|
||||
const ds = await window.apiServerApi.updateDataSource(id, updates)
|
||||
|
||||
Reference in new issue
Block a user