Browse Source

供应商

master
常熟吴彦祖 2 months ago
parent
commit
005c6c234b
  1. 9
      src/api/order/poOrder.js
  2. 172
      src/views/modules/order/com_poOrderAdvancedQuery.vue
  3. 142
      src/views/modules/order/poOrder.vue
  4. 89
      src/views/modules/order/poOrderAdvancedQueryConfig.js
  5. 72
      src/views/modules/order/poOrderAdvancedQueryHelper.js
  6. 57
      src/views/modules/order/poOrderStatusOptions.js
  7. 108
      src/views/modules/order/poOrder_search.vue

9
src/api/order/poOrder.js

@ -3,6 +3,9 @@ import { createAPI } from '@/utils/httpRequest.js'
export const searchPoDetailList = (data) => createAPI(`/pODetail/list`, 'post', data) export const searchPoDetailList = (data) => createAPI(`/pODetail/list`, 'post', data)
export const searchPoDetailPage = (data) => createAPI(`/pODetail/page`, 'post', data) export const searchPoDetailPage = (data) => createAPI(`/pODetail/page`, 'post', data)
/** PO 高级查询(动态条件 AND + 顶部基础筛选,独立于 searchPoDetailPage) */
export const searchPoDetailAdvancedPage = (data) => createAPI(`/pODetail/advancedPage`, 'post', data)
export const createPoDetail = (data) => createAPI(`/pODetail/save`, 'post', data) export const createPoDetail = (data) => createAPI(`/pODetail/save`, 'post', data)
export const updatePoDetail = (data) => createAPI(`/pODetail/save`, 'post', data) export const updatePoDetail = (data) => createAPI(`/pODetail/save`, 'post', data)
export const deletePoDetail = (data) => createAPI(`/pODetail/delete`, 'post', data) export const deletePoDetail = (data) => createAPI(`/pODetail/delete`, 'post', data)
@ -10,5 +13,11 @@ export const deletePoDetail = (data) => createAPI(`/pODetail/delete`, 'post', da
//批量更新 //批量更新
export const batchUpdatePoDetail = (data) => createAPI(`/pODetail/batchUpdatePoDetail`, 'post', data) export const batchUpdatePoDetail = (data) => createAPI(`/pODetail/batchUpdatePoDetail`, 'post', data)
/** 关闭 PO 订单行(status → 已关闭) */
export const closePoDetail = (data) => createAPI(`/pODetail/closePoDetail`, 'post', data)
/** 打开 PO 订单行(已关闭 → 按验货数量恢复状态) */
export const openPoDetail = (data) => createAPI(`/pODetail/openPoDetail`, 'post', data)
// 根据PO订单查询验货申请明细 // 根据PO订单查询验货申请明细
export const getInspectionByPODetail = (data) => createAPI(`/pODetail/getInspectionByPODetail`, 'post', data) export const getInspectionByPODetail = (data) => createAPI(`/pODetail/getInspectionByPODetail`, 'post', data)

172
src/views/modules/order/com_poOrderAdvancedQuery.vue

@ -0,0 +1,172 @@
<template>
<!--
AI 维护高级查询弹窗poOrder / poOrder_search 共用
样式参考com_part_SpecParams.vue 属性填写表格 + .rq 紧凑行高
-->
<el-dialog
title="高级查询"
:visible.sync="dialogVisible"
width="900px"
top="3vh"
:close-on-click-modal="false"
v-drag
append-to-body
custom-class="po-advanced-query-dialog"
@open="handleOpen"
@close="handleClose">
<div class="rq po-advanced-query-body">
<el-table
:height="tableHeight"
:data="advancedQueryData.rows"
border
style="width: 100%;">
<el-table-column
prop="label"
label="字段"
header-align="center"
align="left"
min-width="200"
show-overflow-tooltip />
<el-table-column
label="运算符"
header-align="center"
align="center"
width="120">
<template slot-scope="{ row }">
<el-select v-model="row.operator" style="width: 100%;">
<el-option
v-for="op in getOperatorsByDataType(row.dataType)"
:key="op.value"
:label="op.label"
:value="op.value" />
</el-select>
</template>
</el-table-column>
<el-table-column
label="值"
header-align="center"
align="left"
min-width="220">
<template slot-scope="{ row }">
<el-input v-model="row.value" clearable placeholder="留空则不参与筛选" />
</template>
</el-table-column>
</el-table>
<el-footer style="height:25px;margin-top: 10px;text-align:center">
<el-button @click="handleReset">重置</el-button>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleQuery">查询</el-button>
</el-footer>
</div>
</el-dialog>
</template>
<script>
import { getOperatorsByDataType } from './poOrderAdvancedQueryConfig.js'
import { resetAdvancedQueryData } from './poOrderAdvancedQueryHelper.js'
export default {
name: 'PoOrderAdvancedQuery',
props: {
visible: {
type: Boolean,
default: false
},
advancedQueryData: {
type: Object,
required: true
}
},
data () {
return {
tableHeight: 400
}
},
computed: {
dialogVisible: {
get () {
return this.visible
},
set (val) {
this.$emit('update:visible', val)
}
}
},
beforeDestroy () {
window.removeEventListener('resize', this.calcTableHeight)
},
methods: {
getOperatorsByDataType,
handleOpen () {
this.calcTableHeight()
window.addEventListener('resize', this.calcTableHeight)
},
calcTableHeight () {
this.$nextTick(() => {
const vh = window.innerHeight || 800
// dialog + + +
const reserved = 130
this.tableHeight = Math.max(260, Math.min(Math.floor(vh * 0.72) - reserved, 560))
})
},
handleReset () {
resetAdvancedQueryData(this.advancedQueryData)
this.$emit('reset')
},
handleQuery () {
window.removeEventListener('resize', this.calcTableHeight)
this.dialogVisible = false
this.$emit('query')
},
handleClose () {
window.removeEventListener('resize', this.calcTableHeight)
this.$emit('update:visible', false)
}
}
}
</script>
<style scoped lang="scss">
.po-advanced-query-body {
padding: 0 2px;
}
.po-advanced-query-footer {
height: 40px;
margin-top: 12px;
padding: 0;
text-align: center;
line-height: 40px;
}
/* 与产品清单属性填写 com_part_SpecParams 一致的紧凑表格行高 */
.rq.po-advanced-query-body /deep/ .el-table .cell {
line-height: 28px;
font-size: 12px;
height: 28px;
padding: 2px 4px;
}
.rq.po-advanced-query-body /deep/ .el-input__inner {
height: 26px;
line-height: 26px;
font-size: 12px;
}
.rq.po-advanced-query-body /deep/ .el-input__icon {
line-height: 26px;
}
.rq.po-advanced-query-body /deep/ .el-table td,
.rq.po-advanced-query-body /deep/ .el-table th {
padding: 2px 0;
}
</style>
<style lang="scss">
/* 弹窗 body 不出现双滚动条,表格区域单独滚动 */
.po-advanced-query-dialog .el-dialog__body {
padding: 10px 16px 12px;
overflow: hidden;
}
</style>

142
src/views/modules/order/poOrder.vue

@ -1,12 +1,6 @@
<template> <template>
<div class="mod-config"> <div class="mod-config">
<el-form :inline="true" label-position="top" :model="searchData"> <el-form :inline="true" label-position="top" :model="searchData">
<el-form-item label="Customer">
<el-input v-model="searchData.customer" clearable style="width: 120px"></el-input>
</el-form-item>
<el-form-item label="Buyer">
<el-input v-model="searchData.buyer" clearable style="width: 120px"></el-input>
</el-form-item>
<el-form-item label="PO No"> <el-form-item label="PO No">
<el-input v-model="searchData.poNo" clearable style="width: 140px"></el-input> <el-input v-model="searchData.poNo" clearable style="width: 140px"></el-input>
</el-form-item> </el-form-item>
@ -16,16 +10,19 @@
<el-form-item label="Status"> <el-form-item label="Status">
<el-select v-model="searchData.status" placeholder="请选择" style="width:100px" clearable> <el-select v-model="searchData.status" placeholder="请选择" style="width:100px" clearable>
<el-option label="全部" value=""></el-option> <el-option label="全部" value=""></el-option>
<el-option label="已下达" value="已下达"></el-option>
<el-option label="已取消" value="已取消"></el-option>
<el-option
v-for="item in poOrderStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form :inline="true" label-position="top" style="margin-top:10px "> <el-form :inline="true" label-position="top" style="margin-top:10px ">
<el-form-item> <el-form-item>
<el-button type="primary" @click="getDataList()" v-if="!editMode">查询</el-button>
<el-button type="primary" @click="handleSearch()" v-if="!editMode">查询</el-button>
<el-button type="warning" plain @click="advancedQueryVisible = true" v-if="!editMode" style="margin-left: 2px">高级查询</el-button>
<el-button type="primary" style="margin-left: 2px" @click="toggleEditMode"> <el-button type="primary" style="margin-left: 2px" @click="toggleEditMode">
{{ editMode ? '确定' : '编辑' }} {{ editMode ? '确定' : '编辑' }}
</el-button> </el-button>
@ -40,6 +37,24 @@
highlight-current-row highlight-current-row
style="width: 100%;" style="width: 100%;"
@current-change="onTableCurrentChange"> @current-change="onTableCurrentChange">
<el-table-column
v-if="!editMode"
fixed="left"
label="操作"
header-align="center"
align="center"
width="70">
<template slot-scope="scope">
<el-link
v-if="canClosePoOrder(scope.row.status)"
type="primary"
@click.stop="handleClosePoOrder(scope.row)">关闭</el-link>
<el-link
v-if="canOpenPoOrder(scope.row.status)"
type="primary"
@click.stop="handleOpenPoOrder(scope.row)">打开</el-link>
</template>
</el-table-column>
<el-table-column <el-table-column
v-for="(item, index) in visibleColumns" v-for="(item, index) in visibleColumns"
:key="item.serialNumber || index" :key="item.serialNumber || index"
@ -250,20 +265,38 @@
<!-- 运输方式选择弹窗 --> <!-- 运输方式选择弹窗 -->
<Chooselist ref="shipViaList" @getBaseData="getShipViaData"></Chooselist> <Chooselist ref="shipViaList" @getBaseData="getShipViaData"></Chooselist>
<po-order-advanced-query
:visible.sync="advancedQueryVisible"
:advanced-query-data="advancedQueryData"
@query="handleSearch" />
</div> </div>
</template> </template>
<script> <script>
import { searchPoDetailPage, batchUpdatePoDetail } from '@/api/order/poOrder.js'
import { searchPoDetailPage, searchPoDetailAdvancedPage, batchUpdatePoDetail, closePoDetail, openPoDetail } from '@/api/order/poOrder.js'
import {
createAdvancedQueryData,
buildPoOrderQueryParams
} from './poOrderAdvancedQueryHelper.js'
import {
PO_ORDER_STATUS_OPTIONS,
canClosePoOrder,
canOpenPoOrder,
resolvePoOrderStatusByInspectQty,
buildPoDetailActionParams
} from './poOrderStatusOptions.js'
import { getPartList } from '@/api/part/partInfo.js' import { getPartList } from '@/api/part/partInfo.js'
import { checkSrmSupplierList } from '@/api/srm/srmSupplier.js' import { checkSrmSupplierList } from '@/api/srm/srmSupplier.js'
import { searchTransportOptions } from '@/api/port/portTransit.js' import { searchTransportOptions } from '@/api/port/portTransit.js'
import Chooselist from '@/views/modules/common/Chooselist.vue' import Chooselist from '@/views/modules/common/Chooselist.vue'
import PoOrderAdvancedQuery from './com_poOrderAdvancedQuery.vue'
export default { export default {
name: 'PoOrder', name: 'PoOrder',
components: { components: {
Chooselist
Chooselist,
PoOrderAdvancedQuery
}, },
data () { data () {
return { return {
@ -299,10 +332,7 @@ export default {
currentRow: null, currentRow: null,
// select selectOptionsKey selectOptions - rqrq // select selectOptionsKey selectOptions - rqrq
columnSelectOptions: { columnSelectOptions: {
poStatusOptions: [
{ label: '已下达', value: '已下达' },
{ label: '已取消', value: '已取消' }
],
poStatusOptions: PO_ORDER_STATUS_OPTIONS,
poPartNoOptions: [], poPartNoOptions: [],
poDepartureOptions: [], poDepartureOptions: [],
transportOptions: [ transportOptions: [
@ -323,6 +353,10 @@ export default {
sku: '', sku: '',
status: '' status: ''
}, },
advancedQueryVisible: false,
/** 高级查询条件对象(查询均读取;仅弹窗内「重置」可清空) */
advancedQueryData: createAdvancedQueryData(),
poOrderStatusOptions: PO_ORDER_STATUS_OPTIONS,
height: 400, height: 400,
pageIndex: 1, pageIndex: 1,
pageSize: 20, pageSize: 20,
@ -785,7 +819,7 @@ export default {
fixed: '', fixed: '',
columnWidth: 80, columnWidth: 80,
showOverflowTooltip: true, showOverflowTooltip: true,
editAble: true,
editAble: false,
editType: 'select', editType: 'select',
selectOptionsKey: 'poStatusOptions', selectOptionsKey: 'poStatusOptions',
selectOptions: null selectOptions: null
@ -1269,6 +1303,54 @@ export default {
}) })
}, },
methods: { methods: {
canClosePoOrder,
canOpenPoOrder,
handleClosePoOrder (row) {
const params = buildPoDetailActionParams(row, this.$store.state.user.site)
if (!params.id && !(params.orderNo && params.site && params.itemNo != null)) {
this.$message.error('无法识别订单行,请刷新后重试')
return
}
const poLabel = row.poNo ? `PO ${row.poNo}` : '该订单'
const itemLabel = row.itemNo != null ? `${row.itemNo}` : ''
this.$confirm(`确定关闭${poLabel}${itemLabel}`, '提示', { type: 'warning' }).then(() => {
closePoDetail(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('关闭成功')
this.getDataList()
} else {
this.$message.error((data && data.msg) || '关闭失败')
}
}).catch(err => {
this.$message.error((err && err.message) || '关闭失败')
})
}).catch(() => {})
},
handleOpenPoOrder (row) {
const params = buildPoDetailActionParams(row, this.$store.state.user.site)
if (!params.id && !(params.orderNo && params.site && params.itemNo != null)) {
this.$message.error('无法识别订单行,请刷新后重试')
return
}
const poLabel = row.poNo ? `PO ${row.poNo}` : '该订单'
const itemLabel = row.itemNo != null ? `${row.itemNo}` : ''
const targetStatus = resolvePoOrderStatusByInspectQty(row)
this.$confirm(`确定打开${poLabel}${itemLabel}?恢复状态为:${targetStatus}`, '提示', { type: 'warning' }).then(() => {
openPoDetail(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('打开成功')
this.getDataList()
} else {
this.$message.error((data && data.msg) || '打开失败')
}
}).catch(err => {
this.$message.error((err && err.message) || '打开失败')
})
}).catch(() => {})
},
/** /**
* 表格当前行变化将选中行深拷贝到 currentRow取消选中时为 null - rqrq * 表格当前行变化将选中行深拷贝到 currentRow取消选中时为 null - rqrq
*/ */
@ -1294,20 +1376,30 @@ export default {
return [] return []
}, },
getDataList() {
this.loading = true
const params = {
...this.searchData,
buildQueryRequest() {
return buildPoOrderQueryParams({
searchData: this.searchData,
advancedQueryData: this.advancedQueryData,
page: this.pageIndex, page: this.pageIndex,
limit: this.pageSize limit: this.pageSize
}
searchPoDetailPage(params).then(({ data }) => {
})
},
handleSearch() {
this.pageIndex = 1
this.getDataList()
},
getDataList() {
this.loading = true
const { params, useAdvanced } = this.buildQueryRequest()
const request = useAdvanced ? searchPoDetailAdvancedPage(params) : searchPoDetailPage(params)
request.then(({ data }) => {
if (data.code === 0) { if (data.code === 0) {
this.dataList = data.page.list this.dataList = data.page.list
// dataList masterRows changeFlag
this.masterRows = this.dataList.map(row => ({ this.masterRows = this.dataList.map(row => ({
...row, ...row,
changeFlag: 0 //
changeFlag: 0
})) }))
this.pageIndex = data.page.currPage this.pageIndex = data.page.currPage

89
src/views/modules/order/poOrderAdvancedQueryConfig.js

@ -0,0 +1,89 @@
/**
* =============================================================================
* 高级查询静态配置 - AI 维护说明
*
* 修改以下任一内容时必须同步重新生成 PO_ADVANCED_QUERY_FIELD_CONFIG
* 1. poOrder_search.vue columnListcolumnProp / columnLabel / 顺序
* 2. PODetailMapper.xml myPage / myPageAdvanced SELECT 字段及别名
* 3. 运算符规则ADVANCED_QUERY_OPERATOR_OPTIONS / getOperatorsByDataType
*
* 生成规则
* - field = columnProp columnList 完全一致
* - label = columnLabel
* - sortOrder = columnList 顺序 1 开始
* - sqlColumn = myPage SELECT 中可用于 WHERE 的完整 SQL 表达式含表别名函数
* poh.c_enquiryss.supplier_nameCOALESCE(pod.inspect_approve_qty, 0)
* - dataType = string | number | date
*
* 同步修改后端白名单必须与 sqlColumn 完全一致
* PoDetailAdvancedQuerySupport.java FIELD_SQL_MAP
*
* 最后更新2026-06-25
* 对照poOrder_search.vue columnList + PODetailMapper.xml#myPage SELECT
* =============================================================================
*/
/** 运算符:前端 value → 后端 operator(条件之间固定 AND) */
export const ADVANCED_QUERY_OPERATOR_OPTIONS = [
{ label: '等于', value: 'eq' },
{ label: '包含', value: 'contains' },
{ label: '大于', value: 'gt' },
{ label: '小于', value: 'lt' },
{ label: '大于等于', value: 'gte' },
{ label: '小于等于', value: 'lte' }
]
/** 按 dataType 过滤可用运算符(number/date 不提供「包含」) */
export function getOperatorsByDataType (dataType) {
if (dataType === 'string') {
return ADVANCED_QUERY_OPERATOR_OPTIONS
}
return ADVANCED_QUERY_OPERATOR_OPTIONS.filter(o => o.value !== 'contains')
}
/**
* 高级查询字段配置 顺序与 poOrder_search.vue / poOrder.vue 表格 columnList 一致
* sqlColumn多表关联完整表达式计算列写函数表达式
*/
export const PO_ADVANCED_QUERY_FIELD_CONFIG = [
{ sortOrder: 1, field: 'customer', label: 'Customer', sqlColumn: 'poh.c_customer', dataType: 'string' },
{ sortOrder: 2, field: 'buyer', label: 'Buyer', sqlColumn: 'poh.buyer', dataType: 'string' },
{ sortOrder: 3, field: 'supplierName', label: 'Vendor Name', sqlColumn: 'ss.supplier_name', dataType: 'string' },
{ sortOrder: 4, field: 'shortOffice', label: 'V_Short_Office', sqlColumn: 'ss.c_short_office', dataType: 'string' },
{ sortOrder: 5, field: 'shortNpc', label: 'V_Short_NPC', sqlColumn: 'ss.c_short_npc', dataType: 'string' },
{ sortOrder: 6, field: 'poNo', label: 'PO_No', sqlColumn: 'poh.po_no', dataType: 'string' },
{ sortOrder: 7, field: 'partNo', label: 'Item', sqlColumn: 'pod.part_no', dataType: 'string' },
{ sortOrder: 8, field: 'category', label: 'Category', sqlColumn: 'p.category', dataType: 'string' },
{ sortOrder: 9, field: 'sku', label: 'SKU', sqlColumn: 'p.sku', dataType: 'string' },
{ sortOrder: 10, field: 'price', label: 'Unit Price', sqlColumn: 'pod.price', dataType: 'number' },
{ sortOrder: 11, field: 'qty', label: 'PO Qty', sqlColumn: 'pod.qty', dataType: 'number' },
{ sortOrder: 12, field: 'value', label: 'PO Value', sqlColumn: 'pod.c_value', dataType: 'number' },
{ sortOrder: 13, field: 'shipQty', label: 'A-Qty', sqlColumn: 'pod.c_ship_qty', dataType: 'number' },
{ sortOrder: 14, field: 'sumPrice', label: 'A-Value', sqlColumn: 'pod.c_sum_price', dataType: 'number' },
{ sortOrder: 15, field: 'departure', label: 'Departure Port', sqlColumn: 'poh.c_departure', dataType: 'string' },
{ sortOrder: 16, field: 'destination', label: 'Destination Port', sqlColumn: 'poh.c_destination', dataType: 'string' },
{ sortOrder: 17, field: 'shipVia', label: 'Method', sqlColumn: 'poh.ship_via', dataType: 'string' },
{ sortOrder: 18, field: 'orderDate', label: 'Buyer Release Date', sqlColumn: 'poh.order_date', dataType: 'date' },
{ sortOrder: 19, field: 'enquiry', label: 'Planner Release Date', sqlColumn: 'poh.c_enquiry', dataType: 'date' },
{ sortOrder: 20, field: 'status', label: 'Status', sqlColumn: 'pod.status', dataType: 'string' },
{ sortOrder: 21, field: 'confirmed', label: 'PI Confirmed Date', sqlColumn: 'poh.c_confirmed', dataType: 'date' },
{ sortOrder: 22, field: 'wantReceiveDate', label: 'Original Arrival Date', sqlColumn: 'pod.want_receive_date', dataType: 'date' },
{ sortOrder: 23, field: 'narrival', label: 'Final Confirmed Arrival Date', sqlColumn: 'pod.c_narrival', dataType: 'date' },
{ sortOrder: 24, field: 'crd', label: 'PI Confirmed CRD', sqlColumn: 'pod.c_crd', dataType: 'date' },
{ sortOrder: 25, field: 'inspection', label: 'Inspection Date', sqlColumn: 'pod.c_inspection', dataType: 'date' },
{ sortOrder: 26, field: 'realCrd', label: 'Actual Completion Date', sqlColumn: 'pod.c_real_crd', dataType: 'date' },
{ sortOrder: 27, field: 'eta', label: 'ETA', sqlColumn: 'pod.c_eta', dataType: 'date' },
{ sortOrder: 28, field: 'flexid', label: 'Flexport Id', sqlColumn: 'pod.c_flexid', dataType: 'string' },
{ sortOrder: 29, field: 'obd', label: 'On Board Date', sqlColumn: 'pod.c_obd', dataType: 'date' },
{ sortOrder: 30, field: 'docSent', label: 'Doc Sent', sqlColumn: 'pod.c_doc_sent', dataType: 'string' },
{ sortOrder: 31, field: 'telexRelease', label: 'Telex Release', sqlColumn: 'pod.c_telex_release', dataType: 'string' },
{ sortOrder: 32, field: 'advancePayment', label: 'Advance Payment', sqlColumn: 'pod.c_advance_payment', dataType: 'string' },
{ sortOrder: 33, field: 'advancePaid', label: 'Advanc Paid', sqlColumn: 'pod.c_advance_paid', dataType: 'string' },
{ sortOrder: 34, field: 'createTime', label: 'Create Date', sqlColumn: 'pod.create_time', dataType: 'date' },
{ sortOrder: 35, field: 'planner', label: 'M-Planner', sqlColumn: 'pod.c_planner', dataType: 'string' },
{ sortOrder: 36, field: 'edit', label: 'Edit Date', sqlColumn: 'pod.c_edit', dataType: 'string' },
{ sortOrder: 37, field: 'endPlanner', label: 'Last Editor', sqlColumn: 'pod.c_end_planner', dataType: 'string' },
{ sortOrder: 38, field: 'remarkDelay', label: 'Remark Delay', sqlColumn: 'pod.c_remark_delay', dataType: 'string' },
{ sortOrder: 39, field: 'remark', label: 'Comments', sqlColumn: 'pod.remark', dataType: 'string' },
{ sortOrder: 40, field: 'inspectionCompletedQty', label: 'Inspection Completed Qty', sqlColumn: 'COALESCE(pod.inspect_approve_qty, 0)', dataType: 'number' }
]

72
src/views/modules/order/poOrderAdvancedQueryHelper.js

@ -0,0 +1,72 @@
import { PO_ADVANCED_QUERY_FIELD_CONFIG } from './poOrderAdvancedQueryConfig.js'
/**
* AI 维护高级查询状态对象工厂
* advancedQueryData 为页面级唯一对象查询/导出均读取此对象
*/
export function createAdvancedQueryData () {
return {
rows: PO_ADVANCED_QUERY_FIELD_CONFIG.map(item => ({
field: item.field,
label: item.label,
dataType: item.dataType,
sqlColumn: item.sqlColumn,
operator: item.dataType === 'string' ? 'contains' : 'eq',
value: ''
}))
}
}
/** 重置高级查询(仅弹窗内「重置」按钮调用,外部重置不清空) */
export function resetAdvancedQueryData (advancedQueryData) {
advancedQueryData.rows = createAdvancedQueryData().rows
}
/** 收集有效高级条件(AND,空 value 跳过) */
export function getActiveAdvancedConditions (advancedQueryData) {
if (!advancedQueryData || !advancedQueryData.rows) {
return []
}
return advancedQueryData.rows
.filter(r => r.value != null && String(r.value).trim() !== '')
.map(r => ({
field: r.field,
operator: r.operator,
value: String(r.value).trim()
}))
}
export function hasActiveAdvancedConditions (advancedQueryData) {
return getActiveAdvancedConditions(advancedQueryData).length > 0
}
/**
* 组装查询/导出参数
* - 有高级条件时走 advancedPage并附带 searchData 基础字段
* - 无高级条件时走原 page
*/
export function buildPoOrderQueryParams ({ searchData, advancedQueryData, page, limit }) {
const conditions = getActiveAdvancedConditions(advancedQueryData)
const baseParams = {
site: searchData.site,
page,
limit,
customer: searchData.customer || '',
buyer: searchData.buyer || '',
poNo: searchData.poNo || '',
sku: searchData.sku || '',
status: searchData.status || '',
supplierName: searchData.supplierName || '',
partNo: searchData.partNo || ''
}
if (conditions.length > 0) {
return {
params: { ...baseParams, conditions },
useAdvanced: true
}
}
return {
params: { ...searchData, page, limit },
useAdvanced: false
}
}

57
src/views/modules/order/poOrderStatusOptions.js

@ -0,0 +1,57 @@
/**
* PO 订单行状态选项静态数据查询下拉用不查库
*/
export const PO_ORDER_STATUS_OPTIONS = [
{ label: '已下达', value: '已下达' },
{ label: '待验货', value: '待验货' },
{ label: '验货中', value: '验货中' },
{ label: '验货完成', value: '验货完成' },
{ label: '已取消', value: '已取消' },
{ label: '已关闭', value: '已关闭' }
]
/** 是否可「关闭」 */
export function canClosePoOrder (status) {
return !!status && status !== '已关闭' && status !== '已取消'
}
/** 是否可「打开」(仅已关闭) */
export function canOpenPoOrder (status) {
return status === '已关闭'
}
/**
* 打开时根据验货数量推算恢复状态与后端 PoDetailStatusSupport 规则一致
*/
export function resolvePoOrderStatusByInspectQty (row) {
const toInspect = Number(row.toInspectQty != null ? row.toInspectQty : 0)
const approve = Number(row.inspectApproveQty != null ? row.inspectApproveQty : (row.inspectionCompletedQty != null ? row.inspectionCompletedQty : 0))
const qty = Number(row.qty != null ? row.qty : 0)
if (toInspect === 0) {
return '已下达'
}
if (toInspect > 0 && approve === 0) {
return '待验货'
}
if (qty > 0 && approve === qty) {
return '验货完成'
}
if (approve > 0 && (qty === 0 || approve < qty)) {
return '验货中'
}
if (approve > 0 && qty > 0 && approve >= qty) {
return '验货完成'
}
return '待验货'
}
/** 关闭/打开接口入参(id 为空时用 orderNo+site+itemNo 定位) */
export function buildPoDetailActionParams (row, site) {
return {
id: row.id != null && row.id !== '' ? row.id : undefined,
orderNo: row.orderNo,
site: row.site || site,
itemNo: row.itemNo
}
}

108
src/views/modules/order/poOrder_search.vue

@ -2,38 +2,33 @@
<div class="mod-config"> <div class="mod-config">
<!-- 查询条件 --> <!-- 查询条件 -->
<el-form :inline="true" label-position="top" :model="searchData"> <el-form :inline="true" label-position="top" :model="searchData">
<el-form-item label="Customer">
<el-input v-model="searchData.customer" clearable style="width: 120px" @keyup.enter.native="getDataList"></el-input>
</el-form-item>
<el-form-item label="供应商名称">
<el-input v-model="searchData.supplierName" clearable style="width: 140px" @keyup.enter.native="getDataList"></el-input>
<el-form-item label="PO No">
<el-input v-model="searchData.poNo" clearable style="width: 140px" @keyup.enter.native="handleSearch"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="物料编号"> <el-form-item label="物料编号">
<el-input v-model="searchData.partNo" clearable style="width: 120px" @keyup.enter.native="getDataList"></el-input>
</el-form-item>
<el-form-item label="Buyer">
<el-input v-model="searchData.buyer" clearable style="width: 120px" @keyup.enter.native="getDataList"></el-input>
</el-form-item>
<el-form-item label="PO No">
<el-input v-model="searchData.poNo" clearable style="width: 140px" @keyup.enter.native="getDataList"></el-input>
<el-input v-model="searchData.partNo" clearable style="width: 120px" @keyup.enter.native="handleSearch"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="SKU"> <el-form-item label="SKU">
<el-input v-model="searchData.sku" clearable style="width: 120px" @keyup.enter.native="getDataList"></el-input>
<el-input v-model="searchData.sku" clearable style="width: 120px" @keyup.enter.native="handleSearch"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="Status"> <el-form-item label="Status">
<el-select v-model="searchData.status" placeholder="请选择" style="width:100px" clearable> <el-select v-model="searchData.status" placeholder="请选择" style="width:100px" clearable>
<el-option label="全部" value=""></el-option> <el-option label="全部" value=""></el-option>
<el-option label="已下达" value="已下达"></el-option>
<el-option label="已取消" value="已取消"></el-option>
<el-option
v-for="item in poOrderStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form :inline="true" label-position="top" style="margin-top:10px"> <el-form :inline="true" label-position="top" style="margin-top:10px">
<el-form-item> <el-form-item>
<el-button type="primary" @click="getDataList">查询</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button type="primary" @click="exportExcel" style="margin-left: 2px">导出</el-button> <el-button type="primary" @click="exportExcel" style="margin-left: 2px">导出</el-button>
<el-button @click="resetSearch">重置</el-button> <el-button @click="resetSearch">重置</el-button>
<el-button type="warning" plain @click="advancedQueryVisible = true" style="margin-left: 2px">高级查询</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -90,21 +85,33 @@
<inspection-detail-list ref="inspectionDetailList" /> <inspection-detail-list ref="inspectionDetailList" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<po-order-advanced-query
:visible.sync="advancedQueryVisible"
:advanced-query-data="advancedQueryData"
@query="handleSearch" />
</div> </div>
</template> </template>
<script> <script>
import { searchPoDetailPage } from '@/api/order/poOrder.js'
import { searchPoDetailPage, searchPoDetailAdvancedPage } from '@/api/order/poOrder.js'
import {
createAdvancedQueryData,
buildPoOrderQueryParams
} from './poOrderAdvancedQueryHelper.js'
import excel from '@/utils/excel-util.js' import excel from '@/utils/excel-util.js'
import LogisticsPoList from './com_logisticsPoList.vue' import LogisticsPoList from './com_logisticsPoList.vue'
import InspectionDetailList from './com_inspectionDetailList.vue' import InspectionDetailList from './com_inspectionDetailList.vue'
import PoOrderDetail from './com_poOrderDetail.vue' import PoOrderDetail from './com_poOrderDetail.vue'
import PoOrderAdvancedQuery from './com_poOrderAdvancedQuery.vue'
import { PO_ORDER_STATUS_OPTIONS } from './poOrderStatusOptions.js'
export default { export default {
components: { components: {
LogisticsPoList, LogisticsPoList,
InspectionDetailList, InspectionDetailList,
PoOrderDetail
PoOrderDetail,
PoOrderAdvancedQuery
}, },
name: 'PoOrderQuery', name: 'PoOrderQuery',
data() { data() {
@ -118,6 +125,10 @@ export default {
totalPage: 0, totalPage: 0,
dataList: [], dataList: [],
currentRow: {}, currentRow: {},
advancedQueryVisible: false,
/** 高级查询条件对象(查询/导出均读取;仅弹窗内「重置」可清空) */
advancedQueryData: createAdvancedQueryData(),
poOrderStatusOptions: PO_ORDER_STATUS_OPTIONS,
searchData: { searchData: {
site: this.$store.state.user.site, site: this.$store.state.user.site,
customer: '', customer: '',
@ -471,22 +482,27 @@ export default {
}) })
}, },
methods: { methods: {
//
getDataList() {
this.loading = true
const params = {
...this.searchData,
buildQueryRequest() {
return buildPoOrderQueryParams({
searchData: this.searchData,
advancedQueryData: this.advancedQueryData,
page: this.pageIndex, page: this.pageIndex,
limit: this.pageSize limit: this.pageSize
}
searchPoDetailPage(params).then(({ data }) => {
})
},
handleSearch() {
this.pageIndex = 1
this.getDataList()
},
handleListResponse(data) {
if (data.code === 0) { if (data.code === 0) {
this.dataList = data.page.list || [] this.dataList = data.page.list || []
this.pageIndex = data.page.currPage this.pageIndex = data.page.currPage
this.pageSize = data.page.pageSize this.pageSize = data.page.pageSize
this.totalPage = data.page.totalCount this.totalPage = data.page.totalCount
//
if (this.dataList.length > 0) { if (this.dataList.length > 0) {
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.poTable) { if (this.$refs.poTable) {
@ -494,10 +510,20 @@ export default {
} }
this.changeData(this.dataList[0]) this.changeData(this.dataList[0])
}) })
} else {
this.currentRow = {}
} }
} else { } else {
this.$message.error((data && data.msg) || '获取列表失败') this.$message.error((data && data.msg) || '获取列表失败')
} }
},
getDataList() {
this.loading = true
const { params, useAdvanced } = this.buildQueryRequest()
const request = useAdvanced ? searchPoDetailAdvancedPage(params) : searchPoDetailPage(params)
request.then(({ data }) => {
this.handleListResponse(data)
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -505,7 +531,7 @@ export default {
}) })
}, },
//
/** 外部重置:仅清空顶部基础条件,不清 advancedQueryData */
resetSearch() { resetSearch() {
this.searchData = { this.searchData = {
site: this.$store.state.user.site, site: this.$store.state.user.site,
@ -524,9 +550,6 @@ export default {
}, },
// //
exportExcel () { exportExcel () {
console.log('开始导出...')
//
const now = new Date() const now = new Date()
const year = now.getFullYear() const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0') const month = String(now.getMonth() + 1).padStart(2, '0')
@ -536,33 +559,28 @@ export default {
const second = String(now.getSeconds()).padStart(2, '0') const second = String(now.getSeconds()).padStart(2, '0')
const exportName = `PO订单列表${year}${month}${day}${hour}${minute}${second}` const exportName = `PO订单列表${year}${month}${day}${hour}${minute}${second}`
//
const exportParams = {
...this.searchData,
limit: 99999,
page: 1
}
console.log('导出参数:', exportParams)
const { params, useAdvanced } = buildPoOrderQueryParams({
searchData: this.searchData,
advancedQueryData: this.advancedQueryData,
page: 1,
limit: 99999
})
try { try {
excel.exportTable({ excel.exportTable({
url: 'pODetail/page',
url: useAdvanced ? 'pODetail/advancedPage' : 'pODetail/page',
columnMapping: this.visibleColumns, columnMapping: this.visibleColumns,
mergeSetting: [], mergeSetting: [],
params: exportParams,
params,
fileName: exportName + '.xlsx', fileName: exportName + '.xlsx',
rowFetcher: res => { rowFetcher: res => {
console.log('导出接口响应:', res)
// {code, msg, rows}
return { rows: (res.data && res.data.rows) || [] }
const page = res.data && res.data.page
return { rows: (page && page.list) || [] }
}, },
columnFormatter: [], columnFormatter: [],
dropColumns: [] dropColumns: []
}) })
console.log('导出请求已发送')
} catch (error) { } catch (error) {
console.error('导出失败:', error)
this.$message.error('导出失败: ' + error.message) this.$message.error('导出失败: ' + error.message)
} }
}, },

Loading…
Cancel
Save