koishi-plugin-media-luna 0.0.35 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -248,6 +248,25 @@
248
248
  </el-select>
249
249
  </template>
250
250
 
251
+ <!-- Select Remote 类型 -->
252
+ <template v-else-if="field.type === 'select-remote'">
253
+ <el-select
254
+ :model-value="getOverrideValue(plugin.id, field.key)"
255
+ @update:model-value="setOverrideValue(plugin.id, field.key, $event)"
256
+ :placeholder="`全局: ${plugin.config[field.key] ?? '未设置'}`"
257
+ :loading="isRemoteLoading(field)"
258
+ clearable
259
+ filterable
260
+ >
261
+ <el-option
262
+ v-for="opt in getRemoteOptions(field, plugin)"
263
+ :key="String(opt.value)"
264
+ :label="opt.label"
265
+ :value="opt.value"
266
+ />
267
+ </el-select>
268
+ </template>
269
+
251
270
  <!-- Number 类型 -->
252
271
  <template v-else-if="field.type === 'number'">
253
272
  <el-input-number
@@ -257,6 +276,17 @@
257
276
  />
258
277
  </template>
259
278
 
279
+ <!-- Textarea 类型 -->
280
+ <template v-else-if="field.type === 'textarea'">
281
+ <el-input
282
+ :model-value="getOverrideValue(plugin.id, field.key)"
283
+ @update:model-value="setOverrideValue(plugin.id, field.key, $event)"
284
+ type="textarea"
285
+ :rows="3"
286
+ :placeholder="`全局: ${plugin.config[field.key] ?? '未设置'}`"
287
+ />
288
+ </template>
289
+
260
290
  <!-- Text/String 类型 (默认) -->
261
291
  <template v-else>
262
292
  <el-input
@@ -294,8 +324,8 @@
294
324
  </template>
295
325
 
296
326
  <script setup lang="ts">
297
- import { ref, computed, watch } from 'vue'
298
- import { message } from '@koishijs/client'
327
+ import { ref, computed, watch, onMounted } from 'vue'
328
+ import { message, send } from '@koishijs/client'
299
329
  import { ChannelConfig, ConfigField, ConnectorDefinition, MiddlewareInfo, FieldDefinition } from '../types'
300
330
  import { channelApi, connectorApi, middlewareApi, pluginApi, PluginInfo } from '../api'
301
331
  import TagInput from './TagInput.vue'
@@ -332,6 +362,10 @@ const connectorFields = ref<Record<string, ConfigField[]>>({})
332
362
  const allMiddlewares = ref<MiddlewareInfo[]>([])
333
363
  const allPlugins = ref<PluginInfo[]>([])
334
364
 
365
+ // 远程选项缓存(用于 select-remote 类型字段)
366
+ const remoteOptionsCache = ref<Record<string, { label: string; value: any }[]>>({})
367
+ const remoteOptionsLoading = ref<Record<string, boolean>>({})
368
+
335
369
  // 表单
