@@ -1,496 +0,0 @@
< script setup lang = "ts" >
import { computed , nextTick , onMounted , reactive , ref , watch } from 'vue'
import { CircleSlash2 , Eye , Plus } from '@lucide/vue'
import { ElMessage , ElMessageBox , type FormInstance , type FormRules } from 'element-plus'
import { listPlatformTenants , type PlatformTenantResource as PlatformCustomerContract } from '@/modules/iam'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration'
import { getApiErrorDetails , type ApiErrorDetails } from '@/shared/api/http'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import AppDrawer from '@/shared/components/AppDrawer.vue'
import DataTable , { type DataTableColumn } from '@/shared/components/DataTable.vue'
import QueryToolbar , { type QueryField , type QueryModel } from '@/shared/components/QueryToolbar.vue'
import {
createCustomerPricingRuleVersion ,
disableCustomerPricingRule ,
getCustomerPricingRule ,
listCustomerPricingRules ,
} from './api'
import type { CustomerPricingRule , CustomerRuleFormModel } from './types'
const access = useAccessPreviewStore ( )
const canEdit = computed ( ( ) => access . can ( 'firstleg:fba-pricing:rule:edit' ) )
const customers = ref < Array < { id : string ; name : string ; code : string } > > ( [ ] )
const customerLoadError = ref < ApiErrorDetails | null > ( null )
const rules = ref < CustomerPricingRule [ ] > ( [ ] )
const loading = ref ( false )
const error = ref < ApiErrorDetails | null > ( null )
const detailVisible = ref ( false )
const detailLoading = ref ( false )
const detailError = ref < ApiErrorDetails | null > ( null )
const selectedRule = ref < CustomerPricingRule | null > ( null )
const editorVisible = ref ( false )
const editorSaving = ref ( false )
const editorForm = ref < FormInstance > ( )
const editorDirty = ref ( false )
const editorScopeCustomerId = ref ( '' )
const page = ref ( 1 )
const pageSize = ref ( 20 )
type RuleFilters = QueryModel & {
customerId : string
ruleCode : string
customerName : string
chargeMode : '' | 'KG' | 'CBM'
status : string
}
const filters = ref < RuleFilters > ( { customerId : '' , ruleCode : '' , customerName : '' , chargeMode : '' , status : '' } )
const appliedFilters = ref < RuleFilters > ( { ... filters . value } )
const selectedCustomerId = computed ( ( ) => appliedFilters . value . customerId )
const queryFields = computed < QueryField [ ] > ( ( ) => [
{
key : 'customerId' ,
type : 'select' ,
width : 280 ,
placeholder : customerLoadError . value ? '客户列表加载失败' : '全部客户' ,
props : { 'aria-label' : '所属企业' , filterable : true , disabled : Boolean ( customerLoadError . value ) } ,
options : customers . value . map ( ( customer ) => ( {
value : customer . id ,
label : ` ${ customer . name } ( ${ customer . code || customer . id } ) ` ,
} ) ) ,
} ,
{ key : 'ruleCode' , type : 'input' , width : 220 , placeholder : '规则编码' } ,
{ key : 'customerName' , type : 'input' , width : 260 , placeholder : '客户名称' } ,
{
key : 'chargeMode' , type : 'select' , width : 180 , placeholder : '全部计费方式' , options : [
{ label : '按 KG' , value : 'KG' } ,
{ label : '按 CBM' , value : 'CBM' } ,
] ,
} ,
{
key : 'status' , type : 'select' , width : 160 , placeholder : '全部状态' , options : [
{ label : '生效中' , value : 'ACTIVE' } ,
{ label : '已停用' , value : 'INACTIVE' } ,
] ,
} ,
] )
const columns : DataTableColumn [ ] = [
{ key : 'actions' , label : '操作' , width : 210 , fixed : 'left' , slotName : 'actions' } ,
{ key : 'rule' , label : '规则版本' , minWidth : 170 , slotName : 'rule' , showOverflowTooltip : true } ,
{ key : 'customer' , label : '适用客户' , minWidth : 190 , slotName : 'customer' , showOverflowTooltip : true } ,
{ key : 'businessType' , prop : 'businessType' , label : '业务类型' , minWidth : 110 , showOverflowTooltip : true } ,
{ key : 'chargeMode' , label : '计费方式' , width : 105 , slotName : 'chargeMode' } ,
{ key : 'taxMode' , label : '税务模式' , width : 100 , slotName : 'taxMode' } ,
{ key : 'conversionFactor' , prop : 'conversionFactor' , label : '换算系数' , width : 105 } ,
{ key : 'rounding' , label : '舍入规则' , minWidth : 155 , slotName : 'rounding' } ,
{ key : 'currency' , prop : 'currency' , label : '币种' , width : 80 } ,
{ key : 'period' , label : '有效期' , minWidth : 225 , slotName : 'period' } ,
{ key : 'status' , label : '状态' , width : 90 , slotName : 'status' } ,
]
const filteredRules = computed ( ( ) => rules . value . filter ( ( rule ) => {
const customerName = appliedFilters . value . customerName . trim ( ) . toLowerCase ( )
return ( ! customerName || rule . customerName . toLowerCase ( ) . includes ( customerName ) )
&& ( ! appliedFilters . value . chargeMode || rule . chargeMode === appliedFilters . value . chargeMode )
&& ( ! appliedFilters . value . status || rule . status === appliedFilters . value . status )
} ) )
const pagedRules = computed ( ( ) => filteredRules . value . slice ( ( page . value - 1 ) * pageSize . value , page . value * pageSize . value ) )
const tableEmptyText = '暂无符合筛选条件的客户计费规则'
const emptyForm = ( ) : CustomerRuleFormModel => ( {
ruleCode : '' ,
customerId : '' ,
customerName : '' ,
businessType : 'FBA' ,
chargeMode : 'KG' ,
taxMode : 'TAX_INCLUDED' ,
conversionFactor : 167 ,
roundingScale : 3 ,
roundingMode : 'CEILING' ,
currency : 'CNY' ,
effectiveFrom : '' ,
effectiveTo : null ,
remark : null ,
} )
const form = reactive < CustomerRuleFormModel > ( emptyForm ( ) )
const formRules : FormRules < CustomerRuleFormModel > = {
ruleCode : [ { required : true , message : '请输入规则编码' , trigger : 'blur' } ] ,
customerId : [ { required : true , message : '请输入客户 ID' , trigger : 'blur' } ] ,
customerName : [ { required : true , message : '请输入客户名称' , trigger : 'blur' } ] ,
businessType : [ { required : true , message : '请输入业务类型' , trigger : 'blur' } ] ,
chargeMode : [ { required : true , message : '请选择计费方式' , trigger : 'change' } ] ,
taxMode : [ { required : true , message : '请选择税务模式' , trigger : 'change' } ] ,
conversionFactor : [ { required : true , message : '请输入大于 0 的换算系数' , trigger : 'blur' , type : 'number' , min : 0.000001 } ] ,
roundingScale : [ { required : true , message : '请选择保留位数' , trigger : 'change' , type : 'number' , min : 0 , max : 4 } ] ,
roundingMode : [ { required : true , message : '请选择舍入方式' , trigger : 'change' } ] ,
currency : [ { required : true , message : '请选择币种' , trigger : 'change' } ] ,
effectiveFrom : [ { required : true , message : '请选择生效时间' , trigger : 'change' } ] ,
}
useUnsavedWorkRegistration ( {
key : 'customer-pricing-rule-version' ,
label : computed ( ( ) => '客户计费规则版本' ) ,
isOpen : computed ( ( ) => editorVisible . value ) ,
model : form ,
requiredPermission : computed ( ( ) => 'firstleg:fba-pricing:rule:edit' ) ,
} )
watch ( form , ( ) => {
if ( editorVisible . value ) editorDirty . value = true
} , { deep : true } )
async function loadCustomers ( ) {
customerLoadError . value = null
try {
const records : PlatformCustomerContract [ ] = [ ]
let currentPage = 1
let pages = 1
do {
const result = await listPlatformTenants ( { page : currentPage , size : 200 } )
records . push ( ... result . records )
pages = Math . max ( 1 , result . pages )
currentPage += 1
} while ( currentPage <= pages )
customers . value = records . map ( ( customer ) => ( {
id : String ( customer . id ) ,
name : customer . tenantName ,
code : customer . tenantCode ,
} ) )
} catch ( cause ) {
customers . value = [ ]
customerLoadError . value = getApiErrorDetails ( cause , '客户列表加载失败' )
}
}
async function loadRules ( ) {
loading . value = true
error . value = null
try {
rules . value = await listCustomerPricingRules ( {
... ( selectedCustomerId . value ? { tenantId : selectedCustomerId . value } : { } ) ,
ruleCode : appliedFilters . value . ruleCode . trim ( ) ,
} )
} catch ( cause ) {
error . value = getApiErrorDetails ( cause , '客户计费规则加载失败' )
} finally {
loading . value = false
}
}
function applyQuery ( model : QueryModel ) {
const nextCustomerId = String ( model . customerId || '' )
if ( nextCustomerId !== selectedCustomerId . value ) {
rules . value = [ ]
selectedRule . value = null
detailVisible . value = false
detailError . value = null
editorVisible . value = false
editorDirty . value = false
error . value = null
}
appliedFilters . value = {
customerId : nextCustomerId ,
ruleCode : String ( model . ruleCode || '' ) ,
customerName : String ( model . customerName || '' ) ,
chargeMode : ( model . chargeMode || '' ) as RuleFilters [ 'chargeMode' ] ,
status : String ( model . status || '' ) ,
}
page . value = 1
void loadRules ( )
}
async function openDetail ( row : CustomerPricingRule ) {
detailVisible . value = true
detailLoading . value = true
detailError . value = null
selectedRule . value = row
try {
selectedRule . value = await getCustomerPricingRule ( row . tenantId , row . id )
} catch ( cause ) {
detailError . value = getApiErrorDetails ( cause , '规则详情加载失败' )
} finally {
detailLoading . value = false
}
}
function retryDetail ( ) {
if ( selectedRule . value ) void openDetail ( selectedRule . value )
}
function asRule ( row : unknown ) : CustomerPricingRule {
return row as CustomerPricingRule
}
function resetForm ( source ? : CustomerPricingRule ) {
Object . assign ( form , emptyForm ( ) , source ? {
ruleCode : source . ruleCode ,
customerId : source . customerId ,
customerName : source . customerName ,
businessType : source . businessType ,
chargeMode : source . chargeMode ,
taxMode : source . taxMode ,
conversionFactor : source . conversionFactor ,
roundingScale : source . roundingScale ,
roundingMode : source . roundingMode ,
currency : source . currency ,
effectiveTo : source . effectiveTo ,
remark : source . remark ,
} : { customerId : selectedCustomerId . value } )
}
async function openEditor ( source ? : CustomerPricingRule ) {
editorScopeCustomerId . value = source ? . tenantId || selectedCustomerId . value
resetForm ( source )
editorDirty . value = false
editorVisible . value = true
await nextTick ( )
editorForm . value ? . clearValidate ( )
}
async function closeEditor ( ) {
if ( editorDirty . value ) {
try {
await ElMessageBox . confirm ( '尚有未保存的规则版本,确定放弃吗?' , '放弃编辑' , {
confirmButtonText : '放弃' , cancelButtonText : '继续编辑' , type : 'warning' ,
} )
} catch {
editorVisible . value = true
return
}
}
editorVisible . value = false
editorDirty . value = false
}
async function beforeEditorClose ( done : ( ) => void ) {
if ( editorSaving . value ) return
if ( ! editorDirty . value ) {
done ( )
return
}
try {
await ElMessageBox . confirm ( '尚有未保存的规则版本,确定放弃吗?' , '放弃编辑' , {
confirmButtonText : '放弃' , cancelButtonText : '继续编辑' , type : 'warning' ,
} )
editorDirty . value = false
done ( )
} catch {
editorVisible . value = true
}
}
async function saveVersion ( ) {
if ( ! await editorForm . value ? . validate ( ) ) return
editorSaving . value = true
try {
await createCustomerPricingRuleVersion ( editorScopeCustomerId . value , {
... form ,
ruleCode : form . ruleCode . trim ( ) ,
customerId : String ( form . customerId ) ,
customerName : form . customerName . trim ( ) ,
businessType : form . businessType . trim ( ) ,
effectiveTo : form . effectiveTo || null ,
remark : form . remark ? . trim ( ) || null ,
} )
editorDirty . value = false
editorVisible . value = false
ElMessage . success ( '客户计费规则新版本已创建' )
await loadRules ( )
} catch ( cause ) {
ElMessage . error ( getApiErrorDetails ( cause , '规则版本创建失败' ) . message )
} finally {
editorSaving . value = false
}
}
async function disableRule ( row : CustomerPricingRule ) {
try {
await ElMessageBox . confirm ( ` 停用规则“ ${ row . ruleCode } ”的当前版本?历史费用不会改变。 ` , '停用规则' , {
confirmButtonText : '确认停用' , cancelButtonText : '取消' , type : 'warning' ,
} )
await disableCustomerPricingRule ( row . tenantId , row . id )
ElMessage . success ( '规则已停用' )
await loadRules ( )
} catch ( cause ) {
if ( cause === 'cancel' || cause === 'close' ) return
ElMessage . error ( getApiErrorDetails ( cause , '规则停用失败' ) . message )
}
}
function formatDate ( value : string | null ) {
if ( ! value ) return '长期有效'
return value . replace ( 'T' , ' ' ) . slice ( 0 , 16 )
}
function modeLabel ( mode : string ) {
return mode === 'KG' ? '按 KG' : mode === 'CBM' ? '按 CBM' : mode
}
function taxLabel ( mode : string ) {
return mode === 'TAX_INCLUDED' ? '包税' : mode === 'TAX_EXCLUDED' ? '不包税' : mode
}
onMounted ( ( ) => {
access . initializeAfterLogin ( )
void loadCustomers ( )
void loadRules ( )
} )
< / script >
< template >
< div class = "business-page customer-rules-page" >
< QueryToolbar v-model = "filters" class="surface-panel" ariaLabel="客户计费规则筛选" :fields="queryFields" @search="applyQuery" / >
< LoadErrorState v-if = "customerLoadError" title="客户列表加载失败" :message="customerLoadError.message" compact @retry="loadCustomers" / >
< LoadErrorState v-if = "error" title="客户计费规则加载失败" :message="error.message" @retry="loadRules" / >
< section v-else class = "surface-panel table-panel" aria -live = " polite " :aria-busy = "loading" >
< div class = "panel-heading" >
< div >
< h2 > 客户计费规则 < / h2 >
< p > 按企业维护 FBA 的 KG / CBM 计费版本 · 共 { { filteredRules . length } } 个规则版本 < / p >
< / div >
< el-button v-if = "canEdit" type="primary" :disabled="loading || !selectedCustomerId" @click="openEditor()" >
< Plus :size = "16" aria -hidden = " true " / > 新建版本
< / el-button >
< / div >
< DataTable
v -model :page = "page"
v -model :page-size = "pageSize"
:data = "pagedRules"
:columns = "columns"
:loading = "loading"
:total = "filteredRules.length"
: page -sizes = " [ 10 , 20 , 50 ] "
row -key = " id "
:empty-text = "tableEmptyText"
>
< template # actions = "{ row }" >
< div class = "row-actions" >
< el-button link type = "primary" @click ="openDetail(asRule(row))" > < Eye :size = "15" aria -hidden = " true " / > 详情 < / el-button >
< el-button v-if = "canEdit" link type="primary" @click="openEditor(asRule(row))"><Plus :size="15" aria-hidden="true" / > 新版本 < / el-button >
< el-button v-if = "canEdit && row.status === 'ACTIVE'" link type="danger" @click="disableRule(asRule(row))"><CircleSlash2 :size="15" aria-hidden="true" / > 停用 < / el-button >
< / div >
< / template >
< template # rule = "{ row }" > < div class = "primary-cell" > < strong > { { row . ruleCode } } < / strong > < small > 版本 V { { row . ruleVersion ? ? '—' } } < / small > < / div > < / template >
< template # customer = "{ row }" > < strong > { { row . customerName } } < / strong > < small class = "subline" > ID { { row . customerId } } < / small > < / template >
< template # chargeMode = "{ row }" > < el-tag effect = "plain" > { { modeLabel ( row . chargeMode ) } } < / el-tag > < / template >
< template # taxMode = "{ row }" > { { taxLabel ( row . taxMode ) } } < / template >
< template # rounding = "{ row }" > 保留 { { row . roundingScale } } 位 · { { row . roundingMode } } < / template >
< template # period = "{ row }" > < span > { { formatDate ( row . effectiveFrom ) } } < / span > < small class = "subline" > 至 { { formatDate ( row . effectiveTo ) } } < / small > < / template >
< template # status = "{ row }" > < el-tag : type = "row.status === 'ACTIVE' ? 'success' : 'info'" effect = "light" > { { row . status === 'ACTIVE' ? '生效中' : '已停用' } } < / el-tag > < / template >
< template # pagination -left > 共 { { filteredRules . length } } 个规则版本 < / template >
< / DataTable >
< / section >
< AppDrawer v-model = "detailVisible" title="客户计费规则详情" size="min(600px, 94vw)" :loading="detailLoading" :show-footer="false" >
< LoadErrorState v-if = "detailError" title="规则详情加载失败" :message="detailError.message" compact @retry="retryDetail" / >
< div v-else-if = "selectedRule" class="rule-detail" >
< section >
< h3 > 规则归属 < / h3 >
< dl class = "detail-grid" >
< div > < dt > 规则编码 < / dt > < dd > { { selectedRule . ruleCode } } < / dd > < / div >
< div > < dt > 规则版本 < / dt > < dd > V { { selectedRule . ruleVersion ? ? '—' } } < / dd > < / div >
< div > < dt > 适用客户 < / dt > < dd > { { selectedRule . customerName } } < / dd > < / div >
< div > < dt > 客户 ID < / dt > < dd > { { selectedRule . customerId } } < / dd > < / div >
< div > < dt > 业务类型 < / dt > < dd > { { selectedRule . businessType } } < / dd > < / div >
< div > < dt > 状态 < / dt > < dd > < el-tag : type = "selectedRule.status === 'ACTIVE' ? 'success' : 'info'" > { { selectedRule . status === 'ACTIVE' ? '生效中' : '已停用' } } < / el-tag > < / dd > < / div >
< / dl >
< / section >
< section >
< h3 > 计费口径 < / h3 >
< dl class = "detail-grid" >
< div > < dt > 计费方式 < / dt > < dd > { { modeLabel ( selectedRule . chargeMode ) } } < / dd > < / div >
< div > < dt > 税务模式 < / dt > < dd > { { taxLabel ( selectedRule . taxMode ) } } < / dd > < / div >
< div > < dt > 换算系数 < / dt > < dd > { { selectedRule . conversionFactor } } < / dd > < / div >
< div > < dt > 舍入规则 < / dt > < dd > 保留 { { selectedRule . roundingScale } } 位 , { { selectedRule . roundingMode } } < / dd > < / div >
< div > < dt > 币种 < / dt > < dd > { { selectedRule . currency } } < / dd > < / div >
< / dl >
< / section >
< section >
< h3 > 版本有效期 < / h3 >
< dl class = "detail-grid" >
< div > < dt > 生效时间 < / dt > < dd > { { formatDate ( selectedRule . effectiveFrom ) } } < / dd > < / div >
< div > < dt > 失效时间 < / dt > < dd > { { formatDate ( selectedRule . effectiveTo ) } } < / dd > < / div >
< div class = "detail-wide" > < dt > 备注 < / dt > < dd > { { selectedRule . remark || '—' } } < / dd > < / div >
< / dl >
< / section >
< / div >
< / AppDrawer >
< AppDrawer
v-model = "editorVisible"
title = "创建客户计费规则版本"
size = "min(760px, 94vw)"
:confirm-loading = "editorSaving"
confirm -text = " 创建版本 "
:before-close = "beforeEditorClose"
@confirm ="saveVersion"
@cancel ="closeEditor"
>
< el-form ref = "editorForm" :model = "form" :rules = "formRules" label -position = " top " class = "rule-form" >
< div class = "form-section" >
< h2 > 规则归属 < / h2 >
< div class = "form-grid" >
< el-form-item label = "规则编码" prop = "ruleCode" > < el-input v-model = "form.ruleCode" maxlength="50" placeholder="例如 FBA-TAX-KG" / > < / el-form-item >
< el-form-item label = "客户 ID" prop = "customerId" > < el-input v-model = "form.customerId" / > < / el-form-item >
< el-form-item label = "客户名称" prop = "customerName" > < el-input v-model = "form.customerName" maxlength="128" / > < / el-form-item >
< el-form-item label = "业务类型" prop = "businessType" > < el-input v-model = "form.businessType" maxlength="32" / > < / el-form-item >
< / div >
< / div >
< div class = "form-section" >
< h2 > 计费口径 < / h2 >
< div class = "form-grid" >
< el-form-item label = "计费方式" prop = "chargeMode" > < el-segmented v-model = "form.chargeMode" :options="[{ label: '按 KG', value: 'KG' }, { label: '按 CBM', value: 'CBM' }]" / > < / el-form-item >
< el-form-item label = "税务模式" prop = "taxMode" > < el-select v-model = "form.taxMode"><el-option label="包税" value="TAX_INCLUDED" /><el-option label="不包税" value="TAX_EXCLUDED" / > < / el-select > < / el-form-item >
< el-form-item label = "换算系数" prop = "conversionFactor" > < el-input-number v-model = "form.conversionFactor" :min="0.000001" :precision="6" :controls="false" / > < / el-form-item >
< el-form-item label = "保留小数位" prop = "roundingScale" > < el-select v-model = "form.roundingScale"><el-option v-for="scale in [0, 1, 2, 3, 4]" :key="scale" :label="`${scale} 位`" :value="scale" / > < / el-select > < / el-form-item >
< el-form-item label = "舍入方式" prop = "roundingMode" > < el-select v-model = "form.roundingMode"><el-option label="向上取整 CEILING" value="CEILING" /><el-option label="向上舍入 UP" value="UP" /><el-option label="向下舍入 DOWN" value="DOWN" /><el-option label="向下取整 FLOOR" value="FLOOR" /><el-option label="四舍五入 HALF_UP" value="HALF_UP" /><el-option label="五舍六入 HALF_DOWN" value="HALF_DOWN" /><el-option label="银行家舍入 HALF_EVEN" value="HALF_EVEN" / > < / el-select > < / el-form-item >
< el-form-item label = "币种" prop = "currency" > < el-select v-model = "form.currency" filterable allow-create default-first-option><el-option label="人民币 CNY" value="CNY" /><el-option label="美元 USD" value="USD" / > < / el-select > < / el-form-item >
< / div >
< / div >
< div class = "form-section" >
< h2 > 生效范围 < / h2 >
< div class = "form-grid" >
< el-form-item label = "生效时间" prop = "effectiveFrom" > < el-date-picker v-model = "form.effectiveFrom" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="选择生效时间" / > < / el-form-item >
< el-form-item label = "失效时间" > < el-date-picker v-model = "form.effectiveTo" type="datetime" value-format="YYYY-MM-DDTHH:mm:ss" placeholder="不填表示长期有效" / > < / el-form-item >
< el-form-item label = "备注" class = "wide" > < el-input v-model = "form.remark" type="textarea" :rows="3" maxlength="500" show -word -limit / > < / el-form-item >
< / div >
< / div >
< / el-form >
< / AppDrawer >
< / div >
< / template >
< style scoped >
. customer - rules - page { min - width : 0 ; }
. row - actions . el - button { display : inline - flex ; align - items : center ; gap : 6 px ; }
. row - actions { display : flex ; align - items : center ; gap : 3 px ; white - space : nowrap ; }
. primary - cell { display : flex ; flex - direction : column ; gap : 3 px ; }
. primary - cell small , . subline { display : block ; margin - top : 3 px ; color : var ( -- cc - muted ) ; font - size : 11 px ; line - height : 1.45 ; }
. rule - detail { display : grid ; gap : 24 px ; }
. rule - detail section + section { padding - top : 22 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. rule - detail h3 { margin : 0 0 14 px ; color : var ( -- cc - text ) ; font - size : 15 px ; }
. detail - grid { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; gap : 16 px 24 px ; margin : 0 ; }
. detail - grid > div { min - width : 0 ; }
. detail - grid dt { margin - bottom : 5 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. detail - grid dd { margin : 0 ; color : var ( -- cc - text ) ; line - height : 1.55 ; overflow - wrap : anywhere ; }
. detail - wide { grid - column : 1 / - 1 ; }
. rule - form { display : grid ; gap : 24 px ; }
. form - section { display : grid ; gap : 14 px ; }
. form - section + . form - section { padding - top : 22 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. form - section h2 { margin : 0 ; color : var ( -- cc - text ) ; font - size : 16 px ; line - height : 1.4 ; }
. form - grid { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; gap : 2 px 20 px ; }
. wide { grid - column : 1 / - 1 ; }
. form - grid : deep ( . el - select ) , . form - grid : deep ( . el - input - number ) , . form - grid : deep ( . el - date - editor ) { width : 100 % ; }
@ media ( max - width : 760 px ) {
. form - grid { grid - template - columns : 1 fr ; }
. wide { grid - column : auto ; }
}
@ media ( max - width : 480 px ) {
. detail - grid { grid - template - columns : 1 fr ; }
. detail - wide { grid - column : auto ; }
}
< / style >