增加功能报价
This commit is contained in:
@@ -23,10 +23,25 @@
|
||||
<el-alert type="info" :closable="false" show-icon class="tip-alert">
|
||||
<template #default>
|
||||
<p>1、套餐决定租户能开通哪些功能:勾选「功能模块」后,绑定该套餐的租户端只展示对应功能菜单(如 ERP 套餐开通进销存)。</p>
|
||||
<p>2、所有租户都有用户数上限(默认 20 人):达到上限后无法再开账号,可在「租户管理 → 租户详情 → 套餐与用户数」中按单个(如 200 元/人)或加购套餐(如 5 人 500 元)增购。</p>
|
||||
<p>2、套餐按「有效时长」计费(默认 365 天,价格即元/年):到期后自动切换为基础套餐,续费后恢复对应功能。</p>
|
||||
<p>3、所有租户都有用户数上限(默认 20 人):达到上限后无法再开账号,可在「租户管理 → 租户详情 → 套餐与用户数」中按单个(如 200 元/人)或加购套餐(如 5 人 500 元)增购。</p>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<div class="purchase-url-bar">
|
||||
<span class="bar-label">套餐购买链接</span>
|
||||
<el-input
|
||||
v-model="purchaseUrl"
|
||||
placeholder="租户端未开通功能卡片「购买」按钮跳转的链接,如 https://www.example.com/package"
|
||||
clearable
|
||||
class="url-input"
|
||||
/>
|
||||
<el-button type="primary" :loading="purchaseUrlSaving" @click="handleSavePurchaseUrl">
|
||||
保存
|
||||
</el-button>
|
||||
<span class="muted">留空时租户端点击「购买」仅提示联系管理员</span>
|
||||
</div>
|
||||
|
||||
<el-tabs v-model="activeTab" class="package-tabs">
|
||||
<!-- 功能套餐 -->
|
||||
<el-tab-pane label="功能套餐" name="package">
|
||||
@@ -45,6 +60,12 @@
|
||||
<el-tag size="small" type="info" effect="plain">{{ row.code }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="套餐价格" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<span :class="{ 'price-zero': !Number(row.price) }">{{ formatMoney(row.price) }}</span>
|
||||
<span class="muted">{{ priceUnit(row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开通功能" min-width="260">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
@@ -139,6 +160,8 @@ import {
|
||||
deleteTenantPackage,
|
||||
getQuotaPackageList,
|
||||
deleteQuotaPackage,
|
||||
getPackagePurchaseUrl,
|
||||
savePackagePurchaseUrl,
|
||||
} from "@/api/tenantPackage";
|
||||
import PackageEditDialog from "./components/edit.vue";
|
||||
import QuotaEditDialog from "./components/quotaEdit.vue";
|
||||
@@ -154,7 +177,46 @@ const quotaDialogVisible = ref(false);
|
||||
const currentPackage = ref<any>(null);
|
||||
const currentQuota = ref<any>(null);
|
||||
|
||||
// 套餐购买链接(租户端未开通功能卡片「购买」按钮跳转地址)
|
||||
const purchaseUrl = ref("");
|
||||
const purchaseUrlSaving = ref(false);
|
||||
|
||||
const loadPurchaseUrl = async () => {
|
||||
try {
|
||||
const res = await getPackagePurchaseUrl();
|
||||
if (res.code === 200) {
|
||||
purchaseUrl.value = res.data?.purchase_url || "";
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("获取套餐购买链接失败:", e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSavePurchaseUrl = async () => {
|
||||
purchaseUrlSaving.value = true;
|
||||
try {
|
||||
const res = await savePackagePurchaseUrl(purchaseUrl.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("保存成功");
|
||||
} else {
|
||||
ElMessage.error(res.msg || "保存失败");
|
||||
}
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || "保存失败");
|
||||
} finally {
|
||||
purchaseUrlSaving.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const formatMoney = (v: any) => `¥${Number(v || 0).toFixed(2)}`;
|
||||
/** 价格单位随有效时长变化:365天=元/年,30=元/月,90=元/季,其余=元/N天 */
|
||||
const priceUnit = (row: any) => {
|
||||
const d = Number(row.duration_days || 365);
|
||||
if (d === 365) return "/年";
|
||||
if (d === 30) return "/月";
|
||||
if (d === 90) return "/季";
|
||||
return `/${d}天`;
|
||||
};
|
||||
const unitPrice = (row: any) => {
|
||||
const count = Number(row.user_count || 0);
|
||||
if (count <= 0) return 0;
|
||||
@@ -196,6 +258,7 @@ const loadQuotaPackages = async () => {
|
||||
const refresh = () => {
|
||||
loadPackages();
|
||||
loadQuotaPackages();
|
||||
loadPurchaseUrl();
|
||||
};
|
||||
|
||||
const handleAddPackage = () => {
|
||||
@@ -302,6 +365,25 @@ onMounted(refresh);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.purchase-url-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.bar-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.url-input {
|
||||
width: 420px;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.module-tag {
|
||||
margin: 0 6px 6px 0;
|
||||
}
|
||||
@@ -315,6 +397,10 @@ onMounted(refresh);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.price-zero {
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
:deep(.el-empty) {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user