@@ -18,7 +18,7 @@ import { tagGroupsApi } from '@/api/tag-groups'
import { originGoodsApi } from '@/api/origin-goods'
import { syncApi } from '@/api/sync'
import { sameFamily } from '@/utils/family-match'
import { cleanLinkName , deriveLinkTagNames , truncateToProcess } from '@/utils/origin-name'
import { cleanLinkName , deriveLinkTagNames , linkDims , truncateToProcess } from '@/utils/origin-name'
import { productFamiliesApi } from '@/api/product-families'
const mode = ref < 'category' | 'country' | 'global' > ( 'category' )
@@ -566,7 +566,7 @@ const editGood = ref<Good | GoodDetail | null>(null)
const originalOriginGoodId = ref < string > ( '' )
const editForm = ref ( {
id : '' , goodName : '' , goodImage : '' , countryId : '' , cascaderCategory : [ ] as string [ ] ,
categoryId : '' , tagIds : [ ] as string [ ] , positionId : '' ,
categoryId : '' , positionId : '' ,
} )
const editOriginDetail = computed ( ( ) => ( editGood . value as GoodDetail | null ) ? . originDetail ? ? null )
@@ -654,14 +654,57 @@ function addCustomVariant() {
} )
}
// ─── Edit family(编辑弹窗的族成员管理,替代旧主源/副源 ) ───
// ─── Edit family(编辑弹窗的「关联原产品」:成员可展开查看详情并配置标签 ) ───
interface FamilyMemberRow {
id : string
goodName : string
goodImage : string | null
source : string
delisted : boolean
sdsGoodId : string
goodPrice : string | null
variantCount : number
logisticsLabel : string | null
craftLabel : string | null
warehouseLabel : string | null
tagsManual : boolean
tags : Array < { id : string ; tagName : string ; tagColor : string | null ; manual : boolean } >
}
const editFamilyId = ref < string > ( '' )
const editFamilyCode = ref < string | null > ( null )
const editFamilyMembers = ref < Array < { id : string ; goodName : string ; goodImage : string | null } > > ( [ ] )
const editFamilyMembers = ref < FamilyMemberRow [ ] > ( [ ] )
const familyMemberCount = ref < number | null > ( null )
const editFamilyLoaded = ref ( false )
const editFamilyAddKw = ref ( '' )
const editFamilyCandidates = ref < Array < { id : string ; goodName : string } > > ( [ ] )
/** 展开的成员行 key( og id) */
const expandedMemberKeys = ref < Set < string > > ( new Set ( ) )
/** 成员标签编辑态(key = og id) */
const memberTagEdits = ref < Record < string , string [ ] > > ( { } )
const memberTagSaving = ref < string > ( '' )
/** 商品自身的链接定价维度(SKU 表列) */
const editLinkDims = computed ( ( ) => linkDims ( editGood . value ? . originGood ? . goodName ? ? null ) )
function toggleMemberExpand ( key : string ) {
const next = new Set ( expandedMemberKeys . value )
if ( next . has ( key ) ) next . delete ( key )
else next . add ( key )
expandedMemberKeys . value = next
}
/** 成员行视图模型:主链接行补充商品详情接口里的实时数据 */
const familyRows = computed ( ( ) => {
const primaryOgId = String ( editGood . value ? . originGoodId ? ? '' )
return editFamilyMembers . value . map ( ( m ) => {
const isPrimary = m . id === primaryOgId
return {
key : m . id ,
role : ( isPrimary ? 'primary' : 'member' ) as 'primary' | 'member' ,
... m ,
variantCount : isPrimary ? ( editGood . value ? . originGood ? . variantCount ? ? m . variantCount ) : m . variantCount ,
}
} )
} )
function initEditFamily ( family : { familyId ? : string ; familyCode ? : string | null } | null ) {
editFamilyId . value = family ? . familyId ? ? ''
@@ -671,24 +714,72 @@ function initEditFamily(family: { familyId?: string; familyCode?: string | null
editFamilyLoaded . value = false
editFamilyAddKw . value = ''
editFamilyCandidates . value = [ ]
expandedMemberKeys . value = new Set ( )
memberTagEdits . value = { }
if ( editFamilyId . value ) loadEditFamily ( )
}
async function loadEditFamily ( ) {
if ( ! editFamilyId . value ) return
try {
const f = await productFamiliesApi . detail ( editFamilyId . value )
const f = await productFamiliesApi . detail ( editFamilyId . value ) as any
editFamilyCode . value = f . familyCode
familyMemberCount . value = f . _count . originGoods
const primaryId = f . primaryOriginGoodId ? ? editGood . value ? . originGoodId
editFamilyMembers . value = f . originGoods
. filter ( ( m ) => String ( m . id ) !== String ( primaryId ) )
. map ( ( m ) => ( { id : String ( m . id ) , goodName : m . goodName , goodImage : m . goodImage } ) )
editFamilyMembers . value = ( f . originGoods ? ? [ ] ) . map ( ( m : any ) => ( {
id : String ( m . id ) ,
goodName : m . goodName ? ? '' ,
goodImage : m . goodImage ? ? null ,
source : m . source ,
delisted : Boolean ( m . delisted ) ,
sdsGoodId : m . sdsGoodId ? ? '' ,
goodPrice : m . goodPrice ? ? null ,
variantCount : m . _count ? . variants ? ? 0 ,
logisticsLabel : m . logisticsLabel ? ? null ,
craftLabel : m . craftLabel ? ? null ,
warehouseLabel : m . warehouseLabel ? ? null ,
tagsManual : Boolean ( m . tagsManual ) ,
tags : ( m . originGoodTags ? ? [ ] ) . map ( ( t : any ) => ( {
id : String ( t . tag . id ) ,
tagName : t . tag . tagName ,
tagColor : t . tag . tagColor ? ? null ,
manual : Boolean ( t . manual ) ,
} ) ) ,
} ) )
// 标签编辑态 = 各成员已保存标签
const edits : Record < string , string [ ] > = { }
for ( const m of editFamilyMembers . value ) edits [ m . id ] = m . tags . map ( ( t ) => t . id )
memberTagEdits . value = edits
} finally {
editFamilyLoaded . value = true
}
}
async function saveMemberTags ( row : { id : string } ) {
memberTagSaving . value = row . id
try {
await originGoodsApi . updateTags ( row . id , memberTagEdits . value [ row . id ] ? ? [ ] )
ElMessage . success ( '标签已保存,自动同步不再覆盖该链接' )
await refreshAfterFamilyChange ( )
} catch ( e : any ) {
ElMessage . error ( e ? . response ? . data ? . message || '保存失败' )
} finally {
memberTagSaving . value = ''
}
}
async function resetMemberTags ( row : { id : string } ) {
memberTagSaving . value = row . id
try {
await originGoodsApi . resetTags ( row . id )
ElMessage . success ( '已恢复按链接名称自动解析' )
await refreshAfterFamilyChange ( )
} catch ( e : any ) {
ElMessage . error ( e ? . response ? . data ? . message || '恢复失败' )
} finally {
memberTagSaving . value = ''
}
}
async function refreshAfterFamilyChange ( ) {
if ( ! editGood . value ) return
const detail = await goodsApi . getGoodById ( editGood . value . id )
@@ -750,11 +841,6 @@ async function openEdit(g: Good) {
countryId : g . countryId ,
cascaderCategory : findCategoryPath ( allCategories . value , g . categoryId ) ,
categoryId : g . categoryId ,
// 有族时:自动组(物流/工艺/位置)标签为派生数据,不进入可编辑选择
tagIds : ( g . tags || [ ] ) . filter ( ( t : any ) => {
const og = ( g as any ) . originGood ? . family
return ! og || ! t . tagGroupId || ! autoTagGroupIds . value . has ( t . tagGroupId )
} ) . map ( ( t : any ) => t . id ) ,
positionId : g . positionId || '' ,
}
initEditFamily ( ( g as any ) . originGood ? . family ? ? null )
@@ -884,7 +970,6 @@ async function handleEditSubmit() {
: undefined ,
countryId : Number ( editForm . value . countryId ) ,
categoryId : Number ( editForm . value . categoryId ) ,
tagIds : editForm . value . tagIds . map ( Number ) ,
positionId : editForm . value . positionId ? Number ( editForm . value . positionId ) : null ,
} as any )
if ( customPayload ) await goodsApi . updateCustomGoodContent ( editForm . value . id , customPayload )
@@ -1326,15 +1411,7 @@ const groupedTagOptions = computed(() => {
return groups
} )
// ─── 派生标签:物流/工艺/印花数量组由系统按链接名称自动生成,表单中只读 ───
const isAutoTagGroup = ( name : string ) => / 物流 | 工艺 | 位置 | 印花数量 / . test ( name )
const autoTagGroupIds = computed ( ( ) =>
new Set ( allTagGroups . value . filter ( ( g ) => isAutoTagGroup ( g . groupName ) ) . map ( ( g ) => g . id ) ) ,
)
/** 当前商品的自动组标签(只读展示,来自其链接名称的解析结果) */
const editAutoTags = computed ( ( ) =>
( ( editGood . value as any ) ? . tags ? ? [ ] ) . filter ( ( t : any ) => autoTagGroupIds . value . has ( t . tagGroupId ) ) ,
)
// ─── 派生标签已下沉到链接级(origin_good_tags):在「关联原产品」成员行内配置 ───
function toggleTagInSelection ( tagId : string ) : void {
const idx = selectedTagIds . value . indexOf ( tagId )
@@ -1959,9 +2036,6 @@ onMounted(() => loadAll())
< el-form-item label = "图片" >
< ImageUpload v-model = "configForm.goodImage" label="上传图片" / >
< / el-form-item >
< el-form-item label = "标签" >
< div class = "derived-tags-note" > 标签无需手动选择 : 保存后由系统按链接名称自动解析 ( 印花数量 / 工艺 / 物流 ) < / div >
< / el-form-item >
< / el-form >
< template # footer >
< el-button @click ="configVisible = false" > 取消 < / el -button >
@@ -2006,62 +2080,75 @@ onMounted(() => loadAll())
<!-- Edit Good Modal ( direct edit — no separate detail step ) -- >
< el-dialog v-model = "editVisible" :title="cleanLinkName(editGood?.goodName) || '编辑商品'" width="900px" destroy -on -close >
<!-- Origin product reference -- >
< div v-if = "editGood?.originGood" class="edit-og-ref" >
< el -image v-if = "editGood.originGood.goodImage" :src="editGood.originGood.goodImage" fit="cover" class="edit-og-img" / >
< div class = "edit-og-meta" >
< div class = "edit-og-label" > { { editIsCustom ? '自定义商品' : '关联原产品' } } < / div >
< div class = "edit-og-name" : title = "editGood.originGood.goodName ?? undefined" > { { cleanLinkName ( editGood . originGood . goodName ) } } < / div >
< div class = "edit-og-sub" > { { editIsCustom ? '自定义 ID' : 'SDS ID' } } : { { editGood . originGood . sdsGoodId } } < template v-if = "editGood.originGood.goodPrice" > · ¥ {{ editGood.originGood.goodPrice }} < / template > < / div >
< div class = "edit-og-status" >
< el-tag : type = "editGood.originGood.hasDetail ? 'success' : 'warning'" size = "small" >
{ { editGood . originGood . hasDetail ? '详情已同步' : '详情未同步' } }
< / el-tag >
< span v-if = "editGood.originGood.detailSyncedAt" >
{{ new Date ( editGood.originGood.detailSyncedAt ) .toLocaleString ( ) }}
< / span >
< span > SKU { { editGood . originGood . variantCount || 0 } } < / span >
< span > 尺码 { { editGood . originGood . sizeRowCount || 0 } } < / span >
< span > 包装 { { editGood . originGood . packageRowCount || 0 } } < / span >
< / div >
< / div >
< el-button
v-if = "!editIsCustom"
type = "primary"
plain
size = "small"
:icon = "Refresh"
:loading = "detailSyncing"
@click ="handleSyncOneDetail"
> 同步详情 < / el-button >
< / div >
< div v-if = "!editIsCustom" class="edit-merged-box" >
< div class = "edit-merged-title" >
关联原产品 ( 族成员 )
< el-tooltip content = "同族链接合并为一个商品:尺码/包装并集 + 价格矩阵;主链接决定详情与跳转。" >
关联原产品
< el-tooltip content = "同族链接合并为一个商品:尺码/包装并集 + 价格矩阵;主链接决定详情与跳转。展开成员可查看详情并修正标签。 " >
< el-icon > < QuestionFilled / > < / el-icon >
< / el-tooltip >
< span v-if = "editFamilyCode" class="edit-family-code" > 族 {{ editFamilyCode }} · {{ familyMemberCount ? ? editFamilyMembers.length + 1 }} 条链接 < / span >
< span v-if = "editFamilyCode" class="edit-family-code" > 族 {{ editFamilyCode }} · {{ familyMemberCount ? ? editFamilyMembers.length }} 条链接 < / span >
< / div >
< div class = "edit-merged-list" >
< div class = "edit-merged-item primar y" >
< span class = "edit-merged-tag" > 主 < / span >
< span class = "edit-merged-name" : title = "editGood?.originGood?.goodName ?? undefined" > { { cleanLinkName ( editGood ? . originGood ? . goodName ) } } < / span >
< span v-if = "deriveLinkTagNames(editGood?.originGood?.goodName).length" class="member-chips" >
< span v-for = "c in deriveLinkTagNames(editGood?.originGood?.goodName)" :key="c" class="member-chip" > {{ c }} < / span >
< / span >
< / div >
< div v-for = "m in editFamilyMembers" :key="m.id" class="edit-merged-item" >
< span class = "edit-merged-tag sub" > 族 < / span >
< span class = "edit-merged-name" :title = "m.goodName" > { { cleanLinkName ( m . goodName ) } } < / span >
< span v-if = "deriveLinkTagNames(m.goodName).length" class="member-chips " >
< span v-for = "c in deriveLinkTagNames(m.goodName) " :key="c" class="member-chip" > {{ c }} < / span >
< / span >
< div class = "edit-merged-actions" >
< el-button size = "small" link type = "primary" @click ="promoteFamilyPrimary(m)" > 设为主链接 < / el -button >
< el-button size = "small" link type = "danger" @click ="removeFamilyMember(m)" > 移除出族 < / el -button >
< template v-for = "row in familyRows" :key="row.ke y" >
< div class = "edit-merged-item" : class = "{ primary: row.role === 'primary' }" >
< el-icon
class = "member-expand-toggle"
: class = "{ 'is-expanded': expandedMemberKeys.has(row.key) }"
@click ="toggleMemberExpand(row.key)"
> < ArrowDown / > < / el-icon >
< span class = "edit-merged-tag" : class = "{ sub: row.role !== 'primary' }" > { { row . role === 'primary' ? '主' : '族' } } < / span >
< span class = "edit-merged-name" :title = "row.goodName" > { { cleanLinkName ( row . goodName ) } } < / span >
< span v-if = "row.tags.length || deriveLinkTagNames(row.goodName).length" class="member-chips" >
< template v-if = "row.tags.length " >
< span v-for = "c in row.tags " :key="c.id " class="member-chip" :class="{ 'is-manual': c.manual }" > {{ c.tagName }} < / span >
< / template >
< template v-else >
< span v-for = "c in deriveLinkTagNames(row.goodName)" :key="c" class="member-chip is-preview" :title="'按名称解析预览,展开可配置'" > {{ c }} < / span >
< / template >
< / span >
< span v-if = "row.tagsManual" class="member-manual-flag" title="人工接管:自动同步不再覆盖该链接的标签" > 人工 < / span >
< div v-if = "row.role !== 'primary'" class="edit-merged-actions" >
< el -button size = "small" link type = "primary" @click ="promoteFamilyPrimary(row)" > 设为主链接 < / el -button >
< el-button size = "small" link type = "danger" @click ="removeFamilyMember(row)" > 移除出族 < / el -button >
< / div >
< / div >
< / div >
< div v-if = "expandedMemberKeys.has(row.key)" class="member-detail-panel" >
< div class = "member-detail-grid" >
< span class = "md-label" > SDS ID < / span > < span class = "md-val" > { { row . sdsGoodId || '-' } } < / span >
< span class = "md-label" > 链接价格 < / span > < span class = "md-val" > { { row . goodPrice ? ` ¥ ${ row . goodPrice } ` : '-' } } < / span >
< span class = "md-label" > SKU 数 < / span > < span class = "md-val" > { { row . variantCount } } < / span >
< span class = "md-label" > 物流备注 < / span > < span class = "md-val" > { { row . logisticsLabel || '-' } } < / span >
< span class = "md-label" > 工艺位置 < / span > < span class = "md-val" > { { row . craftLabel || '-' } } < / span >
< span class = "md-label" > 仓库 < / span > < span class = "md-val" > { { row . warehouseLabel || '-' } } < / span >
< span class = "md-label" > 原始名称 < / span > < span class = "md-val" :title = "row.goodName" > { { row . goodName } } < / span >
< / div >
< div class = "member-tags-edit" >
< span class = "md-label" > 标签 < / span >
< el-select
v-model = "memberTagEdits[row.key]"
multiple filterable size = "small"
placeholder = "选择标签"
style = "flex:1"
>
< el-option-group v-for = "g in groupedTagOptions" :key="g.id" :label="g.label" >
< el -option v-for = "t in g.tags" :key="t.id" :label="t.tagName" :value="t.id" / >
< / el-option-group >
< / el-select >
< el-button size = "small" type = "primary" : loading = "memberTagSaving === row.key" @click ="saveMemberTags(row)" > 保存标签 < / el -button >
< el-button v-if = "row.tagsManual" size="small" :loading="memberTagSaving === row.key" @click="resetMemberTags(row)" > 恢复自动 < / el -button >
< el-button
v-if = "row.role === 'primary'"
size = "small"
:icon = "Refresh"
:loading = "detailSyncing"
@click ="handleSyncOneDetail"
> 同步详情 < / el-button >
< / div >
< div class = "derived-tags-note" >
标签按链接名称自动解析 ( 印花数量 / 工艺 / 物流 ) ; 解析不对可直接修改 , 保存后自动同步不再覆盖该链接 , 「 恢复自动 」 回到按名称派生 。
< / div >
< / div >
< / template >
< div v-if = "!editFamilyLoaded && editFamilyId" class="edit-family-loading" > 族成员加载中 … < / div >
< div v-else-if = "!editFamilyId" class="edit-family-loading" > 暂未成族 : 配置合并时自动成族 < / div >
< / div >
@@ -2087,15 +2174,6 @@ onMounted(() => loadAll())
< el-form-item label = "分类" >
< el-cascader v-model = "editForm.cascaderCategory" :options="categoryCascader as any" :props="{ checkStrictly: true }" placeholder="请选择分类" @change="onEditCascaderChange" / >
< / el-form-item >
< el-form-item label = "标签" >
< div class = "derived-tags-row derived-tags-readonly" >
< template v-if = "editAutoTags.length" >
< el -tag v-for = "t in editAutoTags" :key="t.id" size="small" class="derived-tag" > {{ t.tagName }} < / el -tag >
< / template >
< span v-else class = "derived-tags-note" > 暂无自动标签 < / span >
< span class = "derived-tags-note" > 由链接名称自动解析 ( 印花数量 / 工艺 / 物流 ) , 不可手动编辑 < / span >
< / div >
< / el-form-item >
< el-form-item v-if = "editIsCustom" label="基础价格" >
< el -input v-model = "customContentForm.goodPrice" placeholder="例如 28.00" / >
< / el-form-item >
@@ -2181,17 +2259,29 @@ onMounted(() => loadAll())
< el-table-column label = "操作" width = "70" > < template # default = "{ $index }" > < el-button link type = "danger" @click ="customContentForm.variants.splice($index, 1)" > 删除 < / el -button > < / template > < / el-table-column >
< / el-table >
< / template >
< el-table v-else :data = "editVariants" border max -height = " 320 " >
< el-table-column prop = "sku" label = "SKU" min -width = " 170 " fixed / >
< el-table-column prop = "sizeName" label = "尺码" width = "90" / >
< el-table-column prop = "colorName" label = "颜色" width = "100" / >
< el-table-column prop = "price" label = "价格 " width = "100 " / >
< el-table-column label = "状态" width = "90" >
< template # default = "{ row }" >
< el-tag : type = "row.enabled ? 'success' : 'info' " size = "small" > { { row . enabled ? '可用' : '停用' } } < / el-tag >
< / template >
< / el-table-column >
< / el-table >
< template v-else >
< div class = "sku-dims-note" > 价格由 物流 × 工艺 × 印花数量 × 尺码 × 颜色 决定 ( 族内同组合取最低价 , 人工改价走族价格覆盖 ) < / div >
< el-table :data = "editVariants" border max -height = " 320 " >
< el-table-column prop = "sku" label = "SKU" min -width = " 170 " fixed / >
< el-table-column label = "物流 " width = "1 10" >
< template # default > { { editLinkDims . logistics || '-' } } < / template >
< / el-table-column >
< el-table-column label = "工艺 " width = "100" >
< template # default > { { editLinkDims . crafts . join ( ' / ' ) || '-' } } < / template >
< / el-table-column >
< el-table-column label = "印花数量" width = "100" >
< template # default > { { editLinkDims . printCount || '-' } } < / template >
< / el-table-column >
< el-table-column prop = "sizeName" label = "尺码" width = "90" / >
< el-table-column prop = "colorName" label = "颜色" width = "100" / >
< el-table-column prop = "price" label = "价格" width = "100" / >
< el-table-column label = "状态" width = "90" >
< template # default = "{ row }" >
< el-tag : type = "row.enabled ? 'success' : 'info'" size = "small" > { { row . enabled ? '可用' : '停用' } } < / el-tag >
< / template >
< / el-table-column >
< / el-table >
< / template >
< / el-tab-pane >
< / el-tabs >
< el-empty v-else-if = "!editDetailLoading" description="尚未同步商品详情" :image-size="60" / >
@@ -2514,16 +2604,6 @@ onMounted(() => loadAll())
. origin - ref { display : flex ; align - items : center ; gap : 8 px ; }
. edit - og - ref {
display : flex ; align - items : center ; gap : 12 px ;
padding : 12 px ; background : # f5f7fa ; border - radius : 8 px ;
}
. edit - og - img { width : 48 px ; height : 48 px ; border - radius : 6 px ; flex - shrink : 0 ; }
. edit - og - label { font - size : 11 px ; color : # 909399 ; text - transform : uppercase ; letter - spacing : 0.5 px ; }
. edit - og - name { font - weight : 600 ; font - size : 14 px ; margin - top : 2 px ; }
. edit - og - sub { color : # 909399 ; font - size : 12 px ; margin - top : 2 px ; }
. edit - og - meta { flex : 1 ; min - width : 0 ; }
. edit - og - status { display : flex ; align - items : center ; flex - wrap : wrap ; gap : 6 px 10 px ; margin - top : 6 px ; color : # 909399 ; font - size : 12 px ; }
. edit - merged - box { margin - top : 12 px ; }
. edit - merged - title {
display : flex ; align - items : center ; gap : 4 px ;
@@ -2562,6 +2642,30 @@ onMounted(() => loadAll())
font - size : 11 px ; line - height : 16 px ; padding : 1 px 7 px ; border - radius : 8 px ;
background : # ecf5ff ; color : var ( -- el - color - primary ) ; white - space : nowrap ;
}
. member - chip . is - manual { background : # f0f9eb ; color : var ( -- el - color - success ) ; }
. member - chip . is - preview { background : # f4f4f5 ; color : # 909399 ; border : 1 px dashed # dcdfe6 ; }
. member - manual - flag {
font - size : 11 px ; line - height : 16 px ; padding : 0 6 px ; border - radius : 4 px ;
background : # f0f9eb ; color : var ( -- el - color - success ) ; flex - shrink : 0 ;
}
. member - expand - toggle {
cursor : pointer ; flex - shrink : 0 ; color : # 909399 ;
transition : transform 0.18 s ;
}
. member - expand - toggle . is - expanded { transform : rotate ( 180 deg ) ; }
. member - detail - panel {
background : # fbfcfe ; border : 1 px solid # ebeef5 ; border - radius : 6 px ;
padding : 10 px 12 px ; margin : - 2 px 0 2 px 30 px ;
}
. member - detail - grid {
display : grid ; grid - template - columns : 64 px minmax ( 0 , 1 fr ) 64 px minmax ( 0 , 1 fr ) ;
gap : 4 px 10 px ; font - size : 12 px ; margin - bottom : 8 px ;
}
. md - label { color : # 909399 ; }
. md - val { color : # 606266 ; overflow : hidden ; text - overflow : ellipsis ; white - space : nowrap ; }
. member - tags - edit { display : flex ; align - items : center ; gap : 8 px ; }
. member - tags - edit . md - label { flex - shrink : 0 ; }
. sku - dims - note { font - size : 12 px ; color : var ( -- el - text - color - secondary ) ; margin - bottom : 8 px ; }
. edit - merged - tag {
padding : 0 5 px ; border - radius : 4 px ; font - size : 11 px ; line - height : 18 px ;
background : var ( -- el - color - primary ) ; color : # fff ; flex - shrink : 0 ;