| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- <script setup lang="ts">
- import { computed, nextTick, onMounted, reactive, ref } from 'vue'
- import { ElMessage } from 'element-plus'
- import type { FormInstance, FormRules } from 'element-plus'
- import EvidenceUpload from '../components/EvidenceUpload.vue'
- import { api } from '../api'
- import { blankEntry } from '../utils/entry'
- import { useUploads } from '../utils/uploads'
- import type { Attachment, Entry } from '../api/indexType'
- import type { WmsLedgerAdminSummaryResponse, WmsLedgerFlowVO, WmsReversalPreCheckResponse } from '../api/indexType'
- import { dateTime, fieldErrors, report, reversalLimit, refreshAfterWrite } from '../utils/ui'
- type LedgerEntry = Entry & { recordId?: number; flowType?: number; alreadyReversedQty: number; reversalState?: number; originFlowDetail?: string; relatedReversalFlows?: string[] }
- type LedgerDetail = WmsLedgerFlowVO
- const entries = ref<LedgerEntry[]>([])
- const pendingUploads = useUploads()
- const summary = ref<WmsLedgerAdminSummaryResponse>()
- async function loadSummary() {
- summary.value = undefined
- summary.value = await api.wmsApi.ledger.adminSummary()
- }
- const total = ref(0)
- const pageSize = 10
- const preCheck = ref<WmsReversalPreCheckResponse>()
- const reversalStates: Record<string, number> = { '未冲销': 0, '部分冲销': 1, '已全额冲销': 2 }
- function toEntry(item: LedgerDetail): LedgerEntry {
- const direction = item.flowType === 1 ? 'inbound' : item.flowType === 2 ? 'outbound'
- : item.reversalDirection === 1 ? 'inbound' : item.reversalDirection === 2 ? 'outbound'
- : (item.qty ?? 0) >= 0 ? 'inbound' : 'outbound'
- return {
- ...blankEntry(direction), id: item.flowNo || '', recordId: item.recordId, flowType: item.flowType,
- status: item.status === 1 ? 'completed' : 'draft', source: item.flowType === 3 || item.flowSource === 'REVERSAL' ? 'reversal' : 'normal',
- skuId: item.skuId || '', quantity: item.qty == null ? null : Math.abs(item.qty),
- alreadyReversedQty: item.alreadyReversedQty ?? 0, reversalState: item.reversalStatus,
- originalId: item.originFlowNo || '', createdAt: item.createTime || '', operator: item.updateUser || item.createUser || '',
- originFlowDetail: item.originFlowDetail,
- relatedReversalFlows: item.relatedReversalFlows,
- remark: item.reversalReason || item.remark || '', orderType: item.orderType === 1 ? 'internal' : item.orderType === 2 ? 'external' : '',
- so: item.soNo || '', company: item.expressCompany || '', tracking: item.expressNo || '',
- evidence: (item.attachments || []).map((file, index) => ({ id: String(file.id ?? index), url: file.fileUrl || '', name: file.fileName || '凭证' })),
- snapshot: { id: item.skuId || '', name: item.skuName || '', spec: item.spec || '', config: item.configDetail || '',
- categoryId: '', sportId: '', brandId: '', category: '', sport: '', brand: '', remark: '', enabled: true, createdAt: '', operator: '' },
- }
- }
- const loading = ref(false)
- let listLoadVersion = 0
- async function loadData() {
- const version = ++listLoadVersion
- loading.value = true
- try {
- const filter = applied.value
- const result = await api.wmsApi.ledger.flowList({
- pageNo: page.value,
- pageSize,
- status: 1,
- keyword: filter.keyword.trim() || undefined,
- flowType: filter.direction ? Number(filter.direction) : undefined,
- flowSource: filter.source || undefined, reversalStatus: reversalStates[filter.reversal],
- })
- if (version !== listLoadVersion) return
- entries.value = (result.rows as WmsLedgerFlowVO[]).map(toEntry)
- total.value = result.total
- }
- catch (error) { if (version === listLoadVersion) throw error }
- finally { if (version === listLoadVersion) loading.value = false }
- }
- const filters = reactive({ keyword: '', direction: '', reversal: '', source: '' })
- const applied = ref({ ...filters })
- const page = ref(1)
- const detail = ref<LedgerEntry>()
- const reverseDialog = ref(false)
- const original = ref<LedgerEntry>()
- const reverseQty = ref<number | null>(1)
- const reverseEvidence = ref<Attachment[]>([])
- const reverseRemark = ref('')
- const reverseFormRef = ref<FormInstance>()
- const reverseForm = computed(() => ({ quantity: reverseQty.value, evidence: reverseEvidence.value }))
- const reverseMax = computed(() => reversalLimit(preCheck.value, original.value?.flowType))
- const reverseRules = computed<FormRules>(() => ({
- quantity: [{ required: true, type: 'integer', min: 1, max: reverseMax.value, message: `冲销数量须为 1 至 ${reverseMax.value} 的整数`, trigger: 'change' }],
- evidence: [{ required: true, type: 'array', min: 1, message: '请上传照片 / 凭证', trigger: 'change' }],
- }))
- async function validateReverseEvidence() {
- await nextTick()
- void reverseFormRef.value?.validateField('evidence').catch(() => false)
- }
- const errors = ref<Record<string, string>>({})
- const busy = ref(false)
- const entrySku = (entry: Entry) => entry.snapshot
- const attachments = (entry: Entry) => [...entry.evidence, ...entry.orderEvidence, ...entry.screenshots]
- const remaining = (entry: LedgerEntry) => Number(entry.quantity) - entry.alreadyReversedQty
- const canReverse = (entry: LedgerEntry) => entry.status === 'completed' && entry.source === 'normal' && entry.reversalState !== 2 && remaining(entry) > 0
- const reversalStatus = (entry: LedgerEntry) => entry.source === 'reversal' ? '—' : entry.reversalState === 2 ? '已全额冲销' : entry.reversalState === 1 ? '部分冲销' : '未冲销'
- const directionName = (entry: Entry) => entry.direction === 'inbound' ? '入库' : '出库'
- onMounted(() => {
- loadData().catch(report)
- loadSummary().catch(report)
- })
- function filterRows() { applied.value = { ...filters }; page.value = 1; loadData().catch(report) }
- async function showDetail(entry: LedgerEntry) {
- try {
- if (entry.recordId == null || entry.flowType == null) throw new Error('接口未返回流水类型或记录 ID')
- const result = await api.wmsApi.ledger.flowDetail({ flowNo: entry.id, flowType: entry.flowType, recordId: entry.recordId })
- if (!result || typeof result !== 'object') throw new Error('流水详情格式不符合预期')
- detail.value = toEntry({ flowNo: entry.id, recordId: entry.recordId, flowType: entry.flowType, status: 1, ...result } as LedgerDetail)
- } catch (error) { report(error) }
- }
- async function openReverse(entry: LedgerEntry) {
- if (!canReverse(entry)) return
- try {
- preCheck.value = await api.wmsApi.reversal.preCheck({ originFlowNo: entry.id, originFlowType: entry.flowType }) as WmsReversalPreCheckResponse
- original.value = entry
- if (!reverseMax.value) throw new Error('当前无可冲销数量,或预检数据不完整,请刷新后重试')
- reverseQty.value = reverseMax.value; reverseEvidence.value = []; reverseRemark.value = ''
- errors.value = {}; detail.value = undefined; reverseDialog.value = true
- } catch (error) { report(error) }
- }
- async function submitReverse() {
- if (busy.value || pendingUploads.value || !original.value) return
- busy.value = true; errors.value = {}
- try {
- const valid = await reverseFormRef.value?.validate().catch(() => false)
- if (!valid) return
- await api.wmsApi.reversal.submit({ originFlowNo: original.value.id, originFlowType: original.value.flowType,
- qty: reverseQty.value ?? undefined, fileUrls: reverseEvidence.value.map(file => file.url),
- fileNames: reverseEvidence.value.map(file => file.name), reversalReason: reverseRemark.value })
- reverseDialog.value = false
- ElMessage.success('冲销成功')
- await refreshAfterWrite(() => Promise.all([loadData(), loadSummary()]))
- } catch (error) { await fieldErrors(error, errors) } finally { busy.value = false }
- }
- </script>
- <template>
- <div v-loading="loading" class="ledger-page">
- <div class="page-heading ledger-heading"><div><h1>库存台账</h1><p>只展示已完成流水;实际库存按已完成入库减已完成出库计算。</p></div><el-button @click="$router.push('/sku')">查看 SKU</el-button></div>
- <div class="ledger-stats"><article><span>当前查询范围</span><strong>{{ summary?.warehouseName ?? summary?.queryScope ?? '—' }}</strong></article><article><span>库存总记录</span><strong>{{ summary?.totalStockCount ?? '—' }} SKU</strong></article><article><span>今日变动流水</span><strong class="ledger-positive">{{ summary?.todayFlowCount ?? '—' }} 笔</strong></article></div>
- <el-config-provider :empty-values="[null, undefined]">
- <form class="ledger-filters" @submit.prevent="filterRows">
- <el-input v-model="filters.keyword" placeholder="skuID / 商品 / 订单号" aria-label="skuID / 商品名称 / 订单号" clearable />
- <el-select v-model="filters.direction" aria-label="出入库类型"><el-option label="出入库类型:全部" value="" /><el-option label="入库" value="1" /><el-option label="出库" value="2" /></el-select>
- <el-select model-value="completed" aria-label="单据状态"><el-option label="单据状态:已完成" value="completed" /></el-select>
- <el-select v-model="filters.reversal" aria-label="原流水状态"><el-option label="原流水状态:全部" value="" /><el-option v-for="value in ['未冲销', '部分冲销', '已全额冲销']" :key="value" :value="value" :label="value" /></el-select>
- <el-select v-model="filters.source" aria-label="流水来源"><el-option label="流水来源:全部" value="" /><el-option label="正常录入" value="NORMAL" /><el-option label="冲销" value="REVERSAL" /></el-select>
- <el-button native-type="submit">筛选</el-button>
- </form>
- </el-config-provider>
- <p class="ledger-note">“原流水状态”用于查看冲销进度;冲销流水自身显示为“—”,通过流水来源和原流水编号追溯。</p>
- <el-table :data="entries" row-key="id" class="ledger-table" empty-text="暂无已完成流水">
- <el-table-column label="流水编号" width="108"><template #default="{ row }"><b class="ledger-code">{{ row.id }}</b></template></el-table-column>
- <el-table-column label="创建时间" width="164"><template #default="{ row }">{{ dateTime(row.createdAt) }}</template></el-table-column>
- <el-table-column label="入 / 出库" width="82"><template #default="{ row }">{{ directionName(row) }}</template></el-table-column>
- <el-table-column label="单据状态" width="96"><template #default><span class="ledger-pill">已完成</span></template></el-table-column>
- <el-table-column label="原流水状态" width="110"><template #default="{ row }"><span v-if="row.source === 'normal'" class="ledger-pill" :class="{ warning: reversalStatus(row) === '部分冲销', muted: reversalStatus(row) === '已全额冲销' }">{{ reversalStatus(row) }}</span><span v-else>—</span></template></el-table-column>
- <el-table-column label="来源" width="104"><template #default="{ row }"><span class="ledger-pill blue">{{ row.source === 'normal' ? '正常录入' : '冲销' }}</span></template></el-table-column>
- <el-table-column label="skuID / 商品" min-width="270"><template #default="{ row }"><strong class="ledger-product">{{ row.skuId }} · {{ entrySku(row)?.name }}</strong></template></el-table-column>
- <el-table-column prop="quantity" label="数量" width="58" />
- <el-table-column label="库存变动" width="82"><template #default="{ row }"><b :class="row.direction === 'inbound' ? 'ledger-positive' : 'ledger-negative'">{{ row.direction === 'inbound' ? '+' : '−' }} {{ row.quantity }}</b></template></el-table-column>
- <el-table-column label="关联原流水" width="110"><template #default="{ row }"><span class="ledger-code">{{ row.originalId || '—' }}</span></template></el-table-column>
- <el-table-column label="操作" fixed="right" width="152"><template #default="{ row }"><el-button link type="primary" @click="showDetail(row)">详情</el-button><el-button v-if="canReverse(row)" link type="primary" @click="openReverse(row)">冲销 / 更正</el-button></template></el-table-column>
- </el-table>
- <el-pagination v-model:current-page="page" :total="total" :page-size="pageSize" layout="total, prev, pager, next" @current-change="loadData().catch(report)" />
- <el-dialog :model-value="!!detail" class="ledger-dialog" modal-class="ledger-overlay" width="760px" align-center @close="detail = undefined">
- <template #header="{ titleId, titleClass }"><h2 :id="titleId" :class="titleClass">流水详情 · {{ detail?.id }}</h2><p v-if="detail" class="ledger-subtitle">已完成 · 原流水状态:{{ reversalStatus(detail) }} · 创建时间:{{ dateTime(detail.createdAt) }}</p></template>
- <template v-if="detail">
- <div class="ledger-grid ledger-detail-fields">
- <div><label>skuID / 商品</label><div class="ledger-readonly">{{ detail.skuId }} · {{ entrySku(detail)?.name }}</div></div>
- <div><label>库存变动</label><div class="ledger-readonly">{{ directionName(detail) }} {{ detail.direction === 'inbound' ? '+' : '−' }}{{ detail.quantity }}</div></div>
- <div><label>{{ directionName(detail) }}数量</label><div class="ledger-readonly">{{ detail.quantity }} {{ entrySku(detail)?.spec }}</div></div>
- <div v-if="detail.source === 'normal' && detail.direction === 'outbound'"><label>订单类型</label><div class="ledger-readonly">{{ detail.orderType === 'internal' ? '内部订单' : '外部订单' }}</div></div>
- </div>
- <template v-if="detail.source === 'normal' && detail.orderType === 'internal'"><div class="ledger-evidence-label">内部订单追溯信息</div><div class="ledger-evidence">内部订单:{{ detail.so }}</div></template>
- <template v-else>
- <div class="ledger-evidence-label">照片 / 凭证</div>
- <div class="ledger-evidence"><span v-if="!attachments(detail).length">暂无凭证</span><div v-for="(file, index) in attachments(detail)" :key="file.id" class="ledger-evidence-item"><el-image :src="file.url" :preview-src-list="attachments(detail).map(item => item.url)" :initial-index="index" preview-teleported fit="cover" /></div><span v-if="detail.tracking">{{ detail.company }} · 快递单号 {{ detail.tracking }}</span></div>
- </template>
- <div v-if="detail.remark" class="ledger-related">备注 / 冲销原因:{{ detail.remark }}</div>
- <div v-if="detail.originFlowDetail">
- <div class="ledger-evidence-label">关联原流水</div>
- <div class="ledger-readonly">{{ detail.originFlowDetail }}</div>
- </div>
- <div v-if="detail.source === 'normal' && detail.relatedReversalFlows?.length" class="ledger-related-reversals">
- <div class="ledger-evidence-label">关联冲销流水</div>
- <div class="ledger-related-reversal-list">
- <div v-for="flow in detail.relatedReversalFlows" :key="flow" class="ledger-related-reversal-item">{{ flow }}</div>
- </div>
- </div>
- </template>
- <template #footer><el-button @click="detail = undefined">关闭</el-button><el-button v-if="detail && canReverse(detail)" type="warning" plain @click="openReverse(detail)">冲销 / 更正</el-button></template>
- </el-dialog>
- <el-dialog v-model="reverseDialog" class="ledger-dialog" modal-class="ledger-overlay" width="548px" align-center :close-on-click-modal="false" :close-on-press-escape="!busy" :show-close="!busy" @closed="reverseFormRef?.clearValidate()">
- <template #header="{ titleId, titleClass }"><h2 :id="titleId" :class="titleClass">冲销 / 更正</h2><p class="ledger-subtitle">将生成与原流水方向相反的新流水,原记录不会被删除</p></template>
- <template v-if="original">
- <el-alert class="ledger-reverse-notice" type="warning" :closable="false" show-icon :title="`原流水:${original.id} · 剩余可冲销数量 ${preCheck?.remainReversalQty ?? '—'}。冲销完成后,请另行录入正确的出入库单。`" />
- <el-alert v-if="errors.form" :title="errors.form" type="error" :closable="false" />
- <el-form ref="reverseFormRef" :model="reverseForm" :rules="reverseRules" label-position="top" :disabled="busy || pendingUploads > 0">
- <div class="ledger-grid"><el-form-item label="冲销方向"><el-input :model-value="original.direction === 'inbound' ? '出库(反向生成)' : '入库(反向生成)'" disabled /></el-form-item><el-form-item label="冲销数量" prop="quantity" required :error="errors.quantity"><el-input-number v-model="reverseQty" :controls="false" :min="1" :max="reverseMax" :precision="0" /></el-form-item></div>
- <p v-if="original.direction === 'inbound'" class="ledger-stock-note">当前可用库存:{{ preCheck?.currentStock ?? '—' }} {{ entrySku(original)?.spec }}</p>
- <el-form-item label="照片 / 凭证" prop="evidence" required :error="errors.evidence"><EvidenceUpload :active="reverseDialog" :disabled="busy" v-model="reverseEvidence" @update:model-value="validateReverseEvidence" /></el-form-item>
- <el-form-item label="冲销原因"><el-input v-model="reverseRemark" type="textarea" :rows="3" placeholder="选填:说明冲销原因" /></el-form-item>
- </el-form>
- </template>
- <template #footer><el-button :disabled="busy" @click="reverseDialog = false">取消</el-button><el-button type="primary" :loading="busy" :disabled="pendingUploads > 0" @click="submitReverse">提交冲销</el-button></template>
- </el-dialog>
- </div>
- </template>
- <style scoped>
- .ledger-heading { margin-bottom: 18px; }
- .ledger-heading h1 { font-size: 24px; letter-spacing: 0; }
- .ledger-heading p { margin-top: 7px; color: #7c8c92; font-size: 12px; }
- .ledger-heading > .el-button { height: 34px; border-radius: 8px; }
- .ledger-stats { display: grid; grid-template-columns: 1.15fr 1fr 1fr; gap: 12px; margin-bottom: 14px; }
- .ledger-stats article { padding: 16px; border: 1px solid #e5ebe7; border-radius: 8px; background: #fffefb; box-shadow: 0 10px 24px #233b2d06; }
- .ledger-stats span { display: block; margin-bottom: 6px; color: #829095; font-size: 11px; }
- .ledger-stats strong { font-size: 22px; line-height: 26px; }
- .ledger-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px; border: 1px solid #e5ebe7; background: #fffefb; border-radius: 8px; }
- .ledger-filters > * { flex: 1 1 0; }
- .ledger-filters > .el-button { flex: 0 0 auto; }
- .ledger-filters > .ledger-search { flex: 1 1 260px; }
- .ledger-search :deep(.el-input__wrapper) { min-height: 36px; border-radius: 8px; }
- .ledger-filter-break { flex-basis: 100%; width: 0; height: 0; }
- .ledger-filters > :nth-child(8) { flex-grow: 1.35; }
- .ledger-filters > * { min-width: 0; }
- .ledger-note { font-size: 11px; color: #829095; line-height: 1.6; margin: 12px 4px; }
- .ledger-pill { display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 20px; background: #e4f5ee; color: #218570; font-size: 10px; line-height: 14px; white-space: nowrap; font-weight: 600; }
- .ledger-pill::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: currentColor; }
- .ledger-pill.warning { background: #fff1d4; color: #ad751c; }
- .ledger-pill.muted { background: #eef1f0; color: #74837f; }
- .ledger-pill.blue { background: #e8f2fc; color: #4685b5; }
- .ledger-positive { color: #17836d; }
- .ledger-negative { color: #dc685d; }
- .ledger-table { --el-table-header-bg-color: #f6f8f6; --el-table-border-color: #edf1ed; --el-table-header-text-color: #819095; --el-table-text-color: #5c6e74; border: 1px solid #e8ede8; border-radius: 8px; box-shadow: 0 15px 30px #233b2d08; }
- .ledger-table :deep(th.el-table__cell) { height: 36px; font-size: 10px; }
- .ledger-table :deep(td.el-table__cell) { height: 47px; font-size: 11px; }
- .ledger-table :deep(.cell) { padding: 0 11px; }
- .ledger-table :deep(.el-button) { font-size: 11px; }
- .ledger-table :deep(.el-button + .el-button) { margin-left: 10px; }
- .ledger-code { color: #486671; font-size: 10px; }
- .ledger-product { color: #26383e; overflow-wrap: anywhere; }
- .ledger-subtitle { margin: 5px 0 0; font-size: 12px; color: #84969c; line-height: 1.6; }
- .ledger-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 14px; }
- .ledger-detail-fields { gap: 16px 14px; }
- .ledger-detail-fields label, .ledger-evidence-label { display: block; font-size: 12px; font-weight: 600; color: #556d74; margin-bottom: 6px; }
- .ledger-readonly { min-height: 38px; padding: 8px 10px; border: 1px solid #dce5e1; border-radius: 7px; background: #f2f6f4; color: #80969d; font-size: 14px; line-height: 20px; overflow-wrap: anywhere; }
- .ledger-evidence-label { margin-top: 16px; }
- .ledger-evidence { display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: 10px; padding: 15px; min-height: 76px; border: 1px dashed #bdddd3; border-radius: 7px; background: #f1faf6; color: #458e7c; font-size: 12px; overflow-wrap: anywhere; }
- .ledger-evidence-item { display: flex; align-items: center; gap: 8px; max-width: 100%; }
- .ledger-evidence-item .el-image { width: 44px; height: 40px; border-radius: 4px; flex-shrink: 0; cursor: zoom-in; }
- .ledger-related { margin-top: 16px; overflow-wrap: anywhere; }
- .ledger-related-reversal-list { padding: 4px 10px; border: 1px solid #dce5e1; border-radius: 7px; background: #f2f6f4; }
- .ledger-related-reversal-item { min-height: 28px; padding: 4px 0; box-sizing: border-box; color: #80969d; font-size: 14px; line-height: 20px; overflow-wrap: anywhere; }
- .ledger-stock-note { font-size: 12px; color: #7b8d91; margin: 0 0 14px; }
- @media (max-width: 1100px) { .ledger-filters > * { flex-basis: calc(33.333% - 8px); } .ledger-filters > :nth-child(8) { flex-grow: 1; } }
- @media (max-width: 600px) { .ledger-heading { align-items: flex-start; gap: 12px; } .ledger-heading h1 { font-size: 22px; } .ledger-stats { grid-template-columns: minmax(0, 1fr); } .ledger-filters > * { flex-basis: calc(50% - 8px); } .ledger-filters > .ledger-search { flex-basis: 100%; } .ledger-grid { grid-template-columns: minmax(0, 1fr); } }
- </style>
- <style>
- .ledger-overlay { backdrop-filter: blur(3px); background: #1c2f3566; }
- .el-dialog.ledger-dialog { padding: 0; max-width: calc(100vw - 32px); border-radius: 16px; overflow: hidden; background: #fffefb; box-shadow: 0 28px 70px #12252233; }
- .ledger-dialog .el-dialog__header { padding: 20px 22px 14px; margin: 0; border-bottom: 1px solid #dfe7e3; }
- .ledger-dialog .el-dialog__title { margin: 0; padding-right: 32px; font-size: 18px; font-weight: 700; color: #1c3039; line-height: 26px; }
- .ledger-dialog .el-dialog__headerbtn { top: 24px; right: 22px; width: 28px; height: 28px; border-radius: 7px; background: #eef3f1; }
- .ledger-dialog .el-dialog__body { padding: 22px; max-height: calc(100dvh - 220px); overflow-y: auto; }
- .ledger-dialog .el-form-item { margin-bottom: 16px; }
- .ledger-dialog .el-form-item__label { font-size: 12px; font-weight: 600; color: #566d73; margin-bottom: 5px; line-height: 18px; }
- .ledger-dialog .el-input__wrapper { min-height: 36px; border-radius: 7px; box-shadow: 0 0 0 1px #dce5e1 inset; }
- .ledger-dialog .el-input.is-disabled .el-input__wrapper { background: #f2f6f4; }
- .ledger-dialog .el-input.is-disabled .el-input__inner { -webkit-text-fill-color: #82959c; }
- .ledger-dialog .el-input-number { width: 100%; }
- .ledger-dialog .el-input-number .el-input__inner { text-align: left; }
- .ledger-dialog .el-dialog__footer { border-top: 1px solid #dfe7e3; padding: 14px 22px; }
- .ledger-dialog .el-dialog__footer .el-button { height: 36px; border-radius: 8px; }
- .ledger-dialog .el-alert { margin-bottom: 18px; }
- .ledger-dialog .ledger-reverse-notice { border: 1px solid #ffe0a5; background: #fffaec; }
- .ledger-dialog .ledger-reverse-notice .el-alert__title { font-size: 12px; line-height: 1.6; }
- .ledger-dialog .evidence { width: 100%; }
- .ledger-dialog .upload-button { display: flex; justify-content: center; align-items: center; gap: 7px; width: 100%; min-height: 68px; box-sizing: border-box; border: 1px dashed #bdddd3; border-radius: 7px; background: #f1faf6; color: #458e7c; font-size: 12px; }
- </style>
|