1
This commit is contained in:
@@ -168,29 +168,33 @@
|
||||
<el-input
|
||||
v-model="historyKeyword"
|
||||
clearable
|
||||
placeholder="搜型号、地址、下单人、订单号、分销标记"
|
||||
placeholder="搜型号、地址、下单人、订单号、分销标记;待填写在前"
|
||||
prefix-icon="el-icon-search"
|
||||
@keyup.enter.native="searchHistory"
|
||||
@clear="searchHistory"
|
||||
/>
|
||||
<el-button type="primary" :loading="historyLoading" @click="searchHistory">搜索</el-button>
|
||||
</div>
|
||||
<p class="history-hint">待填写(生成后未补全)排在前面,已落库记录也保留。</p>
|
||||
<div class="history-list" v-loading="historyLoading">
|
||||
<div v-if="!historyList.length && !historyLoading" class="history-empty">暂无历史记录</div>
|
||||
<div
|
||||
v-for="row in historyList"
|
||||
:key="row.id"
|
||||
:key="row.key"
|
||||
class="history-item"
|
||||
@click="applyHistoryOrder(row)"
|
||||
:class="{ 'is-unfilled': !row.filled }"
|
||||
@click="applyHistoryItem(row)"
|
||||
>
|
||||
<div class="history-item-top">
|
||||
<span class="history-model">{{ historyFullModel(row) || '无型号' }}</span>
|
||||
<span class="history-model">{{ historyItemModel(row) || '无型号' }}</span>
|
||||
<span class="history-time">{{ formatHistoryTime(row) }}</span>
|
||||
</div>
|
||||
<div class="history-item-meta">
|
||||
<el-tag v-if="!row.filled" type="warning" size="mini">待填写</el-tag>
|
||||
<el-tag v-else type="success" size="mini">已落库</el-tag>
|
||||
<span v-if="row.distributionMark">{{ row.distributionMark }}</span>
|
||||
<span v-if="row.buyer">{{ row.buyer }}</span>
|
||||
<span v-if="row.paymentAmount != null">付款 {{ formatMoneyText(row.paymentAmount) }}</span>
|
||||
<span v-if="row.paymentAmount != null && row.paymentAmount !== ''">付款 {{ formatHistoryMoney(row.paymentAmount) }}</span>
|
||||
<span v-if="row.orderId">{{ row.orderId }}</span>
|
||||
</div>
|
||||
<div v-if="row.address" class="history-item-addr">{{ row.address }}</div>
|
||||
@@ -204,7 +208,7 @@
|
||||
:page-size="historyPageSize"
|
||||
:total="historyTotal"
|
||||
:pager-count="isMobile ? 5 : 7"
|
||||
@current-change="loadHistory"
|
||||
@current-change="sliceHistoryPage"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -218,7 +222,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { executeInstruction, executeInstructionWithForce } from '@/api/system/instruction'
|
||||
import { executeInstruction, executeInstructionWithForce, getHistory } from '@/api/system/instruction'
|
||||
import { listJDOrders, listQuickRecordModelOptions, listQuickRecordShopOptions } from '@/api/system/jdorder'
|
||||
import QuickRecordModelShopConfig from './components/QuickRecordModelShopConfig.vue'
|
||||
|
||||
@@ -261,6 +265,7 @@ export default {
|
||||
historyVisible: false,
|
||||
historyLoading: false,
|
||||
historyKeyword: '',
|
||||
historyAll: [],
|
||||
historyList: [],
|
||||
historyPage: 1,
|
||||
historyPageSize: 15,
|
||||
@@ -720,20 +725,200 @@ export default {
|
||||
this.historyPage = 1
|
||||
this.loadHistory()
|
||||
},
|
||||
sliceHistoryPage() {
|
||||
const start = (this.historyPage - 1) * this.historyPageSize
|
||||
this.historyList = this.historyAll.slice(start, start + this.historyPageSize)
|
||||
},
|
||||
extractHistoryParts(item) {
|
||||
const raw = String(item || '')
|
||||
const idx = raw.indexOf(' | ')
|
||||
return {
|
||||
time: idx > 0 ? raw.slice(0, idx) : '',
|
||||
text: idx > 0 ? raw.slice(idx + 3) : raw
|
||||
}
|
||||
},
|
||||
extractFormBody(full) {
|
||||
const raw = String(full || '').replace(/\r\n/g, '\n').trim()
|
||||
if (!raw) return ''
|
||||
const sep = /\n-{3,}\s*落库回执\s*-{3,}\s*\n/
|
||||
const m = sep.exec(raw)
|
||||
return m ? raw.slice(0, m.index).trim() : raw
|
||||
},
|
||||
extractFormField(text, startLabel, endLabels) {
|
||||
const src = String(text || '')
|
||||
const idx = src.indexOf(startLabel)
|
||||
if (idx < 0) return ''
|
||||
let rest = src.slice(idx + startLabel.length)
|
||||
let end = rest.length
|
||||
;(endLabels || []).forEach(lab => {
|
||||
if (!lab) return
|
||||
const i = rest.indexOf(lab)
|
||||
if (i >= 0 && i < end) end = i
|
||||
})
|
||||
return rest
|
||||
.slice(0, end)
|
||||
.replace(/[━—\-]{3,}/g, '')
|
||||
.replace(/\n{2,}/g, '\n')
|
||||
.trim()
|
||||
},
|
||||
parseOrderFormText(text) {
|
||||
const raw = String(text || '').replace(/\r\n/g, '\n')
|
||||
const isNew = raw.includes('下单人(需填):')
|
||||
|| raw.includes('下单链接(必须用这个):')
|
||||
|| raw.includes('—————————')
|
||||
const field = (start, ends) => this.extractFormField(raw, start, ends)
|
||||
if (isNew) {
|
||||
return {
|
||||
remark: field('单:', ['分销标记:']),
|
||||
mark: field('分销标记:', ['第三方单号:', '—————————', '下单链接(必须用这个):']),
|
||||
thirdParty: field('第三方单号:', ['—————————', '下单链接(必须用这个):']),
|
||||
link: field('下单链接(必须用这个):', ['下单地址(注意带分机):', '—————————']),
|
||||
address: field('下单地址(注意带分机):', ['—————————', '型号:']),
|
||||
model: field('型号:', ['下单人(需填):', '下单付款(注意核对):']),
|
||||
buyer: field('下单人(需填):', ['下单付款(注意核对):']),
|
||||
payment: field('下单付款(注意核对):', ['后返金额(注意核对):']),
|
||||
rebate: field('后返金额(注意核对):', ['订单号(需填):']),
|
||||
orderId: field('订单号(需填):', ['物流链接(需填):']),
|
||||
logistics: field('物流链接(需填):', ['备注(下单号码有变动', '—————————', '京粉实际价格'])
|
||||
}
|
||||
}
|
||||
return {
|
||||
remark: field('单:', ['备注:', '分销标记:']),
|
||||
mark: field('分销标记:', ['第三方单号:', '型号:']),
|
||||
thirdParty: field('第三方单号:', ['型号:']),
|
||||
model: field('型号:', ['链接:']),
|
||||
link: field('链接:', ['下单付款:']),
|
||||
payment: field('下单付款:', ['后返金额:']),
|
||||
rebate: field('后返金额:', ['地址:']),
|
||||
address: field('地址:', ['物流链接:']),
|
||||
logistics: field('物流链接:', ['订单号:']),
|
||||
orderId: field('订单号:', ['下单人:']),
|
||||
buyer: field('下单人:', ['京粉实际价格:'])
|
||||
}
|
||||
},
|
||||
isPersistFilledText(parsed) {
|
||||
if (!parsed) return false
|
||||
return !!(
|
||||
String(parsed.buyer || '').trim()
|
||||
&& String(parsed.payment || '').trim()
|
||||
&& String(parsed.orderId || '').trim()
|
||||
&& String(parsed.logistics || '').trim()
|
||||
)
|
||||
},
|
||||
isPersistFilledOrder(row) {
|
||||
if (!row) return false
|
||||
return !!(
|
||||
String(row.buyer || '').trim()
|
||||
&& row.paymentAmount != null && row.paymentAmount !== ''
|
||||
&& String(row.orderId || '').trim()
|
||||
&& String(row.logisticsLink || '').trim()
|
||||
)
|
||||
},
|
||||
historyItemMatchesKeyword(item, kw) {
|
||||
if (!kw) return true
|
||||
const blob = [
|
||||
item.modelNumber,
|
||||
item.modelShop,
|
||||
this.historyItemModel(item),
|
||||
item.address,
|
||||
item.buyer,
|
||||
item.orderId,
|
||||
item.distributionMark,
|
||||
item.thirdPartyOrderNo,
|
||||
item.remark
|
||||
].join(' ').toLowerCase()
|
||||
return blob.includes(kw.toLowerCase())
|
||||
},
|
||||
normalizeDraftItem(rawItem) {
|
||||
const parts = this.extractHistoryParts(rawItem)
|
||||
const body = this.extractFormBody(parts.text)
|
||||
if (!this.formBodyLooksPersistable(body)) return null
|
||||
const parsed = this.parseOrderFormText(body)
|
||||
const modelFull = String(parsed.model || '').split('\n')[0].trim()
|
||||
const shopParsed = this.parseModelWithShop(modelFull)
|
||||
return {
|
||||
key: 'draft-' + (parsed.remark || parts.time || modelFull),
|
||||
source: 'draft',
|
||||
filled: this.isPersistFilledText(parsed),
|
||||
remark: String(parsed.remark || '').trim(),
|
||||
distributionMark: String(parsed.mark || '').trim(),
|
||||
modelNumber: shopParsed.base || modelFull,
|
||||
modelShop: shopParsed.prefix,
|
||||
address: this.compressAddressOneLine(parsed.address),
|
||||
link: String(parsed.link || '').trim(),
|
||||
thirdPartyOrderNo: String(parsed.thirdParty || '').trim(),
|
||||
buyer: String(parsed.buyer || '').trim(),
|
||||
paymentAmount: String(parsed.payment || '').trim(),
|
||||
rebateAmount: String(parsed.rebate || '').trim(),
|
||||
orderId: String(parsed.orderId || '').trim(),
|
||||
logisticsLink: String(parsed.logistics || '').trim(),
|
||||
orderTime: parts.time,
|
||||
rawText: body
|
||||
}
|
||||
},
|
||||
normalizeOrderItem(row) {
|
||||
if (!row) return null
|
||||
return {
|
||||
key: 'order-' + (row.id || row.remark || row.orderId),
|
||||
source: 'order',
|
||||
filled: this.isPersistFilledOrder(row),
|
||||
remark: row.remark || '',
|
||||
distributionMark: row.distributionMark || '',
|
||||
modelNumber: row.modelNumber || '',
|
||||
modelShop: row.modelShop || '',
|
||||
address: row.address || '',
|
||||
link: row.link || '',
|
||||
thirdPartyOrderNo: row.thirdPartyOrderNo || '',
|
||||
buyer: row.buyer || '',
|
||||
paymentAmount: row.paymentAmount,
|
||||
rebateAmount: row.rebateAmount,
|
||||
orderId: row.orderId || '',
|
||||
logisticsLink: row.logisticsLink || '',
|
||||
orderTime: row.orderTime || row.createTime,
|
||||
id: row.id
|
||||
}
|
||||
},
|
||||
async loadHistory() {
|
||||
this.historyLoading = true
|
||||
try {
|
||||
const kw = (this.historyKeyword || '').trim()
|
||||
const res = await listJDOrders({
|
||||
pageNum: this.historyPage,
|
||||
pageSize: this.historyPageSize,
|
||||
orderBy: 'id',
|
||||
isAsc: 'desc',
|
||||
quickRecordSearch: kw || undefined
|
||||
const [histRes, orderRes] = await Promise.all([
|
||||
getHistory('response', 300, kw || undefined),
|
||||
listJDOrders({
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
orderBy: 'id',
|
||||
isAsc: 'desc',
|
||||
quickRecordSearch: kw || undefined
|
||||
})
|
||||
])
|
||||
const orders = ((orderRes && orderRes.rows) || []).map(this.normalizeOrderItem).filter(Boolean)
|
||||
const persistedRemarks = new Set(
|
||||
orders.map(o => String(o.remark || '').trim()).filter(Boolean)
|
||||
)
|
||||
const draftMap = new Map()
|
||||
;((histRes && histRes.data) || []).forEach(raw => {
|
||||
const draft = this.normalizeDraftItem(raw)
|
||||
if (!draft) return
|
||||
if (kw && !this.historyItemMatchesKeyword(draft, kw)) return
|
||||
const remark = draft.remark
|
||||
if (remark && persistedRemarks.has(remark)) return
|
||||
if (remark && draftMap.has(remark)) return
|
||||
const fallbackKey = draft.key
|
||||
if (!remark && draftMap.has(fallbackKey)) return
|
||||
draftMap.set(remark || fallbackKey, draft)
|
||||
})
|
||||
this.historyList = (res && res.rows) || []
|
||||
this.historyTotal = (res && res.total) || 0
|
||||
const drafts = Array.from(draftMap.values()).filter(d => !d.filled)
|
||||
const unfilledOrders = orders.filter(o => !o.filled)
|
||||
const filledOrders = orders.filter(o => o.filled)
|
||||
this.historyAll = [...drafts, ...unfilledOrders, ...filledOrders]
|
||||
this.historyTotal = this.historyAll.length
|
||||
if ((this.historyPage - 1) * this.historyPageSize >= this.historyTotal) {
|
||||
this.historyPage = 1
|
||||
}
|
||||
this.sliceHistoryPage()
|
||||
} catch (e) {
|
||||
this.historyAll = []
|
||||
this.historyList = []
|
||||
this.historyTotal = 0
|
||||
this.$modal.msgError('加载历史记录失败')
|
||||
@@ -741,7 +926,7 @@ export default {
|
||||
this.historyLoading = false
|
||||
}
|
||||
},
|
||||
historyFullModel(row) {
|
||||
historyItemModel(row) {
|
||||
if (!row) return ''
|
||||
const base = String(row.modelNumber || '').trim()
|
||||
const shop = String(row.modelShop || '').trim()
|
||||
@@ -750,6 +935,11 @@ export default {
|
||||
if (base.endsWith(shop)) return base
|
||||
return base + shop
|
||||
},
|
||||
formatHistoryMoney(v) {
|
||||
if (v == null || v === '') return ''
|
||||
if (typeof v === 'number') return this.formatMoneyText(v)
|
||||
return String(v)
|
||||
},
|
||||
formatHistoryTime(row) {
|
||||
const raw = (row && (row.orderTime || row.createTime)) || ''
|
||||
if (!raw) return ''
|
||||
@@ -772,26 +962,26 @@ export default {
|
||||
}
|
||||
this.form.markSuffix = v
|
||||
},
|
||||
applyHistoryOrder(row) {
|
||||
applyHistoryItem(row) {
|
||||
if (!row) return
|
||||
this.applyMarkSuffixFromText(row.distributionMark)
|
||||
if (row.modelShop) {
|
||||
this.form.model = String(row.modelNumber || '').trim()
|
||||
this.form.shopPrefix = String(row.modelShop || '').trim()
|
||||
} else {
|
||||
this.applyModelWithShop(this.historyFullModel(row))
|
||||
this.applyModelWithShop(this.historyItemModel(row))
|
||||
}
|
||||
this.form.address = this.compressAddressOneLine(row.address)
|
||||
this.form.link = String(row.link || '').trim()
|
||||
this.form.thirdPartyOrderNoText = String(row.thirdPartyOrderNo || '').trim()
|
||||
this.form.buyer = String(row.buyer || '').trim()
|
||||
this.form.paymentText = this.formatMoneyText(row.paymentAmount)
|
||||
this.form.rebateText = this.formatMoneyText(row.rebateAmount)
|
||||
this.form.paymentText = this.formatHistoryMoney(row.paymentAmount)
|
||||
this.form.rebateText = this.formatHistoryMoney(row.rebateAmount)
|
||||
this.form.orderIdText = String(row.orderId || '').trim()
|
||||
this.form.logisticsLink = String(row.logisticsLink || '').trim()
|
||||
this.resultText = ''
|
||||
this.resultText = row.rawText || ''
|
||||
this.historyVisible = false
|
||||
this.$modal.msgSuccess('已回填历史记录,可修改后录单')
|
||||
this.$modal.msgSuccess(row.filled ? '已回填历史记录,可修改后录单' : '已回填待填写表单,请补全后录单')
|
||||
this.$nextTick(() => {
|
||||
const formEl = this.$el && this.$el.querySelector('.fadan-form')
|
||||
if (formEl && formEl.scrollIntoView) {
|
||||
@@ -970,6 +1160,12 @@ export default {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-hint {
|
||||
margin: 0 0 10px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.history-list {
|
||||
max-height: 52vh;
|
||||
overflow-y: auto;
|
||||
@@ -997,6 +1193,11 @@ export default {
|
||||
background: #f5faff;
|
||||
}
|
||||
|
||||
.history-item.is-unfilled {
|
||||
border-color: #f5dab1;
|
||||
background: #fdf6ec;
|
||||
}
|
||||
|
||||
.history-item-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user