1
This commit is contained in:
@@ -19,6 +19,14 @@ export function listQuickRecordModelOptions() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 快捷录单页:型号后缀店铺选项(系统参数 quickRecord.modelShopOptions) */
|
||||||
|
export function listQuickRecordShopOptions() {
|
||||||
|
return request({
|
||||||
|
url: '/system/jdorder/quickRecord/shopOptions',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// JD订单详情
|
// JD订单详情
|
||||||
export function getJDOrder(id) {
|
export function getJDOrder(id) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="visible"
|
||||||
|
width="640px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<div slot="title" class="dialog-title">
|
||||||
|
<i class="el-icon-shop"></i>
|
||||||
|
<span>快捷录单型号店铺选项</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-loading="loading">
|
||||||
|
<el-alert
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
title="每行一条,格式:短前缀(完整店名)。录单时仅将短前缀拼接到型号末尾。"
|
||||||
|
style="margin-bottom: 12px;"
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="configText"
|
||||||
|
type="textarea"
|
||||||
|
:rows="8"
|
||||||
|
placeholder="海尔官旗(海尔官方旗舰店) 海尔厨房(海尔厨房电器官方旗舰店)"
|
||||||
|
/>
|
||||||
|
<p class="hint">参数键名:quickRecord.modelShopOptions(保存至系统参数)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button size="small" @click="handleClose">取消</el-button>
|
||||||
|
<el-button type="primary" size="small" :loading="saveLoading" @click="handleSave">保存</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listConfig, addConfig, updateConfig } from '@/api/system/config'
|
||||||
|
|
||||||
|
const CONFIG_KEY = 'quickRecord.modelShopOptions'
|
||||||
|
const CONFIG_NAME = '快捷录单型号店铺选项'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'QuickRecordModelShopConfig',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
saveLoading: false,
|
||||||
|
configText: '',
|
||||||
|
configId: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
this.visible = val
|
||||||
|
if (val) {
|
||||||
|
this.loadConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
visible(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadConfig() {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const res = await listConfig({
|
||||||
|
configKey: CONFIG_KEY,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
const row = res && res.rows && res.rows.find(r => r && r.configKey === CONFIG_KEY)
|
||||||
|
if (row) {
|
||||||
|
this.configId = row.configId
|
||||||
|
this.configText = row.configValue || ''
|
||||||
|
} else {
|
||||||
|
this.configId = null
|
||||||
|
this.configText = ''
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.configId = null
|
||||||
|
this.configText = ''
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleSave() {
|
||||||
|
this.saveLoading = true
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
configName: CONFIG_NAME,
|
||||||
|
configKey: CONFIG_KEY,
|
||||||
|
configValue: (this.configText || '').trim(),
|
||||||
|
configType: 'N'
|
||||||
|
}
|
||||||
|
if (this.configId) {
|
||||||
|
payload.configId = this.configId
|
||||||
|
await updateConfig(payload)
|
||||||
|
} else {
|
||||||
|
await addConfig(payload)
|
||||||
|
}
|
||||||
|
this.$modal.msgSuccess('店铺选项已保存')
|
||||||
|
this.$emit('saved')
|
||||||
|
this.handleClose()
|
||||||
|
} catch (e) {
|
||||||
|
this.$modal.msgError('保存失败,请确认有参数管理权限')
|
||||||
|
} finally {
|
||||||
|
this.saveLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
this.visible = false
|
||||||
|
this.$emit('input', false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dialog-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -14,19 +14,53 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="型号" required>
|
<el-form-item label="型号" required>
|
||||||
|
<div class="model-row">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
v-model="form.model"
|
v-model="form.model"
|
||||||
class="model-input-full"
|
class="model-input-base"
|
||||||
:fetch-suggestions="queryModels"
|
:fetch-suggestions="queryModels"
|
||||||
placeholder="可输入、可改;点选联想项会带出最近一单付款 / 后返"
|
placeholder="型号本体;点选历史型号会拆分店铺并带出付款/后返"
|
||||||
clearable
|
clearable
|
||||||
:trigger-on-focus="true"
|
:trigger-on-focus="true"
|
||||||
@select="onModelSuggestionSelect"
|
@select="onModelSuggestionSelect"
|
||||||
|
@blur="onModelBlur"
|
||||||
>
|
>
|
||||||
<template slot-scope="{ item }">
|
<template slot-scope="{ item }">
|
||||||
<span class="model-suggest-label">{{ item.label }}</span>
|
<span class="model-suggest-label">{{ item.label }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
|
<el-select
|
||||||
|
v-model="form.shopPrefix"
|
||||||
|
class="model-shop-select"
|
||||||
|
:placeholder="shopOptions.length ? '店铺(必选)' : '店铺'"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="opt in shopOptions"
|
||||||
|
:key="opt.prefix"
|
||||||
|
:label="opt.label"
|
||||||
|
:value="opt.prefix"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-button
|
||||||
|
v-if="!isMobile"
|
||||||
|
type="text"
|
||||||
|
class="model-shop-config-btn"
|
||||||
|
icon="el-icon-setting"
|
||||||
|
title="配置型号店铺选项"
|
||||||
|
@click="showShopConfig = true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="model-shop-hint">
|
||||||
|
<template v-if="shopOptions.length">
|
||||||
|
落库型号 = 上方输入 + 所选店铺前缀(如 W5000PLUS2.0白 + 海尔厨房 → W5000PLUS2.0白海尔厨房)
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
尚未配置店铺选项,录单时不强制选择店铺。
|
||||||
|
</template>
|
||||||
|
<el-button type="text" size="mini" @click="showShopConfig = true">配置店铺选项</el-button>
|
||||||
|
</p>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="下单地址" required>
|
<el-form-item label="下单地址" required>
|
||||||
<el-input
|
<el-input
|
||||||
@@ -114,15 +148,19 @@
|
|||||||
<el-button type="primary" :loading="verifyLoading" @click="handleVerify">确认录单</el-button>
|
<el-button type="primary" :loading="verifyLoading" @click="handleVerify">确认录单</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<quick-record-model-shop-config v-model="showShopConfig" @saved="loadShopOptions" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { executeInstruction, executeInstructionWithForce } from '@/api/system/instruction'
|
import { executeInstruction, executeInstructionWithForce } from '@/api/system/instruction'
|
||||||
import { listQuickRecordModelOptions } from '@/api/system/jdorder'
|
import { listQuickRecordModelOptions, listQuickRecordShopOptions } from '@/api/system/jdorder'
|
||||||
|
import QuickRecordModelShopConfig from './components/QuickRecordModelShopConfig.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FadanQuickRecord',
|
name: 'FadanQuickRecord',
|
||||||
|
components: { QuickRecordModelShopConfig },
|
||||||
props: {
|
props: {
|
||||||
isMobile: {
|
isMobile: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -134,6 +172,7 @@ export default {
|
|||||||
form: {
|
form: {
|
||||||
markSuffix: '',
|
markSuffix: '',
|
||||||
model: '',
|
model: '',
|
||||||
|
shopPrefix: '',
|
||||||
address: '',
|
address: '',
|
||||||
link: '',
|
link: '',
|
||||||
thirdPartyOrderNoText: '',
|
thirdPartyOrderNoText: '',
|
||||||
@@ -152,11 +191,14 @@ export default {
|
|||||||
verifyMessage: '',
|
verifyMessage: '',
|
||||||
verifyLoading: false,
|
verifyLoading: false,
|
||||||
pendingCommand: '',
|
pendingCommand: '',
|
||||||
modelOptions: []
|
modelOptions: [],
|
||||||
|
shopOptions: [],
|
||||||
|
showShopConfig: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadModelOptions()
|
this.loadModelOptions()
|
||||||
|
this.loadShopOptions()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dialogWidth() {
|
dialogWidth() {
|
||||||
@@ -261,6 +303,59 @@ export default {
|
|||||||
// 静默失败,不影响手输型号
|
// 静默失败,不影响手输型号
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async loadShopOptions() {
|
||||||
|
try {
|
||||||
|
const res = await listQuickRecordShopOptions()
|
||||||
|
if (!(res && (res.code === 200 || res.msg === '操作成功'))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rows = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.shopOptions = rows
|
||||||
|
.filter(o => o && String(o.prefix || '').trim())
|
||||||
|
.map(o => ({
|
||||||
|
prefix: String(o.prefix).trim(),
|
||||||
|
fullName: o.fullName || '',
|
||||||
|
label: o.label || o.prefix
|
||||||
|
}))
|
||||||
|
.sort((a, b) => b.prefix.length - a.prefix.length)
|
||||||
|
} catch (e) {
|
||||||
|
this.shopOptions = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 从完整型号末尾匹配店铺前缀(长前缀优先),用于回显 */
|
||||||
|
parseModelWithShop(fullModel) {
|
||||||
|
const full = String(fullModel || '').trim()
|
||||||
|
if (!full || !this.shopOptions.length) {
|
||||||
|
return { base: full, prefix: '' }
|
||||||
|
}
|
||||||
|
for (const opt of this.shopOptions) {
|
||||||
|
const p = opt.prefix
|
||||||
|
if (p && full.endsWith(p) && full.length > p.length) {
|
||||||
|
return { base: full.slice(0, -p.length), prefix: p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { base: full, prefix: '' }
|
||||||
|
},
|
||||||
|
applyModelWithShop(fullModel) {
|
||||||
|
const parsed = this.parseModelWithShop(fullModel)
|
||||||
|
this.form.model = parsed.base
|
||||||
|
this.form.shopPrefix = parsed.prefix
|
||||||
|
return parsed
|
||||||
|
},
|
||||||
|
onModelBlur() {
|
||||||
|
if (!this.form.model || !this.shopOptions.length) return
|
||||||
|
const parsed = this.parseModelWithShop(this.form.model)
|
||||||
|
if (parsed.prefix) {
|
||||||
|
this.form.model = parsed.base
|
||||||
|
this.form.shopPrefix = parsed.prefix
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buildFullModelNumber() {
|
||||||
|
const base = (this.form.model || '').trim()
|
||||||
|
const prefix = (this.form.shopPrefix || '').trim()
|
||||||
|
if (!base) return ''
|
||||||
|
return prefix ? base + prefix : base
|
||||||
|
},
|
||||||
queryModels(queryString, cb) {
|
queryModels(queryString, cb) {
|
||||||
const q = (queryString || '').trim().toLowerCase()
|
const q = (queryString || '').trim().toLowerCase()
|
||||||
const rows = this.modelOptions
|
const rows = this.modelOptions
|
||||||
@@ -268,20 +363,27 @@ export default {
|
|||||||
const m = String(o.modelNumber || '').trim()
|
const m = String(o.modelNumber || '').trim()
|
||||||
if (!m) return false
|
if (!m) return false
|
||||||
if (!q) return true
|
if (!q) return true
|
||||||
return m.toLowerCase().includes(q)
|
const parsed = this.parseModelWithShop(m)
|
||||||
|
return m.toLowerCase().includes(q) || parsed.base.toLowerCase().includes(q)
|
||||||
})
|
})
|
||||||
.slice(0, 100)
|
.slice(0, 100)
|
||||||
cb(
|
cb(
|
||||||
rows.map(o => ({
|
rows.map(o => {
|
||||||
value: String(o.modelNumber).trim(),
|
const full = String(o.modelNumber).trim()
|
||||||
label: this.modelOptionLabel(o)
|
const parsed = this.parseModelWithShop(full)
|
||||||
}))
|
const displayBase = parsed.base || full
|
||||||
|
return {
|
||||||
|
value: full,
|
||||||
|
label: this.modelOptionLabel({ ...o, modelNumber: displayBase })
|
||||||
|
}
|
||||||
|
})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
/** 仅从联想列表点选时回填金额;型号本身为输入框,选后仍可继续编辑 */
|
/** 仅从联想列表点选时回填金额;型号拆分为本体 + 店铺前缀 */
|
||||||
onModelSuggestionSelect(item) {
|
onModelSuggestionSelect(item) {
|
||||||
if (!item || !item.value) return
|
if (!item || !item.value) return
|
||||||
const key = String(item.value).trim()
|
const key = String(item.value).trim()
|
||||||
|
this.applyModelWithShop(key)
|
||||||
const hit = this.modelOptions.find(o => o && String(o.modelNumber || '').trim() === key)
|
const hit = this.modelOptions.find(o => o && String(o.modelNumber || '').trim() === key)
|
||||||
if (!hit) return
|
if (!hit) return
|
||||||
const payRaw = hit.lastPaymentAmount
|
const payRaw = hit.lastPaymentAmount
|
||||||
@@ -291,9 +393,18 @@ export default {
|
|||||||
},
|
},
|
||||||
buildCommand() {
|
buildCommand() {
|
||||||
const mark = this.buildDistributionMark()
|
const mark = this.buildDistributionMark()
|
||||||
const model = (this.form.model || '').trim()
|
this.onModelBlur()
|
||||||
|
const model = this.buildFullModelNumber()
|
||||||
this.normalizeAddressField()
|
this.normalizeAddressField()
|
||||||
const address = (this.form.address || '').trim()
|
const address = (this.form.address || '').trim()
|
||||||
|
if (!(this.form.model || '').trim()) {
|
||||||
|
this.$modal.msgError('请填写型号')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (this.shopOptions.length && !this.form.shopPrefix) {
|
||||||
|
this.$modal.msgError('请选择型号对应店铺')
|
||||||
|
return null
|
||||||
|
}
|
||||||
if (!model) {
|
if (!model) {
|
||||||
this.$modal.msgError('请填写型号')
|
this.$modal.msgError('请填写型号')
|
||||||
return null
|
return null
|
||||||
@@ -506,6 +617,7 @@ export default {
|
|||||||
this.form = {
|
this.form = {
|
||||||
markSuffix: '',
|
markSuffix: '',
|
||||||
model: '',
|
model: '',
|
||||||
|
shopPrefix: '',
|
||||||
address: '',
|
address: '',
|
||||||
link: '',
|
link: '',
|
||||||
thirdPartyOrderNoText: '',
|
thirdPartyOrderNoText: '',
|
||||||
@@ -582,6 +694,43 @@ export default {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-input-base {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-shop-select {
|
||||||
|
width: 220px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-shop-config-btn {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 8px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-shop-hint {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadan-quick-record--mobile .model-row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadan-quick-record--mobile .model-shop-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.model-input-full {
|
.model-input-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user