fix(cloudtentacles): 第三轮 Bug 修复 + 体验改进 — Vue3 emit 多参数处理、SKU 刷新空缓存、新增账号改用 ElMessageBox.prompt
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -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)"
|
||||||
|
|||||||
+26
-8
@@ -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 {
|
||||||
|
|||||||
+30
-10
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user