336
370
  const form = ref<Partial<ChannelConfig>>({
337
371
  name: '',
@@ -397,6 +431,92 @@ const pluginsWithConfig = computed(() => {
397
431
  return allPlugins.value.filter(p => p.configFields && p.configFields.length > 0)
398
432
  })
399
433
 
434
+ // ============ 远程选项相关方法 ============
435
+
436
+ // 构建带参数的缓存 key
437
+ const buildCacheKey = (source: string, params?: Record<string, any>) => {
438
+ if (!params || Object.keys(params).length === 0) {
439
+ return source
440
+ }
441
+ const sortedParams = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join('&')
442
+ return `${source}?${sortedParams}`
443
+ }
444
+
445
+ // 获取远程选项(异步)
446
+ const fetchRemoteOptions = async (source: string, params?: Record<string, any>) => {
447
+ const cacheKey = buildCacheKey(source, params)
448
+
449
+ if (remoteOptionsCache.value[cacheKey] || remoteOptionsLoading.value[cacheKey]) {
450
+ return
451
+ }
452
+
453
+ remoteOptionsLoading.value[cacheKey] = true
454
+ try {
455
+ const result = await send(source, params)
456
+ if (result?.success && Array.isArray(result.data)) {
457
+ remoteOptionsCache.value[cacheKey] = result.data
458
+ } else {
459
+ remoteOptionsCache.value[cacheKey] = []
460
+ }
461
+ } catch (e) {
462
+ console.error(`Failed to fetch options from ${source}:`, e)
463
+ remoteOptionsCache.value[cacheKey] = []
464
+ } finally {
465
+ remoteOptionsLoading.value[cacheKey] = false
466
+ }
467
+ }
468
+
469
+ // 获取字段参数(基于 dependsOn 和插件配置)
470
+ const getFieldParams = (field: FieldDefinition, plugin: PluginInfo): Record<string, any> | undefined => {
471
+ if (!field.dependsOn) return undefined
472
+ // 优先使用覆盖值,其次使用全局配置
473
+ const overrideValue = form.value.pluginOverrides?.[plugin.id]?.[field.dependsOn]
474
+ const globalValue = plugin.config[field.dependsOn]
475
+ const dependValue = overrideValue !== undefined ? overrideValue : globalValue
476
+
477
+ if (dependValue === undefined || dependValue === null || dependValue === '') {
478
+ return undefined
479
+ }
480
+ // 提取 dependsOn 的最后一段作为参数名
481
+ const paramName = field.dependsOn.includes('.')
482
+ ? field.dependsOn.split('.').pop()!
483
+ : field.dependsOn
484
+ return { [paramName]: dependValue }
485
+ }
486
+
487
+ // 获取字段的缓存 key
488
+ const getFieldCacheKey = (field: FieldDefinition, plugin: PluginInfo): string => {
489
+ if (!field.optionsSource) return ''
490
+ const params = getFieldParams(field, plugin)
491
+ return buildCacheKey(field.optionsSource, params)
492
+ }
493
+
494
+ // 获取远程选项(同步访问缓存)
495
+ const getRemoteOptions = (field: FieldDefinition, plugin: PluginInfo) => {
496
+ const cacheKey = getFieldCacheKey(field, plugin)
497
+ if (!cacheKey) return []
498
+
499
+ // 如果还没加载,触发加载
500
+ if (!remoteOptionsCache.value[cacheKey] && !remoteOptionsLoading.value[cacheKey]) {
501
+ const params = getFieldParams(field, plugin)
502
+ fetchRemoteOptions(field.optionsSource!, params)
503
+ }
504
+
505
+ return remoteOptionsCache.value[cacheKey] || []
506
+ }
507
+
508
+ // 检查是否正在加载
509
+ const isRemoteLoading = (field: FieldDefinition) => {
510
+ if (!field.optionsSource) return false
511
+ // 简单检查,不考虑参数
512
+ for (const key of Object.keys(remoteOptionsLoading.value)) {
513
+ if (key.startsWith(field.optionsSource) && remoteOptionsLoading.value[key]) {
514
+ return true
515
+ }
516
+ }
517
+ return false
518
+ }
519
+
400
520
  // 方法
401
521
  const getPhaseMiddlewares = (phaseId: string) => {
402
522
  return allMiddlewares.value.filter(mw => mw.phase === phaseId)
@@ -183,7 +183,11 @@ const getFieldParams = (field: ConfigField): Record<string, any> | undefined =>
183
183
  if (dependValue === undefined || dependValue === null || dependValue === '') {
184
184
  return undefined
185
185
  }
186
- return { [field.dependsOn]: dependValue }
186
+ // 提取 dependsOn 的最后一段作为参数名(例如 'promptEnhance.platform' -> 'platform')
187
+ const paramName = field.dependsOn.includes('.')
188
+ ? field.dependsOn.split('.').pop()!
189
+ : field.dependsOn
190
+ return { [paramName]: dependValue }
187
191
  }
188
192
 
189
193
  // 获取字段的缓存 key