订单明细列表页开发

This commit is contained in:
朱昊天
2026-06-04 14:45:26 +08:00
parent 323da20f2a
commit 2ca6a271db
12 changed files with 667 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
import request from '@/utils/request'
export function listContractDetail(query) {
return request({
url: '/oa/contractDetail/list',
method: 'get',
params: query
})
}
export function updateContractDetail(data) {
return request({
url: '/oa/contractDetail',
method: 'put',
data: data
})
}
export function delContractDetail(detailId) {
return request({
url: '/oa/contractDetail/' + detailId,
method: 'delete'
})
}

View File

@@ -0,0 +1,266 @@
<template>
<div class="app-container">
<el-form ref="queryRef" :model="queryParams" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="合同号" prop="contractNo">
<el-input v-model="queryParams.contractNo" placeholder="请输入合同号" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="供方" prop="partyA">
<el-input v-model="queryParams.partyA" placeholder="请输入供方" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="需方" prop="partyB">
<el-input v-model="queryParams.partyB" placeholder="请输入需方" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-input v-model="queryParams.productName" placeholder="请输入产品名称" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="材质" prop="material">
<el-input v-model="queryParams.material" placeholder="请输入材质" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="表面处理" prop="surfaceTreatment">
<el-input v-model="queryParams.surfaceTreatment" placeholder="请输入表面处理" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="包装要求" prop="packagingRequirement">
<el-input v-model="queryParams.packagingRequirement" placeholder="请输入包装要求" clearable @keyup.enter="handleQuery" style="width: 200px" />
</el-form-item>
<el-form-item label="签订日期">
<el-date-picker v-model="queryParams.signDateRange" type="daterange" range-separator="-" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD" style="width: 260px" />
</el-form-item>
<el-form-item label="交货日期">
<el-date-picker v-model="queryParams.deliveryDateRange" type="daterange" range-separator="-" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD" style="width: 260px" />
</el-form-item>
<el-form-item>
<el-button size="small" type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button size="small" icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div class="mb8 toolbar">
<el-button size="small" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
<div class="toolbar-right">
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</div>
</div>
<el-table v-loading="loading" :data="list">
<el-table-column label="合同号" prop="contractNo" min-width="150" />
<el-table-column label="供方" prop="partyA" min-width="220" :show-overflow-tooltip="true" />
<el-table-column label="需方" prop="partyB" min-width="220" :show-overflow-tooltip="true" />
<el-table-column label="签订日期" prop="signDate" width="120" align="center">
<template #default="{ row }">{{ formatDate(row.signDate) }}</template>
</el-table-column>
<el-table-column label="交货日期" prop="deliveryDate" width="120" align="center">
<template #default="{ row }">{{ formatDate(row.deliveryDate) }}</template>
</el-table-column>
<el-table-column label="序号" prop="lineNo" width="80" align="center">
<template #default="{ row }">
<el-input-number v-if="isEditing(row)" v-model="editRow.lineNo" :min="1" controls-position="right" style="width: 90px" />
<span v-else>{{ row.lineNo }}</span>
</template>
</el-table-column>
<el-table-column label="产品名称" prop="productName" min-width="200">
<template #default="{ row }">
<el-input v-if="isEditing(row)" v-model="editRow.productName" />
<span v-else>{{ row.productName }}</span>
</template>
</el-table-column>
<el-table-column label="规格" prop="spec" min-width="140">
<template #default="{ row }">
<el-input v-if="isEditing(row)" v-model="editRow.spec" />
<span v-else>{{ row.spec }}</span>
</template>
</el-table-column>
<el-table-column label="材质" prop="material" width="120" align="center">
<template #default="{ row }">
<el-input v-if="isEditing(row)" v-model="editRow.material" />
<span v-else>{{ row.material }}</span>
</template>
</el-table-column>
<el-table-column label="宽度(mm)" prop="widthMm" width="110" align="right">
<template #default="{ row }">
<el-input-number v-if="isEditing(row)" v-model="editRow.widthMm" :min="0" :precision="4" controls-position="right" style="width: 120px" />
<span v-else>{{ row.widthMm }}</span>
</template>
</el-table-column>
<el-table-column label="厚度(mm)" prop="thicknessMm" width="110" align="right">
<template #default="{ row }">
<el-input-number v-if="isEditing(row)" v-model="editRow.thicknessMm" :min="0" :precision="4" controls-position="right" style="width: 120px" />
<span v-else>{{ row.thicknessMm }}</span>
</template>
</el-table-column>
<el-table-column label="表面处理" prop="surfaceTreatment" min-width="140">
<template #default="{ row }">
<el-input v-if="isEditing(row)" v-model="editRow.surfaceTreatment" />
<span v-else>{{ row.surfaceTreatment }}</span>
</template>
</el-table-column>
<el-table-column label="包装要求" prop="packagingRequirement" min-width="220" :show-overflow-tooltip="true">
<template #default="{ row }">
<el-input v-if="isEditing(row)" v-model="editRow.packagingRequirement" />
<span v-else>{{ row.packagingRequirement }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="160" align="center" class-name="small-padding fixed-width">
<template #default="{ row }">
<template v-if="isEditing(row)">
<el-button link type="primary" icon="Check" :loading="saving" @click="saveRow">保存</el-button>
<el-button link type="primary" icon="Close" :disabled="saving" @click="cancelEdit">取消</el-button>
</template>
<template v-else>
<el-button link type="primary" icon="Edit" :disabled="editingId !== null" @click="startEdit(row)">修改</el-button>
<el-button link type="primary" icon="Delete" :disabled="editingId !== null" @click="deleteRow(row)">删除</el-button>
</template>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</template>
<script setup name="ContractDetailList">
import { getCurrentInstance, onMounted, ref } from 'vue'
import { delContractDetail, listContractDetail, updateContractDetail } from '@/api/oms/contractDetail'
const { proxy } = getCurrentInstance()
const showSearch = ref(true)
const loading = ref(false)
const total = ref(0)
const list = ref([])
const queryRef = ref()
const queryParams = ref({
pageNum: 1,
pageSize: 10,
contractNo: '',
partyA: '',
partyB: '',
productName: '',
material: '',
surfaceTreatment: '',
packagingRequirement: '',
signDateRange: [],
deliveryDateRange: []
})
const editingId = ref(null)
const editRow = ref({})
const saving = ref(false)
function buildQuery() {
const q = { ...queryParams.value }
const signRange = Array.isArray(q.signDateRange) ? q.signDateRange : []
const deliveryRange = Array.isArray(q.deliveryDateRange) ? q.deliveryDateRange : []
delete q.signDateRange
delete q.deliveryDateRange
q.signDateStart = signRange[0] ? `${signRange[0]} 00:00:00` : ''
q.signDateEnd = signRange[1] ? `${signRange[1]} 23:59:59` : ''
q.deliveryDateStart = deliveryRange[0] ? `${deliveryRange[0]} 00:00:00` : ''
q.deliveryDateEnd = deliveryRange[1] ? `${deliveryRange[1]} 23:59:59` : ''
return q
}
function getList() {
loading.value = true
return listContractDetail(buildQuery())
.then((res) => {
list.value = res?.rows || []
total.value = res?.total || 0
})
.finally(() => {
loading.value = false
})
}
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
function resetQuery() {
queryRef.value?.resetFields()
queryParams.value.signDateRange = []
queryParams.value.deliveryDateRange = []
handleQuery()
}
function isEditing(row) {
return row && editingId.value != null && String(row.detailId) === String(editingId.value)
}
function startEdit(row) {
editingId.value = row.detailId
editRow.value = {
detailId: row.detailId,
contractId: row.contractId,
lineNo: row.lineNo,
productName: row.productName || '',
spec: row.spec || '',
material: row.material || '',
widthMm: row.widthMm || 0,
thicknessMm: row.thicknessMm || 0,
surfaceTreatment: row.surfaceTreatment || '',
packagingRequirement: row.packagingRequirement || '',
remark: row.remark || ''
}
}
function cancelEdit() {
editingId.value = null
editRow.value = {}
}
function saveRow() {
if (!editRow.value?.detailId) return
saving.value = true
return updateContractDetail({ ...editRow.value })
.then(() => {
proxy.$modal.msgSuccess('保存成功')
cancelEdit()
return getList()
})
.finally(() => {
saving.value = false
})
}
function deleteRow(row) {
if (!row?.detailId) return
proxy.$modal.confirm('是否确认删除该明细?').then(() => {
return delContractDetail(row.detailId)
}).then(() => {
proxy.$modal.msgSuccess('删除成功')
cancelEdit()
getList()
})
}
function handleExport() {
proxy.download('oa/contractDetail/export', {
...buildQuery()
}, `contract_detail_${new Date().getTime()}.xlsx`)
}
function formatDate(v) {
if (!v) return ''
const d = new Date(v)
if (Number.isNaN(d.getTime())) return ''
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${y}-${m}-${day}`
}
onMounted(() => {
getList()
})
</script>
<style scoped>
.toolbar {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>