<template>
|
<div class="app-container">
|
<el-form :model="searchForm" :inline="true">
|
<el-form-item label="承运商">
|
<el-input
|
v-model="searchForm.carrierName"
|
style="width: 240px"
|
placeholder="输入承运商名称"
|
clearable
|
:prefix-icon="Search"
|
@keyup.enter="handleQuery"
|
/>
|
</el-form-item>
|
|
<el-form-item label="合同编号">
|
<el-input
|
v-model="searchForm.contractCode"
|
style="width: 240px"
|
placeholder="输入合同编号"
|
clearable
|
@keyup.enter="handleQuery"
|
/>
|
</el-form-item>
|
|
<el-form-item label="合同状态">
|
<el-select
|
v-model="searchForm.contractStatus"
|
style="width: 160px"
|
placeholder="全部"
|
clearable
|
>
|
<el-option label="有效" :value="1" />
|
<el-option label="无效" :value="0" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="合同时间">
|
<el-date-picker
|
v-model="searchForm.timeRange"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD"
|
type="datetimerange"
|
start-placeholder="开始时间"
|
end-placeholder="结束时间"
|
clearable
|
@change="changeDateRange"
|
@clear="clearRange"
|
/>
|
</el-form-item>
|
|
<el-form-item>
|
<el-button type="primary" @click="handleQuery" style="margin-left: 10px">
|
搜索
|
</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
</el-form-item>
|
</el-form>
|
|
<div class="table_list">
|
<div style="display: flex; justify-content: flex-end; margin-bottom: 12px">
|
<el-button type="primary" @click="openCreate">创建合同</el-button>
|
</div>
|
|
<PIMTable
|
rowKey="id"
|
:column="tableColumn"
|
:tableData="tableData"
|
:page="page"
|
:isSelection="false"
|
@selection-change="handleSelectionChange"
|
:tableLoading="tableLoading"
|
@pagination="pagination"
|
:total="page.total"
|
>
|
<template #statusSlot="{ row }">
|
<el-tag :type="row.contractStatus === 1 ? 'success' : 'info'">
|
{{ row.contractStatus === 1 ? '有效' : '无效' }}
|
</el-tag>
|
</template>
|
<template #versionSlot="{ row }">
|
<el-tag type="warning">v{{ row.version }}</el-tag>
|
</template>
|
</PIMTable>
|
</div>
|
|
<!-- 创建/维护(编辑)弹窗 -->
|
<el-dialog
|
v-model="editVisible"
|
:title="editMode === 'create' ? '创建承运合同' : '合同维护'"
|
width="720px"
|
:close-on-click-modal="false"
|
destroy-on-close
|
>
|
<el-form ref="editFormRef" :model="editForm" :rules="rules" label-width="120px">
|
<el-row :gutter="12">
|
<el-col :span="12">
|
<el-form-item label="合同编号" prop="contractCode">
|
<el-input v-model="editForm.contractCode" placeholder="如 HT-2026-0001" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="合同名称" prop="contractName">
|
<el-input v-model="editForm.contractName" placeholder="如 销售合同" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="承运商名称" prop="carrierName">
|
<el-input v-model="editForm.carrierName" placeholder="请输入承运商名称" />
|
</el-form-item>
|
</el-col>
|
|
<el-col :span="12">
|
<el-form-item label="合同开始时间" prop="startTime">
|
<el-date-picker
|
v-model="editForm.startTime"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
type="datetime"
|
placeholder="请选择"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
|
<el-col :span="12">
|
<el-form-item label="合同结束时间" prop="endTime">
|
<el-date-picker
|
v-model="editForm.endTime"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
type="datetime"
|
placeholder="可选"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
|
<el-col :span="12">
|
<el-form-item label="合同状态" prop="contractStatus">
|
<el-select v-model="editForm.contractStatus" placeholder="请选择" style="width: 100%">
|
<el-option label="有效" :value="1" />
|
<el-option label="无效" :value="0" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
|
<el-col :span="24">
|
<el-form-item label="备注" prop="remark">
|
<el-input v-model="editForm.remark" type="textarea" :rows="2" placeholder="可选" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
|
<template #footer>
|
<el-button @click="editVisible = false">取消</el-button>
|
<el-button type="primary" :loading="saving" @click="submitEdit">确定</el-button>
|
</template>
|
</el-dialog>
|
|
<!-- 查看弹窗 -->
|
<el-dialog v-model="viewVisible" title="合同信息查看" width="720px" destroy-on-close>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="合同编号">{{ viewRow.contractCode }}</el-descriptions-item>
|
<el-descriptions-item label="承运商">{{ viewRow.carrierName }}</el-descriptions-item>
|
<el-descriptions-item label="状态">{{ viewRow.contractStatus === 1 ? '有效' : '无效' }}</el-descriptions-item>
|
<el-descriptions-item label="开始时间">{{ viewRow.startTime }}</el-descriptions-item>
|
<el-descriptions-item label="结束时间">{{ viewRow.endTime || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="创建时间">{{ viewRow.createTime }}</el-descriptions-item>
|
<el-descriptions-item label="修改时间">{{ viewRow.updateTime }}</el-descriptions-item>
|
<el-descriptions-item label="备注" :span="2">{{ viewRow.remark || '-' }}</el-descriptions-item>
|
</el-descriptions>
|
<template #footer>
|
<el-button @click="viewVisible = false">关闭</el-button>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted } from "vue";
|
import { Search } from "@element-plus/icons-vue";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import useFormData from "@/hooks/useFormData";
|
import dayjs from "dayjs";
|
import PIMTable from "@/components/PIMTable/PIMTable.vue";
|
import {
|
getCarrierContractPage,
|
getCarrierContractDetail,
|
addCarrierContract,
|
updateCarrierContract,
|
deleteCarrierContract,
|
} from "@/api/inventoryManagement/CarrierManagement";
|
|
// ------------------ 数据适配(兼容后端返回结构) ------------------
|
const normalizeRow = (raw = {}) => {
|
// 后端字段:id/contractCode/carrierId/carrierName/contractName/contractStatus/startTime/endTime/remark/createUser/createTime/updateUser/updateTime/tenantId
|
return {
|
id: raw.id,
|
contractCode: raw.contractCode,
|
carrierId: raw.carrierId,
|
carrierName: raw.carrierName,
|
contractName: raw.contractName,
|
contractStatus: raw.contractStatus,
|
startTime: raw.startTime,
|
endTime: raw.endTime,
|
remark: raw.remark,
|
createUser: raw.createUser,
|
createTime: raw.createTime,
|
updateUser: raw.updateUser,
|
updateTime: raw.updateTime,
|
tenantId: raw.tenantId,
|
// version 非后端字段:页面展示兜底
|
version: raw.version ?? 1,
|
};
|
};
|
|
// ------------------ 页面状态 ------------------
|
const tableData = ref([]);
|
const selectedRows = ref([]);
|
const tableLoading = ref(false);
|
|
const page = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
layout: "total, sizes, prev, pager, next, jumper",
|
});
|
|
const { form: searchForm } = useFormData({
|
carrierName: "",
|
contractCode: "",
|
contractName: "",
|
contractStatus: "",
|
timeRange: [],
|
startTime: undefined,
|
endTime: undefined,
|
});
|
|
const tableColumn = ref([
|
{ label: "合同编号", prop: "contractCode", minWidth: 160 },
|
{ label: "合同名称", prop: "contractName", minWidth: 200 },
|
{ label: "承运商", prop: "carrierName", minWidth: 200 },
|
{ label: "状态", prop: "contractStatus", dataType: "slot", slot: "statusSlot", minWidth: 90 },
|
{ label: "开始时间", prop: "startTime", minWidth: 170 },
|
{ label: "结束时间", prop: "endTime", minWidth: 170 },
|
{ label: "修改时间", prop: "updateTime", minWidth: 170 },
|
{
|
label: "操作",
|
prop: "action",
|
dataType: "action",
|
fixed: "right",
|
minWidth: 140,
|
operation: [
|
{ name: "查看", clickFun: (row) => openView(row) },
|
{ name: "编辑", clickFun: (row) => openMaintain(row) },
|
{ name: "删除", clickFun: (row) => handleDelete(row) },
|
],
|
},
|
]);
|
|
const getList = async () => {
|
tableLoading.value = true;
|
try {
|
const { timeRange, ...rest } = searchForm;
|
const params = {
|
...rest,
|
current: page.current,
|
size: page.size,
|
};
|
|
const res = await getCarrierContractPage(params);
|
const data = res?.data ?? res;
|
const records = data?.records ?? data?.rows ?? data?.list ?? [];
|
const total = data?.total ?? data?.count ?? 0;
|
|
tableData.value = (records || []).map(normalizeRow);
|
page.total = total;
|
} catch (e) {
|
ElMessage.error(e?.message || e?.msg || "加载失败");
|
} finally {
|
tableLoading.value = false;
|
}
|
};
|
|
/** 搜索按钮操作 */
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
|
const resetQuery = () => {
|
searchForm.carrierName = "";
|
searchForm.contractCode = "";
|
searchForm.contractName = "";
|
searchForm.contractStatus = "";
|
searchForm.timeRange = [];
|
searchForm.startTime = undefined;
|
searchForm.endTime = undefined;
|
page.current = 1;
|
getList();
|
};
|
|
const pagination = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection;
|
};
|
|
const changeDateRange = (date) => {
|
if (date && date.length === 2) {
|
searchForm.startTime = date[0];
|
searchForm.endTime = date[1];
|
} else {
|
searchForm.startTime = undefined;
|
searchForm.endTime = undefined;
|
}
|
getList();
|
};
|
|
const clearRange = () => {
|
searchForm.timeRange = [];
|
searchForm.startTime = undefined;
|
searchForm.endTime = undefined;
|
getList();
|
};
|
|
// ------------------ 弹窗:查看/维护 ------------------
|
const viewVisible = ref(false);
|
const viewRow = reactive({});
|
|
const openView = async (row) => {
|
// 先展示行数据
|
Object.assign(viewRow, row);
|
viewVisible.value = true;
|
|
// 再拉详情补全
|
if (!row?.id) return;
|
try {
|
const res = await getCarrierContractDetail(row.id);
|
const detail = res?.data ?? res;
|
Object.assign(viewRow, normalizeRow(detail));
|
} catch {
|
// 详情失败不阻断查看
|
}
|
};
|
|
const editVisible = ref(false);
|
const editMode = ref("create"); // create | maintain
|
const editFormRef = ref();
|
const saving = ref(false);
|
const editForm = reactive({
|
id: undefined,
|
contractCode: "",
|
carrierId: undefined,
|
carrierName: "",
|
contractName: "",
|
contractStatus: 1,
|
startTime: "",
|
endTime: "",
|
remark: "",
|
});
|
|
const rules = {
|
contractCode: [{ required: true, message: "请输入合同编号", trigger: "blur" }],
|
carrierName: [{ required: true, message: "请输入承运商名称", trigger: "blur" }],
|
contractName: [{ required: true, message: "请输入合同名称", trigger: "blur" }],
|
contractStatus: [{ required: true, message: "请选择合同状态", trigger: "change" }],
|
startTime: [{ required: true, message: "请选择合同开始时间", trigger: "change" }],
|
endTime:[{ required: true, message: "请选择合同开始时间", trigger: "change" }]
|
};
|
|
const openCreate = () => {
|
editMode.value = "create";
|
Object.assign(editForm, {
|
id: undefined,
|
contractCode: "",
|
carrierId: undefined,
|
carrierName: "",
|
contractName: "",
|
contractStatus: 1,
|
startTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
endTime: "",
|
remark: "",
|
});
|
editVisible.value = true;
|
queueMicrotask(() => editFormRef.value?.clearValidate?.());
|
};
|
|
const openMaintain = async (row) => {
|
editMode.value = "maintain";
|
Object.assign(editForm, {
|
id: row.id,
|
contractCode: row.contractCode,
|
carrierId: row.carrierId,
|
carrierName: row.carrierName,
|
contractName: row.contractName,
|
contractStatus: row.contractStatus,
|
startTime: row.startTime,
|
endTime: row.endTime,
|
remark: row.remark,
|
});
|
|
// 拉详情,避免列表字段不全
|
if (row?.id) {
|
try {
|
const res = await getCarrierContractDetail(row.id);
|
const detail = res?.data ?? res;
|
const d = normalizeRow(detail);
|
Object.assign(editForm, {
|
id: d.id,
|
contractCode: d.contractCode,
|
carrierId: d.carrierId,
|
carrierName: d.carrierName,
|
contractName: d.contractName,
|
contractStatus: d.contractStatus,
|
startTime: d.startTime,
|
endTime: d.endTime,
|
remark: d.remark,
|
});
|
} catch {
|
// ignore
|
}
|
}
|
|
editVisible.value = true;
|
queueMicrotask(() => editFormRef.value?.clearValidate?.());
|
};
|
|
const submitEdit = async () => {
|
saving.value = true;
|
try {
|
await editFormRef.value?.validate?.();
|
|
const payload = {
|
id: editForm.id,
|
contractCode: editForm.contractCode,
|
carrierId: editForm.carrierId,
|
carrierName: editForm.carrierName,
|
contractName: editForm.contractName,
|
contractStatus: editForm.contractStatus,
|
startTime: editForm.startTime,
|
endTime: editForm.endTime,
|
remark: editForm.remark,
|
};
|
|
if (editMode.value === "create") {
|
await addCarrierContract(payload);
|
ElMessage.success("创建成功");
|
page.current = 1;
|
} else {
|
await updateCarrierContract(payload);
|
ElMessage.success("更新成功");
|
}
|
|
editVisible.value = false;
|
await getList();
|
} catch (e) {
|
if (e?.message) ElMessage.error(e.message);
|
} finally {
|
saving.value = false;
|
}
|
};
|
|
const handleDelete = async (row) => {
|
await ElMessageBox.confirm(`确认删除合同【${row.contractCode}】?`, "提示", {
|
confirmButtonText: "删除",
|
cancelButtonText: "取消",
|
type: "warning",
|
});
|
|
tableLoading.value = true;
|
try {
|
await deleteCarrierContract(row.id);
|
ElMessage.success("删除成功");
|
|
// 删除后若当前页没数据,回退一页
|
const res = await getCarrierContractPage({
|
...searchForm,
|
current: page.current,
|
size: page.size,
|
});
|
const data = res?.data ?? res;
|
const records = data?.records ?? data?.rows ?? data?.list ?? [];
|
if ((records || []).length === 0 && page.current > 1) {
|
page.current -= 1;
|
}
|
|
await getList();
|
} catch (e) {
|
ElMessage.error(e?.message || e?.msg || "删除失败");
|
} finally {
|
tableLoading.value = false;
|
}
|
};
|
|
// ------------------ 旧的“生成新版本”功能:后端暂无接口,暂不启用 ------------------
|
|
onMounted(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.table_list {
|
margin-top: unset;
|
}
|
</style>
|