fix(cloudtentacles): 第三轮 Bug 修复 + 体验改进 — Vue3 emit 多参数处理、SKU 刷新空缓存、新增账号改用 ElMessageBox.prompt

This commit is contained in:
yml
2026-05-20 01:36:57 +08:00
parent b4bb53f307
commit 5474d77799
4 changed files with 112 additions and 38 deletions
@@ -1,9 +1,45 @@
{ {
"enabled": true, "enabled": true,
"sources": [
{
"key": "default",
"label": "默认账号",
"baseUrl": "https://123.207.217.176", "baseUrl": "https://123.207.217.176",
"username": "17665234375", "username": "17665234375",
"password": "yaochao11", "password": "yaochao11",
"phone": "17665234375", "phone": "17665234375",
"deviceId": "-", "deviceId": "-",
"deviceType": 0 "deviceType": 0
},
{
"key": "account2",
"label": "备用账号 1",
"baseUrl": "https://123.207.217.176",
"username": "",
"password": "",
"phone": "",
"deviceId": "-",
"deviceType": 0
},
{
"key": "account3",
"label": "备用账号 2",
"baseUrl": "https://123.207.217.176",
"username": "",
"password": "",
"phone": "",
"deviceId": "-",
"deviceType": 0
},
{
"key": "测试12",
"label": "测试12",
"baseUrl": "https://123.207.217.176",
"username": "",
"password": "",
"phone": "",
"deviceId": "-",
"deviceType": 0
}
]
} }
@@ -12,7 +12,7 @@ import { useKuaishouCloudSku } from './composables/useKuaishouCloudSku'
const config = useKuaishouCloudConfig() const config = useKuaishouCloudConfig()
const ninetyone = useKuaishouCloudNinetyone(config) const ninetyone = useKuaishouCloudNinetyone(config)
const cloudSku = useKuaishouCloudSku() const cloudSku = useKuaishouCloudSku(config.cloudtentaclesSourceOptions)
onMounted(config.loadConfigs) onMounted(config.loadConfigs)
</script> </script>
@@ -73,9 +73,9 @@ onMounted(config.loadConfigs)
@add-item="config.addItem()" @add-item="config.addItem()"
@save-configs="config.saveConfigs()" @save-configs="config.saveConfigs()"
@toggle-collapsed="config.toggleCollapsed($event)" @toggle-collapsed="config.toggleCollapsed($event)"
@handle-cloud-sku-selected="cloudSku.handleCloudSkuSelected($event.item, $event.value)" @handle-cloud-sku-selected="(item, value) => cloudSku.handleCloudSkuSelected(item, value)"
@handle-cloud-sku-dropdown-visible=" @handle-cloud-sku-dropdown-visible="
cloudSku.handleCloudSkuDropdownVisible($event.item, $event.visible) (item, visible) => cloudSku.handleCloudSkuDropdownVisible(item, visible)
" "
@handle-kuaishou-consume-shop-selected="config.handleKuaishouConsumeShopSelected($event)" @handle-kuaishou-consume-shop-selected="config.handleKuaishouConsumeShopSelected($event)"
@remove-item="config.removeItem($event)" @remove-item="config.removeItem($event)"
@@ -6,7 +6,7 @@ import type { AdminCloudtentaclesSkuItem } from '@/types/admin'
import type { EditableItem } from './types' import type { EditableItem } from './types'
export function useKuaishouCloudSku() { export function useKuaishouCloudSku(cloudtentaclesSourceOptions?: { value: { key: string }[] }) {
const cloudSkuCatalogLoadingBySourceKey = ref<Record<string, boolean>>({}) const cloudSkuCatalogLoadingBySourceKey = ref<Record<string, boolean>>({})
const cloudSkuCatalogErrorMessage = ref('') const cloudSkuCatalogErrorMessage = ref('')
const cloudSkuCatalogBySourceKey = ref<Record<string, AdminCloudtentaclesSkuItem[]>>({}) const cloudSkuCatalogBySourceKey = ref<Record<string, AdminCloudtentaclesSkuItem[]>>({})
@@ -26,7 +26,9 @@ export function useKuaishouCloudSku() {
try { try {
const response = await fetchAdminCloudtentaclesSkuList({ sourceKey }) const response = await fetchAdminCloudtentaclesSkuList({ sourceKey })
cloudSkuCatalogBySourceKey.value[sourceKey] = Array.isArray(response.data.items) ? response.data.items : [] cloudSkuCatalogBySourceKey.value[sourceKey] = Array.isArray(response.data.items)
? response.data.items
: []
return cloudSkuCatalogBySourceKey.value[sourceKey] return cloudSkuCatalogBySourceKey.value[sourceKey]
} catch (error) { } catch (error) {
cloudSkuCatalogBySourceKey.value[sourceKey] = [] cloudSkuCatalogBySourceKey.value[sourceKey] = []
@@ -147,12 +149,26 @@ export function useKuaishouCloudSku() {
const count = cloudSkuCatalogBySourceKey.value[sourceKey]?.length ?? 0 const count = cloudSkuCatalogBySourceKey.value[sourceKey]?.length ?? 0
showSuccess(`cloud SKU 列表(${sourceKey})已刷新,共 ${count}`) showSuccess(`cloud SKU 列表(${sourceKey})已刷新,共 ${count}`)
} else { } else {
// No item provided — refresh all loaded caches // No item provided — refresh all configured sourceKeys, or at least 'default'
const keys = Object.keys(cloudSkuCatalogBySourceKey.value) const cachedKeys = Object.keys(cloudSkuCatalogBySourceKey.value)
for (const key of keys) { const configuredKeys = cloudtentaclesSourceOptions?.value?.map((s) => s.key) || []
await ensureCloudSkuCatalogLoaded({ cloudSourceKey: key, localId: '' } as EditableItem, true) const keysToRefresh =
cachedKeys.length > 0
? cachedKeys
: configuredKeys.length > 0
? configuredKeys
: ['default']
for (const key of keysToRefresh) {
await ensureCloudSkuCatalogLoaded(
{ cloudSourceKey: key, localId: '' } as EditableItem,
true,
)
} }
const total = Object.values(cloudSkuCatalogBySourceKey.value).reduce((sum, list) => sum + list.length, 0) const total = Object.values(cloudSkuCatalogBySourceKey.value).reduce(
(sum, list) => sum + list.length,
0,
)
showSuccess(`cloud SKU 列表已全部刷新,共 ${total}`) showSuccess(`cloud SKU 列表已全部刷新,共 ${total}`)
} }
} catch (error) { } catch (error) {
@@ -164,7 +180,9 @@ export function useKuaishouCloudSku() {
// Maintain backward-compat: derive a combined loading state // Maintain backward-compat: derive a combined loading state
// The template uses cloudSkuCatalogLoading for the refresh button spinner // The template uses cloudSkuCatalogLoading for the refresh button spinner
function syncCloudSkuCatalogLoading() { function syncCloudSkuCatalogLoading() {
cloudSkuCatalogLoading.value = Object.values(cloudSkuCatalogLoadingBySourceKey.value).some(Boolean) cloudSkuCatalogLoading.value = Object.values(cloudSkuCatalogLoadingBySourceKey.value).some(
Boolean,
)
} }
return { return {
@@ -1,6 +1,6 @@
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { showError, showSuccess } from '@/lib/feedback' import { showError, showPrompt, showSuccess, isFeedbackDismissed } from '@/lib/feedback'
import { import {
deleteAdminCloudtentaclesSource, deleteAdminCloudtentaclesSource,
saveAdminCloudtentaclesSourceConfig, saveAdminCloudtentaclesSourceConfig,
@@ -60,17 +60,13 @@ export function useAdminCloudtentaclesPlatform() {
selectedSourceKey, selectedSourceKey,
) )
const sourceOptions = computed(() => const sourceOptions = computed(() => sources.value.map((s) => ({ key: s.key, label: s.label })))
sources.value.map((s) => ({ key: s.key, label: s.label })),
)
const currentSource = computed( const currentSource = computed(
() => sources.value.find((s) => s.key === selectedSourceKey.value) || sources.value[0], () => sources.value.find((s) => s.key === selectedSourceKey.value) || sources.value[0],
) )
const currentSession = computed( const currentSession = computed(() => sessions.value[selectedSourceKey.value] || null)
() => sessions.value[selectedSourceKey.value] || null,
)
const cloudtentaclesStats = computed(() => ({ const cloudtentaclesStats = computed(() => ({
hasCredential: Boolean( hasCredential: Boolean(
@@ -144,11 +140,31 @@ export function useAdminCloudtentaclesPlatform() {
hydrateFormFromSource(sourceKey) hydrateFormFromSource(sourceKey)
} }
function addSource() { async function addSource() {
const newKey = `account${sources.value.length + 1}` try {
const result = await showPrompt(
'请输入新账号名称(例如:运营号、客服号)',
'新增 cloudtentacles 账号',
{
inputPattern: /\S/,
inputErrorMessage: '账号名称不能为空',
},
)
const trimmed = (result.value as string).trim()
if (!trimmed) {
showError('账号名称不能为空')
return
}
// Generate a URL-safe key from the label, ensure uniqueness
const baseKey = trimmed.replace(/[^a-zA-Z0-9\u4e00-\u9fff_]/g, '_').toLowerCase()
let newKey = baseKey
let counter = 2
while (sources.value.some((s) => s.key === newKey)) {
newKey = `${baseKey}_${counter++}`
}
const newSource: AdminCloudtentaclesSourceItem = { const newSource: AdminCloudtentaclesSourceItem = {
key: newKey, key: newKey,
label: `备用账号 ${sources.value.length}`, label: trimmed,
baseUrl: 'https://123.207.217.176', baseUrl: 'https://123.207.217.176',
username: '', username: '',
password: '', password: '',
@@ -159,6 +175,10 @@ export function useAdminCloudtentaclesPlatform() {
sources.value.push(newSource) sources.value.push(newSource)
selectedSourceKey.value = newKey selectedSourceKey.value = newKey
hydrateFormFromSource(newKey) hydrateFormFromSource(newKey)
} catch (error) {
if (isFeedbackDismissed(error)) return // user cancelled / closed
showError(error instanceof Error ? error.message : '新增账号失败')
}
} }
async function removeSource(sourceKey: string) { async function removeSource(sourceKey: string) {