fix(account): 支持跨平台同名账号——(platform,name)联合唯一+Asset.account_id外键重构
This commit is contained in:
+9
-8
@@ -41,10 +41,10 @@ const AssetModal = {
|
||||
<option v-for="(l,k) in Fmt.STATUS_LABELS" :key="k" :value="k">{{ l }}</option>
|
||||
</select></label>
|
||||
<label class="block"><span class="text-xs text-slate-500">所属账号</span>
|
||||
<input v-model="f.account" list="account-options" placeholder="在「平台」页管理账号" class="mt-1 w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm">
|
||||
<datalist id="account-options">
|
||||
<option v-for="a in store.accounts" :key="a.id" :value="a.name">{{ accountLabel(a) }}</option>
|
||||
</datalist></label>
|
||||
<select v-model.number="f.account_id" class="mt-1 w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-900 text-sm">
|
||||
<option :value="null">无(在「平台」页管理账号)</option>
|
||||
<option v-for="a in store.accounts" :key="a.id" :value="a.id">{{ accountLabel(a) }}</option>
|
||||
</select></label>
|
||||
<div class="col-span-2 flex gap-5 text-sm text-slate-600 dark:text-slate-300">
|
||||
<label class="flex items-center gap-2"><input type="checkbox" v-model="f.auto_renew"> 自动续费</label>
|
||||
<label class="flex items-center gap-2"><input type="checkbox" v-model="f.is_archived"> 已归档</label>
|
||||
@@ -131,11 +131,12 @@ const AssetModal = {
|
||||
const p = store.providers.find(x => x.id === f.value.provider_id);
|
||||
if (p) f.value.provider = p.slug;
|
||||
}
|
||||
// 账号候选显示:说明优先,其次平台名(platform 存的是 slug,回退原值)
|
||||
// 账号候选显示:平台名 + 账号标识(同名账号靠平台前缀区分),说明优先
|
||||
function accountLabel(a) {
|
||||
if (a.remark) return a.remark + ' · ' + a.name;
|
||||
const p = store.providers.find(x => x.slug === a.platform);
|
||||
return p ? a.name + '(' + p.name + ')' : a.name;
|
||||
const pname = p ? p.name : (a.platform || '未指定平台');
|
||||
if (a.remark) return pname + ' · ' + a.remark + '(' + a.name + ')';
|
||||
return pname + ' · ' + a.name;
|
||||
}
|
||||
return { store, Fmt, f, providersForType, onProviderChange, accountLabel, save: saveAsset };
|
||||
},
|
||||
@@ -362,7 +363,7 @@ const AccountsViewModal = {
|
||||
return p ? p.name : slug;
|
||||
}
|
||||
function assetsOf(a) {
|
||||
return store.assets.filter(x => x.account === a.name);
|
||||
return store.assets.filter(x => x.account_id === a.id);
|
||||
}
|
||||
function toggle(id) { expanded[id] = !expanded[id]; }
|
||||
// 账号所属平台配了 sdk_type 且账号有 API 配置时,提供测试/同步
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ function applyDark() {
|
||||
function emptyAssetForm() {
|
||||
return {
|
||||
name: '', asset_type: 'vps', provider: '', provider_id: null, renewal_cycle: 'monthly', renew_url: '', cancel_url: '',
|
||||
account: '', expiry_date: '', auto_renew: false, cost: 0, currency: 'USD',
|
||||
account_id: null, expiry_date: '', auto_renew: false, cost: 0, currency: 'USD',
|
||||
status: 'active', is_archived: false, remark: '',
|
||||
vps_detail: { ip_address: '', tailscale_ip: '', region: '', os: '', cpu_cores: 1, memory_gb: 1, disk_gb: 20, bandwidth_gb: null, ssh_port: 22, panel_url: '', ssh_user: '', login_method: 'key', ssh_key: '', password: '', purpose: '' },
|
||||
domain_detail: { domain_name: '', registrar: '', dns_provider: '', cloudflare_account: '', is_using: true, redirect_target: '', bind_asset_id: null },
|
||||
@@ -52,7 +52,7 @@ function buildAssetPayload(f) {
|
||||
name: f.name, asset_type: f.asset_type, provider: f.provider,
|
||||
provider_id: f.provider_id || null, renewal_cycle: f.renewal_cycle || null,
|
||||
renew_url: f.renew_url || null, cancel_url: f.cancel_url || null,
|
||||
account: f.account || null, expiry_date: f.expiry_date || null,
|
||||
account_id: f.account_id || null, expiry_date: f.expiry_date || null,
|
||||
auto_renew: !!f.auto_renew, cost: Number(f.cost) || 0, currency: f.currency,
|
||||
status: f.status, is_archived: !!f.is_archived, remark: f.remark || null,
|
||||
};
|
||||
@@ -113,7 +113,7 @@ function openAICreate(provider) {
|
||||
}
|
||||
function openAssetEdit(a) {
|
||||
const form = emptyAssetForm();
|
||||
['name', 'asset_type', 'provider', 'provider_id', 'renewal_cycle', 'renew_url', 'cancel_url', 'account', 'expiry_date', 'auto_renew', 'cost', 'currency', 'status', 'is_archived', 'remark'].forEach(k => { form[k] = a[k]; });
|
||||
['name', 'asset_type', 'provider', 'provider_id', 'renewal_cycle', 'renew_url', 'cancel_url', 'account_id', 'expiry_date', 'auto_renew', 'cost', 'currency', 'status', 'is_archived', 'remark'].forEach(k => { form[k] = a[k]; });
|
||||
if (a.vps_detail) Object.assign(form.vps_detail, a.vps_detail);
|
||||
if (a.domain_detail) Object.assign(form.domain_detail, a.domain_detail);
|
||||
if (a.ai_detail) Object.assign(form.ai_detail, a.ai_detail);
|
||||
|
||||
Reference in New Issue
Block a user