|
|
@@ -64,6 +64,7 @@
|
|
|
<el-button size="mini" type="text" icon="el-icon-key" style="color:#722ed1" @click="handleResetPwd(scope.row)">重置密码</el-button>
|
|
|
<el-button size="mini" type="text" style="color:#52c41a" icon="el-icon-coin" @click="handleRecharge(scope.row)">充值/扣款</el-button>
|
|
|
<el-button size="mini" type="text" style="color:#722ed1" icon="el-icon-menu" @click="handleEditMenu(scope.row, 'sys')">管理端菜单</el-button>
|
|
|
+ <el-button size="mini" type="text" style="color:#e6a23c" icon="el-icon-price-tag" @click="handleModulePricing(scope.row)">模块定价</el-button>
|
|
|
<el-button size="mini" type="text" style="color:#13c2c2" icon="el-icon-sell" @click="handleEditMenu(scope.row, 'com')">销售菜单</el-button>
|
|
|
<el-button
|
|
|
v-if="scope.row.status == 1"
|
|
|
@@ -125,6 +126,13 @@
|
|
|
<span style="color:#999;font-size:12px;margin-left:8px">(通过充值/扣款调整)</span>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="归属代理" prop="proxyId">
|
|
|
+ <el-select v-model="viewForm.proxyId" placeholder="请选择代理" clearable filterable style="width:100%">
|
|
|
+ <el-option v-for="p in proxyOptions" :key="p.proxyId" :label="p.proxyName" :value="p.proxyId" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
<el-col :span="12">
|
|
|
<el-form-item label="租户状态">
|
|
|
<el-switch v-model="viewForm.statusBool" active-text="正常" inactive-text="禁用"
|
|
|
@@ -185,6 +193,13 @@
|
|
|
<el-date-picker v-model="addDialog.form.expireTime" type="date" value-format="yyyy-MM-dd" placeholder="选择到期时间" style="width:100%" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="归属代理" prop="proxyId">
|
|
|
+ <el-select v-model="addDialog.form.proxyId" placeholder="请选择代理" clearable filterable style="width:100%">
|
|
|
+ <el-option v-for="p in proxyOptions" :key="p.proxyId" :label="p.proxyName" :value="p.proxyId" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
<el-col :span="12">
|
|
|
<el-form-item label="状态" prop="status">
|
|
|
<el-radio-group v-model="addDialog.form.status">
|
|
|
@@ -255,11 +270,53 @@
|
|
|
<el-button type="primary" :loading="menuDialog.submitting" @click="submitMenuEdit">确 定</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- ===== 模块定价弹窗 ===== -->
|
|
|
+ <el-dialog :title="'模块定价 - ' + pricingDialog.tenantName" :visible.sync="pricingDialog.visible" width="800px" append-to-body destroy-on-close>
|
|
|
+ <div v-loading="pricingDialog.loading">
|
|
|
+ <el-table :data="pricingDialog.modules" border size="small" style="width:100%">
|
|
|
+ <el-table-column label="模块" align="center" prop="moduleName" min-width="120" />
|
|
|
+ <el-table-column label="全局售价" align="center" min-width="100">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span style="color:#909399">{{ scope.row.globalPrice != null ? scope.row.globalPrice : '-' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="全局成本" align="center" min-width="100">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span style="color:#909399">{{ scope.row.globalCost != null ? scope.row.globalCost : '-' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="租户售价" align="center" min-width="130">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input-number v-model="scope.row.price" :precision="4" :min="0" :step="0.01" size="small" style="width:150px" placeholder="跟随全局" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="成本价" align="center" min-width="130">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input-number v-model="scope.row.costPrice" :precision="4" :min="0" :step="0.01" size="small" style="width:150px" placeholder="跟随全局" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="状态" align="center" min-width="80">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" active-text="启用" inactive-text="禁" size="small" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div style="color:#909399;font-size:12px;margin-top:8px">* 租户售价/成本价留空或填0则使用全局定价</div>
|
|
|
+ </div>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="pricingDialog.visible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" :loading="pricingDialog.submitting" @click="submitModulePricing">保 存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { listAllCompanies, getCompanyInfo, addCompany, updateTenant, disableCompany, enableCompany, rechargeCompany, exportCompany, getTenantMenuTree, editTenantMenu, resetTenantPwd } from '@/api/admin/sysCompany'
|
|
|
+import { listTrafficPricing, addTrafficPricing, updateTrafficPricing } from '@/api/admin/trafficPricing'
|
|
|
+import { allEnabledProxies } from '@/api/admin/proxy'
|
|
|
+import { listServiceCost } from '@/api/admin/serviceCost'
|
|
|
import { generateRandomPwd } from '@/utils/index'
|
|
|
|
|
|
export default {
|
|
|
@@ -331,13 +388,30 @@ export default {
|
|
|
allMenuIds: [], // 所有菜单ID
|
|
|
loading: false,
|
|
|
submitting: false
|
|
|
- }
|
|
|
+ },
|
|
|
+ // 模块定价弹窗
|
|
|
+ pricingDialog: {
|
|
|
+ visible: false,
|
|
|
+ tenantId: null,
|
|
|
+ tenantName: '',
|
|
|
+ loading: false,
|
|
|
+ submitting: false,
|
|
|
+ modules: []
|
|
|
+ },
|
|
|
+ // 代理列表(下拉框用)
|
|
|
+ proxyOptions: []
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
this.getList()
|
|
|
+ this.loadProxyOptions()
|
|
|
},
|
|
|
methods: {
|
|
|
+ loadProxyOptions() {
|
|
|
+ allEnabledProxies().then(res => {
|
|
|
+ this.proxyOptions = res.data || []
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
getList() {
|
|
|
this.loading = true
|
|
|
listAllCompanies(this.queryParams).then(response => {
|
|
|
@@ -363,6 +437,7 @@ export default {
|
|
|
userName: '',
|
|
|
password: generateRandomPwd(12),
|
|
|
manager: '',
|
|
|
+ proxyId: null,
|
|
|
startTime: null,
|
|
|
expireTime: null,
|
|
|
status: 1
|
|
|
@@ -388,7 +463,7 @@ export default {
|
|
|
inputType: 'text'
|
|
|
}).then(({ value }) => {
|
|
|
resetTenantPwd(row.id, value).then(() => {
|
|
|
- this.$modal.msgSuccess('密码重置成功,新密码为:' + value)
|
|
|
+ this.$message.success('密码重置成功,新密码为:' + value)
|
|
|
}).catch(() => {
|
|
|
this.$message.error('密码重置失败')
|
|
|
})
|
|
|
@@ -420,6 +495,8 @@ export default {
|
|
|
this.$nextTick(() => {
|
|
|
if (this.$refs.editForm) this.$refs.editForm.clearValidate()
|
|
|
})
|
|
|
+ }).catch(() => {
|
|
|
+ this.$message.error('获取租户信息失败')
|
|
|
})
|
|
|
},
|
|
|
/** 提交编辑租户 */
|
|
|
@@ -433,7 +510,8 @@ export default {
|
|
|
contactName: this.viewForm.contactName,
|
|
|
contactPhone: this.viewForm.contactPhone,
|
|
|
expireTime: this.viewForm.expireTime,
|
|
|
- status: this.viewForm.statusBool
|
|
|
+ status: this.viewForm.statusBool,
|
|
|
+ proxyId: this.viewForm.proxyId
|
|
|
}
|
|
|
updateTenant(data).then(() => {
|
|
|
this.$message.success('保存成功')
|
|
|
@@ -553,6 +631,73 @@ export default {
|
|
|
this.menuDialog.loading = false
|
|
|
})
|
|
|
},
|
|
|
+ /** 模块定价 */
|
|
|
+ handleModulePricing(row) {
|
|
|
+ this.pricingDialog = {
|
|
|
+ visible: true,
|
|
|
+ tenantId: row.id,
|
|
|
+ tenantName: row.tenantName,
|
|
|
+ loading: true,
|
|
|
+ submitting: false,
|
|
|
+ modules: []
|
|
|
+ }
|
|
|
+ // 从收费配置API获取启用的模块列表(排除手拨外呼serviceType=6)
|
|
|
+ Promise.all([
|
|
|
+ listServiceCost(),
|
|
|
+ listTrafficPricing({ tenantId: row.id, pageSize: 100 })
|
|
|
+ ]).then(([costRes, pricingRes]) => {
|
|
|
+ const costList = (costRes.data || []).filter(c => c.enabled === 1 && c.serviceType !== 6)
|
|
|
+ const tenantPricings = pricingRes.rows || []
|
|
|
+ const pricingMap = {}
|
|
|
+ tenantPricings.forEach(p => { pricingMap[p.serviceType] = p })
|
|
|
+ this.pricingDialog.modules = costList.map(c => {
|
|
|
+ const existing = pricingMap[c.serviceType]
|
|
|
+ return {
|
|
|
+ serviceType: c.serviceType,
|
|
|
+ moduleName: c.configName,
|
|
|
+ unit: c.feeUnit,
|
|
|
+ globalPrice: c.feeStandard,
|
|
|
+ globalCost: c.platformCost,
|
|
|
+ price: existing ? existing.price : null,
|
|
|
+ costPrice: existing ? existing.costPrice : null,
|
|
|
+ status: existing ? existing.status : 1,
|
|
|
+ id: existing ? existing.id : null
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.pricingDialog.loading = false
|
|
|
+ }).catch(() => {
|
|
|
+ this.pricingDialog.loading = false
|
|
|
+ this.$message.error('加载定价数据失败')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 提交模块定价 */
|
|
|
+ submitModulePricing() {
|
|
|
+ this.pricingDialog.submitting = true
|
|
|
+ const tenantId = this.pricingDialog.tenantId
|
|
|
+ const promises = this.pricingDialog.modules.map(m => {
|
|
|
+ const data = {
|
|
|
+ tenantId: tenantId,
|
|
|
+ serviceType: m.serviceType,
|
|
|
+ price: m.price,
|
|
|
+ costPrice: m.costPrice,
|
|
|
+ status: m.status
|
|
|
+ }
|
|
|
+ if (m.id) {
|
|
|
+ data.id = m.id
|
|
|
+ return updateTrafficPricing(data)
|
|
|
+ } else {
|
|
|
+ return addTrafficPricing(data)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ Promise.all(promises).then(() => {
|
|
|
+ this.$message.success('模块定价保存成功')
|
|
|
+ this.pricingDialog.visible = false
|
|
|
+ }).catch(() => {
|
|
|
+ this.$message.error('部分定价保存失败,请重试')
|
|
|
+ }).finally(() => {
|
|
|
+ this.pricingDialog.submitting = false
|
|
|
+ })
|
|
|
+ },
|
|
|
/** 提交菜单编辑 */
|
|
|
submitMenuEdit() {
|
|
|
const tree = this.$refs.menuTree
|