<template>
|
<el-dialog
|
v-model="visible"
|
:title="dialogTitle"
|
:before-close="handleClose"
|
destroy-on-close
|
class="product-order-dialog"
|
width="1000px"
|
>
|
<div class="order-container" v-loading="loading">
|
<!-- 产品基本信息 -->
|
<el-card class="product-info-card" shadow="never">
|
|
|
<div v-if="productInfo" class="product-details">
|
<el-descriptions :column="2" border>
|
<!-- 顶部空内容标题行:基本信息 -->
|
<el-descriptions-item :span="2">
|
<template #label>
|
<div class="desc-label-with-icon">
|
<el-icon class="desc-label-icon"><Goods /></el-icon>
|
<span>基本信息</span>
|
</div>
|
</template>
|
<span></span>
|
</el-descriptions-item>
|
<el-descriptions-item label="产品名称">{{ productInfo.name }}</el-descriptions-item>
|
<el-descriptions-item label="行业板块">{{ productInfo.industry }}</el-descriptions-item>
|
<el-descriptions-item label="提报者">{{ productInfo.submitter }}</el-descriptions-item>
|
<el-descriptions-item label="用户姓名">{{ orderForm.userName }}</el-descriptions-item>
|
<el-descriptions-item label="单位">{{ orderForm.unit }}</el-descriptions-item>
|
<el-descriptions-item label="部门">{{ orderForm.department }}</el-descriptions-item>
|
</el-descriptions>
|
</div>
|
|
<el-empty v-else description="未找到产品信息" />
|
</el-card>
|
|
<!-- 选中套件列表(表格布局) -->
|
<el-card class="selected-suites-card" shadow="never">
|
<div v-if="selectedSuites.length > 0" class="suite-table-wrapper">
|
<table class="suite-table">
|
<thead>
|
<tr>
|
<th class="col-detail th-left">
|
<span class="th-detail">
|
<el-icon class="th-detail-icon"><List /></el-icon>
|
<span>套件详情</span>
|
</span>
|
</th>
|
<th class="col-spec th-center" colspan="2">规格</th>
|
<th class="col-price th-center">单价</th>
|
<th class="col-qty th-center">数量</th>
|
<th class="col-years th-center">期限(年)</th>
|
<th class="col-action th-center">操作</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr v-for="(suite, index) in selectedSuites" :key="suite.id">
|
<!-- 详情:选择 + 套件名称 -->
|
<td class="cell-detail">
|
<div class="detail-content">
|
<el-checkbox v-model="suite.selected" />
|
<span class="suite-name">{{ getSuiteDisplayName(suite) }}</span>
|
</div>
|
</td>
|
|
<!-- 规格1:销售形式 + 账户数量(两行) -->
|
<td class="cell-spec">
|
<div class="spec-line">销售形式:{{ getSalesFormText(suite.salesForm) }}</div>
|
<div class="spec-line">账户数量:{{ suite.accountQuantityUnlimited ? '不限' : suite.accountQuantity }}</div>
|
</td>
|
|
<!-- 规格2:客户对象 + 并发节点数(两行) -->
|
<td class="cell-spec">
|
<div class="spec-line">客户对象:{{ getCustomerObjectText(suite.customerObject) }}</div>
|
<div class="spec-line">并发节点数:{{ suite.concurrentNodeQuantityUnlimited ? '不限' : suite.concurrentNodeQuantity }}</div>
|
</td>
|
|
<!-- 单价:根据价格设置展示优先:积分>货币>免费/协议 -->
|
<td class="cell-price">
|
<div class="price-inline">
|
<el-select v-model="suite.priceType" size="small" style="width: 60px">
|
<el-option
|
v-for="t in getAvailablePriceTypes(suite)"
|
:key="t.value"
|
:label="t.label"
|
:value="t.value"
|
/>
|
</el-select>
|
<div class="price-display">
|
<template v-if="suite.priceType === 'POINTS'">
|
<span class="price-tag points">{{ formatNumber(suite.pointsAmount) }}</span>
|
<span class="price-unit">{{ getUnitSuffix(suite.priceUnit) }}</span>
|
</template>
|
<template v-else-if="suite.priceType === 'CURRENCY'">
|
<span class="price-label">¥</span>
|
<span class="price-tag currency">{{ formatNumber(suite.currencyAmount) }}</span>
|
<span class="price-unit">{{ getUnitSuffix(suite.priceUnit) }}</span>
|
</template>
|
<template v-else-if="suite.priceType === 'AGREEMENT'">
|
<span class="price-agreement">/</span><span>{{ getUnitSuffix(suite.priceUnit).replace('/', '') }}</span>
|
</template>
|
<template v-else-if="suite.priceType === 'FREE'">
|
<span class="price-free">/</span><span>{{ getUnitSuffix(suite.priceUnit).replace('/', '') }}</span>
|
</template>
|
<template v-else>
|
-
|
</template>
|
</div>
|
</div>
|
</td>
|
|
<!-- 数量 -->
|
<td class="cell-input">
|
<el-input-number v-model="suite.quantity" :min="1" :max="999" :controls="false" size="small" />
|
</td>
|
|
<!-- 期限(年) -->
|
<td class="cell-input">
|
<el-input-number v-model="suite.duration" :min="1" :max="10" :controls="false" size="small" />
|
</td>
|
|
<!-- 操作 -->
|
<td class="cell-action">
|
<el-button type="danger" link @click="removeSuite(index)">删除</el-button>
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
</div>
|
<el-empty v-else description="暂无选中的软件套件" />
|
</el-card>
|
|
<!-- 订购统计 -->
|
<div class="order-summary">
|
<div class="summary-left">
|
<div class="summary-row">
|
<span class="summary-label">已选</span>
|
<span class="summary-value highlight">{{ selectedCount }}</span>
|
<span class="summary-text">件产品</span>
|
<span class="summary-spacer"></span>
|
<span class="summary-label">总计:</span>
|
<span class="summary-value total">积分:{{ formatNumber(totalByType.points) }}</span>
|
<template v-if="totalByType.currency > 0">
|
<span class="summary-spacer"></span>
|
<span class="summary-value currency">货币:{{ formatNumber(totalByType.currency) }}</span>
|
</template>
|
</div>
|
</div>
|
<div class="summary-actions">
|
<el-button @click="handleClose">取消</el-button>
|
<el-button type="primary" @click="handleSubmitOrder" :loading="submitting">提交申请</el-button>
|
</div>
|
</div>
|
</div>
|
|
|
</el-dialog>
|
|
<!-- 订单状态对话框 -->
|
<ProductOrderStatusDialog
|
v-model="statusDialogVisible"
|
:order-id="currentOrderId"
|
/>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, computed, watch } from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { Goods, List } from '@element-plus/icons-vue'
|
import ProductOrderStatusDialog from '../productOrderStatusDialog/index.vue'
|
|
interface ProductInfo {
|
id: string
|
name: string
|
industry: string
|
submitter: string
|
submitUnit: string
|
description: string
|
}
|
|
interface SuiteItem {
|
id: number
|
productId: string
|
productSuite: string
|
salesForm: string
|
customerObject: 'ENTERPRISE' | 'PERSONAL' | 'PROJECT_DEPARTMENT'
|
accountQuantity: number
|
accountQuantityUnlimited: boolean
|
concurrentNodeQuantity: number
|
concurrentNodeQuantityUnlimited: boolean
|
priceSettings: Array<'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE'>
|
pointsAmount: number
|
currencyAmount: number
|
priceUnit: string
|
enableStatus: 'ENABLED' | 'DISABLED'
|
// 订购相关字段
|
selected: boolean
|
quantity: number
|
duration: number
|
// 展示用:选择的价格类型
|
priceType?: 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE'
|
}
|
|
interface OrderForm {
|
userName: string
|
unit: string
|
department: string
|
}
|
|
interface Props {
|
modelValue: boolean
|
productId?: string
|
suiteIds?: number[]
|
}
|
|
interface Emits {
|
(e: 'update:modelValue', value: boolean): void
|
(e: 'order-success', orderData: any): void
|
}
|
|
const props = withDefaults(defineProps<Props>(), {
|
modelValue: false,
|
productId: '',
|
suiteIds: () => []
|
})
|
|
const emit = defineEmits<Emits>()
|
|
const visible = computed({
|
get: () => props.modelValue,
|
set: (value) => emit('update:modelValue', value)
|
})
|
|
const loading = ref(false)
|
const submitting = ref(false)
|
const productInfo = ref<ProductInfo | null>(null)
|
const selectedSuites = ref<SuiteItem[]>([])
|
|
// 订单状态弹窗
|
const statusDialogVisible = ref(false)
|
const currentOrderId = ref<string | number>('')
|
|
// 订购表单信息(模拟用户信息)
|
const orderForm = ref<OrderForm>({
|
userName: '张静',
|
unit: '信科集团',
|
department: '门户系统临时组'
|
})
|
|
// 弹窗标题:显示【产品名称】产品订购
|
const dialogTitle = computed(() => {
|
const name = productInfo.value?.name || ''
|
return `【${name}】产品订购`
|
})
|
|
// 选中套件数量
|
const selectedCount = computed(() => {
|
return selectedSuites.value.filter(suite => suite.selected).length
|
})
|
|
// 总计:按类型分别统计
|
const totalByType = computed(() => {
|
const result = { points: 0, currency: 0 }
|
selectedSuites.value
|
.filter(suite => suite.selected)
|
.forEach(suite => {
|
const quantity = suite.quantity || 1
|
const duration = suite.duration || 1
|
let multiplier = 1
|
if (suite.priceUnit === 'SET_PER_YEAR' || suite.priceUnit === 'YEAR') multiplier = duration
|
|
switch (suite.priceType) {
|
case 'POINTS':
|
result.points += (suite.pointsAmount || 0) * quantity * multiplier
|
break
|
case 'CURRENCY':
|
result.currency += (suite.currencyAmount || 0) * quantity * multiplier
|
break
|
default:
|
break
|
}
|
})
|
return result
|
})
|
|
// 模拟产品信息数据
|
const mockProductData: Record<string, ProductInfo> = {
|
'10001': {
|
id: '10001',
|
name: '中交方远智能实测实量管理系统',
|
industry: '公路,市政,建筑',
|
submitter: '中交建筑集团第一工程有限公司',
|
submitUnit: '中交建筑集团第一工程有限公司',
|
description: '智能实测实量管理系统'
|
},
|
'10002': {
|
id: '10002',
|
name: '数字化产品B',
|
industry: '市政工程',
|
submitter: '中交二航局',
|
submitUnit: '中交二航局',
|
description: '面向城市管廊监测的传感设备'
|
}
|
}
|
|
// 模拟套件数据(与 ProductPriceViewer 保持一致)
|
const mockSuiteData: Record<string, SuiteItem[]> = {
|
'10001': [
|
{
|
id: 1,
|
productId: '10001',
|
productSuite: 'ENTERPRISE_PRIVATE_SAAS_LICENSE',
|
salesForm: 'BUYOUT',
|
customerObject: 'ENTERPRISE',
|
accountQuantity: 50,
|
accountQuantityUnlimited: false,
|
concurrentNodeQuantity: 50,
|
concurrentNodeQuantityUnlimited: false,
|
priceSettings: ['POINTS', 'CURRENCY', 'AGREEMENT'],
|
pointsAmount: 50000,
|
currencyAmount: 50000,
|
priceUnit: 'SET',
|
enableStatus: 'ENABLED',
|
selected: true,
|
quantity: 1,
|
duration: 1
|
},
|
{
|
id: 2,
|
productId: '10001',
|
productSuite: 'ENTERPRISE_PRIVATE_SAAS_OTA',
|
salesForm: 'OTA',
|
customerObject: 'ENTERPRISE',
|
accountQuantity: 50,
|
accountQuantityUnlimited: false,
|
concurrentNodeQuantity: 50,
|
concurrentNodeQuantityUnlimited: false,
|
priceSettings: ['CURRENCY'],
|
pointsAmount: 7500,
|
currencyAmount: 7500,
|
priceUnit: 'SET_PER_YEAR',
|
enableStatus: 'ENABLED',
|
selected: true,
|
quantity: 1,
|
duration: 1
|
},
|
{
|
id: 3,
|
productId: '10001',
|
productSuite: 'ENTERPRISE_PRIVATE_SAAS_USER_INCREMENT',
|
salesForm: 'PRIVATE_INCREMENT',
|
customerObject: 'ENTERPRISE',
|
accountQuantity: 100,
|
accountQuantityUnlimited: false,
|
concurrentNodeQuantity: 100,
|
concurrentNodeQuantityUnlimited: false,
|
priceSettings: ['CURRENCY'],
|
pointsAmount: 0,
|
currencyAmount: 10000,
|
priceUnit: 'YEAR',
|
enableStatus: 'ENABLED',
|
selected: false,
|
quantity: 1,
|
duration: 1
|
},
|
{
|
id: 4,
|
productId: '10001',
|
productSuite: 'ENTERPRISE_PUBLIC_SAAS_LICENSE',
|
salesForm: 'LEASE',
|
customerObject: 'PERSONAL',
|
accountQuantity: 1,
|
accountQuantityUnlimited: false,
|
concurrentNodeQuantity: 1,
|
concurrentNodeQuantityUnlimited: false,
|
priceSettings: ['FREE'],
|
pointsAmount: 0,
|
currencyAmount: 0,
|
priceUnit: 'SET',
|
enableStatus: 'ENABLED',
|
selected: false,
|
quantity: 1,
|
duration: 1
|
}
|
]
|
}
|
|
// 获取套件显示名称
|
const getSuiteDisplayName = (suite: SuiteItem) => {
|
const map: Record<string, string> = {
|
ENTERPRISE_PRIVATE_SAAS_LICENSE: '企业私有SaaS版许可',
|
ENTERPRISE_PRIVATE_SAAS_OTA: '企业私有SaaS版OTA升级服务',
|
ENTERPRISE_PRIVATE_SAAS_USER_INCREMENT: '企业私有SaaS版用户增量包',
|
PROJECT_PRIVATE_SAAS_OTA: '项目私有SaaS版OTA升级服务',
|
PROJECT_PRIVATE_SAAS_USER_INCREMENT: '项目私有SaaS版用户增量包',
|
ENTERPRISE_PUBLIC_SAAS_LICENSE: '企业公有SaaS版许可',
|
ENTERPRISE_PUBLIC_SAAS_OTA: '企业公有SaaS版OTA服务',
|
ENTERPRISE_PUBLIC_SAAS_USER_INCREMENT: '企业公有SaaS版用户增量包',
|
ENTERPRISE_PUBLIC_SAAS_CLOUD: '企业公有SaaS版云服务',
|
PERSONAL_PUBLIC_SAAS_LICENSE: '个人公有SaaS化许可'
|
}
|
return map[suite.productSuite] || suite.productSuite
|
}
|
|
// 获取销售形式文本
|
const getSalesFormText = (salesForm: string) => {
|
const map: Record<string, string> = {
|
BUYOUT: '买断',
|
LEASE: '租赁',
|
PRIVATE_INCREMENT: '私有增量包',
|
PUBLIC_INCREMENT: '公有增量包',
|
OTA: 'OTA服务',
|
CLOUD: '云服务'
|
}
|
return map[salesForm] || salesForm
|
}
|
|
// 获取客户对象文本
|
const getCustomerObjectText = (customerObject: string) => {
|
const map: Record<string, string> = {
|
ENTERPRISE: '企业',
|
PERSONAL: '个人',
|
PROJECT_DEPARTMENT: '项目部'
|
}
|
return map[customerObject] || customerObject
|
}
|
|
// 获取价格单位选项
|
const getPriceUnitOptions = (suite: SuiteItem) => {
|
const allOptions = [
|
{ label: '积分', value: 'POINTS' },
|
{ label: '套', value: 'SET' },
|
{ label: '套/年', value: 'SET_PER_YEAR' },
|
{ label: '年', value: 'YEAR' }
|
]
|
|
// 根据套件的价格设置过滤可用单位
|
if (suite.priceSettings.includes('FREE')) {
|
return [{ label: '免费', value: 'FREE' }]
|
}
|
|
return allOptions.filter(option => {
|
if (option.value === 'POINTS') return suite.priceSettings.includes('POINTS')
|
return true
|
})
|
}
|
|
// 单价单位后缀
|
const getUnitSuffix = (unit?: string) => {
|
const map: Record<string, string> = { SET: '/套', SET_PER_YEAR: '/套/年', YEAR: '/年', FREE: '' }
|
return map[unit || ''] || ''
|
}
|
|
// 数字格式化
|
const formatNumber = (val?: number) => {
|
if (!val && val !== 0) return ''
|
return Number(val).toLocaleString()
|
}
|
|
// 可用价格类型
|
const getAvailablePriceTypes = (suite: SuiteItem) => {
|
const types: { label: string; value: 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE' }[] = []
|
if (suite.priceSettings.includes('POINTS')) types.push({ label: '积分', value: 'POINTS' })
|
if (suite.priceSettings.includes('CURRENCY')) types.push({ label: '货币', value: 'CURRENCY' })
|
if (suite.priceSettings.includes('AGREEMENT')) types.push({ label: '协议', value: 'AGREEMENT' })
|
if (suite.priceSettings.includes('FREE')) types.push({ label: '免费', value: 'FREE' })
|
return types
|
}
|
|
// 默认价格类型(优先级:积分>货币>协议>免费)
|
const getDefaultPriceType = (suite: SuiteItem): 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE' => {
|
if (suite.priceSettings.includes('POINTS')) return 'POINTS'
|
if (suite.priceSettings.includes('CURRENCY')) return 'CURRENCY'
|
if (suite.priceSettings.includes('AGREEMENT')) return 'AGREEMENT'
|
return 'FREE'
|
}
|
|
// 获取产品和套件数据
|
const fetchOrderData = async (productId: string, suiteIds: number[]) => {
|
if (!productId) {
|
ElMessage.warning('未提供产品ID')
|
return
|
}
|
|
loading.value = true
|
try {
|
// 模拟API调用
|
await new Promise(resolve => setTimeout(resolve, 500))
|
|
// 获取产品信息
|
productInfo.value = mockProductData[productId] || null
|
|
// 获取选中的套件信息
|
const allSuites = mockSuiteData[productId] || []
|
selectedSuites.value = allSuites
|
.filter(suite => suiteIds.length === 0 || suiteIds.includes(suite.id))
|
.map(suite => ({
|
...suite,
|
selected: true,
|
quantity: 1,
|
duration: 1,
|
priceType: getDefaultPriceType(suite)
|
}))
|
|
if (!productInfo.value) {
|
ElMessage.warning('未找到产品信息')
|
}
|
|
if (selectedSuites.value.length === 0) {
|
ElMessage.warning('未找到指定的套件信息')
|
}
|
} catch (error) {
|
console.error('获取订购数据失败:', error)
|
ElMessage.error('获取订购数据失败')
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 删除套件
|
const removeSuite = (index: number) => {
|
selectedSuites.value.splice(index, 1)
|
}
|
|
// 监听弹窗显示状态
|
watch(() => visible.value, (newVisible) => {
|
if (newVisible && props.productId) {
|
fetchOrderData(props.productId, props.suiteIds)
|
}
|
})
|
|
// 监听产品ID和套件ID变化
|
watch(() => [props.productId, props.suiteIds], () => {
|
if (visible.value && props.productId) {
|
fetchOrderData(props.productId, props.suiteIds)
|
}
|
})
|
|
// 关闭弹窗
|
const handleClose = () => {
|
visible.value = false
|
}
|
|
// 提交订购申请
|
const handleSubmitOrder = async () => {
|
const selectedItems = selectedSuites.value.filter(suite => suite.selected)
|
|
if (selectedItems.length === 0) {
|
ElMessage.warning('请至少选择一个套件')
|
return
|
}
|
|
try {
|
await ElMessageBox.confirm(
|
`确认要提交订购申请吗?`,
|
'确认订购',
|
{
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}
|
)
|
|
submitting.value = true
|
|
// 模拟提交API调用
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
// 模拟生成订单号(使用与状态弹窗模拟数据一致的示例ID,便于联调UI)
|
const orderId = '4348442557619205545'
|
|
const orderData = {
|
id: orderId,
|
productId: props.productId,
|
productName: productInfo.value?.name,
|
suites: selectedItems,
|
totalByType: totalByType.value,
|
orderForm: orderForm.value,
|
orderTime: new Date().toISOString()
|
}
|
|
emit('order-success', orderData)
|
ElMessage.success('订购申请提交成功')
|
// 打开订单状态对话框
|
currentOrderId.value = orderId
|
statusDialogVisible.value = true
|
handleClose()
|
} catch (error) {
|
if (error !== 'cancel') {
|
console.error('提交订购申请失败:', error)
|
ElMessage.error('提交订购申请失败')
|
}
|
} finally {
|
submitting.value = false
|
}
|
}
|
</script>
|
|
<style scoped lang="scss">
|
.product-order-dialog {
|
:deep(.el-dialog__title) {
|
font-size: 14px;
|
font-weight: 600;
|
}
|
|
:deep(.el-dialog) {
|
max-width: 95vw;
|
min-width: 1000px;
|
}
|
|
:deep(.el-dialog__body) {
|
max-height: 70vh;
|
overflow-y: auto;
|
padding-top: 10px;
|
}
|
}
|
|
.order-container {
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
font-size: 14px;
|
font-weight: 600;
|
|
.section-icon {
|
margin-right: 6px;
|
color: #409eff;
|
}
|
|
.unit-info,
|
.quantity-info,
|
.duration-info,
|
.action-info {
|
color: #606266;
|
font-size: 13px;
|
font-weight: 500;
|
min-width: 60px;
|
text-align: center;
|
}
|
}
|
|
.product-info-card {
|
:deep(.el-card__body) {
|
padding: 5px;
|
}
|
|
.product-details {
|
:deep(.el-descriptions__table) {
|
table-layout: fixed;
|
width: 100%;
|
}
|
|
:deep(.el-descriptions__label),
|
:deep(.el-descriptions__content) {
|
font-size: 12px;
|
padding-top: 3px;
|
padding-bottom: 3px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.desc-label-with-icon {
|
display: inline-flex;
|
align-items: center;
|
gap: 6px;
|
font-size: 12px;
|
font-weight: 600;
|
color: #606266;
|
}
|
.desc-label-icon { color: #409eff; }
|
|
/* 让基本信息首行背景与套件表头一致 */
|
:deep(.el-descriptions__table tr:first-child th),
|
:deep(.el-descriptions__table tr:first-child td) {
|
background-color: #f5f7fa;
|
}
|
/* 仅移除首行“标签”单元格的右侧分隔线 */
|
:deep(.el-descriptions__table tr:first-child .el-descriptions__label) {
|
border-right: 0 !important;
|
}
|
/* 同时移除首行“内容”单元格的左侧分隔线,避免双边线视觉 */
|
:deep(.el-descriptions__table tr:first-child .el-descriptions__content) {
|
border-left: 0 !important;
|
}
|
}
|
}
|
|
.selected-suites-card {
|
:deep(.el-card__body) {
|
padding: 5px;
|
}
|
}
|
|
.suite-table-wrapper { overflow-x: auto; }
|
|
.suite-table {
|
width: 100%;
|
border-collapse: collapse;
|
background: #fff;
|
}
|
|
.suite-table th,
|
.suite-table td {
|
border: 1px solid #e4e7ed;
|
padding: 4px 8px;
|
text-align: left;
|
vertical-align: middle;
|
font-size: 12px;
|
}
|
|
.suite-table thead th {
|
background: #f5f7fa;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.suite-table thead .th-center { text-align: center; }
|
.suite-table thead .th-left { text-align: left; }
|
|
.th-detail { display: inline-flex; align-items: center; gap: 6px; }
|
.th-detail-icon { color: #409eff; }
|
|
.cell-detail .detail-content {
|
display: inline-flex;
|
align-items: center;
|
gap: 8px;
|
}
|
|
.suite-name { font-weight: 600; color: #303133; }
|
.spec-line { color: #606266; font-size: 12px; line-height: 20px; }
|
|
.cell-price { white-space: nowrap; }
|
.price-type-select { margin-bottom: 6px; }
|
.price-inline { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
|
.price-tag.points { color: #E6A23C; font-weight: 600; }
|
.price-tag.currency { color: #F56C6C; font-weight: 600; }
|
.price-free { color: #67C23A; font-weight: 600; }
|
.price-agreement { color: #409EFF; }
|
|
.cell-input { text-align: center; }
|
.cell-action { text-align: center; }
|
.cell-action :deep(.el-button.is-link) { color: #f56c6c; }
|
|
/* 列宽优化:收窄 数量 与 期限(年),加宽 操作 */
|
.suite-table .col-price { width: 160px; }
|
.suite-table .col-qty { width: 72px; }
|
.suite-table .col-years { width: 88px; }
|
.suite-table .col-action { width: 60px; }
|
|
/* 数量与期限输入宽度收窄以适配列宽 */
|
.cell-input :deep(.el-input-number) { width: 74px; }
|
|
.order-summary {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 12px 0;
|
border-top: 1px solid #e4e7ed;
|
background: #fafafa;
|
border-radius: 4px;
|
|
.summary-left { flex: 1; }
|
|
.summary-row {
|
display: inline-flex;
|
align-items: center;
|
gap: 8px;
|
font-size: 12px;
|
|
.summary-label { color: #606266; }
|
.summary-value { font-weight: 600; }
|
.summary-value.highlight { color: #409eff; }
|
.summary-value.total { color: #e6a23c; font-size: 12px; }
|
.summary-value.currency { color: #f56c6c; font-size: 12px; }
|
.summary-text { color: #606266; }
|
.summary-spacer { width: 20px; }
|
}
|
|
.summary-actions {
|
display: inline-flex;
|
gap: 12px;
|
}
|
}
|
|
.dialog-footer {
|
display: flex;
|
justify-content: flex-end;
|
gap: 12px;
|
}
|
</style>
|