Commit 328a4f11 authored by 何远江's avatar 何远江

添加多字段映射,接口对接

parent 5ea0d8dc
...@@ -88,3 +88,75 @@ export const useExcelStore = defineStore('excelStore', { ...@@ -88,3 +88,75 @@ export const useExcelStore = defineStore('excelStore', {
} }
} }
}) })
export const useExcelChangeStore = defineStore('excelChangeStore', {
state: () => ({
allMapConfigs: {}, // 缓存当前这条数据的所有映射关系
scriptList: [], // 脚本
orderFieldList: [], // 订单字段
variableField: [], // 后端获取的变量字段
usedFieldList: [] // 当前编辑column使用过的映射字段
}),
getters: {
getAllMapConfigs(): any {
return this.allMapConfigs
},
getScriptList(): any {
return this.scriptList
},
getEffectConfigs(): any[] {
const currenttitle = this.usedFieldList[0]?.title || ''
const res: any = [...this.usedFieldList]
for (const key in this.allMapConfigs) {
if (key != currenttitle) {
if (this.allMapConfigs[key].orderFiledConfs.length) {
res.push(...this.allMapConfigs[key].orderFiledConfs)
}
}
}
return res.map((item) => item.mapField)
},
getAllFields(): any {
return [
{
label: '普通字段',
options: this.orderFieldList.map((item) => {
this.getEffectConfigs.includes(item.filedName)
? (item.disabled = true)
: (item.disabled = false)
return item
})
},
{
label: '变量字段',
options: this.variableField.map((item) => {
this.getEffectConfigs.includes(item.filedName)
? (item.disabled = true)
: (item.disabled = false)
return item
})
}
]
}
},
actions: {
setAllMapConfigs(config: any) {
this.allMapConfigs = config
},
setSingleFieldMap(config: any) {
this.allMapConfigs[config.title] = config
},
setScriptList(list: any) {
this.scriptList = list
},
setOrderFieldList(list: any) {
this.orderFieldList = list
},
setVariableField(list: any) {
this.variableField = list
},
setUsedFieldList(list: any) {
this.usedFieldList = list
}
}
})
...@@ -201,17 +201,23 @@ export function filterRunData(data: any, config: boolean = false) { ...@@ -201,17 +201,23 @@ export function filterRunData(data: any, config: boolean = false) {
// 映射字段配置生成 // 映射字段配置生成
const configs: Recordable = {} const configs: Recordable = {}
const temConf = { const temConf = {
// title: '',
// content: '',
// mapField: '',
// scriptName: '',
// groupTitle: '',
// templateFileId: '',
// excelOrderFiledConfId: '',
// params: {},
// orderFiled: {},
excelOrderFiledConfId:'',
title: '', title: '',
content: '', orderFiledConfs: [],
mapField: '', templateFileId: ''
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: '',
params: {},
orderFiled: {}
} }
console.log(data, 'data-----')
data.forEach((row: any) => { data.forEach((row: any) => {
const rw: Recordable = {} const rw: Recordable = {}
row.order.forEach((itm: any) => { row.order.forEach((itm: any) => {
...@@ -239,6 +245,8 @@ export function filterRunData(data: any, config: boolean = false) { ...@@ -239,6 +245,8 @@ export function filterRunData(data: any, config: boolean = false) {
res.push(rw) res.push(rw)
}) })
console.log('----res', res)
return { return {
res, res,
titles: [...titles], titles: [...titles],
......
...@@ -113,7 +113,10 @@ ...@@ -113,7 +113,10 @@
<vxe-column :title="item" :field="item" width="200"> <vxe-column :title="item" :field="item" width="200">
<template #header> <template #header>
<div class="header-cell" @click="(e) => showPopover(e, item)"> <div class="header-cell" @click="(e) => showPopover(e, item)">
<span>{{ allMapConfigs[item]?.orderFiled.fliedTitle || '' }}</span> <template v-for="cf in getAllMapConfigs[item].orderFiledConfs">
<span>{{ cf.orderFiled.fliedTitle }}</span>
</template>
<!-- <span>{{ allMapConfigs[item]?.orderFiled.fliedTitle || '' }}</span> -->
<el-icon v-if="currentRow.status == 'un_convert'"><Setting /></el-icon> <el-icon v-if="currentRow.status == 'un_convert'"><Setting /></el-icon>
</div> </div>
</template> </template>
...@@ -133,73 +136,13 @@ ...@@ -133,73 +136,13 @@
width="360" width="360"
transition="" transition=""
> >
<el-form size="small" label-width="7em" inline :model="currentConfigColumn"> <ConfigForm
<el-row> :title="currentConfigTitle"
<el-col :span="24"> :current-conf="currentColConf"
<el-form-item label="对应字段" prop="mapField"> :current-row="currentRow"
<el-select @cancel="popoverVisible = false"
v-model="currentConfigColumn.mapField" @confirm="confirmConfig"
style="width: 220px"
filterable
placeholder="请选择"
:teleported="false"
clearable
>
<el-option-group v-for="group in allFields" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.filedName"
:label="item.fliedTitle"
:value="item.filedName"
:disabled="!!item.disabled"
/> />
</el-option-group>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" v-if="currentConfigColumn.mapField">
<el-form-item label="脚本">
<el-select
style="width: 220px"
v-model="currentConfigColumn.scriptName"
:teleported="false"
clearable
>
<el-option
v-for="item in scriptList"
:key="item.srciptName"
:value="item.srciptName"
:label="item.srciptName"
></el-option>
</el-select>
</el-form-item>
</el-col>
<template v-for="params in currentScriptParamsList" :key="params.fliedTitle">
<el-col :span="24">
<el-form-item :label="params.fliedTitle">
<el-input v-model="scriptPs[params.filedName]" style="width: 220px" />
</el-form-item>
</el-col>
</template>
<el-col :span="24" v-if="currentConfigColumn.scriptName && !!currentConfigColumn.content">
<el-form-item label="脚本语句">
<el-input
style="width: 220px"
rows="3"
disabled
type="textarea"
v-model.trim="currentConfigColumn.content"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button type="primary" @click="confirmConfig">确认</el-button>
<el-button type="primary" @click="popoverVisible = false">取消</el-button>
</el-form-item>
</el-form>
</el-popover> </el-popover>
<template #footer> <template #footer>
...@@ -212,7 +155,7 @@ ...@@ -212,7 +155,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, reactive, ref, watch } from 'vue' import { onMounted, reactive, ref, watch } from 'vue'
import { Setting } from '@element-plus/icons-vue' import { Setting } from '@element-plus/icons-vue'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import { import {
...@@ -224,14 +167,18 @@ import { ...@@ -224,14 +167,18 @@ import {
getConfByExcelOrderId, getConfByExcelOrderId,
saveConfExcelFileOrderPage saveConfExcelFileOrderPage
} from '@/api/order' } from '@/api/order'
import { ElMessage, ElMessageBox, ClickOutside as vClickOutside } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import type { VxeTableInstance } from 'vxe-table' import type { VxeTableInstance } from 'vxe-table'
import type { Recordable } from '@/types/global' import type { Recordable } from '@/types/global'
import { filterRunData } from '@/utils/excel' import { filterRunData } from '@/utils/excel'
import { apiGetOrderField, apiGetScript, getVariableField } from '@/api/excel'
import { apiDictList } from '@/api/common' import { apiDictList } from '@/api/common'
import ConfigForm from './components/ConfigForm.vue'
import { useExcelChangeStore } from '@/stores/excel'
import { storeToRefs } from 'pinia'
const loading = ref(false) const loading = ref(false)
const excelChangeStore = useExcelChangeStore()
const { getAllMapConfigs } = storeToRefs(excelChangeStore)
/**查询参数 */ /**查询参数 */
const queryParams = reactive({ const queryParams = reactive({
status: '', status: '',
...@@ -242,32 +189,14 @@ const queryParams = reactive({ ...@@ -242,32 +189,14 @@ const queryParams = reactive({
order: 'desc' order: 'desc'
}) })
/**所有列映射配置 */ const currentColConf = reactive({
const allMapConfigs = ref<Recordable>({})
const effectConfigs = computed(() => {
return Object.values(allMapConfigs.value).filter((item) => item.title != '')
})
/**当前表单映射字段配置 */
const currentConfigColumn = reactive({
title: '',
content: '',
mapField: '',
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: '', excelOrderFiledConfId: '',
params: {}, title: '',
orderFiled: {} orderFiledConfs: [],
templateFileId: ''
}) })
const currentConfigTitle = ref('') const currentConfigTitle = ref('')
const scriptPs = ref<Recordable>({})
/**所有脚本 */
const scriptList = ref<Recordable[]>([])
/**所有映射字段 */
const orderFieldList = ref<Recordable[]>([])
const variableField = ref([])
const xTable = ref<VxeTableInstance>() const xTable = ref<VxeTableInstance>()
const tableData = ref([]) const tableData = ref([])
/**当前选择行 */ /**当前选择行 */
...@@ -291,16 +220,30 @@ const queryDict = async (code: string) => { ...@@ -291,16 +220,30 @@ const queryDict = async (code: string) => {
const popoverRef = ref() const popoverRef = ref()
const buttonRef = ref() const buttonRef = ref()
const popoverVisible = ref(false) const popoverVisible = ref(false)
const showPopover = (e: any, title: string, groupTitle: string = '') => { const showPopover = (e: any, title: string) => {
if (currentRow.status != 'un_convert') { if (currentRow.status != 'un_convert') {
return return
} }
buttonRef.value = e.target buttonRef.value = e.target
const t = groupTitle ? `${groupTitle}-${title}` : title
// 设置标题 // 设置标题
currentConfigTitle.value = t currentConfigTitle.value = title
Object.assign(currentConfigColumn, { ...allMapConfigs.value[t], title, groupTitle }) const hasConf = !!getAllMapConfigs.value[title].orderFiledConfs.length
const conf = hasConf
? getAllMapConfigs.value[title]
: {
excelOrderFiledConfId: '',
title,
orderFiledConfs: [
{
mapField: '',
orderFiled: {},
scripts: []
}
],
templateFileId: currentRow.templateFileId
}
Object.assign(currentColConf, conf)
// 打开popover // 打开popover
popoverVisible.value = true popoverVisible.value = true
} }
...@@ -311,122 +254,17 @@ watch([detailVisible, popoverVisible], (val) => { ...@@ -311,122 +254,17 @@ watch([detailVisible, popoverVisible], (val) => {
if (val.includes(false)) { if (val.includes(false)) {
// 解决关闭弹窗之后,popover未关闭情况 // 解决关闭弹窗之后,popover未关闭情况
popoverVisible.value = false popoverVisible.value = false
// 重置表单
resetConfigForm()
} }
}) })
/**监听currentConfigColumn.mapField字段,重置/设置 orderFiled */ /** 确认字段映射及脚本的配置 */
watch( const confirmConfig = (configList: any) => {
() => currentConfigColumn.mapField, excelChangeStore.setSingleFieldMap({
(val) => { ...currentColConf,
// 如果有值设置 currentConfigColumn.orderFiled字段 orderFiledConfs: cloneDeep(configList.filter((v) => !!v.mapField))
if (val) {
let item = orderFieldList.value.find((v) => v.filedName == val)
if (!item) {
item = variableField.value.find((v) => v.filedName == val)
}
Reflect.set(currentConfigColumn, 'orderFiled', item)
} else {
Reflect.set(currentConfigColumn, 'orderFiled', {})
Reflect.set(currentConfigColumn, 'scriptName', '')
Reflect.set(currentConfigColumn, 'content', '')
}
}
)
const allFields = computed(() => {
return [
{
label: '普通字段',
options: orderFieldList.value.map((item) => {
return {
...item,
disabled: effectConfigs.value.some((v) => v.mapField == item.filedName)
}
}) })
},
{
label: '变量字段',
options: variableField.value.map((item) => {
return {
...item,
disabled: effectConfigs.value.some((v) => v.mapField == item.filedName)
}
})
}
]
})
/**重置popover配置表单 */
const resetConfigForm = () => {
Object.assign(currentConfigColumn, {
title: '',
content: '',
mapField: '',
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: ''
})
}
/** 脚本参数List */
const currentScriptParamsList = computed(() => {
const item: any = scriptList.value.find((v) => v.srciptName == currentConfigColumn.scriptName)
Reflect.set(currentConfigColumn, 'content', item?.scriptContent || '')
// 生成脚本参数表单
gScriptPs(item?.paramsName)
return item?.paramsName != null ? item.paramsName : []
})
/**通过选中的脚本生成脚本配置表单 */
const gScriptPs = (scriptNames: null | Recordable[] | undefined) => {
// 如果没有配置参数,清空脚本表单
if (scriptNames == null && scriptNames == undefined) {
scriptPs.value = {}
} else {
// 查询是否有已经设置过的值
const { title, groupTitle } = currentConfigColumn
const t = groupTitle ? `${groupTitle}__${title}` : title
const params = allMapConfigs.value[t].params
scriptNames.forEach((item) => {
Reflect.set(scriptPs.value, item.filedName, params[item.filedName] || '')
})
}
}
/** 保存字段映射及脚本的配置 */
const confirmConfig = () => {
// 合并脚本参数
Reflect.set(currentConfigColumn, 'params', scriptPs.value)
Reflect.set(currentConfigColumn, 'templateFileId', currentRow.templateFileId)
// 处理标题
const { title, groupTitle } = currentConfigColumn
// 保存本地配置
title && Reflect.set(allMapConfigs.value, title, cloneDeep(currentConfigColumn))
// 关闭popover // 关闭popover
popoverVisible.value = false popoverVisible.value = false
console.log('allMapConfigs.value', allMapConfigs.value)
}
const getScriptList = async () => {
const { data } = await apiGetScript()
scriptList.value = data.result
}
const getOrderFields = async () => {
const { data } = await apiGetOrderField()
orderFieldList.value = data.result
}
const getOrderVariableField = async () => {
const { data } = await getVariableField(currentRow.excelOrderId)
if (data.code != 200) {
ElMessage.warning(data.message)
}
variableField.value = data.result || []
} }
/**确认解析/转换的订单的状态 */ /**确认解析/转换的订单的状态 */
...@@ -465,13 +303,9 @@ const confirmOrderStatus = async (row: any) => { ...@@ -465,13 +303,9 @@ const confirmOrderStatus = async (row: any) => {
const saveOrderField = async () => { const saveOrderField = async () => {
const params = { const params = {
templateFileId: currentRow.templateFileId, templateFileId: currentRow.templateFileId,
confs: Object.values(allMapConfigs.value).filter((v) => { confs: Object.values(getAllMapConfigs.value).filter(
if (v.title !== '') { (v) => v.title !== '' && !!v.orderFiledConfs.length
v.templateFileId = currentRow.templateFileId )
return true
}
return false
})
} }
saveConfExcelFileOrderPage(params).then(({ data }) => { saveConfExcelFileOrderPage(params).then(({ data }) => {
...@@ -501,30 +335,13 @@ const confirmChange = async (row) => { ...@@ -501,30 +335,13 @@ const confirmChange = async (row) => {
} }
const toDetail = async (row: any) => { const toDetail = async (row: any) => {
allMapConfigs.value = {}
Object.assign(currentRow, row) Object.assign(currentRow, row)
const { res, titles, configs } = filterRunData(row.orders, true) const { res, titles, configs } = filterRunData(row.orders, true)
await getOrderVariableField()
const { data } = await getConfByExcelOrderId(row.excelOrderId) const { data } = await getConfByExcelOrderId(row.excelOrderId)
if (data.result.length) { data.result?.forEach((item: any) => {
const tmp = { configs[item.title] = item
title: '',
content: '',
mapField: '',
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: '',
params: {},
orderFiled: {}
}
data.result.forEach((item: any) => {
item.params == null && (item.params = {})
item.orderFiled == null && (item.orderFiled = {})
configs[item.title] = Object.assign({}, tmp, item)
}) })
}
// 排除通过循环不显示的column // 排除通过循环不显示的column
const excludeTitles = ['sortNum', '数据区', 'expendData'] const excludeTitles = ['sortNum', '数据区', 'expendData']
detailTable.value = res detailTable.value = res
...@@ -535,13 +352,7 @@ const toDetail = async (row: any) => { ...@@ -535,13 +352,7 @@ const toDetail = async (row: any) => {
Reflect.deleteProperty(configs, key) Reflect.deleteProperty(configs, key)
}) })
Object.assign(allMapConfigs.value, configs) excelChangeStore.setAllMapConfigs(configs)
console.log('allMapConfigs.value', allMapConfigs.value)
}
const filterObjKeys = (data: any) => {
return Object.keys(data).filter((v) => v !== '_X_ROW_KEY')
} }
/**批量删除行 */ /**批量删除行 */
...@@ -570,8 +381,6 @@ const onQuery = async () => { ...@@ -570,8 +381,6 @@ const onQuery = async () => {
onMounted(() => { onMounted(() => {
onQuery() onQuery()
getOrderFields()
getScriptList()
queryDict('excel_order_status') queryDict('excel_order_status')
}) })
</script> </script>
......
<template>
<!-- 字段映射设置 -->
<el-col>
<el-form-item label="对应字段" prop="mapField">
<el-select
v-model="item.mapField"
style="width: 220px"
filterable
placeholder="请选择"
@change="mapFieldChange"
clearable
>
<el-option-group v-for="group in getAllFields" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.filedName"
:label="item.fliedTitle"
:value="item.filedName"
:disabled="!!item.disabled"
/>
</el-option-group>
</el-select>
<el-button v-if="props.index != 0" circle type="danger" @click="emits('remove', props.index)"
><el-icon><CircleClose /></el-icon
></el-button>
</el-form-item>
</el-col>
<!-- 脚本设置 -->
<el-col :span="24" v-if="item.mapField">
<template v-for="(sitem, idx) in item.scripts">
<el-form-item :label="'脚本' + (idx ? idx + 1 : '')">
<el-row>
<el-col>
<el-select
style="width: 220px"
v-model="sitem.scriptName"
@change="(e) => scriptChange(sitem, e)"
clearable
>
<el-option
v-for="item in getScriptList"
:key="item.srciptName"
:value="item.srciptName"
:label="item.srciptName"
></el-option>
</el-select>
<span>
<el-button v-if="idx == 0" @click="addScript" type="primary" circle
><el-icon><Plus /></el-icon
></el-button>
<el-button v-if="idx != 0" @click="removeScript(idx)" type="danger" circle
><el-icon><Minus /></el-icon
></el-button>
</span>
</el-col>
<el-col v-if="sitem.scriptName" class="mt-1">
<el-input
type="textarea"
style="width: 220px"
disabled
rows="3"
v-model="sitem.content"
></el-input>
</el-col>
</el-row>
</el-form-item>
</template>
</el-col>
</template>
<script lang="ts" setup>
import { useExcelChangeStore } from '@/stores/excel'
import { Plus, Minus, CircleClose } from '@element-plus/icons-vue'
import { storeToRefs } from 'pinia'
import { watch } from 'vue'
const props = defineProps<{ item?: any; index: number }>()
const emits = defineEmits(['remove'])
const excelChangeStore = useExcelChangeStore()
const { getAllFields, getScriptList } = storeToRefs(excelChangeStore)
const scriptChange = (sitem, e) => {
if (e) {
sitem.content = getScriptList.value.find((item) => item.srciptName == e)?.scriptContent
} else {
sitem.content = ''
}
}
const mapFieldChange = (e) => {
if (e) {
getAllFields.value.some((items) => {
return items.options.some((item) => {
if (item.filedName == e) {
props.item.orderFiled = item
return true
}
return false
})
})
} else {
props.item.orderFiled = null
}
}
const removeScript = (index: number) => {
props.item.scripts.splice(index, 1)
}
const addScript = () => {
props.item.scripts.push({
content: '',
scriptName: ''
})
}
watch(
() => props.item.mapField,
(val) => {
// 如果有值,添加脚本
if (val && props.item.scripts.length == 0) {
props.item.scripts.push({
content: '',
scriptName: ''
})
}
}
)
</script>
<style lang="scss" scoped></style>
<template> <template>
<div> <el-scrollbar max-height="350px">
123 <el-form size="small" label-width="60px">
</div> <template v-for="(item, index) in configList" :key="item.time">
<ConfigFormItem :item="item" :index="index" @remove="removeMapField" />
<el-divider v-if="index + 1 != configList.length">{{ index + 2 }}映射字段 </el-divider>
</template>
</el-form>
</el-scrollbar>
<el-row type="flex" justify="center">
<el-button size="small" type="primary" @click="emits('confirm', configList)">确认</el-button>
<el-button size="small" type="primary" @click="addFormItem">添加字段</el-button>
<el-button size="small" @click="emits('cancel')">取消</el-button>
</el-row>
</template> </template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import type { Recordable } from '@/types/global'
import ConfigFormItem from './ConfigFormItem.vue'
import { cloneDeep } from 'loadsh'
import { ElMessage } from 'element-plus'
import { apiGetOrderField, apiGetScript, getVariableField } from '@/api/excel'
import { useExcelChangeStore } from '@/stores/excel'
/**
* 数据结构
* {templateFileId: '', confs: [{title: '',orderFiledConfs: [{mapField: '',orderFiled: {}, scripts: {}}], templateFileId: ''}]}
*/
const props = defineProps<{ title: string; currentRow: Recordable; currentConf: Recordable }>()
const emits = defineEmits(['cancel', 'confirm'])
const excelChangeStore = useExcelChangeStore()
const configList = ref<Recordable[]>([])
const getOrderVariableField = async () => {
const { data } = await getVariableField(props.currentRow.excelOrderId)
if (data.code != 200) {
ElMessage.warning(data.message)
}
excelChangeStore.setVariableField(data.result || [])
}
// 添加映射字段表单对象
const addFormItem = () => {
configList.value.push({
time: Date.now(),
mapField: '',
orderFiled: {},
scripts: []
})
}
const removeMapField = (index: number) => {
configList.value.splice(index, 1)
}
const getScriptList = async () => {
const { data } = await apiGetScript()
excelChangeStore.setScriptList(data.result)
}
const getOrderFields = async () => {
const { data } = await apiGetOrderField()
excelChangeStore.setOrderFieldList(data.result)
}
// 监听选中行变化
watch(
() => props.currentRow.excelOrderId,
(val) => {
getOrderVariableField()
},
{ immediate: true }
)
watch(
() => props.currentConf.title,
(val) => {
console.log('watch--props.currentConf.title', val, props.currentConf)
configList.value = cloneDeep(props.currentConf).orderFiledConfs.map((item, i) => {
item.time = Date.now() + i
return item
})
},
{
immediate: true
}
)
watch(
configList,
(val) => {
console.log('configList----', val)
excelChangeStore.setUsedFieldList(val)
},
{ deep: true }
)
onMounted(() => {
getScriptList()
getOrderFields()
})
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment