Implement product Excel file import functionality, including new service methods for handling Excel attachments. Update the ProductController to list imported Excel files by product code. Enhance BmsProduct and related entities to store references to the imported Excel files. Update front-end components to support displaying and managing Excel file attachments for products.
This commit is contained in:
@@ -167,3 +167,11 @@ export async function importProductCountryExcelAsync(file, countryCode, effectiv
|
||||
}
|
||||
return pollProductImportTask(taskId, onProgress)
|
||||
}
|
||||
|
||||
/** List imported Excel attachments for product_code */
|
||||
export function listProductExcelFiles(productCode) {
|
||||
return request({
|
||||
url: '/price/product/' + encodeURIComponent(productCode) + '/excelFiles',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-drawer v-model="visible" size="860px" :title="title" append-to-body>
|
||||
<el-table v-loading="loading" :data="list" border max-height="calc(100vh - 160px)" empty-text="该产品暂无导入附件">
|
||||
<el-table-column label="文件名称" prop="fileName" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column label="生效时间" prop="effectiveTime" width="170" align="center" />
|
||||
<el-table-column label="大小" width="100" align="right">
|
||||
<template #default="{ row }">{{ formatSize(row.fileSize) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传人" prop="createBy" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="上传时间" prop="createTime" width="170" align="center" />
|
||||
<el-table-column label="操作" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" :disabled="!row.filePath" @click="handleDownload(row)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { listProductExcelFiles } from '@/api/price/product'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const visible = ref(false)
|
||||
const title = ref('')
|
||||
const loading = ref(false)
|
||||
const list = ref([])
|
||||
const product = ref(null)
|
||||
|
||||
function open(row) {
|
||||
product.value = row
|
||||
title.value = (row.productCode || '') + ' · ' + (row.productName || '') + ' · 导入附件'
|
||||
visible.value = true
|
||||
loadList()
|
||||
}
|
||||
|
||||
function loadList() {
|
||||
if (!product.value || !product.value.productCode) return
|
||||
loading.value = true
|
||||
listProductExcelFiles(product.value.productCode).then(res => {
|
||||
list.value = res.data || []
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function formatSize(bytes) {
|
||||
const n = Number(bytes)
|
||||
if (!n || n < 0) return '-'
|
||||
if (n < 1024) return n + ' B'
|
||||
if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB'
|
||||
return (n / (1024 * 1024)).toFixed(2) + ' MB'
|
||||
}
|
||||
|
||||
function handleDownload(row) {
|
||||
if (!row || !row.filePath) {
|
||||
proxy.$modal.msgWarning('文件路径不存在')
|
||||
return
|
||||
}
|
||||
proxy.$download.resource(row.filePath)
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
@@ -52,8 +52,16 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新内容" prop="updateNote" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
title="价格"
|
||||
icon="Document"
|
||||
@click="excelFileRef.open(row)"
|
||||
v-hasPermi="['price:product:query']"
|
||||
></el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@@ -73,16 +81,19 @@
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="loadList"
|
||||
/>
|
||||
<product-excel-file-drawer ref="excelFileRef" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { listProduct } from '@/api/price/product'
|
||||
import ProductExcelFileDrawer from './ProductExcelFileDrawer.vue'
|
||||
|
||||
const emit = defineEmits(['view-country'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { bms_product_effect_status } = useDict('bms_product_effect_status')
|
||||
|
||||
const excelFileRef = ref()
|
||||
const title = '失效价格'
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
</template>
|
||||
|
||||
<template #col-action="{ row }">
|
||||
<el-button link type="primary" title="价格" icon="Document" @click="excelFileRef.open(row)" v-hasPermi="['price:product:query']"></el-button>
|
||||
<el-button link type="primary" title="产品明细" icon="View" @click="countryRef.open(row)" v-hasPermi="['price:product:query']"></el-button>
|
||||
<el-button link type="primary" title="附加费" icon="Money" @click="surchargeRef.open(row)" v-hasPermi="['price:surcharge:query']"></el-button>
|
||||
<el-button title="编辑" link type="primary" icon="Edit" @click="handleUpdate(row)" v-hasPermi="['price:product:edit']"></el-button>
|
||||
@@ -54,6 +55,7 @@
|
||||
</basic-table>
|
||||
|
||||
<product-form-dialog ref="formRef" @success="() => tableRef.refresh()" />
|
||||
<product-excel-file-drawer ref="excelFileRef" />
|
||||
<product-country-drawer ref="countryRef" />
|
||||
<product-surcharge-drawer ref="surchargeRef" @success="() => tableRef.refresh()" />
|
||||
<product-expired-drawer ref="expiredRef" @view-country="(row) => countryRef.open(row)" />
|
||||
@@ -146,6 +148,7 @@
|
||||
<script setup name="PriceProduct">
|
||||
import ExcelImportDialog from '@/components/ExcelImportDialog'
|
||||
import ProductFormDialog from './components/ProductFormDialog.vue'
|
||||
import ProductExcelFileDrawer from './components/ProductExcelFileDrawer.vue'
|
||||
import ProductCountryDrawer from './components/ProductCountryDrawer.vue'
|
||||
import ProductSurchargeDrawer from './components/ProductSurchargeDrawer.vue'
|
||||
import ProductExpiredDrawer from './components/ProductExpiredDrawer.vue'
|
||||
@@ -157,6 +160,7 @@ const { bms_product_effect_status } = useDict('bms_product_effect_status')
|
||||
const extraParams = { statusGroup: 'active' }
|
||||
const tableRef = ref()
|
||||
const formRef = ref()
|
||||
const excelFileRef = ref()
|
||||
const countryRef = ref()
|
||||
const surchargeRef = ref()
|
||||
const expiredRef = ref()
|
||||
|
||||
@@ -182,7 +182,7 @@ const props = defineProps({
|
||||
buildModeDirty: { type: Boolean, default: false }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:psvId', 'update:priceBuildMode'])
|
||||
const emit = defineEmits(['update:psvId', 'update:priceBuildMode', 'update:pefId'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { bms_tax_mode } = useDict('bms_tax_mode')
|
||||
const { hydrateRow } = useDetailCascade(props.refData)
|
||||
@@ -447,6 +447,9 @@ async function runImportAsync(uploadFile) {
|
||||
details: isModifyImport.value ? (props.details || []) : undefined
|
||||
})
|
||||
const data = res.data || {}
|
||||
if (data.pefId != null) {
|
||||
emit('update:pefId', data.pefId)
|
||||
}
|
||||
const products = isModifyImport.value ? (props.products || []) : (data.products || [])
|
||||
applyLocalDraft(products, data.details || [])
|
||||
importProgressPercent.value = 100
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
:set-type="form.basic.setType"
|
||||
:price-build-mode="form.version.priceBuildMode"
|
||||
@update:price-build-mode="onPriceBuildModeUpdate"
|
||||
@update:pef-id="v => { draftPefId.value = v }"
|
||||
:version-no="form.version.versionNo"
|
||||
:version-status="form.version.status"
|
||||
:ref-data="refData"
|
||||
@@ -110,6 +111,8 @@ const form = reactive({
|
||||
products: [],
|
||||
customers: []
|
||||
})
|
||||
/** Draft IMPORT Excel attachment id; stamped onto prc_price_set_product on finish */
|
||||
const draftPefId = ref(undefined)
|
||||
const savedPriceBuildMode = ref(undefined)
|
||||
const savedProductsSnapshot = ref([])
|
||||
const buildModeDirty = computed(() =>
|
||||
@@ -298,6 +301,9 @@ function buildPayload(opts = {}) {
|
||||
priceBuildMode: version.priceBuildMode || undefined
|
||||
}
|
||||
}
|
||||
if (draftPefId.value != null) {
|
||||
payload.pefId = draftPefId.value
|
||||
}
|
||||
if (opts.forceDetails || hasUnsavedDetail) {
|
||||
payload.details = detailRows.map(d => {
|
||||
const p = toDetailPayload(d)
|
||||
@@ -343,6 +349,9 @@ function onPriceBuildModeUpdate(mode) {
|
||||
savedProductsSnapshot.value = (form.products || []).map(p => ({ ...p }))
|
||||
}
|
||||
form.version.priceBuildMode = mode
|
||||
if (mode !== 'IMPORT') {
|
||||
draftPefId.value = undefined
|
||||
}
|
||||
form.details.splice(0, form.details.length)
|
||||
if (detailsRef.value && detailsRef.value.clearLocalDraft) {
|
||||
detailsRef.value.clearLocalDraft()
|
||||
@@ -408,6 +417,7 @@ function applySetData(data, asCopy, asNewVersion) {
|
||||
form.version.expireTime = undefined
|
||||
form.version.status = undefined
|
||||
form.version.priceBuildMode = undefined
|
||||
draftPefId.value = undefined
|
||||
savedPriceBuildMode.value = undefined
|
||||
form.details = []
|
||||
form.products = []
|
||||
@@ -419,6 +429,7 @@ function applySetData(data, asCopy, asNewVersion) {
|
||||
form.version.expireTime = undefined
|
||||
form.version.status = current.status || '0'
|
||||
form.version.priceBuildMode = undefined
|
||||
draftPefId.value = undefined
|
||||
savedPriceBuildMode.value = undefined
|
||||
form.details = []
|
||||
form.products = []
|
||||
@@ -429,6 +440,7 @@ function applySetData(data, asCopy, asNewVersion) {
|
||||
form.version.expireTime = current.expireTime
|
||||
form.version.status = current.status
|
||||
form.version.priceBuildMode = current.priceBuildMode || undefined
|
||||
draftPefId.value = undefined
|
||||
savedPriceBuildMode.value = current.priceBuildMode || undefined
|
||||
form.details = []
|
||||
form.products = (current.products || []).map(p => ({ ...p }))
|
||||
|
||||
Reference in New Issue
Block a user