feat(erp): 采购计划/采购审核/到货跟踪 + 供应商管理

- 采购计划:选合同自动带出明细、合同/供应商表格选择器、批量填充(可生成N行)、卷号/数量列、送审/重新送审流程
- 采购审核:通过/驳回 + 申请意见,每次审核留痕(erp_purchase_plan_audit_log),计划详情展示审核历史/驳回理由
- 到货跟踪:上传到货Excel按牌号+规格回填明细到货量与状态,列校验/kg→t纠正,满额自动归档
- 供应商管理页(复用既有 erp_supplier 后端)
- 综合搜索(计划号/供货商/合同号)、左右分栏工作台、全局表单按钮对齐修复
- 清理无用旧 erp 页面(看板/需求/订单/收货/退货/汇总)
- DDL 与菜单脚本:docs/purchase-plan-ddl.sql(按 path 解析父目录、可重复执行)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 16:53:21 +08:00
parent 47931b75ae
commit ce3998db74
38 changed files with 3559 additions and 2842 deletions

View File

@@ -1,545 +1,232 @@
<template>
<div class="erp-supplier-page">
<section class="surface-panel supplier-panel">
<header class="surface-header">
<span>供应商档案</span>
<el-button type="primary" size="small" @click="openSupplierDialog()">新增</el-button>
</header>
<div class="inline-filter">
<el-input v-model="supplierQuery.name" placeholder="供应商名称" size="small" clearable />
<el-select v-model="supplierQuery.creditRating" placeholder="信用等级" size="small" clearable>
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
<el-option label="D" value="D" />
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" size="small">
<el-form-item label="编码" prop="supplierCode">
<el-input v-model="queryParams.supplierCode" clearable placeholder="供应商编码" style="width:150px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" clearable placeholder="供应商名称" style="width:170px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" clearable placeholder="全部" style="width:140px">
<el-option v-for="t in typeOptions" :key="t.value" :label="t.label" :value="t.value" />
</el-select>
<div class="filter-actions">
<el-button size="small" type="primary" @click="loadSuppliers">查询</el-button>
<el-button size="small" @click="resetSupplierQuery">重置</el-button>
</div>
</div>
<div class="supplier-grid" v-loading="supplierLoading">
<div
v-for="item in supplierList"
:key="item.supplierId"
class="supplier-card"
>
<div class="card-head">
<div>
<p class="title">{{ item.name }}</p>
<p class="sub">编码{{ item.supplierCode || '-' }}</p>
</div>
<div class="tag-group">
<el-tag size="mini" type="info">{{ supplierTypeLabel(item.type) }}</el-tag>
<el-tag size="mini" type="plain">信用 {{ item.creditRating || '-' }}</el-tag>
</div>
</div>
<ul class="card-body">
<li><span>联系人</span><strong>{{ item.contactPerson || '-' }}</strong></li>
<li><span>电话</span><strong>{{ item.contactPhone || '-' }}</strong></li>
<li><span>地址</span><strong>{{ item.address || '-' }}</strong></li>
<li><span>备注</span><strong>{{ item.remark || '-' }}</strong></li>
</ul>
<div class="card-actions">
<el-button type="text" size="mini" @click="openSupplierDialog(item)">编辑</el-button>
<el-button type="text" size="mini" @click="openPriceDrawer(item)">价格</el-button>
<el-button type="text" size="mini" class="danger" @click="handleDeleteSupplier(item)">删除</el-button>
</div>
</div>
<el-empty v-if="!supplierList.length && !supplierLoading" description="暂无数据" />
</div>
</section>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-drawer
title="供应商价格表"
:visible.sync="priceDrawer.visible"
size="480px"
direction="rtl"
append-to-body
custom-class="price-drawer"
@close="closePriceDrawer"
>
<div class="price-drawer-body">
<div class="drawer-header" v-if="priceDrawer.supplier">
<div class="drawer-title-block">
<p class="drawer-title">{{ priceDrawer.supplier.name }}</p>
<p class="drawer-sub">编码{{ priceDrawer.supplier.supplierCode || '-' }}</p>
</div>
<el-button type="primary" size="mini" @click="openPriceDialog()">新增价格</el-button>
</div>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['erp:supplier:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete()" v-hasPermi="['erp:supplier:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
</el-row>
<div class="drawer-section">
<div class="drawer-section-title">价格列表</div>
<el-collapse v-model="activePricePanels" accordion>
<el-collapse-item
v-for="item in priceList"
:name="item.priceId"
:title="`${item.materialTypeCode || '未指定'} · ¥${item.price || 0}`"
:key="item.priceId"
>
<ul class="price-info">
<li><span>规格</span>{{ item.specification || '-' }}</li>
<li><span>含税价</span>{{ item.price || '-' }}</li>
<li><span>有效期</span>{{ formatRange(item.validFrom, item.validTo) }}</li>
<li><span>备注</span>{{ item.remark || '-' }}</li>
</ul>
<div class="price-actions">
<el-button type="text" size="mini" @click="openPriceDialog(item)">编辑</el-button>
<el-button type="text" size="mini" class="danger" @click="handleDeletePrice(item)">删除</el-button>
</div>
</el-collapse-item>
</el-collapse>
<el-empty v-if="!priceList.length && !priceLoading" description="暂无价格记录" />
<el-skeleton v-if="priceLoading" animated rows="4" />
</div>
</div>
</el-drawer>
<el-table v-loading="loading" :data="list" border size="small" @selection-change="onSelectionChange">
<el-table-column type="selection" width="46" align="center" />
<el-table-column label="供应商编码" prop="supplierCode" width="140" show-overflow-tooltip />
<el-table-column label="供应商名称" prop="name" min-width="180" show-overflow-tooltip />
<el-table-column label="类型" width="120" align="center">
<template slot-scope="s">{{ typeText(s.row.type) }}</template>
</el-table-column>
<el-table-column label="信用等级" width="90" align="center">
<template slot-scope="s"><span class="sp-credit" :class="'c' + (s.row.creditRating || '')">{{ s.row.creditRating || '—' }}</span></template>
</el-table-column>
<el-table-column label="联系人" prop="contactPerson" width="100" />
<el-table-column label="联系电话" prop="contactPhone" width="130" />
<el-table-column label="地址" prop="address" min-width="180" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" min-width="140" show-overflow-tooltip />
<el-table-column label="操作" width="130" align="center" fixed="right">
<template slot-scope="s">
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleUpdate(s.row)" v-hasPermi="['erp:supplier:edit']">编辑</el-button>
<el-button type="text" size="mini" icon="el-icon-delete" @click="handleDelete(s.row)" v-hasPermi="['erp:supplier:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 供应商弹窗 -->
<el-dialog :title="supplierDialog.title" :visible.sync="supplierDialog.visible" width="520px">
<el-form :model="supplierDialog.form" :rules="supplierRules" ref="supplierForm" label-width="90px" size="small">
<el-form-item label="编码" prop="supplierCode">
<el-input v-model="supplierDialog.form.supplierCode" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="supplierDialog.form.name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="supplierDialog.form.type" placeholder="请选择类型">
<el-option v-for="opt in supplierTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
<el-form-item label="信用等级">
<el-select v-model="supplierDialog.form.creditRating" clearable>
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
<el-option label="D" value="D" />
</el-select>
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="supplierDialog.form.contactPerson" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="supplierDialog.form.contactPhone" />
</el-form-item>
<el-form-item label="地址">
<el-input v-model="supplierDialog.form.address" />
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="supplierDialog.form.remark" />
</el-form-item>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<el-dialog :title="title" :visible.sync="open" width="640px" append-to-body>
<el-form :model="form" :rules="rules" ref="form" label-width="90px" size="small">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="供应商编码" prop="supplierCode">
<el-input v-model="form.supplierCode" placeholder="请输入编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商名称" prop="name">
<el-input v-model="form.name" placeholder="请输入名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="type">
<el-select v-model="form.type" clearable placeholder="请选择" style="width:100%">
<el-option v-for="t in typeOptions" :key="t.value" :label="t.label" :value="t.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="信用等级" prop="creditRating">
<el-select v-model="form.creditRating" clearable placeholder="请选择" style="width:100%">
<el-option v-for="c in creditOptions" :key="c" :label="c" :value="c" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="contactPerson">
<el-input v-model="form.contactPerson" placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="form.contactPhone" placeholder="请输入电话" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="地址" prop="address">
<el-input v-model="form.address" placeholder="请输入地址" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="form.remark" :rows="2" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer">
<el-button @click="supplierDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitSupplier"> </el-button>
</div>
</el-dialog>
<!-- 价格弹窗 -->
<el-dialog :title="priceDialog.title" :visible.sync="priceDialog.visible" width="520px">
<el-form :model="priceDialog.form" :rules="priceRules" ref="priceForm" label-width="100px" size="small">
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="priceDialog.form.supplierId" placeholder="选择供应商">
<el-option v-for="sp in supplierOptions" :key="sp.supplierId" :label="sp.name" :value="sp.supplierId" />
</el-select>
</el-form-item>
<el-form-item label="原料" prop="rawMaterialId">
<RawMaterialSelect v-model="priceDialog.form.rawMaterialId" @change="handleMaterialChange" />
</el-form-item>
<el-form-item label="物料编码">
<el-input v-model="priceDialog.form.materialTypeCode" placeholder="选择原料后自动带出" readonly />
</el-form-item>
<el-form-item label="规格">
<el-input v-model="priceDialog.form.specification" placeholder="选择原料后可调整" />
</el-form-item>
<el-form-item label="含税价格" prop="price">
<el-input-number v-model="priceDialog.form.price" :min="0" :precision="2" />
</el-form-item>
<el-form-item label="有效期">
<el-date-picker
v-model="priceValidRange"
type="daterange"
value-format="yyyy-MM-dd"
start-placeholder="开始"
end-placeholder="结束"
/>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="priceDialog.form.remark" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="priceDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitPrice"> </el-button>
<el-button @click="open = false">取消</el-button>
<el-button type="primary" :loading="buttonLoading" @click="submitForm">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listSupplier,
addSupplier,
updateSupplier,
delSupplier,
listSupplierPrice,
addSupplierPrice,
updateSupplierPrice,
delSupplierPrice
} from '@/api/erp/purchase'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import { listSupplier, addSupplier, updateSupplier, delSupplier } from '@/api/erp/purchase'
export default {
name: 'ErpSupplierManage',
components: { RawMaterialSelect },
name: 'ErpSupplier',
data() {
return {
supplierTypeOptions: [
{ label: '原料供应商', value: 'RAW' },
{ label: '其他供应商', value: 'OTHER' }
loading: true,
buttonLoading: false,
showSearch: true,
total: 0,
list: [],
ids: [],
multiple: true,
title: '',
open: false,
form: {},
queryParams: { pageNum: 1, pageSize: 20, supplierCode: undefined, name: undefined, type: undefined },
typeOptions: [
{ value: 'RAW', label: '原料供应商' },
{ value: 'AUX', label: '辅料供应商' },
{ value: 'OTHER', label: '其他' }
],
supplierQuery: { pageNum: 1, pageSize: 50, name: null, creditRating: null },
supplierList: [],
supplierLoading: false,
supplierDialog: { visible: false, title: '', form: {} },
supplierRules: {
supplierCode: [{ required: true, message: '请输入编码', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
},
priceQuery: { pageNum: 1, pageSize: 50, supplierId: null },
priceList: [],
priceLoading: false,
priceDialog: { visible: false, title: '', form: {} },
priceRules: {
supplierId: [{ required: true, message: '请选择供应商', trigger: 'change' }],
rawMaterialId: [{ required: true, message: '请选择原料', trigger: 'change' }],
price: [{ required: true, message: '请输入价格', trigger: 'change' }]
},
priceValidRange: [],
supplierOptions: [],
priceDrawer: { visible: false, supplier: null },
activePricePanels: []
creditOptions: ['A', 'B', 'C', 'D'],
rules: {
supplierCode: [{ required: true, message: '请输入供应商编码', trigger: 'blur' }],
name: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }]
}
}
},
created() {
this.loadSuppliers()
this.loadPrices()
this.getList()
},
methods: {
loadSuppliers() {
this.supplierLoading = true
listSupplier(this.supplierQuery)
.then(res => {
this.supplierList = res.rows || []
this.supplierOptions = this.supplierList
})
.finally(() => {
this.supplierLoading = false
})
getList() {
this.loading = true
listSupplier(this.queryParams).then(res => {
this.list = res.rows || []
this.total = res.total || 0
this.loading = false
})
},
resetSupplierQuery() {
this.supplierQuery = { pageNum: 1, pageSize: 50, name: null, creditRating: null }
this.loadSuppliers()
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
openSupplierDialog(row) {
if (row) {
this.supplierDialog.form = { ...row }
this.supplierDialog.title = '编辑供应商'
} else {
this.supplierDialog.form = { supplierCode: '', name: '', creditRating: 'A', type: 'RAW' }
this.supplierDialog.title = '新增供应商'
}
this.supplierDialog.visible = true
this.$nextTick(() => this.$refs.supplierForm && this.$refs.supplierForm.clearValidate())
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
submitSupplier() {
this.$refs.supplierForm.validate(valid => {
onSelectionChange(sel) {
this.ids = sel.map(i => i.supplierId)
this.multiple = !sel.length
},
reset() {
this.form = { supplierId: null, supplierCode: '', name: '', type: undefined, creditRating: undefined, contactPerson: '', contactPhone: '', address: '', remark: '' }
this.resetForm('form')
},
handleAdd() {
this.reset()
this.title = '新增供应商'
this.open = true
},
handleUpdate(row) {
this.reset()
this.form = { ...row }
this.title = '编辑供应商'
this.open = true
},
submitForm() {
this.$refs['form'].validate(valid => {
if (!valid) return
const api = this.supplierDialog.form.supplierId ? updateSupplier : addSupplier
api(this.supplierDialog.form).then(() => {
this.$message.success('保存成功')
this.supplierDialog.visible = false
this.loadSuppliers()
})
this.buttonLoading = true
const api = this.form.supplierId ? updateSupplier : addSupplier
api(this.form).then(() => {
this.$modal.msgSuccess('保存成功')
this.open = false
this.getList()
}).finally(() => { this.buttonLoading = false })
})
},
handleDeleteSupplier(row) {
this.$confirm('确认删除该供应商吗?', '提示').then(() => {
return delSupplier(row.supplierId)
handleDelete(row) {
const ids = row && row.supplierId ? row.supplierId : this.ids
const tip = row && row.name ? '「' + row.name + '」' : '选中的 ' + this.ids.length + ' 个供应商'
this.$modal.confirm('确认删除' + tip + '').then(() => {
return delSupplier(ids)
}).then(() => {
this.$message.success('删除成功')
this.loadSuppliers()
})
this.$modal.msgSuccess('删除成功')
this.getList()
}).catch(() => {})
},
supplierTypeLabel(val) {
const target = this.supplierTypeOptions.find(opt => opt.value === val)
return target ? target.label : '其他供应商'
handleExport() {
this.download('erp/supplier/export', { ...this.queryParams }, `supplier_${new Date().getTime()}.xlsx`)
},
// price
openPriceDrawer(item) {
this.priceDrawer = { visible: true, supplier: item }
this.priceQuery = { ...this.priceQuery, supplierId: item.supplierId, pageNum: 1 }
this.loadPrices()
},
closePriceDrawer() {
this.priceDrawer.visible = false
this.priceDrawer.supplier = null
this.priceList = []
},
loadPrices() {
if (!this.priceQuery.supplierId) {
this.priceList = []
return
}
this.priceLoading = true
listSupplierPrice(this.priceQuery)
.then(res => {
this.priceList = res.rows || []
this.activePricePanels = (this.priceList[0] && [this.priceList[0].priceId]) || []
})
.finally(() => {
this.priceLoading = false
})
},
matchSupplier(id) {
const target = this.supplierOptions.find(sp => sp.supplierId === id)
return target ? target.name : id
},
openPriceDialog(row) {
if (!this.supplierOptions.length) {
this.$message.warning('请先维护供应商')
return
}
if (row) {
this.priceDialog.form = { ...row }
this.priceValidRange = [row.validFrom, row.validTo]
this.priceDialog.title = '编辑价格'
} else {
const currentSupplierId = this.priceDrawer.supplier?.supplierId || null
this.priceDialog.form = { supplierId: currentSupplierId, rawMaterialId: '', materialTypeCode: '', specification: '', price: 0 }
this.priceValidRange = []
this.priceDialog.title = '新增价格'
}
this.priceDialog.visible = true
this.$nextTick(() => this.$refs.priceForm && this.$refs.priceForm.clearValidate())
},
submitPrice() {
this.$refs.priceForm.validate(valid => {
if (!valid) return
if (this.priceValidRange && this.priceValidRange.length === 2) {
this.priceDialog.form.validFrom = this.priceValidRange[0]
this.priceDialog.form.validTo = this.priceValidRange[1]
}
if (!this.priceDialog.form.materialTypeCode) {
this.$message.warning('请先选择原料')
return
}
const api = this.priceDialog.form.priceId ? updateSupplierPrice : addSupplierPrice
api(this.priceDialog.form).then(() => {
this.$message.success('保存成功')
this.priceDialog.visible = false
this.loadPrices()
})
})
},
handleDeletePrice(row) {
this.$confirm('确认删除该价格吗?', '提示').then(() => {
return delSupplierPrice(row.priceId)
}).then(() => {
this.$message.success('删除成功')
this.loadPrices()
})
},
handleMaterialChange(val, rows) {
const target = Array.isArray(rows) ? rows[0] : null
this.priceDialog.form.rawMaterialId = val
if (target) {
this.priceDialog.form.materialTypeCode = target.rawMaterialCode
this.priceDialog.form.specification = target.specification
}
},
formatRange(start, end) {
if (!start && !end) return '-'
return `${start || '-'} ~ ${end || '-'}`
typeText(t) {
const o = this.typeOptions.find(x => x.value === t)
return o ? o.label : (t || '—')
}
}
}
</script>
<style lang="scss" scoped>
.erp-supplier-page {
padding: 16px;
min-height: 100%;
}
.surface-panel {
background: #fff;
border: 1px solid #d6dce1;
border-radius: 4px;
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.surface-header {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 600;
color: #1b2a38;
}
.inline-filter {
display: flex;
flex-wrap: wrap;
gap: 8px;
.filter-actions {
display: flex;
gap: 8px;
}
> *:not(.filter-actions) {
flex: 1 1 150px;
}
}
.supplier-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 12px;
}
.supplier-card {
border: 1px solid #d6dce1;
padding: 12px;
border-radius: 4px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.card-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
.title {
font-weight: 600;
margin: 0;
color: #15212d;
}
.sub {
margin: 2px 0 0;
color: #79828c;
font-size: 12px;
}
.tag-group {
display: flex;
gap: 4px;
flex-wrap: wrap;
}
}
.card-body {
list-style: none;
padding: 0;
margin: 0;
li {
display: flex;
justify-content: space-between;
font-size: 13px;
color: #4a5663;
& + li {
margin-top: 4px;
}
span {
color: #8a96a3;
}
strong {
color: #151e26;
}
}
}
.card-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
.danger {
color: #c0392b;
}
}
.price-drawer {
.price-drawer-body {
padding: 16px 20px 12px;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.drawer-header {
margin-bottom: 12px;
padding: 8px 10px;
border-radius: 4px;
background-color: #f5f7fa;
border: 1px solid #e4e7ed;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.drawer-title-block {
display: flex;
flex-direction: column;
}
.drawer-title {
margin: 0;
font-weight: 600;
color: #1f2a37;
}
.drawer-sub {
margin-top: 4px;
color: #7a8694;
font-size: 12px;
}
.drawer-section {
margin-top: 14px;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.drawer-section-title {
font-size: 13px;
color: #5c6c7b;
margin-bottom: 8px;
}
::v-deep .el-collapse-item__header {
padding-left: 10px;
}
::v-deep .el-collapse-item__content {
padding: 10px 10px 12px;
}
.price-info {
list-style: none;
padding: 0;
margin: 0 0 4px;
li {
display: flex;
justify-content: space-between;
font-size: 13px;
color: #4a5663;
& + li {
margin-top: 4px;
}
span {
color: #8a96a3;
}
}
}
.price-actions {
margin-top: 8px;
display: flex;
justify-content: flex-end;
gap: 8px;
.danger {
color: #c0392b;
}
}
$accent: #5b8db8;
.sp-credit {
display: inline-block; min-width: 18px; font-size: 12px; font-weight: 600; color: #909399;
&.cA { color: #3a8a4d; }
&.cB { color: $accent; }
&.cC { color: #d6a256; }
&.cD { color: #c45656; }
}
</style>