订单明细列表页开发

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,57 @@
package com.gear.oa.controller;
import com.gear.common.annotation.Log;
import com.gear.common.annotation.RepeatSubmit;
import com.gear.common.core.controller.BaseController;
import com.gear.common.core.domain.PageQuery;
import com.gear.common.core.domain.R;
import com.gear.common.core.page.TableDataInfo;
import com.gear.common.core.validate.EditGroup;
import com.gear.common.enums.BusinessType;
import com.gear.common.utils.poi.ExcelUtil;
import com.gear.oa.domain.bo.GearContractDetailBo;
import com.gear.oa.domain.vo.GearContractDetailVo;
import com.gear.oa.service.IGearContractDetailService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import java.util.Arrays;
import java.util.List;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/oa/contractDetail")
public class GearContractDetailController extends BaseController {
private final IGearContractDetailService iGearContractDetailService;
@GetMapping("/list")
public TableDataInfo<GearContractDetailVo> list(GearContractDetailBo bo, PageQuery pageQuery) {
return iGearContractDetailService.queryPageList(bo, pageQuery);
}
@Log(title = "订单明细列表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(GearContractDetailBo bo, HttpServletResponse response) {
List<GearContractDetailVo> list = iGearContractDetailService.queryList(bo);
ExcelUtil.exportExcel(list, "订单明细列表", GearContractDetailVo.class, response);
}
@Log(title = "订单明细列表", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody GearContractDetailBo bo) {
return toAjax(iGearContractDetailService.updateByBo(bo));
}
@Log(title = "订单明细列表", businessType = BusinessType.DELETE)
@DeleteMapping("/{detailIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] detailIds) {
return toAjax(iGearContractDetailService.deleteWithValidByIds(Arrays.asList(detailIds), true));
}
}

View File

@@ -0,0 +1,45 @@
package com.gear.oa.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gear.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("gear_contract_detail")
public class GearContractDetail extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(value = "detail_id")
private Long detailId;
private Long contractId;
private Integer lineNo;
private String productName;
private String spec;
private String material;
private BigDecimal widthMm;
private BigDecimal thicknessMm;
private String surfaceTreatment;
private String packagingRequirement;
private String remark;
@TableLogic(value = "0", delval = "2")
private String delFlag;
}

View File

@@ -0,0 +1,46 @@
package com.gear.oa.domain.bo;
import com.gear.common.core.domain.BaseEntity;
import com.gear.common.core.validate.AddGroup;
import com.gear.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
public class GearContractDetailBo extends BaseEntity {
@NotNull(message = "明细ID不能为空", groups = {EditGroup.class})
private Long detailId;
@NotNull(message = "合同ID不能为空", groups = {AddGroup.class, EditGroup.class})
private Long contractId;
private Integer lineNo;
private String contractNo;
private String partyA;
private String partyB;
private String effectiveFlag;
private String productName;
private String spec;
private String material;
private BigDecimal widthMm;
private BigDecimal thicknessMm;
private String surfaceTreatment;
private String packagingRequirement;
}

View File

@@ -0,0 +1,65 @@
package com.gear.oa.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.gear.common.core.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ExcelIgnoreUnannotated
public class GearContractDetailVo extends BaseEntity {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "明细ID")
private Long detailId;
@ExcelProperty(value = "合同ID")
private Long contractId;
@ExcelProperty(value = "合同号")
private String contractNo;
@ExcelProperty(value = "供方")
private String partyA;
@ExcelProperty(value = "需方")
private String partyB;
@ExcelProperty(value = "签订日期")
private Date signDate;
@ExcelProperty(value = "交货日期")
private Date deliveryDate;
@ExcelProperty(value = "序号")
private Integer lineNo;
@ExcelProperty(value = "产品名称")
private String productName;
@ExcelProperty(value = "规格")
private String spec;
@ExcelProperty(value = "材质")
private String material;
@ExcelProperty(value = "宽度(mm)")
private BigDecimal widthMm;
@ExcelProperty(value = "厚度(mm)")
private BigDecimal thicknessMm;
@ExcelProperty(value = "表面处理")
private String surfaceTreatment;
@ExcelProperty(value = "包装要求")
private String packagingRequirement;
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,13 @@
package com.gear.oa.mapper;
import com.gear.common.core.mapper.BaseMapperPlus;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import com.gear.oa.domain.GearContractDetail;
import com.gear.oa.domain.vo.GearContractDetailVo;
public interface GearContractDetailMapper extends BaseMapperPlus<GearContractDetailMapper, GearContractDetail, GearContractDetailVo> {
Page<GearContractDetailVo> selectVoPagePlus(Page<?> page, @Param("ew") Wrapper<GearContractDetail> wrapper);
}

