|
|
|
@ -15,6 +15,7 @@ |
|
|
|
<div class="business-workspace"> |
|
|
|
<t-tabs v-model="tab" class="business-tdesign-tabs"> |
|
|
|
<t-tab-panel value="packages" label="套餐管理" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="sim-packages" label="通信卡套餐" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="purchases" label="采购入池" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="ledger" label="账务流水" :destroy-on-hide="false" /> |
|
|
|
</t-tabs> |
|
|
|
@ -74,6 +75,13 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-show="tab === 'sim-packages'" class="packages-panel"> |
|
|
|
<div class="asset-toolbar"><div class="toolbar-group"><t-select v-model="simPkgStatus" :options="pkgStatusFilterOptions" style="width:140px" @change="reloadSimPackages" /></div><div class="page-actions"><t-button shape="square" variant="outline" @click="loadSimPackages">刷新</t-button><t-button variant="outline" @click="openProviderPlans">从 SIMBOSS 查询套餐</t-button><t-button theme="primary" @click="openSimPkgAdd">新建通信卡套餐</t-button></div></div> |
|
|
|
<div class="asset-table-wrap"><t-table row-key="id" :data="simPkgList" :columns="simPkgColumns" empty="暂无通信卡套餐"><template #status="{ row }"><span class="table-status" :class="row.status === 'active' ? 'online' : 'offline'"><i></i>{{ row.status === 'active' ? '上架' : '下架' }}</span></template><template #actions="{ row }"><t-button variant="text" theme="primary" @click="openSimPkgEdit(row)">编辑</t-button><t-button v-if="row.status === 'active'" variant="text" theme="danger" @click="disableSimPkg(row)">下架</t-button></template></t-table></div> |
|
|
|
<div class="table-footer"><t-pagination v-model:current="simPkgPage" :total="simPkgTotal" :page-size="10" @current-change="loadSimPackages" /></div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div v-show="tab === 'purchases'" class="purchases-panel"> |
|
|
|
<div v-if="poolMissing" class="pool-empty"> |
|
|
|
尚未建立资源池,首次录入采购后自动创建 |
|
|
|
@ -195,6 +203,8 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<t-dialog v-model:visible="simPkgModal" :header="simPkgEditing ? '编辑通信卡套餐' : '新建通信卡套餐'" width="520px" destroy-on-close dialog-class-name="add-dock-dialog"><form novalidate @submit.prevent="submitSimPkg"><label><span>套餐编码<b>*</b></span><t-input v-model="simPkgForm.code" :disabled="simPkgEditing" /></label><label><span>套餐名称<b>*</b></span><t-input v-model="simPkgForm.name" /></label><div class="form-row"><label><span>运营商</span><t-input v-model="simPkgForm.carrier" disabled /></label><label><span>供应商套餐ID</span><t-input-number v-model="simPkgForm.providerRatePlanId" :min="1" style="width:100%" disabled /></label></div><div class="form-row"><label><span>流量(GB)<b>*</b></span><t-input-number v-model="simPkgForm.amountGb" :min="1" style="width:100%" /></label><label><span>有效期(月)<b>*</b></span><t-input-number v-model="simPkgForm.validityMonths" :min="1" style="width:100%" /></label></div><div class="form-row"><label><span>销售价(元)<b>*</b></span><t-input-number v-model="simPkgForm.saleFeeFen" :min="0.01" :step="0.01" :decimal-places="2" style="width:100%" /></label><label><span>成本价(元)</span><t-input-number v-model="simPkgForm.costFeeFen" :min="0" :step="0.01" :decimal-places="2" style="width:100%" /></label></div><label v-if="simPkgEditing"><span>状态</span><t-select v-model="simPkgForm.status" :options="pkgStatusOptions" /></label><div class="form-error">{{ simPkgError }}</div></form><template #footer><t-button variant="outline" @click="simPkgModal=false">取消</t-button><t-button theme="primary" @click="submitSimPkg">保存</t-button></template></t-dialog> |
|
|
|
|
|
|
|
<t-dialog |
|
|
|
v-model:visible="pkgModalVisible" |
|
|
|
:header="pkgEditingId ? '编辑套餐' : '新建套餐'" |
|
|
|
@ -274,6 +284,8 @@ |
|
|
|
</template> |
|
|
|
</t-dialog> |
|
|
|
|
|
|
|
<t-dialog v-model:visible="providerPlansModal" header="SIMBOSS 供应商套餐" width="760px" destroy-on-close><div class="asset-toolbar"><t-input v-model="providerIccid" placeholder="输入通信卡 ICCID" /><t-button theme="primary" :loading="providerPlansLoading" @click="queryProviderPlans">查询</t-button></div><t-table row-key="ratePlanId" :data="providerPlans" :columns="providerPlanColumns" empty="暂无供应商套餐"><template #actions="{ row }"><t-button variant="text" theme="primary" @click="useProviderPlan(row)">使用此套餐</t-button></template></t-table></t-dialog> |
|
|
|
|
|
|
|
<t-dialog |
|
|
|
v-model:visible="purchaseModalVisible" |
|
|
|
header="录入采购" |
|
|
|
@ -598,6 +610,39 @@ async function disablePackage(row) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const providerPlansModal = ref(false) |
|
|
|
const providerIccid = ref('') |
|
|
|
const providerPlans = ref([]) |
|
|
|
const providerPlansLoading = ref(false) |
|
|
|
const providerPlanColumns = [{ colKey: 'ratePlanId', title: '供应商套餐ID' }, { colKey: 'name', title: '名称' }, { colKey: 'dataVolume', title: '流量' }, { colKey: 'timeLength', title: '时长' }, { colKey: 'actions', title: '操作' }] |
|
|
|
async function queryProviderPlans() { if (!providerIccid.value.trim()) { ui.toast('请输入 ICCID'); return }; providerPlansLoading.value = true; try { providerPlans.value = await request.post(urls.ADMIN_SIM_PROVIDER_PLANS, { iccid: providerIccid.value.trim() }) } catch (e) { ui.toast(e.message || '查询供应商套餐失败') } finally { providerPlansLoading.value = false } } |
|
|
|
function openProviderPlans() { providerIccid.value = ''; providerPlans.value = []; providerPlansModal.value = true } |
|
|
|
function useProviderPlan(row) { Object.assign(simPkgForm, { providerRatePlanId: row.ratePlanId, name: row.name || simPkgForm.name, amountGb: Math.max(1, Math.round(Number(row.dataVolume) || 1)), validityMonths: Math.max(1, Math.round(Number(row.timeLength) / 30) || 1) }); simPkgModal.value = true; providerPlansModal.value = false; simPkgEditing.value = null; simPkgError.value = '' } |
|
|
|
|
|
|
|
|
|
|
|
const simPkgList = ref([]) |
|
|
|
const simPkgTotal = ref(0) |
|
|
|
const simPkgPage = ref(1) |
|
|
|
const simPkgStatus = ref('') |
|
|
|
const simPkgModal = ref(false) |
|
|
|
const simPkgEditing = ref(null) |
|
|
|
const simPkgError = ref('') |
|
|
|
const simPkgForm = reactive({ code: '', name: '', carrier: '', providerRatePlanId: 0, amountGb: 1, validityMonths: 1, costFeeFen: 0, saleFeeFen: 0.01, status: 'active' }) |
|
|
|
const simPkgColumns = [ |
|
|
|
{ colKey: 'code', title: '编码' }, { colKey: 'name', title: '名称' }, { colKey: 'carrier', title: '运营商' }, |
|
|
|
{ colKey: 'providerRatePlanId', title: '供应商套餐ID' }, { colKey: 'amountGb', title: '流量(GB)' }, { colKey: 'validityMonths', title: '有效期(月)' }, |
|
|
|
{ colKey: 'saleFeeText', title: '售价' }, { colKey: 'status', title: '状态' }, { colKey: 'actions', title: '操作' } |
|
|
|
] |
|
|
|
async function loadSimPackages() { |
|
|
|
try { const page = await request.get(urls.ADMIN_SIM_PACKAGES, { params: { pageNum: simPkgPage.value, pageSize: 10, status: simPkgStatus.value || undefined } }); simPkgTotal.value = page?.total || 0; simPkgList.value = (page?.records || []).map((p) => ({ ...p, id: String(p.id), saleFeeText: `¥${(Number(p.saleFeeFen || 0) / 100).toFixed(2)}` })) } catch (e) { ui.toast(e.message || '加载通信卡套餐失败') } |
|
|
|
} |
|
|
|
function reloadSimPackages() { simPkgPage.value = 1; loadSimPackages() } |
|
|
|
function openSimPkgAdd() { Object.assign(simPkgForm, { code: '', name: '', carrier: '', providerRatePlanId: 0, amountGb: 1, validityMonths: 1, costFeeFen: 0, saleFeeFen: 0.01, status: 'active' }); simPkgEditing.value = null; simPkgError.value = ''; simPkgModal.value = true } |
|
|
|
function openSimPkgEdit(row) { Object.assign(simPkgForm, { ...row, costFeeFen: Number(row.costFeeFen || 0) / 100, saleFeeFen: Number(row.saleFeeFen || 0) / 100 }); simPkgEditing.value = row.id; simPkgError.value = ''; simPkgModal.value = true } |
|
|
|
async function submitSimPkg() { simPkgError.value = ''; if (!simPkgForm.name || !simPkgForm.carrier || !simPkgForm.providerRatePlanId || !simPkgForm.amountGb || !simPkgForm.validityMonths || !(Number(simPkgForm.saleFeeFen) > 0) || (!simPkgEditing.value && !simPkgForm.code)) { simPkgError.value = '请完整填写套餐信息'; return }; try { const payload = { ...simPkgForm, providerRatePlanId: Number(simPkgForm.providerRatePlanId), amountGb: Number(simPkgForm.amountGb), validityMonths: Number(simPkgForm.validityMonths), costFeeFen: Math.round(Number(simPkgForm.costFeeFen || 0) * 100), saleFeeFen: Math.round(Number(simPkgForm.saleFeeFen) * 100) }; if (simPkgEditing.value) await request.put(urls.ADMIN_SIM_PACKAGE(simPkgEditing.value), payload); else await request.post(urls.ADMIN_SIM_PACKAGES, payload); simPkgModal.value = false; ui.toast('通信卡套餐已保存'); await loadSimPackages() } catch (e) { simPkgError.value = e.message || '保存失败' } } |
|
|
|
async function disableSimPkg(row) { const ok = await ui.confirm(`确认下架套餐 ${row.name}?`, '下架后用户侧不可购买。'); if (!ok) return; try { await request.delete(urls.ADMIN_SIM_PACKAGE(row.id)); await loadSimPackages(); ui.toast('套餐已下架') } catch (e) { ui.toast(e.message || '下架失败') } } |
|
|
|
|
|
|
|
|
|
|
|
const pool = ref(null) |
|
|
|
const poolMissing = ref(false) |
|
|
|
const purchaseList = ref([]) |
|
|
|
@ -924,6 +969,7 @@ function reloadLedger() { |
|
|
|
|
|
|
|
watch(tab, (v) => { |
|
|
|
if (v === 'packages') loadPackages() |
|
|
|
if (v === 'sim-packages') loadSimPackages() |
|
|
|
if (v === 'purchases') loadPurchasesTab() |
|
|
|
if (v === 'ledger') loadLedger() |
|
|
|
}) |
|
|
|
|