Files
flowable_management/base-vue/src/views/modules/contract/contract-add-or-update.vue
2026-02-04 16:24:30 +08:00

808 lines
31 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
append-to-body
title="单据详情"
:visible.sync="dialogVisible"
fullscreen
@close="close"
@open="open"
>
<div class="nl-theme page-container">
<div class="page-header">
<div class="logo">NOBLELIFT</div>
<div class="muted">诺力物流机器人</div>
<div class="subtitle">产品购销合同</div>
</div>
<el-row :gutter="16" style="margin-top:8px;">
<!-- 左侧主要内容 -->
<el-col :span="18" class="vertical-line">
<!-- 需方供方信息 -->
<el-row :gutter="16">
<el-col :span="12">
<el-card shadow="never">
<el-form :model="client" label-width="100px" size="small">
<el-form-item label="合同编号"><el-input disabled placeholder="系统生成" v-model="dataForm.contractCode" /></el-form-item>
<el-form-item label="需方">
<el-select
v-model="dataForm.clientId"
@change="changeClient($event, dictData[1])"
clearable>
<el-option v-for="item in dictData[1]" :key="item.key" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="供方"><el-input disabled v-model="dataForm.finc" /></el-form-item>
</el-form>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<el-form :model="dataForm" label-width="100px" size="small">
<el-form-item label="生效日期"><el-date-picker v-model="dataForm.effectiveTime" type="date" value-format="yyyy-MM-dd" /></el-form-item>
<el-form-item label="合同类型"><el-input v-model="dataForm.contractType" /></el-form-item>
<el-form-item label="项目类型"><el-input v-model="dataForm.projectType" /></el-form-item>
</el-form>
</el-card>
</el-col>
</el-row>
<!-- 物料明细表格 -->
<div class="clause-item" style="display: grid; grid-template-columns: 1fr auto; align-items: center;">
<strong > 产品明细</strong>
<el-button type="primary" size="small" @click="addMaterial">新增物料</el-button>
</div>
<el-card shadow="never">
<el-table :data="materData" border style="width:100%" size="small" show-summary :summary-method="summaryMethod" header-cell-class-name="nl-table-header" cell-class-name="nl-table-cell">
<el-table-column label="序号" type="index" width="60" />
<el-table-column label="物料名称" prop="materialName" width="150" />
<el-table-column label="物料型号" prop="materialName" width="150" />
<el-table-column label="数量" prop="qty" width="100" >
<template slot-scope="scope">
<el-input
v-model="scope.row.qty"
size="mini"
></el-input>
</template>
</el-table-column>
<el-table-column label="单位" prop="unitName" width="60" />
<el-table-column label="未税收费价" prop="salePrice" width="120" >
<template slot-scope="scope">
<el-input
v-model="scope.row.salePrice"
size="mini"
></el-input>
</template>
</el-table-column>
<el-table-column label="税率%" prop="tax" width="120" >
<template slot-scope="scope">
<el-input
v-model="scope.row.tax"
size="mini"
></el-input>
</template>
</el-table-column>
<el-table-column label="总价" prop="amount" width="120" :formatter='tamount'/>
<el-table-column label="备注" prop="remark" width="120" />
<el-table-column
fixed="right"
header-align="center"
align="center"
width="150"
label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="removeItem(scope.row,scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<div style="margin:24px 0; text-align:right;"/>
<!-- 条款 -->
<div class="clauses-section">
<div class="clause-item">
<strong> 质量要求技术标准供方对质量负责的条件和期限:</strong>
<span v-text="dataForm.qc" @input="this.dataForm.qc = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;">
</span>
</div>
<div class="clause-item">
<strong> 售后服务:</strong>
<span v-text="dataForm.after_sales" @input="this.dataForm.after_sales = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;">
</span>
</div>
<div class="clause-item">
<strong> 交货时间地点:</strong>
货期:
<span v-text="dataForm.delivery" @input="this.dataForm.delivery = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
交货地:
<span v-text="dataForm.place" @input="this.dataForm.place = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 运输方式及到达站和费用负担:</strong>
<span v-text="dataForm.transport" @input="this.dataForm.transport = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 包装标准:</strong>
<span v-text="dataForm.packaging" @input="this.dataForm.packaging = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 结算方式:</strong>
<span v-text="dataForm.pay" @input="this.dataForm.pay = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
付款方式:
<span v-text="dataForm.payment" @input="this.dataForm.payment = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 违约责任:</strong>
<span v-text="dataForm.breach" @input="this.dataForm.breach = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 解决合同纠纷的方式:</strong>
<span v-text="dataForm.solve_dispute" @input="this.dataForm.solve_dispute = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
<div class="clause-item">
<strong> 其它约定事项:</strong>
<span v-text="dataForm.supplement" @input="this.dataForm.supplement = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
</div>
</div>
<!-- 底部签字盖章 -->
<div style="margin:24px 0; text-align:right;"/>
<el-row :gutter="16">
<el-col :span="12">
<el-card shadow="never">
<el-form :model="client" label-width="100px" size="small">
<strong>需方</strong>
<el-form-item label="单位名称:">
<span size="mini">{{client.name}}</span>盖章
</el-form-item>
<el-form-item label="地址:">
<span size="mini">{{client.address}}</span>
</el-form-item>
<el-form-item label="委托代理人:">
<span size="mini">{{client.juridical_person}}</span>
</el-form-item>
<el-form-item label="电话:">
<span size="mini">{{client.tel}}</span>
</el-form-item>
<el-form-item label="传真:">
<span size="mini">{{client.fax}}</span>
</el-form-item>
<el-form-item label="开户银行:">
<span size="mini">{{client.bank}}</span>
</el-form-item>
<el-form-item label="银行卡号:">
<span size="mini">{{client.card}}</span>
</el-form-item>
</el-form>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<el-form :model="client" label-width="100px" size="small">
<strong>供方</strong>
<el-form-item label="单位名称:">
<span size="mini">{{supply.name}}</span>盖章
</el-form-item>
<el-form-item label="地址:">
<span size="mini">{{supply.address}}</span>
</el-form-item>
<el-form-item label="委托代理人:">
<span size="mini">{{supply.juridical_person}}</span>
</el-form-item>
<el-form-item label="电话:">
<span size="mini">{{supply.tel}}</span>
</el-form-item>
<el-form-item label="传真:">
<span size="mini">{{supply.fax}}</span>
</el-form-item>
<el-form-item label="开户银行:">
<span size="mini">{{supply.bank}}</span>
</el-form-item>
<el-form-item label="银行卡号:">
<span size="mini">{{supply.card}}</span>
</el-form-item>
</el-form>
</el-card>
</el-col>
</el-row>
<!-- 备注与附件 -->
<el-card shadow="never" style="margin-top:12px;">
<template #header>
<span class="panel-title">其他注意事项</span>
</template>
<el-input v-model="dataForm.remarks" type="textarea" :rows="6" placeholder="xxxxxxx" />
<template #header>
<span class="panel-title">附件</span>
</template>
<el-upload
class="upload-demo"
ref="upload"
action="https://jsonplaceholder.typicode.com/posts/"
:on-change="handleChange"
:on-remove="handleRemove"
:on-preview="handleLoad"
:file-list="fileList"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能上传图片,word,excel,pdf文件且不超过50MB</div>
</el-upload>
</el-card>
<div class="footer-actions">
<el-button v-if="dataForm.contractId == ''" type="info" plain @click="tempSave">暂存</el-button>
<el-button type="primary" @click="submitPrice">保存</el-button>
</div>
</el-col>
<!-- 右侧侧栏 -->
<el-col :span="6">
<el-card shadow="never">
<template #header>
<span class="panel-title">我的修改记录</span>
</template>
<el-table :data="records" border size="small" @row-click="reLoad">
<el-table-column label="单据名称" prop="orderName" width="80"/>
<el-table-column label="时间" prop="createTime" />
<el-table-column label="附件" prop="annex" width="40">
<template slot-scope="scope">
<i v-if="scope.row.annex" class="el-icon-document"></i>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</div>
<el-dialog
title="选择物料"
:visible.sync="innerVisible"
append-to-body>
<el-form size="mini" :inline="true" :model="innerDataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="innerDataForm.key" placeholder="编码或名称" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
size="mini"
max-height="400"
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;">
<el-table-column
type="selection"
header-align="center"
align="center"
width="50">
</el-table-column>
<el-table-column
type="index"
header-align="center"
align="center"
label="序号">
</el-table-column>
<el-table-column
prop="materialCode"
header-align="center"
align="center"
label="物料编码">
</el-table-column>
<el-table-column
prop="materialName"
header-align="center"
align="center"
label="物料名称">
</el-table-column>
<el-table-column
prop="materialSpec"
header-align="center"
align="center"
label="规格">
</el-table-column>
<el-table-column
prop="costPrice"
header-align="center"
align="center"
label="成本价">
</el-table-column>
<el-table-column
prop="salePrice"
header-align="center"
align="center"
label="销售价">
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="innerVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="innerSubmit">确定</el-button>
</span>
</el-dialog>
</el-dialog>
</template>
<script>
import { apiUtils } from '@/utils/dict'
export default {
name: 'ViewDialog',
data () {
return {
cols: [],
dataForm: {
contractId: '',
contractType: '',
projectType: '',
parentContract: null,
contractCode: '',
clientId: '',
isMaster: true,
qc: '技术标准符合行业标准。',
after_sales: '保修期6个月人为造成的损坏不在质保范围内',
finc: '上海诺力智能科技有限公司',
fattn: '',
fmobile: '',
ftel: '021-39888170',
fadd: '上海市青浦区高光路215弄99号4号楼302室',
effectiveTime: null,
delivery: '与客户协商一致',
place: '____',
transport: '由供方提供',
packaging: '按国内标准包装',
pay: '款到发货',
payment: '电汇',
breach: '按《中华人民共和国民法典》执行',
solve_dispute: '买卖双方首先友好协商解决,协商不成,任何一方均可向有管辖权法院起诉',
supplement: '合同扫描件有效,签字盖章之日起生效',
remarks: '',
annex: '',
materialJson: []
},
client: {name: '',
address: '',
juridical_person: '',
tel: '',
fax: '',
bank: '',
card: ''
},
supply: {name: '上海诺力智能科技有限公司',
address: '上海市青浦区高光路215弄99号4号楼302室',
juridical_person: '委托代理人',
tel: '021-39888170',
fax: '',
bank: '招商银行上海虹桥支行',
card: '121917025010901'
},
innerDataForm: {
key: ''
},
dataList: [],
records: [],
dictConfigs: [{url: '/client/client/list', type: 'list', value: 'clientId', label: 'clientName'},
{url: '/sys/user/list', type: 'list', value: 'userId', label: 'username'}],
fileList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
materData: [],
dialogVisible: false,
innerVisible: false
}
},
props: {
dialogShow: {
type: Boolean,
default: false
},
dictData: Array,
rowmst: {
type: Object
}
},
mixins: [apiUtils],
components: {
},
watch: {
dialogShow: {
handler (newValue) {
this.dialogVisible = newValue
}
},
rowmst: {
handler (newValue) {
this.form = newValue
}
}
},
methods: {
handleRemove (a, fileList) {
if (a.storageId !== undefined) {
let arr = this.dataForm.annex.split(',')
const filteredArr = arr.filter(item => item != a.storageId)
this.dataForm.annex = filteredArr.join(',')
}
console.log(this.dataForm.annex)
this.fileList = fileList
},
handleLoad (a, fileList) {
this.loadFileUrl(a)
},
handleChange (a, fileList) {
this.fileList = fileList
},
init (id) {
this.dataForm.contractId = id
this.dialogVisible = true
this.$nextTick(() => {
this.materData = []
if (this.dataForm.contractId) {
this.$http({
url: this.$http.adornUrl(`/flow/contract/info/${this.dataForm.contractId}`),
method: 'get',
params: this.$http.adornParams()
}).then(({data}) => {
if (data && data.code === 200) {
this.dataForm.contractId = data.contract.contractId
this.dataForm.contractType = data.contract.contractType
this.dataForm.projectType = data.contract.projectType
this.dataForm.isMaster = data.contract.isMaster
this.dataForm.parentContract = data.contract.parentContract
this.dataForm.contractCode = data.contract.contractCode
this.dataForm.totalPrice = data.contract.totalPrice
this.dataForm.clientId = data.contract.clientId
this.dataForm.materialJson = data.contract.materialJson
this.dataForm.isAcceptance = data.contract.isAcceptance
this.dataForm.acceptanceTime = data.contract.acceptanceTime
this.dataForm.priceId = data.contract.priceId
this.dataForm.effectiveTime = data.contract.effectiveTime
this.dataForm.createTime = data.contract.createTime
this.dataForm.CreateName = data.contract.CreateName
this.dataForm.updateTime = data.contract.updateTime
this.dataForm.qc = data.contract.qc
this.dataForm.afterSales = data.contract.afterSales
this.dataForm.delivery = data.contract.delivery
this.dataForm.place = data.contract.place
this.dataForm.transport = data.contract.transport
this.dataForm.pay = data.contract.pay
this.dataForm.payment = data.contract.payment
this.dataForm.breach = data.contract.breach
this.dataForm.solveDispute = data.contract.solveDispute
this.dataForm.supplement = data.contract.supplement
this.dataForm.packaging = data.contract.packaging
this.dataForm.annex = data.contract.annex
this.dataForm.status = data.contract.status
this.dataForm.remarks = data.contract.remarks
this.materData = JSON.parse(data.contract.materialJson)
this.client = data.contract.client
this.getFileUrl(data.contract.annex)
this.$http({
url: this.$http.adornUrl(`/flow/orderRecord/list`),
method: 'get',
params: this.$http.adornParams({'orderCode': data.contract.contractCode})
}).then(({data}) => {
if (data && data.code === 200) {
this.records = data.orderRecord
}
})
}
})
}
})
},
getFileUrl (annex) {
this.$http({
url: this.$http.adornUrl('/api/localStorage'),
method: 'get',
params: this.$http.adornParams({'annex':annex})
}).then(({data}) => {
this.fileList = [...data]
})
},
reLoad (row) {
let price = JSON.parse(row.data)
this.dataForm.priceType = String(price.priceType)
this.dataForm.contractCode = price.contractCode
this.dataForm.quoter = price.quoter
this.dataForm.finc = price.finc
this.dataForm.fattn = price.fattn
this.dataForm.fmobile = price.fmobile
this.dataForm.ftel = price.ftel
this.dataForm.fadd = price.fadd
this.dataForm.tinc = price.tinc
this.dataForm.tattn = price.tattn
this.dataForm.tmobile = price.tmobile
this.dataForm.ttel = price.ttel
this.dataForm.tadd = price.tadd
this.dataForm.effective = price.effective
this.dataForm.delivery = price.delivery
this.dataForm.place = price.place
this.dataForm.valid = price.valid
this.dataForm.pay = price.pay
this.dataForm.materialJson = price.materialJson
this.dataForm.totalPrice = price.totalPrice
this.dataForm.remarks = price.remarks
this.dataForm.annex = price.annex
this.materData = JSON.parse(price.materialJson)
this.getFileUrl(price.annex)
},
loadFileUrl (file) {
// eslint-disable-next-line eqeqeq
if (file.storageId == undefined) {
const url = URL.createObjectURL(file.raw)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
const fileName = file.name
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
} else {
this.$http({
url: this.$http.adornUrl('/api/localStorage/download'),
responseType: 'blob',
params: this.$http.adornParams({'storageId': file.storageId})
}).then(({data}) => {
const url = window.URL.createObjectURL(new Blob([data]))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
const fileName = file.name
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
}
},
open () {
this.dialogVisible = true
},
close () {
this.dialogVisible = false
this.innerDataForm = {
key: ''
}
this.dataForm = {}
this.dataList = []
this.fileList = []
this.materData = []
},
handleMobileInput (value) {
console.log(value)
let mobile = value.replace(/\D/g, '').slice(0, 11)
this.dataForm.fmobile = mobile
},
changeClient (event, dictData) {
if (dictData.length > 0) {
const foundItem = dictData.find(item => item.value == event);
if (foundItem !== undefined) {
// eslint-disable-next-line no-unused-expressions
this.client = foundItem
}
}
},
changeUser (event, dictData, dataForm, field1) {
if (dictData.length > 0) {
const foundItem = dictData.find(item => item.value == event);
if (foundItem !== undefined) {
this.$set(dataForm, field1, foundItem.moblie)
}
}
},
addMaterial () {
this.innerVisible = true
this.getDataList()
},
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
// 当前页
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
// 多选
selectionChangeHandle (val) {
this.dataListSelections = val
},
innerSubmit () {
this.innerVisible = false
const existingIds = new Set(this.materData.map(item => item.materialCode))
// 筛选出 dataListSelections 中不重复的数据
// eslint-disable-next-line no-unused-vars
const newItems = this.dataListSelections.filter(item => !existingIds.has(item.materialCode))
this.materData = [...this.materData, ...newItems]
// eslint-disable-next-line no-sequences
this.materData.forEach(a => {
this.$set(a, 'tax', 13)
this.$set(a, 'rate', 100)
this.$set(a, 'qty', 1)
this.$set(a, 'amount', (a.qty * a.salePrice * (1 + a.tax / 100)).toFixed(2))
this.$set(a, 'discounted', (a.amount * a.rate / 100).toFixed(2))
// 返回格式化后的字符串,例如保留两位小数
})
},
// 获取数据列表
getDataList () {
this.dataListLoading = true
this.$http({
url: this.$http.adornUrl('/material/material/list'),
method: 'get',
params: this.$http.adornParams({
'page': this.pageIndex,
'limit': this.pageSize,
'key': this.innerDataForm.key
})
}).then(({data}) => {
if (data && data.code === 200) {
this.dataList = data.page.list
this.totalPage = data.page.totalCount
} else {
this.dataList = []
this.totalPage = 0
}
this.dataListLoading = false
})
},
// 上传附件
beforeUpload (file) {
if (file.size > 1024) {
// ElMessage.error(`${file.name} 超过 5MB已跳过`)
return false
}
return true
},
tempSave () {
this.$refs.upload.submit();
},
submitPrice () {
if (this.fileList.length > 0) {
this.fileList.forEach(a => {
if (a.size > 10 * 1024 * 1024) {
return false
}
})
}
this.dataForm.materialJson = this.materData
var formdata = new FormData()
this.fileList.forEach(a => {
formdata.append('file', a.raw)
})
formdata.append('form', JSON.stringify(this.dataForm))
let url = `/flow/contract/save`
if (this.dataForm.contractId != undefined){
url = `/flow/contract/update`
}
this.$http({
url: this.$http.adornUrl(url),
method: 'post',
data: formdata
}).then(({data}) => {
if (data && data.code === 200) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.close()
} else {
this.$message.error(data.msg)
}
})
},
saveMaterial () {
},
removeItem (row, index) {
this.materData.splice(index, 1)
},
tamount (row, index) {
const amount = (row.qty * row.salePrice * (1 + row.tax / 100)).toFixed(2)
// 返回格式化后的字符串,例如保留两位小数
row.amount = amount
this.$set(row, 'amount', amount)
return amount
},
tdiscounted (row, index) {
const amount = (row.amount * row.rate / 100).toFixed(2)
// 返回格式化后的字符串,例如保留两位小数
row.discounted = amount
this.$set(row, 'discounted', amount)
return amount
},
summaryMethod (params) {
const { columns, data } = params
const sums = []
let totalAmount = 0
let totalDiscounted = 0
data.forEach(row => { totalAmount += Number(row.amount) || 0; totalDiscounted += Number(row.discounted) || 0 })
columns.forEach((col, idx) => {
if (idx === 6) sums[idx] = '合计'
else if (col.property === 'amount') sums[idx] = totalAmount.toFixed(2)
else if (col.property === 'discounted') sums[idx] = totalDiscounted.toFixed(2)
else if (col.property === 'rate') sums[idx] = (totalDiscounted * 100 / totalAmount).toFixed(2)
else sums[idx] = ''
})
this.dataForm.totalPrice = totalAmount
return sums
}
}
}
</script>
<style>
:root { --header-bg: #f6f8fb; --border: #f1efef; --primary:#1E90FF; }
body { background:#f3f5f7; color:#222; }
.page-container { max-width: 1400px; margin: 24px auto; }
.page-header { border-radius:12px; padding:12px 16px; display:flex; align-items:center; gap:16px; }
.logo { font-weight:800; font-size:26px; color:#ff5a36; letter-spacing:1px; }
.muted { color:#666; font-size:13px; }
.subtitle {position: absolute;
left: 40%; color:#333; font-weight:800; font-size:24px; }
.panel-title { font-weight:700; font-size:14px; color:#334; }
.upload-tip { font-size:12px; color:#666; margin-left:8px; }
.footer-actions { display:flex; gap:12px; justify-content:center; padding:16px; }
.table-remark { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vertical-line {
position: relative;
}
.clause-item {
margin-bottom: 20px;
}
/* 完全去除边框 */
.no-border-form .el-form-item__content:before, .no-border-form .el-form-item__content:after {
display: none; /* 隐藏伪元素生成的边框 */
}
.vertical-line::after {
content: '';
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
height: 120%; /* 可以调整竖线的高度这里设置为80% */
width: 1px;
background-color: #e0e0e0;
}
/* 主题覆盖使Element Plus风格更贴近原始样式 */
.nl-theme {
--el-color-primary: var(--primary);
--el-border-color: var(--border);
--el-border-radius-small: 6px;
--el-border-radius-base: 8px;
--el-box-shadow-light: none;
}
.nl-theme .el-card { border:1px solid var(--border); box-shadow:none; }
.nl-theme .el-card__header { background:#f6f8fb; padding:10px 14px; font-weight:700; }
.nl-theme .el-form-item { margin-bottom:8px; }
.nl-theme .el-form-item__label { color:#333; font-size:13px; font-weight:600; }
.nl-theme .el-input--small .el-input__wrapper,
.nl-theme .el-select--small .el-select__wrapper { min-height:28px; }
.nl-theme .el-input__wrapper, .nl-theme .el-select__wrapper { box-shadow:none; border:1px solid var(--border); }
.nl-theme .el-button--primary { background: var(--primary); border-color: var(--primary); }
.nl-theme .el-button--primary.is-plain { color: var(--primary); background:#fff; }
/* 表格细节对齐 */
.nl-theme .el-table { font-size:13px; }
.nl-theme .el-table thead { background:#f7f9fc; }
.nl-theme .el-table__header-wrapper th { background:#f7f9fc; font-weight:600; color:#334; }
.nl-theme .el-table__row { height:36px; }
.nl-theme .nl-table-header { background:#f7f9fc; }
.nl-theme .nl-table-cell { padding:8px 10px; }
.attachments-row { margin-top:12px; display:flex; align-items:center; gap:12px; }
</style>