Commit c73c6180 authored by 何远江's avatar 何远江

添加订单转换

parent 0ca14499
...@@ -45,3 +45,48 @@ export const deleteCustomerEmails = (customerEmailIds: string) => { ...@@ -45,3 +45,48 @@ export const deleteCustomerEmails = (customerEmailIds: string) => {
headers: formHeader headers: formHeader
}) })
} }
/** excel文件解析列表 */
export const getExcelFileOrderPage = (params: any) => {
return axios.get('/api/excelFileOrder/page', {
params,
headers: formHeader
})
}
/** 设置订单字段 */
export const saveConfExcelFileOrderPage = (data: any) => {
return axios.post('/api/excelFileOrder/saveConf', data)
}
/** 批量删除 */
export const deleteExcelFileOrderById = (ids: any) => {
return axios.get('/api/excelFileOrder/batchDeleteByIds', {
params: { ids },
headers: formHeader
})
}
/** 转换订单 */
export const convertExcelFileOrder = (excelOrderId: string) => {
return axios.get('/api/excelFileOrder/convert', {
params: { excelOrderId },
headers: formHeader
})
}
/** 解析后确认订单 */
export const unconvertExcelFileOrder = (excelOrderId: string) => {
return axios.get('/api/excelFileOrder/unconvert', {
params: { excelOrderId },
headers: formHeader
})
}
/** 转换后确认订单 */
export const confirmExcelFileOrderById = (excelOrderId: string) => {
return axios.get('/api/excelFileOrder/confirmById', {
params: { excelOrderId },
headers: formHeader
})
}
...@@ -42,6 +42,14 @@ export const routes = [ ...@@ -42,6 +42,14 @@ export const routes = [
title: '订单文件' title: '订单文件'
} }
}, },
{
path: '/order/change',
name: 'OrderChange',
component: () => import('@/views/order/orderChange/OrderChange.vue'),
meta: {
title: '订单转换'
}
},
{ {
path: '/order/customer', path: '/order/customer',
name: 'OrderCustomer', name: 'OrderCustomer',
......
...@@ -83,6 +83,7 @@ export function handleRangeTitle(range: any) { ...@@ -83,6 +83,7 @@ export function handleRangeTitle(range: any) {
const title = { const title = {
title: '', title: '',
sheet: sheetNum, sheet: sheetNum,
numFlag: 'N',
row: !isVertical ? +beginRow + rowLen - 1 : endRow - rowLen - 1, row: !isVertical ? +beginRow + rowLen - 1 : endRow - rowLen - 1,
colum: isVertical ? +beginColum + columnLen - 1 : endColum - columnLen - 1 colum: isVertical ? +beginColum + columnLen - 1 : endColum - columnLen - 1
} }
...@@ -190,3 +191,58 @@ export function setRangeBackground(range: Recordable, bg: string, isChangeSheet: ...@@ -190,3 +191,58 @@ export function setRangeBackground(range: Recordable, bg: string, isChangeSheet:
false false
) )
} }
/**
* 解析后数据,处理表头和表格数据
* @param data
*/
export function filterRunData(data: any) {
const res: Recordable[] = []
const titles: string[] = []
// 映射字段配置生成
const configs: Recordable = {}
const temConf = {
title: '',
content: '',
mapField: '',
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: '',
params: {},
orderFiled: {}
}
data.forEach((row: any) => {
const rw: Recordable = {}
row.order.forEach((itm: any) => {
Reflect.set(rw, itm.title, itm.value)
if (!titles.includes(itm.title)) {
titles.push(itm.title)
Reflect.set(configs, itm.title, temConf)
}
})
// 是否有附加信息
// if (row?.groups?.length) {
// Reflect.set(rw, 'expendData', {})
// row.groups.forEach((itm: any) => {
// rw['expendData'][itm.title] = []
// const r: Recordable = {}
// itm.item.forEach((v: any) => {
// r[v.title] = v.value
// Reflect.set(configs, itm.title+'__'+v.title, temConf)
// })
// rw['expendData'][itm.title].push(r)
// })
// }
res.push(rw)
})
return {
res,
titles,
configs
}
}
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
<!-- <vxe-column field="customerEmailId" title="id" width="200"></vxe-column> --> <!-- <vxe-column field="customerEmailId" title="id" width="200"></vxe-column> -->
<vxe-column field="customerId_dictText" title="客户名称" width="200"></vxe-column> <vxe-column field="customerId_dictText" title="客户名称" width="200"></vxe-column>
<vxe-column field="email" title="邮箱地址"></vxe-column> <vxe-column field="email" title="邮箱地址"></vxe-column>
<vxe-column field="createTime" title="创建时间" width="180"></vxe-column>
<vxe-column field="action" title="操作" width="100"> <vxe-column field="action" title="操作" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" text size="small" @click="editRow(row)">修改</el-button> <el-button type="primary" text size="small" @click="editRow(row)">修改</el-button>
...@@ -109,7 +111,7 @@ const formState = reactive({ ...@@ -109,7 +111,7 @@ const formState = reactive({
customerId: '', customerId: '',
currentPage: 1, currentPage: 1,
pageSize: 10, pageSize: 10,
total: 0 total: 0,
}) })
const modalType = ref('') const modalType = ref('')
......
<template>
<div class="w-full h-full bg-white p-4">
<p class="font-bold text-lg leading-10 border-b-2">解析列表</p>
<el-form class="pt-4" :inline="true" :model="queryParams">
<el-form-item label="excelOrderId">
<el-input v-model="queryParams.excelOrderId" placeholder="" clearable />
</el-form-item>
<el-form-item label="templateFileId">
<el-input v-model="queryParams.templateFileId" placeholder="" clearable />
</el-form-item>
<el-form-item>
<el-button type="default" @click="onReset">重置</el-button>
<el-button type="primary" @click="onQuery">查询</el-button>
</el-form-item>
</el-form>
<div class="">
<vxe-toolbar>
<template #buttons>
<el-button type="danger" @click="removeRows">删除</el-button>
</template>
</vxe-toolbar>
<vxe-table
ref="xTable"
size="small"
min-height="460"
border
:loading="loading"
:data="tableData"
>
<vxe-column type="checkbox" width="50"></vxe-column>
<vxe-column field="fileId_dictText" title="文件名称"></vxe-column>
<vxe-column field="status_dictText" title="订单状态" width="200"></vxe-column>
<vxe-column field="createTime" title="创建时间" width="180"></vxe-column>
<vxe-column field="action" title="操作" width="120">
<template #default="{ row }">
<el-link style="font-size: 12px" type="primary" @click="toDetail(row)">查看</el-link>
<el-link
class="ml-1"
style="font-size: 12px"
v-if="row.status == 'un_confirm' || row.status == 'converted'"
type="primary"
@click="confirmOrderStatus(row)"
>确认</el-link
>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="small"
background
v-model:current-page="queryParams.currentPage"
v-model:page-size="queryParams.pageSize"
:total="queryParams.total"
@page-change="onQuery"
:layouts="['PrevPage', 'JumpNumber', 'NextPage', 'Sizes', 'FullJump', 'Total']"
>
</vxe-pager>
</div>
</div>
<vxe-modal v-model="detailVisible" title="解析详情" width="80%" show-footer>
<vxe-table
size="mini"
show-overflow="tooltip"
show-header-overflow="tooltip"
:data="detailTable"
border
:expand-config="expandConfig"
height="500"
>
<vxe-column title="行号" type="expand" width="120">
<template #default="{ row }">{{ row.sortNum }}</template>
<template #content="{ row, rowIndex }">
<div style="padding: 10px">
<template v-for="attchName of filterObjKeys(row.expendData)" :key="attchName">
<p>{{ attchName }}</p>
<vxe-table
:data="row.expendData[attchName]"
:header-row-style="{ background: '#f9f8f9' }"
min-height="120"
height="120"
size="mini"
show-overflow="tooltip"
show-header-overflow="tooltip"
style="width: 70vw"
border
>
<vxe-colgroup
v-for="key in filterObjKeys(row.expendData[attchName][0])"
:key="key"
:title="key"
>
<vxe-column :title="key" :field="key" width="200">
<template #header>
<div class="header-cell" @click="(e) => showPopover(e, key, attchName)">
<span>{{
allMapConfigs[attchName + '__' + key]?.orderFiled.fliedTitle || ''
}}</span>
<el-icon><Setting /></el-icon>
</div>
</template>
</vxe-column>
</vxe-colgroup>
</vxe-table>
</template>
</div>
</template>
</vxe-column>
<vxe-column title="数据区" width="120">
<template #default="{ row }">{{ row['数据区'] }}</template>
</vxe-column>
<template v-for="item in tableTitle" :key="item">
<vxe-colgroup :title="item">
<vxe-column :title="item" :field="item" width="200">
<template #header>
<div class="header-cell" @click="(e) => showPopover(e, item)">
<span>{{ allMapConfigs[item]?.orderFiled.fliedTitle || '' }}</span>
<el-icon><Setting /></el-icon>
</div>
</template>
</vxe-column>
</vxe-colgroup>
</template>
</vxe-table>
<el-popover
ref="popoverRef"
placement="bottom"
:virtual-ref="buttonRef"
trigger="click"
:title="currentConfigTitle"
:visible="popoverVisible"
virtual-triggering
width="360"
transition=""
>
<el-form size="small" label-width="7em" inline :model="currentConfigColumn">
<el-row>
<el-col :span="24">
<el-form-item label="对应字段" prop="mapField">
<el-select v-model="currentConfigColumn.mapField" :teleported="false" clearable>
<el-option
v-for="item in orderFieldList"
:key="item.filedName"
:value="item.filedName"
:label="item.fliedTitle"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" v-if="currentConfigColumn.mapField">
<el-form-item label="脚本">
<el-select 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">
<el-col :span="24">
<el-form-item :label="params.fliedTitle">
<el-input v-model="scriptPs[params.filedName]" />
</el-form-item>
</el-col>
</template>
<el-col :span="24" v-if="currentConfigColumn.scriptName">
<el-form-item label="脚本语句">
<el-input
rows="3"
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>
<template #footer>
<el-button @click="confirmChange">确认转换</el-button>
</template>
</vxe-modal>
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { Setting } from '@element-plus/icons-vue'
import { cloneDeep } from 'lodash-es'
import {
confirmExcelFileOrderById,
convertExcelFileOrder,
deleteExcelFileOrderById,
getExcelFileOrderPage,
unconvertExcelFileOrder
} from '@/api/order'
import { ElMessage, ElMessageBox, ClickOutside as vClickOutside } from 'element-plus'
import type { VxeTableInstance } from 'vxe-table'
import type { Recordable } from '@/types/global'
import { filterRunData } from '@/utils/excel'
import { apiGetOrderField, apiGetScript } from '@/api/excel'
const loading = ref(false)
/**查询参数 */
const queryParams = reactive({
templateFileId: '',
excelOrderId: '',
currentPage: 1,
pageSize: 10,
total: 0,
column: 'createTime',
order: 'desc'
})
/**所有列映射配置 */
const allMapConfigs = reactive<Recordable>({})
/**当前表单映射字段配置 */
const currentConfigColumn = reactive({
title: '',
content: '',
mapField: '',
scriptName: '',
groupTitle: '',
templateFileId: '',
excelOrderFiledConfId: '',
params: {},
orderFiled: {}
})
const currentConfigTitle = ref('')
const scriptPs = ref<Recordable>({})
/**所有脚本 */
const scriptList = ref<Recordable[]>([])
/**所有映射字段 */
const orderFieldList = ref<Recordable[]>([])
const xTable = ref<VxeTableInstance>()
const tableData = ref([])
/**当前选择行 */
const currentRow = reactive<Recordable>({})
/**弹窗显示 */
const detailVisible = ref(false)
/**详情表格数据 */
const detailTable = ref<Recordable[]>([])
/**表格title */
const tableTitle = ref<string[]>([])
const expandConfig = reactive({
visibleMethod({ row }) {
if (typeof row.expendData === 'object') {
return true
}
return false
}
})
const popoverRef = ref()
const buttonRef = ref()
const popoverVisible = ref(false)
const showPopover = (e: any, title: string, groupTitle: string = '') => {
buttonRef.value = e.target
const t = groupTitle ? `${groupTitle}-${title}` : title
// 设置标题
currentConfigTitle.value = t
Object.assign(currentConfigColumn, { ...allMapConfigs[t], title, groupTitle })
// 打开popover
popoverVisible.value = true
}
/**监听popover和modal显示状态。重置表单信息 */
watch([detailVisible, popoverVisible], (val) => {
// 关闭弹窗或者关闭popover
if (val.includes(false)) {
// 解决关闭弹窗之后,popover未关闭情况
popoverVisible.value = false
// 重置表单
resetConfigForm()
}
})
/**监听currentConfigColumn.mapField字段,重置/设置 orderFiled */
watch(
() => currentConfigColumn.mapField,
(val) => {
// 如果有值设置 currentConfigColumn.orderFiled字段
if (val) {
const item = orderFieldList.value.find((v) => v.filedName == val)
Reflect.set(currentConfigColumn, 'orderFiled', item)
} else {
Reflect.set(currentConfigColumn, 'orderFiled', {})
Reflect.set(currentConfigColumn, 'scriptName', '')
Reflect.set(currentConfigColumn, 'content', '')
}
}
)
/**重置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)
// 生成脚本参数表单
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[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,
groupTitle ? `${groupTitle}__${title}` : title,
cloneDeep(currentConfigColumn)
)
// 关闭popover
popoverVisible.value = false
console.log('allMapConfigs', allMapConfigs)
}
const getScriptList = async () => {
const { data } = await apiGetScript()
scriptList.value = data.result
}
const getOrderFields = async () => {
const { data } = await apiGetOrderField()
orderFieldList.value = data.result
}
/**确认解析/转换的订单的状态 */
const confirmOrderStatus = async (row: any) => {
if (row.status === 'un_confirm') {
await ElMessageBox.confirm('是否确认解析后的订单?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
const { data } = await unconvertExcelFileOrder(row.excelOrderId)
if (data.code == 200) {
ElMessage.success(data.message || '操作成功!')
}
} else if (row.status == 'converted') {
await ElMessageBox.confirm('是否确认转换后的订单?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
const {data} = await confirmExcelFileOrderById(row.excelOrderId)
if (data.code == 200) {
ElMessage.success(data.message || '操作成功!')
} else {
ElMessage.error(data.message || '操作失败!')
}
}
onQuery()
}
/** 确认订单转换 */
const confirmChange = async () => {
await ElMessageBox.confirm('是否确认订单转换?', '提示', {
confirmButtonText: '转换',
cancelButtonText: '取消',
type: 'warning'
})
const { data } = await convertExcelFileOrder(currentRow.excelOrderId)
if (data.code == 200) {
ElMessage.success(data.message || '转换成功!')
detailVisible.value = false
return
}
ElMessage.error(data.message || '转换失败!')
}
const toDetail = (row: any) => {
Object.assign(currentRow, row)
const { res, titles, configs } = filterRunData(row.orders)
// 排除通过循环不显示的column
const excludeTitles = ['sortNum', '数据区', 'expendData']
detailTable.value = res
tableTitle.value = titles.filter((v) => !excludeTitles.includes(v))
detailVisible.value = true
excludeTitles.forEach((key) => {
Reflect.deleteProperty(configs, key)
})
Object.assign(allMapConfigs, configs)
}
const filterObjKeys = (data: any) => {
return Object.keys(data).filter((v) => v !== '_X_ROW_KEY')
}
/**批量删除行 */
const removeRows = async () => {
const list = xTable.value?.getCheckboxRecords()
if (list?.length) {
const ids = list.map((v) => v.excelOrderId).join(',')
await deleteExcelFileOrderById(ids)
ElMessage.success('删除成功')
onQuery()
}
}
const onReset = () => {}
const onQuery = async () => {
loading.value = true
try {
const { data } = await getExcelFileOrderPage(queryParams)
tableData.value = data.result.records
queryParams.total = +data.result.total
} catch {}
loading.value = false
}
onMounted(() => {
onQuery()
getOrderFields()
getScriptList()
})
</script>
<style lang="scss" scoped>
.header-cell {
display: flex;
justify-content: space-between;
align-items: center;
width: 178px;
}
.expandTableHeader {
background: #e8eaec;
}
</style>
<template>
<div>
123
</div>
</template>
\ No newline at end of file
...@@ -26,18 +26,20 @@ ...@@ -26,18 +26,20 @@
size="small" size="small"
min-height="460" min-height="460"
border border
show-overflow='ellipsis'
:loading="loading" :loading="loading"
:data="tableData" :data="tableData"
> >
<vxe-column type="checkbox" width="50"></vxe-column> <vxe-column type="checkbox" width="50"></vxe-column>
<!-- <vxe-column field="orderFileId" title="文件id" width="200"></vxe-column> --> <!-- <vxe-column field="orderFileId" title="文件id" width="200"></vxe-column> -->
<vxe-column field="customerId_dictText" title="客户名称" width="200"></vxe-column> <vxe-column field="customerId_dictText" title="客户名称" width="120"></vxe-column>
<vxe-column field="filePath" title="原始文件地址"></vxe-column> <vxe-column field="filePath" title="原始文件地址"></vxe-column>
<vxe-column field="mergeFilePath" title="标注文件地址"></vxe-column> <vxe-column field="mergeFilePath" title="标注文件地址"></vxe-column>
<vxe-column field="action" title="操作" width="140"> <vxe-column field="createTime" title="创建时间" width="180"></vxe-column>
<vxe-column field="action" title="操作" width="80">
<template #default="{row}"> <template #default="{row}">
<el-button type="primary" text size="small" @click="toDetail(row)">查看</el-button> <el-button type="primary" text size="small" @click="toDetail2(row)">查看</el-button>
<el-button type="primary" text size="small" @click="toDetail2(row)">查看新</el-button> <!-- <el-button type="primary" text size="small" @click="toDetail2(row)">查看新</el-button> -->
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
...@@ -72,7 +74,7 @@ const formState = reactive({ ...@@ -72,7 +74,7 @@ const formState = reactive({
currentPage: 1, currentPage: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
column: 'orderFileId', column: 'createTime',
order: 'desc' order: 'desc'
}) })
......
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