新增路线产品

This commit is contained in:
liuminghui
2026-11-06 13:39:26 +08:00
parent b4da248815
commit 6f342d424f
32 changed files with 1850 additions and 785 deletions
@@ -28,6 +28,18 @@
</template>
</el-upload>
<div v-if="recognizing" class="parse-progress">
<el-progress
:percentage="parsePercent"
:stroke-width="16"
:status="parseStatus"
striped
striped-flow
:duration="12"
/>
<div class="parse-progress-msg">{{ parseMessage }}</div>
</div>
<div v-if="preview" v-loading="recognizing" class="preview-box">
<el-alert
:title="`${preview.sourceFile || ''} 归属 ${preview.supplierName || '-'} 生效 ${preview.effectiveDate || '-'} 共 ${products.length} 个产品`"
@@ -97,7 +109,7 @@
<script setup>
import { ElMessageBox } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { previewPay, savePay } from '@/api/price/pay'
import { previewPay, payParseProgress, savePay } from '@/api/price/pay'
import { useDict } from '@/utils/dict'
import PayConfigDetail from './PayConfigDetail.vue'
@@ -116,17 +128,24 @@ const selected = ref([])
const tableRef = ref()
const activeKey = ref('')
const uploadKey = ref(0)
const parsePercent = ref(0)
const parseMessage = ref('')
const parseStatus = ref(undefined)
const products = computed(() => preview.value?.products || [])
const activeProduct = computed(() => products.value.find(item => item.rowKey === activeKey.value) || products.value[0])
const skippedText = computed(() => (preview.value?.skippedSheets || []).filter(Boolean).join('、'))
let parseSeq = 0
let progressTimer = null
function open() {
reset()
visible.value = true
}
function reset() {
parseSeq += 1
preview.value = null
selected.value = []
overwrite.value = false
@@ -135,6 +154,10 @@ function reset() {
activeKey.value = ''
recognizing.value = false
saving.value = false
parsePercent.value = 0
parseMessage.value = ''
parseStatus.value = undefined
stopProgress()
uploadKey.value += 1
}
@@ -145,9 +168,26 @@ async function onFile(uploadFile) {
proxy.$modal.msgError('请上传xlsx价卡')
return
}
const seq = ++parseSeq
const progressId = createProgressId()
recognizing.value = true
parsePercent.value = 0
parseMessage.value = '正在上传价卡…'
parseStatus.value = undefined
startProgress(seq, progressId)
try {
const res = await previewPay(raw, dictValue.value)
const res = await previewPay(raw, dictValue.value, progressId, event => {
if (seq !== parseSeq || !event?.total) return
const uploaded = Math.min(8, Math.round(event.loaded * 8 / event.total))
if (uploaded > parsePercent.value) {
parsePercent.value = uploaded
parseMessage.value = '正在上传价卡…'
}
})
if (seq !== parseSeq) return
parsePercent.value = 100
parseMessage.value = '解析完成'
parseStatus.value = 'success'
const data = res.data || {}
data.products = (data.products || []).map((item, index) => ({
...item,
@@ -160,8 +200,48 @@ async function onFile(uploadFile) {
await nextTick()
tableRef.value?.clearSelection()
picked.forEach(row => tableRef.value?.toggleRowSelection(row, true))
} catch (error) {
if (seq !== parseSeq) return
parseStatus.value = 'exception'
parseMessage.value = error?.message || '价卡解析失败'
} finally {
recognizing.value = false
if (seq === parseSeq) {
stopProgress()
recognizing.value = false
}
}
}
function createProgressId() {
if (window.crypto?.randomUUID) return window.crypto.randomUUID()
return `pay${Date.now().toString(16)}${Math.random().toString(16).slice(2, 10)}`
}
function startProgress(seq, progressId) {
stopProgress()
progressTimer = window.setInterval(async () => {
if (seq !== parseSeq) return
try {
const res = await payParseProgress(progressId)
if (seq !== parseSeq) return
const data = res.data || {}
if (!data.status || data.status === 'PENDING') return
const server = Math.min(99, Number(data.percent) || 0)
if (server >= parsePercent.value) {
parsePercent.value = server
if (data.message) parseMessage.value = data.message
}
if (data.status === 'FAIL') parseStatus.value = 'exception'
} catch {
// 进度查询失败时继续等预览结果
}
}, 400)
}
function stopProgress() {
if (progressTimer) {
window.clearInterval(progressTimer)
progressTimer = null
}
}
@@ -262,6 +342,14 @@ defineExpose({ open })
.import-form {
margin-bottom: 8px;
}
.parse-progress {
margin-top: 14px;
}
.parse-progress-msg {
margin-top: 8px;
color: var(--el-text-color-regular);
font-size: 13px;
}
.sheet-scroll {
display: flex;
gap: 8px;