| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608 |
- <template>
- <div class="fixed-assets-table-container">
- <el-table
- :data="flattenedTableData"
- border
- style="width: 100%"
- size="small"
- :row-class-name="getRowClassName"
- >
- <!-- 序号列 -->
- <!-- <el-table-column prop="seq" label="序号" width="80" align="center">
- <template slot-scope="scope">
- <span v-if="scope.row.isCategory" class="category-seq">
- —
- </span>
- <span v-else>{{ scope.row.seq }}</span>
- </template>
- </el-table-column> -->
- <!-- 动态表头列 -->
- <el-table-column
- v-for="column in dynamicColumns"
- :key="column.prop"
- :prop="column.prop"
- :label="column.label"
- :min-width="column.minWidth || 120"
- :align="column.align || 'center'"
- >
- <template slot-scope="scope">
- <!-- parentid 为 -1 的行只读显示 -->
- <span
- v-if="
- scope.row.parentid === '-1' ||
- scope.row.parentid === -1 ||
- scope.row.parentId === '-1' ||
- scope.row.parentId === -1 ||
- scope.row.isCategory
- "
- class="category-value"
- >
- {{ scope.row[column.prop] || '-' }}
- </span>
- <!-- 子项可编辑 -->
- <el-date-picker
- v-else-if="column.type === 'date'"
- v-model="scope.row[column.prop]"
- type="date"
- placeholder="选择日期"
- size="mini"
- format="yyyy-MM-dd"
- value-format="yyyy-MM-dd"
- :disabled="
- isViewMode ||
- scope.row.notDeletable === true ||
- scope.row.fromTemplate === true ||
- scope.row.notEditable === true
- "
- style="width: 100%"
- />
- <el-input
- v-else
- v-model="scope.row[column.prop]"
- :placeholder="column.placeholder || '请输入' + column.label"
- size="mini"
- :disabled="
- isViewMode ||
- scope.row.notDeletable === true ||
- scope.row.fromTemplate === true ||
- scope.row.notEditable === true
- "
- @blur="handleCellBlur(scope.row, column.prop)"
- />
- </template>
- </el-table-column>
- <!-- 操作列(仅非查看模式显示) -->
- <el-table-column
- v-if="!isViewMode"
- label="操作"
- width="100"
- align="center"
- fixed="right"
- >
- <template slot-scope="scope">
- <div
- v-if="scope.row.parentid === '-1' || scope.row.parentid === -1"
- class="operation-buttons"
- >
- <el-button
- type="text"
- size="mini"
- icon="el-icon-plus"
- :disabled="isViewMode"
- @click="handleAddRow(scope.row)"
- />
- <!-- <el-button
- type="text"
- size="mini"
- icon="el-icon-minus"
- :disabled="isViewMode"
- @click="handleDeleteRow(scope.row)"
- /> -->
- </div>
- <div v-else class="operation-buttons">
- <el-button
- type="text"
- size="mini"
- icon="el-icon-minus"
- :disabled="
- isViewMode ||
- scope.row.notDeletable === true ||
- scope.row.fromTemplate === true ||
- scope.row.notEditable === true
- "
- @click="handleDeleteChildRow(scope.row)"
- />
- </div>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </template>
- <script>
- import { Message } from 'element-ui'
- import { saveSingleRecordSurvey } from '@/api/audit/survey'
- export default {
- name: 'FixedAssetsTable',
- props: {
- // 表格数据配置(嵌套结构)
- tableItems: {
- type: Array,
- default: () => [],
- },
- // 是否有保存的数据
- savedData: {
- type: [Object, Array],
- default: () => ({}),
- },
- // 是否查看模式
- isViewMode: {
- type: Boolean,
- default: false,
- },
- // 固定字段标签(逗号分隔的字符串)
- fixedFields: {
- type: String,
- default: '',
- },
- // 固定字段ID(逗号分隔的字符串)
- fixedFieldids: {
- type: String,
- default: '',
- },
- // 保存所需的公共字段
- auditedUnitId: {
- type: String,
- default: '',
- },
- surveyTemplateId: {
- type: String,
- default: '',
- },
- catalogId: {
- type: String,
- default: '',
- },
- uploadId: {
- type: String,
- default: '',
- },
- // 动态表调查填报表格的行ID
- periodRecordId: {
- type: String,
- default: '',
- },
- },
- data() {
- return {
- // 嵌套的表格数据
- fixedAssetsData: [],
- // 验证错误
- validationErrors: [],
- // 记录被删除的行rowid/id,用于保存时过滤
- deletedRowids: [],
- // 扁平化的表格数据(响应式)
- flattenedData: [],
- autoIdSeed: 1,
- // 原始保存的数据(用于回显)
- rawSavedData: null,
- }
- },
- computed: {
- // 扁平化的表格数据(从嵌套结构生成)
- flattenedTableData() {
- return this.flattenedData
- },
- // 动态表头列配置
- dynamicColumns() {
- if (!this.fixedFields || !this.fixedFieldids) {
- // 如果没有 fixedFields,返回默认列配置
- return this.getDefaultColumns()
- }
- const labels = this.fixedFields.split(',').map((item) => item.trim())
- const ids = this.fixedFieldids.split(',').map((item) => item.trim())
- return labels.map((label, index) => {
- const fieldId = ids[index] || `field_${index}`
- // 数据中的字段名就是 label(中文),所以 prop 使用 label
- // fieldId 用于保存时映射回字段ID
- const prop = label
- // 根据字段名判断类型
- const isDateField =
- label.includes('日期') ||
- label.includes('时间') ||
- label.includes('Date') ||
- label.includes('Time')
- return {
- prop: prop, // 使用中文字段名作为 prop,直接对应数据中的键名
- fieldId: fieldId, // 保存字段ID,用于保存时映射
- label: label,
- minWidth: isDateField ? 180 : 120,
- align: 'center',
- type: isDateField ? 'date' : 'input',
- placeholder: `请输入${label}`,
- }
- })
- },
- },
- watch: {
- tableItems: {
- handler(newVal) {
- if (newVal && newVal.length > 0) {
- // 若 tableItems 为扁平结构(带 parentId/parentid),按父子关系组装后再渲染
- const normalized = this.normalizeTableItemsSource(newVal)
- this.fixedAssetsData =
- normalized && normalized.length > 0
- ? normalized
- : this.deepClone(newVal)
- } else {
- // 不使用假数据,等待接口返回数据
- this.fixedAssetsData = []
- }
- // 在渲染前将传入的子项标记为只读
- this.markInitialChildrenReadonly()
- // 重新生成扁平数据
- this.generateFlattenedData()
- },
- immediate: true,
- deep: true,
- },
- savedData: {
- handler(newVal) {
- console.log('newVal', newVal)
- // 保存原始数据用于回显
- this.rawSavedData = newVal
- // 回显新数据时清空已删除记录
- this.deletedRowids = []
- if (newVal) {
- const normalized = this.normalizeSavedData(newVal)
- if (normalized && normalized.length > 0) {
- // 使用接口返回的数据,不使用假数据
- this.fixedAssetsData = normalized
- } else {
- // 如果没有数据,清空
- this.fixedAssetsData = []
- }
- } else {
- this.fixedAssetsData = []
- }
- // 在渲染前将传入的子项标记为只读
- this.markInitialChildrenReadonly()
- // 数据变化时重新生成扁平数据
- this.generateFlattenedData()
- },
- deep: true,
- immediate: true,
- },
- },
- methods: {
- // 将传入的子项标记为只读(不可编辑/删除),新增的行不受影响
- markInitialChildrenReadonly() {
- const data = this.fixedAssetsData || []
- data.forEach((node) => {
- if (!node || typeof node !== 'object') return
- const children = Array.isArray(node.children) ? node.children : []
- children.forEach((child) => {
- if (!child || typeof child !== 'object') return
- // 仅标记已有的传入子项(保留模板标记)
- if (child.notEditable !== false) {
- child.notEditable = true
- }
- })
- })
- },
- // 生成扁平数据
- generateFlattenedData() {
- // 先同步扁平数据中的修改到嵌套结构,避免数据丢失
- // 只有在已有扁平数据时才同步(避免初始化时出错)
- const shouldSync =
- this.flattenedData &&
- this.flattenedData.length > 0 &&
- this.fixedAssetsData &&
- this.fixedAssetsData.length > 0
- if (shouldSync) {
- this.syncFlattenedDataToNested()
- }
- const result = []
- let seq = 1
- const processItem = (item, parentCategory = null) => {
- const isCategory = this.isCategoryItem(item)
- const currentItem = this.normalizeItemNode(item)
- if (isCategory) {
- // 分类行(父项)
- const categoryRowData = {
- ...currentItem,
- seq: currentItem.categorySeq || currentItem.id,
- isCategory: true,
- categorySeq: currentItem.categorySeq || currentItem.id,
- }
- // 直接使用 currentItem 中的数据(normalizeSavedData 已经保留了所有原始字段)
- // 将所有字段值复制到 categoryRowData(除了系统字段)
- Object.keys(currentItem).forEach((key) => {
- if (
- currentItem[key] !== undefined &&
- key !== 'id' &&
- key !== 'children' &&
- key !== 'isCategory' &&
- key !== 'categorySeq' &&
- key !== 'seq' &&
- !key.startsWith('_')
- ) {
- categoryRowData[key] = currentItem[key]
- }
- })
- // 根据表头字段确保所有列都有值(如果数据中没有对应字段,初始化为空)
- this.dynamicColumns.forEach((column) => {
- if (categoryRowData[column.prop] === undefined) {
- categoryRowData[column.prop] = currentItem[column.prop] || ''
- }
- })
- result.push(categoryRowData)
- // 处理分类下的子项
- if (currentItem.children && Array.isArray(currentItem.children)) {
- currentItem.children.forEach((child) => {
- processItem(child, currentItem)
- })
- }
- } else {
- // 普通行
- const rowData = {
- ...currentItem,
- seq: seq++,
- isCategory: false,
- }
- // 如果有父分类,设置分类信息
- if (parentCategory) {
- rowData.categoryId = parentCategory.id
- rowData.categorySeq =
- parentCategory.categorySeq || parentCategory.id
- }
- // 直接使用 currentItem 中的数据(normalizeSavedData 已经保留了所有原始字段)
- // 将所有字段值复制到 rowData(除了系统字段)
- Object.keys(currentItem).forEach((key) => {
- if (
- currentItem[key] !== undefined &&
- key !== 'id' &&
- key !== 'children' &&
- key !== 'isCategory' &&
- key !== 'categorySeq' &&
- key !== 'seq' &&
- !key.startsWith('_')
- ) {
- rowData[key] = currentItem[key]
- }
- })
- // 根据表头字段确保所有列都有值(优先使用数据中的值,如果没有则初始化为空)
- this.dynamicColumns.forEach((column) => {
- // 如果数据中没有该字段,初始化为空字符串
- if (rowData[column.prop] === undefined) {
- rowData[column.prop] = currentItem[column.prop] || ''
- }
- })
- result.push(rowData)
- // 如果有子项,递归处理
- if (item.children && Array.isArray(item.children)) {
- item.children.forEach((child) => {
- processItem(child, item)
- })
- }
- }
- }
- // 处理所有项
- this.fixedAssetsData.forEach((item) => {
- processItem(item)
- })
- // 使用 Vue.set 确保响应式
- this.$set(this, 'flattenedData', result)
- },
- // 深拷贝
- deepClone(obj) {
- if (obj === null || typeof obj !== 'object') return obj
- if (obj instanceof Date) return new Date(obj.getTime())
- if (obj instanceof Array) return obj.map((item) => this.deepClone(item))
- if (typeof obj === 'object') {
- const clonedObj = {}
- for (const key in obj) {
- if (obj.hasOwnProperty(key)) {
- clonedObj[key] = this.deepClone(obj[key])
- }
- }
- return clonedObj
- }
- },
- // 将三元组明细数组(rowid,parentId,rkey,rvalue)聚合为树形行数据
- transformTripletArrayToRows(items) {
- if (!Array.isArray(items) || items.length === 0) return []
- const rowsByRowid = new Map()
- const parentRowids = new Set()
- items.forEach((rec) => {
- if (!rec || typeof rec !== 'object') return
- const rowid = rec.rowid || rec.rowId
- if (!rowid) return
- const parentId = rec.parentId ?? rec.parentID ?? rec.parentid
- if (parentId && parentId !== '-1' && parentId !== -1) {
- parentRowids.add(String(parentId))
- }
- if (!rowsByRowid.has(rowid)) {
- rowsByRowid.set(rowid, {
- id: rowid,
- rowid: rowid,
- parentid:
- parentId === undefined || parentId === null
- ? ''
- : String(parentId),
- children: [],
- })
- }
- const row = rowsByRowid.get(rowid)
- const key = rec.rkey
- const val = rec.rvalue
- if (key !== undefined) {
- row[key] = val
- }
- })
- const allRows = Array.from(rowsByRowid.values())
- allRows.forEach((row) => {
- if (
- row.parentid === '-1' ||
- row.parentid === -1 ||
- parentRowids.has(row.rowid)
- ) {
- row.isCategory = true
- }
- })
- const byRowid = new Map(allRows.map((r) => [r.rowid, r]))
- const roots = []
- allRows.forEach((row) => {
- const p = row.parentid
- if (p && p !== '-1' && p !== -1) {
- const parent = byRowid.get(String(p))
- if (parent) {
- if (!Array.isArray(parent.children)) parent.children = []
- parent.children.push(row)
- parent.isCategory = true
- } else {
- roots.push(row)
- }
- } else {
- roots.push(row)
- }
- })
- return roots
- },
- // 当没有详情数据时,tableItems 可能为扁平结构,这里根据 parentId/parentid 组装树
- normalizeTableItemsSource(items) {
- if (!Array.isArray(items) || items.length === 0) return []
- const cloned = this.deepClone(items)
- // 三元组格式直接转换
- const isTriplet =
- cloned.length > 0 &&
- cloned.every(
- (it) =>
- it &&
- typeof it === 'object' &&
- 'rkey' in it &&
- 'rvalue' in it &&
- ('rowid' in it || 'rowId' in it)
- )
- if (isTriplet) {
- return this.transformTripletArrayToRows(cloned)
- }
- const hasNestedChildren = cloned.some(
- (it) => it && Array.isArray(it.children) && it.children.length > 0
- )
- if (hasNestedChildren) {
- return cloned.map((it) => this.normalizeItemNode(it))
- }
- // 扁平结构:根据 parentId/parentid 组装
- const idMap = new Map()
- const rowidMap = new Map()
- const nodes = cloned.map((raw) => this.normalizeItemNode(raw))
- nodes.forEach((node, idx) => {
- const raw = cloned[idx]
- const id = node.id
- const rowid = raw.rowid || raw.rowId || node.rowid || node.id
- if (id) idMap.set(id, node)
- if (rowid) rowidMap.set(rowid, node)
- })
- const roots = []
- cloned.forEach((raw, idx) => {
- const node = nodes[idx]
- const parentKey =
- raw.parentId ??
- raw.parentid ??
- raw.parentID ??
- raw.parentCode ??
- raw.parent_code
- if (parentKey && parentKey !== '-1' && parentKey !== -1) {
- // 先按 id 匹配,再按 rowid 兜底
- const parent = idMap.get(parentKey) || rowidMap.get(parentKey)
- if (parent) {
- if (!Array.isArray(parent.children)) parent.children = []
- parent.children.push(node)
- parent.isCategory = true
- } else {
- roots.push(node)
- }
- } else {
- roots.push(node)
- }
- })
- return roots.length > 0 ? roots : nodes
- },
- // 获取行样式类名
- getRowClassName({ row }) {
- // parentid 为 -1 的行(父项)使用分类行样式
- if (
- row.parentid === '-1' ||
- row.parentid === -1 ||
- row.parentId === '-1' ||
- row.parentId === -1 ||
- row.isCategory
- ) {
- return 'category-row'
- }
- return ''
- },
- // 添加行(添加子项)
- handleAddRow(row) {
- // 先同步扁平数据中的修改到嵌套结构,避免数据丢失
- this.syncFlattenedDataToNested()
- // row 是 parentid 为 -1 的父项
- // 找到对应的父项节点
- const parentNode = this.findNodeByRowid(row.rowid)
- if (parentNode) {
- // 生成新的子项
- const newRowid = `${Date.now()}.${Math.random()
- .toString(36)
- .substr(2, 9)}`
- const newItem = {
- parentid: row.rowid, // 设置父项的 rowid
- rowid: newRowid,
- id: newRowid, // 临时使用 rowid 作为 id
- }
- // 根据表头字段初始化新项的所有字段
- this.dynamicColumns.forEach((column) => {
- newItem[column.prop] = ''
- })
- // 在父项的 children 数组末尾添加新行
- if (!parentNode.children) {
- this.$set(parentNode, 'children', [])
- }
- parentNode.children.push(newItem)
- // 重新生成扁平数据(generateFlattenedData 内部会再次同步,确保数据不丢失)
- this.generateFlattenedData()
- Message.success('添加子项成功')
- } else {
- Message.error('找不到父项')
- }
- },
- // 删除行(删除父项下的最后一个子项)
- handleDeleteRow(row) {
- // 先同步扁平数据中的修改到嵌套结构,避免数据丢失
- this.syncFlattenedDataToNested()
- // row 是 parentid 为 -1 的父项
- // 找到对应的父项节点
- const parentNode = this.findNodeByRowid(row.rowid)
- if (
- parentNode &&
- parentNode.children &&
- parentNode.children.length > 0
- ) {
- // 删除最后一个子项
- const removedChild = parentNode.children.pop()
- // 记录被删除的行标识,保存时过滤
- const removedKey = String(
- (removedChild &&
- (removedChild.rowid || removedChild.rowId || removedChild.id)) ||
- ''
- )
- if (removedKey) {
- if (!this.deletedRowids.includes(removedKey)) {
- this.deletedRowids.push(removedKey)
- }
- // 同步从扁平数据中移除该行,避免同步时被回填
- const withoutRemoved = (this.flattenedData || []).filter((r) => {
- const rk = String(r.rowid || r.rowId || r.id || '')
- return rk !== removedKey
- })
- this.$set(this, 'flattenedData', withoutRemoved)
- }
- // 重新生成扁平数据
- this.generateFlattenedData()
- Message.success('删除子项成功')
- } else {
- Message.warning('该父项下没有可删除的子项')
- }
- },
- // 删除子项(点击子项行的减号删除当前这条)
- handleDeleteChildRow(row) {
- // 模板数据不可删除
- if (row && (row.notDeletable === true || row.fromTemplate === true)) {
- Message.warning('该行由模板生成,无法删除')
- return
- }
- // 先同步扁平数据中的修改到嵌套结构,避免数据丢失
- this.syncFlattenedDataToNested()
- const childRowid = row.rowid || row.rowId || row.id
- if (!childRowid) {
- Message.error('无法识别该行标识,删除失败')
- return
- }
- // 记录被删除的行标识,保存时过滤
- const key = String(childRowid)
- if (key && !this.deletedRowids.includes(key)) {
- this.deletedRowids.push(key)
- }
- // 从整棵树中移除此节点
- const removed = this.removeRowByRowid(childRowid)
- if (removed) {
- // 同步从扁平数据中移除该行,避免同步时被回填
- const withoutRemoved = (this.flattenedData || []).filter((r) => {
- const rk = String(r.rowid || r.rowId || r.id || '')
- return rk !== key
- })
- this.$set(this, 'flattenedData', withoutRemoved)
- // 重新生成扁平数据并刷新视图
- this.generateFlattenedData()
- this.$nextTick(() => {
- this.$forceUpdate()
- })
- Message.success('删除成功')
- } else {
- Message.warning('未找到可删除的记录')
- }
- },
- // 在嵌套数据中移除指定 rowid 的节点
- removeRowByRowid(targetRowid) {
- if (!Array.isArray(this.fixedAssetsData)) return false
- const toKey = (n) => String(n.rowid || n.rowId || n.id || '')
- const targetKey = String(targetRowid)
- // 尝试在根级删除
- const idx = this.fixedAssetsData.findIndex(
- (n) => toKey(n) === targetKey
- )
- if (idx >= 0) {
- this.fixedAssetsData.splice(idx, 1)
- return true
- }
- // 递归在 children 中删除
- const dfsRemove = (nodes) => {
- for (const node of nodes) {
- if (Array.isArray(node.children) && node.children.length > 0) {
- const i = node.children.findIndex((c) => toKey(c) === targetKey)
- if (i >= 0) {
- node.children.splice(i, 1)
- return true
- }
- if (dfsRemove(node.children)) return true
- }
- }
- return false
- }
- return dfsRemove(this.fixedAssetsData)
- },
- // 同步扁平数据中的修改到嵌套结构
- syncFlattenedDataToNested() {
- const flatData = this.flattenedData
- if (!flatData || flatData.length === 0) return
- // 建立 rowid 到嵌套节点的映射
- const nodeMap = new Map()
- const buildMap = (items) => {
- items.forEach((item) => {
- const rowid = item.rowid || item.rowId || item.id
- if (rowid) {
- nodeMap.set(rowid, item)
- }
- if (item.children && Array.isArray(item.children)) {
- buildMap(item.children)
- }
- })
- }
- buildMap(this.fixedAssetsData)
- // 将扁平数据中的修改同步到嵌套结构
- flatData.forEach((flatRow) => {
- const rowid = flatRow.rowid || flatRow.rowId || flatRow.id
- if (!rowid) return
- const nestedNode = nodeMap.get(rowid)
- if (nestedNode) {
- // 同步所有表头字段的值(使用 hasOwnProperty 确保即使值为空字符串也能同步)
- this.dynamicColumns.forEach((column) => {
- if (flatRow.hasOwnProperty(column.prop)) {
- nestedNode[column.prop] = flatRow[column.prop]
- }
- })
- // 同步其他字段(除了系统字段)
- Object.keys(flatRow).forEach((key) => {
- if (
- key !== 'id' &&
- key !== 'rowid' &&
- key !== 'rowId' &&
- key !== 'children' &&
- key !== 'isCategory' &&
- key !== 'categorySeq' &&
- key !== 'seq' &&
- key !== 'categoryId' &&
- !key.startsWith('_')
- ) {
- // 使用 hasOwnProperty 确保即使值为空字符串也能同步
- if (flatRow.hasOwnProperty(key)) {
- nestedNode[key] = flatRow[key]
- }
- }
- })
- // 确保 parentid 被保留
- if (flatRow.hasOwnProperty('parentid')) {
- nestedNode.parentid = flatRow.parentid
- }
- } else {
- // 如果找不到节点,可能是新添加的行,需要添加到对应的父节点下
- const parentid = flatRow.parentid || flatRow.parentId
- if (parentid && parentid !== '-1') {
- const parentNode = nodeMap.get(parentid)
- if (parentNode) {
- // 创建新节点并添加到父节点的 children 中
- const newNode = {
- ...flatRow,
- id: rowid,
- rowid: rowid,
- parentid: parentid,
- }
- // 移除系统字段
- delete newNode.isCategory
- delete newNode.categorySeq
- delete newNode.seq
- delete newNode.categoryId
- if (!parentNode.children) {
- this.$set(parentNode, 'children', [])
- }
- // 检查是否已存在,避免重复添加
- const exists = parentNode.children.some(
- (child) => (child.rowid || child.rowId || child.id) === rowid
- )
- if (!exists) {
- parentNode.children.push(newNode)
- } else {
- // 如果已存在,更新数据
- const existingNode = parentNode.children.find(
- (child) =>
- (child.rowid || child.rowId || child.id) === rowid
- )
- if (existingNode) {
- // 同步所有字段
- this.dynamicColumns.forEach((column) => {
- if (flatRow.hasOwnProperty(column.prop)) {
- existingNode[column.prop] = flatRow[column.prop]
- }
- })
- Object.keys(flatRow).forEach((key) => {
- if (
- key !== 'id' &&
- key !== 'rowid' &&
- key !== 'rowId' &&
- key !== 'children' &&
- key !== 'isCategory' &&
- key !== 'categorySeq' &&
- key !== 'seq' &&
- key !== 'categoryId' &&
- !key.startsWith('_')
- ) {
- if (flatRow.hasOwnProperty(key)) {
- existingNode[key] = flatRow[key]
- }
- }
- })
- }
- }
- }
- }
- }
- })
- },
- // 根据 rowid 查找节点
- findNodeByRowid(rowid) {
- const findInArray = (items) => {
- for (const item of items) {
- if (item.rowid === rowid || item.rowId === rowid) {
- return item
- }
- if (item.children && Array.isArray(item.children)) {
- const found = findInArray(item.children)
- if (found) return found
- }
- }
- return null
- }
- return findInArray(this.fixedAssetsData)
- },
- // 根据ID在保存的数据中查找(支持通过 id 或 rowid 查找)
- findSavedItemById(id) {
- // 优先从 rawSavedData 中查找(原始数据)
- const dataSource = this.rawSavedData || this.savedData
- if (!dataSource) return null
- // 递归查找(支持通过 id、rowid、rowId 匹配)
- const findInArray = (items) => {
- if (!Array.isArray(items)) return null
- for (const item of items) {
- // 匹配 id、rowid、rowId
- if (
- item.id === id ||
- item.rowid === id ||
- item.rowId === id ||
- item.itemId === id ||
- item.code === id ||
- item.key === id
- ) {
- return item
- }
- if (item.children && Array.isArray(item.children)) {
- const found = findInArray(item.children)
- if (found) return found
- }
- }
- return null
- }
- // 如果 dataSource 是数组
- if (Array.isArray(dataSource)) {
- return findInArray(dataSource)
- }
- // 如果 dataSource 是对象,尝试查找
- if (typeof dataSource === 'object') {
- // 优先查找 itemlist
- if (Array.isArray(dataSource.itemlist)) {
- const found = findInArray(dataSource.itemlist)
- if (found) return found
- }
- if (Array.isArray(dataSource.items)) {
- const found = findInArray(dataSource.items)
- if (found) return found
- }
- if (Array.isArray(dataSource.data)) {
- const found = findInArray(dataSource.data)
- if (found) return found
- }
- if (Array.isArray(dataSource.value)) {
- const found = findInArray(dataSource.value)
- if (found) return found
- }
- // 可能是一个映射对象,key 是 id
- if (dataSource[id]) {
- return dataSource[id]
- }
- // 或者是嵌套结构
- return findInArray([dataSource])
- }
- return null
- },
- // 根据ID查找分类
- findCategoryById(id) {
- const findInArray = (items) => {
- for (const item of items) {
- if (item.id === id) {
- return item
- }
- if (item.children && Array.isArray(item.children)) {
- const found = findInArray(item.children)
- if (found) return found
- }
- }
- return null
- }
- return findInArray(this.fixedAssetsData)
- },
- // 单元格失焦验证
- handleCellBlur(row, field) {
- // 实时验证格式
- if (field === 'originalValue' || field === 'depreciationExpense') {
- const value = row[field]
- if (value && !/^\d+(\.\d+)?$/.test(value)) {
- Message.warning(
- `${this.getFieldLabel(field)}格式不正确,请输入数字`
- )
- }
- }
- if (field === 'depreciationPeriod') {
- const value = row[field]
- if (value && !/^\d+$/.test(value)) {
- Message.warning(`${this.getFieldLabel(field)}必须是正整数`)
- }
- }
- },
- // 获取字段标签
- getFieldLabel(field) {
- const labels = {
- originalValue: '固定资产原值',
- depreciationPeriod: '折旧年限',
- depreciationExpense: '折旧费',
- }
- return labels[field] || field
- },
- // 获取默认列配置(当没有 fixedFields 时使用)
- getDefaultColumns() {
- return [
- {
- prop: 'unit',
- label: '计量单位',
- minWidth: 120,
- align: 'center',
- type: 'input',
- placeholder: '请输入计量单位',
- },
- {
- prop: 'originalValue',
- label: '固定资产原值',
- minWidth: 150,
- align: 'center',
- type: 'input',
- placeholder: '请输入原值',
- },
- {
- prop: 'entryDate',
- label: '入帐或竣工验收日期',
- minWidth: 180,
- align: 'center',
- type: 'date',
- placeholder: '选择日期',
- },
- {
- prop: 'depreciationPeriod',
- label: '折旧年限',
- minWidth: 120,
- align: 'center',
- type: 'input',
- placeholder: '请输入年限',
- },
- {
- prop: 'depreciationExpense',
- label: '折旧费',
- minWidth: 120,
- align: 'center',
- type: 'input',
- placeholder: '请输入费用',
- },
- {
- prop: 'fundSource',
- label: '资金来源',
- minWidth: 120,
- align: 'center',
- type: 'input',
- placeholder: '请输入来源',
- },
- {
- prop: 'remark',
- label: '备注',
- minWidth: 150,
- align: 'left',
- type: 'input',
- placeholder: '请输入备注',
- },
- ]
- },
- // 验证表单
- // validate() {
- // this.validationErrors = []
- // const errors = []
- // // 验证扁平数据(因为用户编辑的是扁平数据)
- // const flatData = this.flattenedTableData
- // flatData.forEach((item, index) => {
- // if (!item.isCategory) {
- // // 非空验证
- // if (!item.itemName || String(item.itemName).trim() === '') {
- // errors.push(`第${item.seq}行:项目名称不能为空`)
- // }
- // if (!item.unit || String(item.unit).trim() === '') {
- // errors.push(`第${item.seq}行:计量单位不能为空`)
- // }
- // if (
- // !item.originalValue ||
- // String(item.originalValue).trim() === ''
- // ) {
- // errors.push(`第${item.seq}行:固定资产原值不能为空`)
- // }
- // if (!item.entryDate || String(item.entryDate).trim() === '') {
- // errors.push(`第${item.seq}行:入帐或竣工验收日期不能为空`)
- // }
- // if (
- // !item.depreciationPeriod ||
- // String(item.depreciationPeriod).trim() === ''
- // ) {
- // errors.push(`第${item.seq}行:折旧年限不能为空`)
- // }
- // if (
- // !item.depreciationExpense ||
- // String(item.depreciationExpense).trim() === ''
- // ) {
- // errors.push(`第${item.seq}行:折旧费不能为空`)
- // }
- // if (!item.fundSource || String(item.fundSource).trim() === '') {
- // errors.push(`第${item.seq}行:资金来源不能为空`)
- // }
- // // 格式验证
- // if (
- // item.originalValue &&
- // String(item.originalValue).trim() !== '' &&
- // !/^\d+(\.\d+)?$/.test(String(item.originalValue))
- // ) {
- // errors.push(`第${item.seq}行:固定资产原值格式不正确,请输入数字`)
- // }
- // if (
- // item.depreciationPeriod &&
- // String(item.depreciationPeriod).trim() !== '' &&
- // !/^\d+$/.test(String(item.depreciationPeriod))
- // ) {
- // errors.push(`第${item.seq}行:折旧年限必须是正整数`)
- // }
- // if (
- // item.depreciationExpense &&
- // String(item.depreciationExpense).trim() !== '' &&
- // !/^\d+(\.\d+)?$/.test(String(item.depreciationExpense))
- // ) {
- // errors.push(`第${item.seq}行:折旧费格式不正确,请输入数字`)
- // }
- // }
- // })
- // this.validationErrors = errors
- // return errors.length === 0
- // },
- // 获取表格数据(用于保存)
- // 需要将扁平数据同步回嵌套结构
- getTableData() {
- // 同步扁平数据的修改到嵌套结构
- const flatData = this.flattenedData
- const syncDataToNested = (items) => {
- return items.map((item) => {
- if (item.isCategory) {
- // 分类行
- const newItem = { ...item }
- if (item.children && Array.isArray(item.children)) {
- newItem.children = syncDataToNested(item.children)
- }
- return newItem
- } else {
- // 普通行,从扁平数据中同步
- const flatItem = flatData.find(
- (f) => f.id === item.id && !f.isCategory
- )
- if (flatItem) {
- return {
- ...item,
- itemName: flatItem.itemName,
- unit: flatItem.unit,
- originalValue: flatItem.originalValue,
- entryDate: flatItem.entryDate,
- depreciationPeriod: flatItem.depreciationPeriod,
- depreciationExpense: flatItem.depreciationExpense,
- fundSource: flatItem.fundSource,
- remark: flatItem.remark,
- }
- }
- return item
- }
- })
- }
- return syncDataToNested(this.fixedAssetsData)
- },
- // 保存数据(调用 saveSingleRecordSurvey 接口)
- async saveData() {
- // 保存前校验
- const validationErrors = this.validateBeforeSave()
- if (validationErrors && validationErrors.length > 0) {
- Message.error('表单验证失败,请检查后再保存')
- return false
- }
- try {
- // 格式化保存数据为接口需要的格式
- const saveData = []
- // 需要过滤掉已删除的行
- const isDeleted = (row) => {
- const key = String(row.rowid || row.rowId || row.id || '')
- return key && this.deletedRowids.includes(key)
- }
- const flatData = (this.flattenedData || []).filter(
- (row) => !isDeleted(row)
- )
- // 建立 rowid -> id 的映射,用于计算 parentId(子项需要父项的 id)
- const rowidToIdMap = new Map()
- flatData.forEach((row) => {
- const rowid = row.rowid || row.id
- const id = row.id || row.rowid || row.rowId
- if (rowid && id) {
- rowidToIdMap.set(rowid, id)
- }
- })
- // 遍历所有行数据(包括父项和子项)
- flatData.forEach((row) => {
- const rowid = row.rowid || row.id
- // 计算 parentId:父项为 '-1';子项为父项的 id(通过 parent 的 rowid 映射得到)
- let parentId = '-1'
- const parentRowid = row.parentid || row.parentId || row.parentID
- if (parentRowid && parentRowid !== '-1' && parentRowid !== -1) {
- parentId =
- rowidToIdMap.get(parentRowid) ||
- row.categoryId || // 兼容 generateFlattenedData 填充的父分类 id
- ''
- }
- // 遍历所有表头字段,保存每个字段的值
- this.dynamicColumns.forEach((column) => {
- const value = row[column.prop]
- // 如果值存在,添加到保存数据中(父项和子项都保存)
- if (value !== undefined && value !== null && value !== '') {
- saveData.push({
- rowid: rowid,
- parentId: String(parentId),
- rkey: column.label, // 字段标签(对应 fixedFields)
- rvalue: String(value), // 字段值
- })
- }
- })
- })
- // 为每条数据添加公共字段
- const finalSaveData = saveData.map((item) => {
- const dataItem = {
- ...item,
- auditedUnitId: this.auditedUnitId || '',
- surveyTemplateId: this.surveyTemplateId || '',
- catalogId: this.catalogId || '',
- }
- // 如果有 uploadId(编辑模式),添加 uploadId 字段
- if (this.uploadId) {
- dataItem.uploadId = this.uploadId
- }
- // 添加 periodRecordId(动态表调查填报表格的行ID)
- if (this.periodRecordId) {
- dataItem.periodRecordId = this.periodRecordId
- }
- return dataItem
- })
- console.log('保存数据:', finalSaveData)
- // 调用保存接口
- const res = await saveSingleRecordSurvey(finalSaveData)
- if (res && res.code === 200) {
- Message.success('保存成功')
- // 触发保存事件
- this.$emit('save', finalSaveData)
- // 触发刷新事件
- this.$emit('refresh')
- return true
- } else {
- Message.error(res?.message || '保存失败')
- return false
- }
- } catch (err) {
- console.error('保存失败', err)
- Message.error(err?.message || '保存失败')
- return false
- }
- },
- // 保存前验证
- validateBeforeSave() {
- const errors = []
- const categories = Array.isArray(this.fixedAssetsData)
- ? this.fixedAssetsData
- : []
- categories.forEach((category) => {
- const items = Array.isArray(category.items) ? category.items : []
- items.forEach((item, index) => {
- const rowNum = index + 1
- // 必填校验
- if (!item.name) {
- errors.push(
- `${category.category} 第${rowNum}行:项目名称不能为空`
- )
- }
- if (!item.unit) {
- errors.push(
- `${category.category} 第${rowNum}行:计量单位不能为空`
- )
- }
- if (
- item.originalValue === '' ||
- item.originalValue === undefined ||
- item.originalValue === null
- ) {
- errors.push(
- `${category.category} 第${rowNum}行:固定资产原值不能为空`
- )
- } else if (isNaN(Number(item.originalValue))) {
- errors.push(
- `${category.category} 第${rowNum}行:固定资产原值必须为数字`
- )
- }
- if (!item.entryDate) {
- errors.push(
- `${category.category} 第${rowNum}行:入帐或竣工验收日期不能为空`
- )
- }
- if (
- item.depreciationPeriod === '' ||
- item.depreciationPeriod === undefined ||
- item.depreciationPeriod === null
- ) {
- errors.push(
- `${category.category} 第${rowNum}行:折旧年限不能为空`
- )
- } else if (isNaN(Number(item.depreciationPeriod))) {
- errors.push(
- `${category.category} 第${rowNum}行:折旧年限必须为数字`
- )
- }
- if (
- item.depreciationExpense === '' ||
- item.depreciationExpense === undefined ||
- item.depreciationExpense === null
- ) {
- errors.push(`${category.category} 第${rowNum}行:折旧费不能为空`)
- } else if (isNaN(Number(item.depreciationExpense))) {
- errors.push(
- `${category.category} 第${rowNum}行:折旧费必须为数字`
- )
- }
- if (!item.fundSource) {
- errors.push(
- `${category.category} 第${rowNum}行:资金来源不能为空`
- )
- }
- })
- })
- this.validationErrors = errors
- return errors
- },
- isCategoryItem(item) {
- if (!item) return false
- const flag = item.isCategory
- if (typeof flag === 'boolean') return flag
- if (typeof flag === 'number') return flag !== 0
- if (typeof flag === 'string') {
- const normalized = flag.toLowerCase()
- if (['1', 'true', 'yes', 'y'].includes(normalized)) return true
- }
- if (Array.isArray(item.children) && item.children.length > 0) {
- return true
- }
- return false
- },
- // 规范化节点数据(保留所有原始字段)
- normalizeItemNode(item) {
- if (!item || typeof item !== 'object') return item
- // 深拷贝保留所有原始字段
- const cloned = this.deepClone(item)
- // 确保 id 存在
- cloned.id =
- cloned.rowid ||
- cloned.rowId ||
- cloned.id ||
- cloned.itemId ||
- cloned.code ||
- cloned.key ||
- `auto-${this.autoIdSeed++}`
- // 保留 rowid 字段(用于父子关系匹配)
- if (!cloned.rowid && !cloned.rowId) {
- cloned.rowid = cloned.id
- } else {
- cloned.rowid = cloned.rowid || cloned.rowId || cloned.id
- }
- // 规范化常用字段(如果不存在则设置默认值,但不覆盖已有值)
- if (!cloned.itemName) {
- cloned.itemName = cloned.name || cloned.title || cloned['项目'] || ''
- }
- if (cloned.unit === undefined) {
- cloned.unit = cloned.unitName || cloned['单位'] || ''
- }
- if (cloned.originalValue === undefined) {
- cloned.originalValue = cloned['原值'] || cloned.value || ''
- }
- if (cloned.entryDate === undefined) {
- cloned.entryDate =
- cloned['入帐或竣工验收日期'] || cloned.entry_date || ''
- }
- if (cloned.depreciationPeriod === undefined) {
- cloned.depreciationPeriod = cloned['折旧年限'] || cloned.period || ''
- }
- if (cloned.depreciationExpense === undefined) {
- cloned.depreciationExpense = cloned['折旧费'] || cloned.expense || ''
- }
- if (cloned.fundSource === undefined) {
- cloned.fundSource = cloned.fund_source || cloned['资金来源'] || ''
- }
- if (cloned.remark === undefined) {
- cloned.remark = cloned.note || cloned['备注'] || ''
- }
- if (!cloned.categorySeq) {
- cloned.categorySeq =
- cloned.category_code ||
- cloned.seq ||
- cloned.index ||
- cloned['序号'] ||
- cloned.id
- }
- // 如果已经是分类项,保持 isCategory 状态
- if (cloned.isCategory === undefined) {
- cloned.isCategory = false // 默认不是分类,后续会根据是否有子项来设置
- }
- // 处理 children
- if (Array.isArray(cloned.children)) {
- cloned.children = this.deepClone(cloned.children)
- } else {
- cloned.children = []
- }
- return cloned
- },
- // 规范化保存的数据
- normalizeSavedData(saved) {
- if (!saved) return null
- const extractArray = (value) => {
- if (!value) return null
- if (Array.isArray(value)) return this.deepClone(value)
- if (value && typeof value === 'object') {
- if (Array.isArray(value.itemlist))
- return this.deepClone(value.itemlist)
- if (Array.isArray(value.items)) return this.deepClone(value.items)
- if (Array.isArray(value.children))
- return this.deepClone(value.children)
- if (Array.isArray(value.data)) return this.deepClone(value.data)
- if (Array.isArray(value.value)) return this.deepClone(value.value)
- if (Array.isArray(value.records))
- return this.deepClone(value.records)
- if (Array.isArray(value.rows)) return this.deepClone(value.rows)
- }
- return null
- }
- let normalized = extractArray(saved)
- // 检测三元组格式并转换
- if (
- Array.isArray(normalized) &&
- normalized.length > 0 &&
- normalized.every(
- (it) =>
- it &&
- typeof it === 'object' &&
- 'rkey' in it &&
- 'rvalue' in it &&
- ('rowid' in it || 'rowId' in it)
- )
- ) {
- normalized = this.transformTripletArrayToRows(normalized)
- }
- if (!normalized && saved && typeof saved === 'object') {
- const values = Object.values(saved)
- if (
- values.length > 0 &&
- values.every(
- (item) =>
- item &&
- typeof item === 'object' &&
- (item.itemName || item.children || item.isCategory)
- )
- ) {
- normalized = this.deepClone(values)
- }
- }
- if (!normalized || normalized.length === 0) return null
- const hasNestedChildren = normalized.some(
- (item) =>
- item && Array.isArray(item.children) && item.children.length > 0
- )
- if (hasNestedChildren) {
- return normalized.map((item) => this.normalizeItemNode(item))
- }
- // 如果是扁平结构,尝试根据 parentId 组装
- // 首先建立 rowid 到节点的映射(用于根据 parentid 查找父节点)
- const itemsMapById = new Map() // 通过 id 查找节点
- const itemsMapByRowid = new Map() // 通过 rowid 查找节点(用于父子关系)
- normalized.forEach((raw) => {
- const node = this.normalizeItemNode(raw)
- // 获取节点的 id
- const nodeId = node.id
- // 获取节点的 rowid(可能用于作为父节点的标识)
- const nodeRowid = raw.rowid || raw.rowId || raw.id || nodeId
- itemsMapById.set(nodeId, node)
- itemsMapByRowid.set(nodeRowid, node)
- })
- const roots = []
- normalized.forEach((raw) => {
- const nodeId =
- raw.id ||
- raw.itemId ||
- raw.rowid ||
- raw.rowId ||
- raw.code ||
- raw.key
- const node = itemsMapById.get(nodeId)
- if (!node) return
- // 获取父引用字段:优先支持 parentId(按父项 id 关联),兼容 parentid(按父项 rowid 关联)
- const parentid =
- raw.parentid ??
- raw.parentId ??
- raw.parentID ??
- raw.parentCode ??
- raw.parent_code
- const parentIdById = raw.parentId ?? raw.parentID
- // 判定根节点:parentId 为 "-1" 或未提供父引用
- const isRootById = parentIdById === '-1'
- const hasAnyParentRef =
- (parentIdById !== undefined &&
- parentIdById !== null &&
- parentIdById !== '') ||
- (parentid !== undefined && parentid !== null && parentid !== '')
- if (!hasAnyParentRef || isRootById || parentid === '-1') {
- // 作为根节点(父项)
- // 检查是否存在子项指向它(通过 id 或 rowid)
- const hasChildren = normalized.some((item) => {
- const childParentId = item.parentId ?? item.parentID
- const childParentid =
- item.parentid ?? item.parentId ?? item.parentID
- const currentRowid = raw.rowid || raw.rowId || raw.id
- return (
- (childParentId &&
- childParentId !== '-1' &&
- childParentId === nodeId) ||
- (childParentid &&
- childParentid !== '-1' &&
- childParentid === currentRowid)
- )
- })
- if (hasChildren) {
- node.isCategory = true
- }
- roots.push(node)
- } else {
- // 处理子项:优先使用 parentId -> idMap;否则使用 parentid(rowid) -> rowidMap
- const parentNode =
- (parentIdById &&
- parentIdById !== '-1' &&
- itemsMapById.get(parentIdById)) ||
- (parentid && parentid !== '-1' && itemsMapByRowid.get(parentid))
- if (parentNode) {
- if (!Array.isArray(parentNode.children)) {
- parentNode.children = []
- }
- parentNode.children.push(node)
- // 父项标记为分类(不可操作)
- parentNode.isCategory = true
- } else {
- // 找不到父节点,作为根节点
- roots.push(node)
- }
- }
- })
- return roots.length > 0 ? roots : normalized
- },
- },
- }
- </script>
- <style scoped lang="scss">
- .fixed-assets-table-container {
- // 分类行样式
- ::v-deep .category-row {
- background-color: #f5f7fa !important;
- td {
- background-color: #f5f7fa !important;
- font-weight: bold;
- }
- .category-name {
- color: #409eff;
- font-weight: bold;
- }
- .category-seq {
- color: #409eff;
- font-weight: bold;
- }
- .category-value {
- color: #606266;
- font-weight: normal;
- }
- }
- // 操作按钮样式
- .operation-buttons {
- display: flex;
- justify-content: center;
- gap: 5px;
- .el-button {
- padding: 5px;
- min-width: 24px;
- height: 24px;
- border-radius: 50%;
- background-color: #000;
- color: #fff;
- border: none;
- &:hover {
- background-color: #333;
- }
- i {
- font-size: 14px;
- }
- }
- }
- // 输入框样式
- ::v-deep .el-input__inner {
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- &:focus {
- border-color: #409eff;
- }
- }
- // 日期选择器样式
- ::v-deep .el-date-editor {
- width: 100%;
- }
- }
- </style>
|