View File

@@ -0,0 +1,21 @@
package com.gear.oa.service;
import com.gear.common.core.domain.PageQuery;
import com.gear.common.core.page.TableDataInfo;
import com.gear.oa.domain.bo.GearContractDetailBo;
import com.gear.oa.domain.vo.GearContractDetailVo;
import java.util.Collection;
import java.util.List;
public interface IGearContractDetailService {
TableDataInfo<GearContractDetailVo> queryPageList(GearContractDetailBo bo, PageQuery pageQuery);
List<GearContractDetailVo> queryList(GearContractDetailBo bo);
Boolean updateByBo(GearContractDetailBo bo);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,75 @@
package com.gear.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gear.common.core.domain.PageQuery;
import com.gear.common.core.page.TableDataInfo;
import com.gear.common.utils.StringUtils;
import com.gear.oa.domain.GearContractDetail;
import com.gear.oa.domain.bo.GearContractDetailBo;
import com.gear.oa.domain.vo.GearContractDetailVo;
import com.gear.oa.mapper.GearContractDetailMapper;
import com.gear.oa.service.IGearContractDetailService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@RequiredArgsConstructor
@Service
public class GearContractDetailServiceImpl implements IGearContractDetailService {
private final GearContractDetailMapper baseMapper;
@Override
public TableDataInfo<GearContractDetailVo> queryPageList(GearContractDetailBo bo, PageQuery pageQuery) {
QueryWrapper<GearContractDetail> qw = buildQueryWrapperPlus(bo);
Page<GearContractDetailVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), qw);
return TableDataInfo.build(result);
}
@Override
public List<GearContractDetailVo> queryList(GearContractDetailBo bo) {
QueryWrapper<GearContractDetail> qw = buildQueryWrapperPlus(bo);
return baseMapper.selectVoList(qw);
}
private QueryWrapper<GearContractDetail> buildQueryWrapperPlus(GearContractDetailBo bo) {
Map<String, Object> params = bo.getParams();
QueryWrapper<GearContractDetail> qw = Wrappers.query();
qw.eq("d.del_flag", "0");
qw.eq(bo.getContractId() != null, "d.contract_id", bo.getContractId());
qw.eq(bo.getLineNo() != null, "d.line_no", bo.getLineNo());
qw.like(StringUtils.isNotBlank(bo.getProductName()), "d.product_name", bo.getProductName());
qw.like(StringUtils.isNotBlank(bo.getSpec()), "d.spec", bo.getSpec());
qw.like(StringUtils.isNotBlank(bo.getMaterial()), "d.material", bo.getMaterial());
qw.like(StringUtils.isNotBlank(bo.getSurfaceTreatment()), "d.surface_treatment", bo.getSurfaceTreatment());
qw.like(StringUtils.isNotBlank(bo.getPackagingRequirement()), "d.packaging_requirement", bo.getPackagingRequirement());
qw.like(StringUtils.isNotBlank(bo.getContractNo()), "c.contract_no", bo.getContractNo());
qw.like(StringUtils.isNotBlank(bo.getPartyA()), "c.party_a", bo.getPartyA());
qw.like(StringUtils.isNotBlank(bo.getPartyB()), "c.party_b", bo.getPartyB());
qw.eq(StringUtils.isNotBlank(bo.getEffectiveFlag()), "c.effective_flag", bo.getEffectiveFlag());
qw.orderByAsc("d.contract_id");
qw.orderByAsc("d.line_no");
return qw;
}
@Override
public Boolean updateByBo(GearContractDetailBo bo) {
GearContractDetail update = BeanUtil.toBean(bo, GearContractDetail.class);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gear.oa.mapper.GearContractDetailMapper">
<select id="selectVoPagePlus" resultType="com.gear.oa.domain.vo.GearContractDetailVo">
SELECT
d.*,
c.contract_no AS contractNo,
c.party_a AS partyA,
c.party_b AS partyB,
c.sign_date AS signDate,
c.delivery_date AS deliveryDate
FROM gear_contract_detail d
LEFT JOIN gear_contract c ON d.contract_id = c.contract_id AND c.del_flag = '0'
${ew.customSqlSegment}
</select>
</mapper>

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>

View File

@@ -0,0 +1,32 @@
-- ================================
-- 订单明细列表(用于“销售管理 -> 合同管理 -> 订单明细列表”)
-- 目标:按合同维度维护订单/合同的产品明细(可行内编辑并保存)
-- 说明:
-- 1) 明细表通过 contract_id 关联 gear_contract
-- 2) 逻辑删除使用 del_flag0存在 2删除
-- ================================
DROP TABLE IF EXISTS gear_contract_detail;
CREATE TABLE gear_contract_detail (
detail_id bigint(20) NOT NULL COMMENT '明细ID',
contract_id bigint(20) NOT NULL COMMENT '合同ID gear_contract.contract_id',
line_no int NOT NULL DEFAULT 1 COMMENT '序号',
product_name varchar(255) DEFAULT '' COMMENT '产品名称(快照/可编辑)',
spec varchar(255) DEFAULT '' COMMENT '规格(快照/可编辑)',
material varchar(255) DEFAULT '' COMMENT '材质(可编辑)',
width_mm decimal(18,4) DEFAULT 0 COMMENT '宽度(mm)',
thickness_mm decimal(18,4) DEFAULT 0 COMMENT '厚度(mm)',
surface_treatment varchar(255) DEFAULT '' COMMENT '表面处理(可编辑)',
packaging_requirement varchar(500) DEFAULT '' COMMENT '包装要求(可编辑)',
remark varchar(500) DEFAULT NULL COMMENT '备注',
del_flag char(1) NOT NULL DEFAULT '0' COMMENT '删除标志0存在 2删除',
create_by varchar(64) DEFAULT '' COMMENT '创建者',
create_time datetime COMMENT '创建时间',
update_by varchar(64) DEFAULT '' COMMENT '更新者',
update_time datetime COMMENT '更新时间',
PRIMARY KEY (detail_id),
KEY idx_contract_id (contract_id),
KEY idx_line_no (line_no),
KEY idx_product_name (product_name(32))
) ENGINE=InnoDB COMMENT='合同订单明细表(订单明细列表)';

View File

@@ -206,3 +206,4 @@ INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2041816674390265858, '薪资补录', 1952975318515830785, 98, 'wageMakeup', 'oms/wageMakeup/index', NULL, 1, 0, 'C', '0', '0', NULL, 'edit', 'admin', '2026-04-08 17:53:25', 'admin', '2026-04-08 17:53:25', '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2060000000000000001, '合同编辑', 1962721165348478977, 8, 'contract', NULL, NULL, 1, 0, 'M', '0', '0', NULL, 'edit', 'admin', '2026-05-28 10:00:00', 'admin', '2026-05-28 10:00:00', '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2060000000000000002, '合同编辑详情', 2060000000000000001, 1, 'editDetail', 'oms/contractEdit/index', NULL, 1, 0, 'C', '0', '0', NULL, 'table', 'admin', '2026-05-28 10:00:00', 'admin', '2026-05-28 10:00:00', '');
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2060000000000000003, '订单明细列表', 2060000000000000001, 2, 'orderDetailList', 'oms/contractDetail/index', NULL, 1, 0, 'C', '0', '0', NULL, 'table', 'admin', '2026-05-28 10:00:00', 'admin', '2026-05-28 10:00:00', '');