借库逻辑实现
This commit is contained in:
@ -92,20 +92,19 @@
|
||||
<span v-else class="text-placeholder">-</span>
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop === 'qty_stock'">
|
||||
<span class="stock-num">{{ scope.row.qty_stock }}</span>
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop === 'qty_available'">
|
||||
<span class="avail-num">{{ scope.row.qty_available }}</span>
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop === 'status'">
|
||||
<el-tag :type="getStatusType(scope.row.status)" effect="light" round>
|
||||
{{ scope.row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop === 'qty_stock'">
|
||||
<span class="stock-num">{{ scope.row.qty_stock }}</span>
|
||||
</template>
|
||||
<template #default="scope" v-else-if="col.prop === 'qty_available'">
|
||||
<span class="avail-num">{{ scope.row.qty_available }}</span>
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="['arrival_photo', 'inspection_report'].includes(col.prop)">
|
||||
<div v-if="getImagesOnly(scope.row[col.prop]).length > 0" style="display: flex; align-items: center; justify-content: center;">
|
||||
<el-image
|
||||
@ -128,12 +127,8 @@
|
||||
</template>
|
||||
|
||||
<template #default="scope" v-else-if="col.prop.includes('link')">
|
||||
<el-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank"
|
||||
:underline="false">
|
||||
<el-icon>
|
||||
<Link/>
|
||||
</el-icon>
|
||||
查看
|
||||
<el-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank" :underline="false">
|
||||
<el-icon><Link/></el-icon> 查看
|
||||
</el-link>
|
||||
</template>
|
||||
|
||||
@ -146,10 +141,7 @@
|
||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="warning" size="default" @click="handlePrint(row)">
|
||||
<el-icon>
|
||||
<Printer/>
|
||||
</el-icon>
|
||||
打印
|
||||
<el-icon><Printer/></el-icon> 打印
|
||||
</el-button>
|
||||
<el-button link type="primary" size="default" @click="handleUpdate(row)">编辑</el-button>
|
||||
<el-popconfirm title="确定删除该条记录吗?不可恢复。" @confirm="handleDelete(row)" width="220">
|
||||
@ -234,10 +226,8 @@
|
||||
<div class="read-only-grid">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8"><el-form-item label="名称"><el-input v-model="form.material_name" disabled class="is-text-view"/></el-form-item></el-col>
|
||||
|
||||
<el-col :span="8"><el-form-item label="类型"><el-input v-model="form.material_type" disabled class="is-text-view"/></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="类别"><el-input v-model="form.category" disabled class="is-text-view"/></el-form-item></el-col>
|
||||
|
||||
<el-col :span="8"><el-form-item label="规格型号"><el-input v-model="form.spec_model" disabled class="is-text-view"/></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="单位"><el-input v-model="form.unit" disabled class="is-text-view"/></el-form-item></el-col>
|
||||
</el-row>
|
||||
@ -273,7 +263,7 @@
|
||||
<el-radio-button label="batch">按批号入库 (Batch)</el-radio-button>
|
||||
<el-radio-button label="serial">按序列号入库 (SN)</el-radio-button>
|
||||
</el-radio-group>
|
||||
<span v-if="modeLocked" class="locked-msg"><el-icon><Lock/></el-icon> 历史锁定</span>
|
||||
<span v-if="modeLocked" class="locked-msg"><el-icon><Lock/></el-icon> 历史锁定 (同物料遵循历史模式)</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
@ -385,7 +375,9 @@
|
||||
</el-dialog>
|
||||
|
||||
<input type="file" ref="cameraInputRef" accept="image/*" capture="environment" style="display: none" @change="handleCameraFile"/>
|
||||
|
||||
<el-dialog v-model="dialogVisibleImage" append-to-body width="50%"><img style="width: 100%" :src="dialogImageUrl" alt="Preview Image" /></el-dialog>
|
||||
|
||||
<el-dialog v-model="printVisible" title="标签打印预览" width="400px" destroy-on-close append-to-body>
|
||||
<div style="text-align: center;">
|
||||
<div v-loading="printLoading" class="preview-box">
|
||||
@ -455,23 +447,20 @@ const inspection_report_url = ref('')
|
||||
// 基础列
|
||||
const baseColumns = [
|
||||
{prop: 'material_name', label: '名称'},
|
||||
{prop: 'material_type', label: '类型'}, // 移到类别前面
|
||||
{prop: 'material_type', label: '类型'},
|
||||
{prop: 'category', label: '类别'},
|
||||
{prop: 'spec_model', label: '规格型号'},
|
||||
{prop: 'unit', label: '单位'},
|
||||
]
|
||||
|
||||
// [修改] 库存与商务列配置:将序列号/批号改为 "序列号/批号"
|
||||
// 库存与商务列
|
||||
const stockColumns = [
|
||||
{prop: 'id', label: 'ID', minWidth: '60'},
|
||||
{prop: 'base_id', label: 'BaseID', minWidth: '80'},
|
||||
{prop: 'sku', label: 'SKU', minWidth: '120'},
|
||||
{prop: 'inbound_date', label: '入库日期', minWidth: '120'},
|
||||
{prop: 'barcode', label: '条码', minWidth: '120'},
|
||||
|
||||
// 新的合并列,修改 label 为 "序列号/批号"
|
||||
{prop: 'sn_bn', label: '序列号/批号', minWidth: '160'},
|
||||
|
||||
{prop: 'status', label: '状态', minWidth: '100'},
|
||||
{prop: 'inspection_status', label: '到检', minWidth: '100'},
|
||||
{prop: 'qty_inbound', label: '入库量', minWidth: '100'},
|
||||
@ -492,11 +481,8 @@ const stockColumns = [
|
||||
]
|
||||
|
||||
const allColumns = [...baseColumns, ...stockColumns]
|
||||
// [修改] 更新 key 以强制用户获取新默认值
|
||||
const STORAGE_KEY_COLS = 'stock_buy_visible_columns_v2'
|
||||
|
||||
// [修改] 默认列配置:加入 'sn_bn' 和 'warehouse_loc'
|
||||
// 同时这里也要对应上方的顺序变化,先 material_type 后 category
|
||||
const defaultColumns = [
|
||||
'material_name', 'material_type', 'category', 'spec_model', 'unit',
|
||||
'inbound_date', 'sn_bn', 'warehouse_loc', 'status', 'inspection_status',
|
||||
@ -516,7 +502,7 @@ const form = reactive({
|
||||
arrival_photo: [] as string[], inspection_report: [] as string[]
|
||||
})
|
||||
|
||||
// ... (以下逻辑保持不变)
|
||||
// 历史记录辅助函数
|
||||
const HISTORY_KEYS = { SUPPLIER: 'history_suppliers', PURCHASER: 'history_purchasers', EMAIL: 'history_emails', MATERIAL: 'history_materials' }
|
||||
const saveToHistory = (key: string, value: string) => {
|
||||
if (!value) return
|
||||
@ -595,15 +581,19 @@ const onMaterialSelected = (val: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// 校验规则
|
||||
// ------------------------------------
|
||||
const validateUnique = (rule: any, value: string, callback: any) => {
|
||||
if (!value) return callback()
|
||||
// 前端仅做当前页面的简单重复提示,真正的校验在后端
|
||||
const isDuplicate = tableData.value.some((row: any) => {
|
||||
if (dialogStatus.value === 'update' && row.id === form.id) return false
|
||||
if (rule.field === 'serial_number' && row.serial_number === value) return true
|
||||
if (rule.field === 'batch_number' && row.batch_number === value) return true
|
||||
if (rule.field === 'batch_number' && row.batch_number === value && row.base_id === form.base_id) return true
|
||||
return false
|
||||
})
|
||||
if (isDuplicate) callback(new Error('编号重复'))
|
||||
if (isDuplicate) callback(new Error('当前列表页存在相同编号(后端将进行全局校验)'))
|
||||
else callback()
|
||||
}
|
||||
const validateIdentity = (rule: any, value: any, callback: any) => {
|
||||
@ -618,26 +608,54 @@ const rules = {
|
||||
batch_number: [{validator: validateIdentity, trigger: 'blur'}, {validator: validateUnique, trigger: 'blur'}]
|
||||
}
|
||||
|
||||
// 自动计算批号逻辑
|
||||
const checkHistoryAndSetMode = async (baseId: number) => {
|
||||
try {
|
||||
const res: any = await getBuyList({page: 1, pageSize: 1000})
|
||||
const res: any = await getBuyList({page: 1, pageSize: 1000}) // 获取最近数据
|
||||
const historyItems = (res.data.items || []).filter((item: any) => item.base_id === baseId)
|
||||
|
||||
if (historyItems.length > 0) {
|
||||
modeLocked.value = true
|
||||
// 找最新的那条记录
|
||||
const latest = historyItems.sort((a: any, b: any) => b.id - a.id)[0]
|
||||
if (latest.serial_number) { entryMode.value = 'serial'; form.serial_number = ''; form.batch_number = '' }
|
||||
else { entryMode.value = 'batch'; form.serial_number = ''; form.batch_number = incrementBatchNumber(latest.batch_number || '000000') }
|
||||
} else { modeLocked.value = false; entryMode.value = 'batch'; form.batch_number = '000001' }
|
||||
if (formRef.value) { formRef.value.clearValidate('serial_number'); formRef.value.clearValidate('batch_number') }
|
||||
} catch (e) { modeLocked.value = false; entryMode.value = 'batch'; form.batch_number = '000001' }
|
||||
if (latest.serial_number) {
|
||||
entryMode.value = 'serial'
|
||||
form.serial_number = ''
|
||||
form.batch_number = ''
|
||||
} else {
|
||||
entryMode.value = 'batch'
|
||||
form.serial_number = ''
|
||||
// 自动递增批号
|
||||
form.batch_number = incrementBatchNumber(latest.batch_number || '000000')
|
||||
}
|
||||
} else {
|
||||
modeLocked.value = false
|
||||
entryMode.value = 'batch'
|
||||
form.batch_number = '000001'
|
||||
}
|
||||
if (formRef.value) {
|
||||
formRef.value.clearValidate('serial_number')
|
||||
formRef.value.clearValidate('batch_number')
|
||||
}
|
||||
} catch (e) {
|
||||
modeLocked.value = false
|
||||
entryMode.value = 'batch'
|
||||
form.batch_number = '000001'
|
||||
}
|
||||
}
|
||||
const incrementBatchNumber = (batchStr: string) => {
|
||||
if (!batchStr || !/^\d+$/.test(batchStr)) return '000001'
|
||||
return (parseInt(batchStr, 10) + 1).toString().padStart(6, '0')
|
||||
}
|
||||
const handleEntryModeChange = (val: string) => {
|
||||
if (val === 'batch') { form.serial_number = ''; form.batch_number = '000001'; if(formRef.value) formRef.value.clearValidate('serial_number') }
|
||||
else { form.batch_number = ''; if(formRef.value) formRef.value.clearValidate('batch_number') }
|
||||
if (val === 'batch') {
|
||||
form.serial_number = ''
|
||||
form.batch_number = '000001'
|
||||
if(formRef.value) formRef.value.clearValidate('serial_number')
|
||||
} else {
|
||||
form.batch_number = ''
|
||||
if(formRef.value) formRef.value.clearValidate('batch_number')
|
||||
}
|
||||
}
|
||||
watch(() => [form.in_quantity, form.unit_price], () => { form.total_price = Number((form.in_quantity * form.unit_price).toFixed(4)) })
|
||||
|
||||
@ -688,6 +706,46 @@ const handleUpdate = (row: any) => {
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// 提交逻辑
|
||||
// ------------------------------------
|
||||
const submitForm = async () => {
|
||||
if (!formRef.value) return
|
||||
await formRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
submitting.value = true
|
||||
const finalReportList = [...form.inspection_report]
|
||||
if (inspection_report_url.value && !finalReportList.includes(inspection_report_url.value)) finalReportList.push(inspection_report_url.value)
|
||||
const onlyImages = finalReportList.filter(item => !isExternalLink(item))
|
||||
if (inspection_report_url.value) onlyImages.push(inspection_report_url.value)
|
||||
const payload = { ...form, inspection_report: onlyImages, in_quantity: Number(form.in_quantity), unit_price: Number(form.unit_price) }
|
||||
try {
|
||||
if (dialogStatus.value === 'create') {
|
||||
const res: any = await createBuyInbound(payload)
|
||||
ElMessage.success('入库成功')
|
||||
if (res.data) {
|
||||
ElMessage.info('发送打印指令...')
|
||||
try { await executePrint(res.data); ElMessage.success('打印指令已发送') }
|
||||
catch (printErr: any) { ElMessage.warning('打印失败:' + (printErr.msg || '未知错误')) }
|
||||
}
|
||||
} else { await updateBuyInbound(form.id!, payload); ElMessage.success('更新成功') }
|
||||
|
||||
// 成功后保存历史记录
|
||||
saveToHistory(HISTORY_KEYS.SUPPLIER, form.supplier_name)
|
||||
saveToHistory(HISTORY_KEYS.PURCHASER, form.purchaser)
|
||||
saveToHistory(HISTORY_KEYS.EMAIL, form.purchaser_email)
|
||||
|
||||
await fetchData()
|
||||
visible.value = false
|
||||
} catch (e: any) {
|
||||
// 重点:捕获后端唯一性校验错误
|
||||
ElMessage.error(e.msg || '操作失败')
|
||||
} finally { submitting.value = false }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 其他辅助函数保持不变
|
||||
const getImageUrl = (url: string) => { return !url ? '' : (url.startsWith('http') ? url : url) }
|
||||
const isExternalLink = (str: string) => { return str && (str.startsWith('http://') || str.startsWith('https://')) && !str.includes('/api/v1/common/files') }
|
||||
const getImagesOnly = (list: string[]) => { return !list ? [] : list.filter(item => !isExternalLink(item)) }
|
||||
@ -740,33 +798,6 @@ const handleCameraFile = async (event: Event) => {
|
||||
} catch (e) { ElMessage.error('网络错误,上传失败') } finally { loadingMsg.close(); input.value = '' }
|
||||
}
|
||||
}
|
||||
|
||||
const submitForm = async () => {
|
||||
if (!formRef.value) return
|
||||
await formRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
submitting.value = true
|
||||
const finalReportList = [...form.inspection_report]
|
||||
if (inspection_report_url.value && !finalReportList.includes(inspection_report_url.value)) finalReportList.push(inspection_report_url.value)
|
||||
const onlyImages = finalReportList.filter(item => !isExternalLink(item))
|
||||
if (inspection_report_url.value) onlyImages.push(inspection_report_url.value)
|
||||
const payload = { ...form, inspection_report: onlyImages, in_quantity: Number(form.in_quantity), unit_price: Number(form.unit_price) }
|
||||
try {
|
||||
if (dialogStatus.value === 'create') {
|
||||
const res: any = await createBuyInbound(payload)
|
||||
ElMessage.success('入库成功')
|
||||
if (res.data) {
|
||||
ElMessage.info('发送打印指令...')
|
||||
try { await executePrint(res.data); ElMessage.success('打印指令已发送') }
|
||||
catch (printErr: any) { ElMessage.warning('打印失败:' + (printErr.msg || '未知错误')) }
|
||||
}
|
||||
} else { await updateBuyInbound(form.id!, payload); ElMessage.success('更新成功') }
|
||||
saveToHistory(HISTORY_KEYS.SUPPLIER, form.supplier_name); saveToHistory(HISTORY_KEYS.PURCHASER, form.purchaser); saveToHistory(HISTORY_KEYS.EMAIL, form.purchaser_email)
|
||||
await fetchData(); visible.value = false
|
||||
} catch (e: any) { ElMessage.error(e.msg || '操作失败') } finally { submitting.value = false }
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleDelete = async (row: any) => { try { await deleteBuyInbound(row.id); ElMessage.success('删除成功'); fetchData() } catch (e) { ElMessage.error('删除失败') } }
|
||||
const handlePrint = async (row: any) => {
|
||||
printVisible.value = true; printLoading.value = true; previewUrl.value = ''
|
||||
@ -786,6 +817,7 @@ onMounted(() => fetchData())
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式部分保持不变,直接复用原有代码 */
|
||||
.buy-module { background: #f5f7fa; padding: 20px; min-height: 100vh; }
|
||||
.header-tools { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; background: #fff; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); }
|
||||
.left-tools { display: flex; gap: 10px; align-items: center; flex: 1; }
|
||||
|
||||
@ -425,9 +425,24 @@ const form = reactive({
|
||||
quality_report_link: [] as string[], inspection_report_link: [] as string[], product_photo: [] as string[], detail_link: ''
|
||||
})
|
||||
|
||||
// ------------------------------------
|
||||
// 校验规则 (前端 pre-check)
|
||||
// ------------------------------------
|
||||
const validateUnique = (rule: any, value: string, callback: any) => {
|
||||
if (!value) return callback()
|
||||
// 简单的列表前端查重
|
||||
const isDuplicate = tableData.value.some((row: any) => {
|
||||
if (dialogStatus.value === 'update' && row.id === form.id) return false
|
||||
if (rule.field === 'serial_number' && row.serial_number === value) return true
|
||||
return false
|
||||
})
|
||||
if (isDuplicate) callback(new Error('当前列表页存在相同SN(后端将进行全局校验)'))
|
||||
else callback()
|
||||
}
|
||||
|
||||
const rules = {
|
||||
base_id: [{ required: true, message: '必选', trigger: 'change' }],
|
||||
serial_number: [{ required: true, message: '必填', trigger: 'blur' }],
|
||||
serial_number: [{ required: true, message: '必填', trigger: 'blur' }, { validator: validateUnique, trigger: 'blur' }],
|
||||
in_quantity: [{ required: true, message: '必填', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
@ -585,7 +600,10 @@ const submitForm = async () => {
|
||||
} else { await updateProductInbound(form.id!, payload); ElMessage.success('更新成功') }
|
||||
saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, form.production_manager)
|
||||
visible.value = false; fetchData()
|
||||
} catch(e:any) { ElMessage.error(e.msg || '失败') } finally { submitting.value = false }
|
||||
} catch(e:any) {
|
||||
// 捕获后端报错
|
||||
ElMessage.error(e.msg || '操作失败')
|
||||
} finally { submitting.value = false }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -611,10 +611,11 @@ const validateUnique = (rule: any, value: string, callback: any) => {
|
||||
const isDuplicate = tableData.value.some((row: any) => {
|
||||
if (dialogStatus.value === 'update' && row.id === form.id) return false
|
||||
if (rule.field === 'serial_number' && row.serial_number === value) return true
|
||||
if (rule.field === 'batch_number' && row.batch_number === value) return true
|
||||
// 批号校验需要同时匹配物料
|
||||
if (rule.field === 'batch_number' && row.batch_number === value && row.base_id === form.base_id) return true
|
||||
return false
|
||||
})
|
||||
if (isDuplicate) callback(new Error('编号重复'))
|
||||
if (isDuplicate) callback(new Error('当前列表页存在相同编号(后端将进行全局校验)'))
|
||||
else callback()
|
||||
}
|
||||
const validateIdentity = (rule: any, value: any, callback: any) => {
|
||||
@ -778,7 +779,10 @@ const submitForm = async () => {
|
||||
} else { await updateSemiInbound(form.id!, payload); ElMessage.success('更新成功') }
|
||||
saveToHistory(HISTORY_KEYS.PRODUCTION_MANAGER, form.production_manager)
|
||||
await fetchData(); visible.value = false
|
||||
} catch (e: any) { ElMessage.error(e.msg || '操作失败') } finally { submitting.value = false }
|
||||
} catch (e: any) {
|
||||
// 捕获后端报错
|
||||
ElMessage.error(e.msg || '操作失败')
|
||||
} finally { submitting.value = false }
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -822,12 +826,8 @@ onMounted(() => fetchData())
|
||||
.card-title .sub-title { font-size: 12px; color: #909399; font-weight: normal; margin-left: 10px; }
|
||||
.card-content { padding: 20px; }
|
||||
.basic-card { border-left: 4px solid #409EFF; }
|
||||
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
|
||||
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background-color: #f5f7fa; border-bottom: 1px solid #dcdfe6; border-radius: 0; padding-left: 0; }
|
||||
.is-text-view :deep(.el-input__inner) { color: #606266; font-weight: 500; }
|
||||
.inbound-card { border-left: 4px solid #67C23A; }
|
||||
.production-card { border-left: 4px solid #E6A23C; }
|
||||
.production-card .card-title .icon { color: #E6A23C; }
|
||||
.production-card { border-left: 4px solid #E6A23C; } .production-card .card-title .icon { color: #E6A23C; }
|
||||
.identity-panel { background: #fffbf0; border: 1px dashed #e6a23c; border-radius: 6px; padding: 15px; margin-bottom: 20px; }
|
||||
.custom-radio-group { margin-bottom: 10px; }
|
||||
.locked-msg { font-size: 12px; color: #e6a23c; margin-left: 15px; }
|
||||
@ -839,16 +839,12 @@ onMounted(() => fetchData())
|
||||
.divider-text::before { margin-right: 15px; }
|
||||
.divider-text::after { margin-left: 15px; }
|
||||
.dialog-footer { display: flex; justify-content: flex-end; gap: 15px; margin-top: 20px; padding: 20px; border-top: 1px solid #ebeef5; }
|
||||
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center;}
|
||||
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center; }
|
||||
.opt-name { font-weight: bold; }
|
||||
.opt-spec { color: #8492a6; font-size: 13px; margin-right: 10px; }
|
||||
.total-price-input :deep(.el-input__inner) { color: #F56C6C; font-weight: bold; }
|
||||
.preview-box { min-height: 150px; display: flex; justify-content: center; align-items: center; background: #f5f7fa; border-radius: 4px; }
|
||||
.empty-preview { color: #909399; }
|
||||
.more-images-badge { margin-left: 5px; background: #909399; color: #fff; border-radius: 10px; padding: 0 6px; font-size: 12px; }
|
||||
.clickable-text { color: #409EFF; cursor: pointer; font-weight: 500; text-decoration: underline; }
|
||||
.clickable-text:hover { color: #66b1ff; }
|
||||
/* Scroll container specific to Product style */
|
||||
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background-color: #f5f7fa; border-bottom: 1px solid #dcdfe6; border-radius: 0; padding-left: 0; }
|
||||
.is-text-view :deep(.el-input__inner) { color: #606266; font-weight: 500; }
|
||||
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
|
||||
.dialog-scroll-container { padding: 20px; max-height: 70vh; overflow-y: auto; }
|
||||
.upload-container { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
:deep(.el-upload--picture-card) { width: 100px; height: 100px; line-height: 100px; }
|
||||
|
||||
Reference in New Issue
Block a user