Merge branch 'main' of https://giee.aiotagro.com/xuqiuyun/cattleTransportation
This commit is contained in:
126
pc-cattle-transportation/src/api/slaughter.js
Normal file
126
pc-cattle-transportation/src/api/slaughter.js
Normal file
@@ -0,0 +1,126 @@
|
||||
import request from '@/utils/axios.ts';
|
||||
|
||||
// 屠宰场管理
|
||||
export function slaughterHouseList(data) {
|
||||
return request({
|
||||
url: '/slaughter/house/list',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterHouseAdd(data) {
|
||||
return request({
|
||||
url: '/slaughter/house/add',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterHouseEdit(data) {
|
||||
return request({
|
||||
url: '/slaughter/house/edit',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterHouseDel(id) {
|
||||
return request({
|
||||
url: `/slaughter/house/delete?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterHouseDetail(id) {
|
||||
return request({
|
||||
url: `/slaughter/house/detail?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterHouseAll() {
|
||||
return request({
|
||||
url: '/slaughter/house/all',
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
// 进场管理
|
||||
export function slaughterEntryList(data) {
|
||||
return request({
|
||||
url: '/slaughter/entry/list',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterEntryAdd(data) {
|
||||
return request({
|
||||
url: '/slaughter/entry/add',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterEntryEdit(data) {
|
||||
return request({
|
||||
url: '/slaughter/entry/edit',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterEntryDel(id) {
|
||||
return request({
|
||||
url: `/slaughter/entry/delete?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterEntryDetail(id) {
|
||||
return request({
|
||||
url: `/slaughter/entry/detail?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
// 屠宰记录
|
||||
export function slaughterRecordList(data) {
|
||||
return request({
|
||||
url: '/slaughter/record/list',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterRecordAdd(data) {
|
||||
return request({
|
||||
url: '/slaughter/record/add',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterRecordEdit(data) {
|
||||
return request({
|
||||
url: '/slaughter/record/edit',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterRecordDel(id) {
|
||||
return request({
|
||||
url: `/slaughter/record/delete?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function slaughterRecordDetail(id) {
|
||||
return request({
|
||||
url: `/slaughter/record/detail?id=${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -327,6 +327,48 @@ export const constantRoutes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
],
|
||||
},
|
||||
// 屠宰场管理路由
|
||||
{
|
||||
path: '/slaughter',
|
||||
component: LayoutIndex,
|
||||
meta: {
|
||||
title: '屠宰场管理',
|
||||
keepAlive: true,
|
||||
requireAuth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'house',
|
||||
name: 'house',
|
||||
meta: {
|
||||
title: '屠宰场管理',
|
||||
keepAlive: true,
|
||||
requireAuth: true,
|
||||
},
|
||||
component: () => import('~/views/slaughter/house.vue'),
|
||||
},
|
||||
{
|
||||
path: 'entry',
|
||||
name: 'entry',
|
||||
meta: {
|
||||
title: '进场管理',
|
||||
keepAlive: true,
|
||||
requireAuth: true,
|
||||
},
|
||||
component: () => import('~/views/slaughter/entry.vue'),
|
||||
},
|
||||
{
|
||||
path: 'record',
|
||||
name: 'record',
|
||||
meta: {
|
||||
title: '屠宰记录',
|
||||
keepAlive: true,
|
||||
requireAuth: true,
|
||||
},
|
||||
component: () => import('~/views/slaughter/record.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/datav',
|
||||
name: 'DataV',
|
||||
|
||||
@@ -109,12 +109,13 @@
|
||||
<el-table-column label="司机姓名" prop="driverName"> </el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime"></el-table-column>
|
||||
<el-table-column label="创建人" prop="createByName"></el-table-column>
|
||||
<el-table-column label="操作" width="400">
|
||||
<el-table-column label="操作" width="480">
|
||||
<template #default="scope">
|
||||
<div class="table_column_operation">
|
||||
<el-button type="primary" link @click="details(scope.row, scope.row.warningTypeList ? scope.row.warningTypeList.length : 0)" v-hasPermi="['entry:view']">详情</el-button>
|
||||
<el-button type="primary" link @click="viewDevices(scope.row)" v-hasPermi="['entry:device']">查看设备</el-button>
|
||||
<el-button type="primary" link @click="showAddOrderDialog(scope.row.id)" v-hasPermi="['entry:order:create']">新增订单</el-button>
|
||||
<el-button type="primary" link @click="showRelatedOrders(scope.row)" v-hasPermi="['entry:view']">相关订单</el-button>
|
||||
<el-button type="warning" link @click="editDelivery(scope.row)" v-hasPermi="['entry:edit']">编辑</el-button>
|
||||
<el-button type="success" link @click="updateStatus(scope.row)" v-hasPermi="['entry:status']">修改状态</el-button>
|
||||
<el-button type="info" link @click="downloadPackage(scope.row)" :loading="downLoading[scope.row.id]" v-hasPermi="['entry:download']">打包文件</el-button>
|
||||
@@ -140,6 +141,44 @@
|
||||
<createDeliveryDialog ref="editDialogRef" @success="getDataList" />
|
||||
<!-- 订单对话框 -->
|
||||
<OrderDialog ref="OrderDialogRef" @success="handleOrderSuccess" />
|
||||
|
||||
<!-- 相关订单对话框 -->
|
||||
<el-dialog v-model="relatedOrdersDialog.visible" :title="`相关订单 - 运单号: ${relatedOrdersDialog.deliveryNumber || '--'}`" width="900px">
|
||||
<el-table :data="relatedOrdersDialog.orders" border v-loading="relatedOrdersDialog.loading" style="width: 100%">
|
||||
<el-table-column label="订单ID" prop="id" width="100"></el-table-column>
|
||||
<el-table-column label="买方" prop="buyerName" width="150"></el-table-column>
|
||||
<el-table-column label="卖方" prop="sellerName" width="150"></el-table-column>
|
||||
<el-table-column label="结算方式" prop="settlementType" width="120">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.settlementType === 1">上车重量</span>
|
||||
<span v-else-if="scope.row.settlementType === 2">下车重量</span>
|
||||
<span v-else-if="scope.row.settlementType === 3">按肉价结算</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="约定价格(元/斤)" prop="firmPrice" width="140">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.firmPrice">{{ scope.row.firmPrice }}</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="预付款(元)" prop="advancePayment" width="120">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.advancePayment">{{ scope.row.advancePayment }}</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime" width="180"></el-table-column>
|
||||
<template #empty>
|
||||
<div style="text-align: center; padding: 20px; color: #999">暂无相关订单</div>
|
||||
</template>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="relatedOrdersDialog.visible = false">关闭</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -152,7 +191,8 @@ import Pagination from '@/components/Pagination/index.vue';
|
||||
import createDeliveryDialog from '@/views/shipping/createDeliveryDialog.vue';
|
||||
import OrderDialog from '@/views/shipping/orderDialog.vue';
|
||||
import { inspectionList, downloadZip, pageDeviceList } from '@/api/abroad.js';
|
||||
import { updateDeliveryStatus, deleteDeliveryLogic, downloadDeliveryPackage, getDeliveryDetail, downloadAcceptanceForm } from '@/api/shipping.js';
|
||||
import { updateDeliveryStatus, deleteDeliveryLogic, downloadDeliveryPackage, getDeliveryDetail, downloadAcceptanceForm, orderPageQuery, orderGetDetail } from '@/api/shipping.js';
|
||||
import { sysUserList } from '@/api/sys.js';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
@@ -169,6 +209,16 @@ const data = reactive({
|
||||
rows: [],
|
||||
total: 10,
|
||||
deviceCounts: {}, // 存储每个订单的设备数量 {orderId: {host: 0, ear: 0, collar: 0, total: 0}}
|
||||
userMap: {}, // 存储用户ID到用户名的映射 {userId: userName}
|
||||
});
|
||||
|
||||
// 相关订单对话框数据
|
||||
const relatedOrdersDialog = reactive({
|
||||
visible: false,
|
||||
loading: false,
|
||||
orders: [],
|
||||
deliveryId: null,
|
||||
deliveryNumber: ''
|
||||
});
|
||||
const formItemList = reactive([
|
||||
{
|
||||
@@ -258,6 +308,94 @@ const getEarTagCount = (deliveryId) => {
|
||||
return counts ? counts.ear : 0;
|
||||
};
|
||||
|
||||
// 映射创建人名称
|
||||
const mapCreatedByName = async () => {
|
||||
if (!data.rows || data.rows.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否所有记录都已经有 createByName 字段(后端可能已经返回)
|
||||
const needMapping = data.rows.some(row => !row.createByName && row.createdBy);
|
||||
|
||||
if (!needMapping) {
|
||||
// 如果所有记录都有 createByName,不需要映射
|
||||
return;
|
||||
}
|
||||
|
||||
// 收集所有的 createdBy 字段值(去重)
|
||||
const createdByIds = [...new Set(data.rows
|
||||
.map(row => row.createdBy)
|
||||
.filter(id => id != null && id !== '' && id !== undefined))];
|
||||
|
||||
if (createdByIds.length === 0) {
|
||||
// 如果没有创建人ID,设置默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
row.createByName = '--';
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询用户信息
|
||||
const userRes = await sysUserList({
|
||||
pageNum: 1,
|
||||
pageSize: 1000 // 设置一个较大的值以获取所有用户
|
||||
});
|
||||
|
||||
if (userRes.code === 200) {
|
||||
const userList = userRes.data?.rows || userRes.data || [];
|
||||
|
||||
// 创建用户ID到用户名的映射(只映射需要的用户)
|
||||
const idSet = new Set(createdByIds.map(id => String(id)));
|
||||
userList.forEach(user => {
|
||||
const userId = String(user.id);
|
||||
if (idSet.has(userId) && user.name) {
|
||||
data.userMap[userId] = user.name;
|
||||
// 同时支持数字ID和字符串ID的映射
|
||||
data.userMap[user.id] = user.name;
|
||||
}
|
||||
});
|
||||
|
||||
// 为每条记录设置 createByName(只设置没有值的记录)
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
if (row.createdBy) {
|
||||
const userId = String(row.createdBy);
|
||||
// 尝试多种方式查找用户名
|
||||
row.createByName = data.userMap[row.createdBy]
|
||||
|| data.userMap[userId]
|
||||
|| data.userMap[Number(row.createdBy)]
|
||||
|| '--';
|
||||
} else {
|
||||
row.createByName = '--';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// API返回错误,使用默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
row.createByName = row.createdBy ? String(row.createdBy) : '--';
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
// 如果获取用户信息失败,显示ID或默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
if (row.createdBy) {
|
||||
row.createByName = String(row.createdBy);
|
||||
} else {
|
||||
row.createByName = '--';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const searchFrom = () => {
|
||||
form.pageNum = 1;
|
||||
getDataList();
|
||||
@@ -326,6 +464,10 @@ const getDataList = () => {
|
||||
}
|
||||
|
||||
console.log('[INSPECTION-LIST] 解析后的数据 - 总数:', data.total, '当前页数据:', data.rows.length);
|
||||
|
||||
// 映射创建人名称
|
||||
await mapCreatedByName();
|
||||
|
||||
dataListLoading.value = false;
|
||||
|
||||
// 为每个订单获取设备数量
|
||||
@@ -876,6 +1018,80 @@ const handleOrderSuccess = () => {
|
||||
getDataList();
|
||||
};
|
||||
|
||||
// 显示相关订单
|
||||
const showRelatedOrders = async (row) => {
|
||||
relatedOrdersDialog.visible = true;
|
||||
relatedOrdersDialog.loading = true;
|
||||
relatedOrdersDialog.orders = [];
|
||||
relatedOrdersDialog.deliveryId = row.id;
|
||||
relatedOrdersDialog.deliveryNumber = row.deliveryNumber || '';
|
||||
|
||||
try {
|
||||
// 从运送清单数据中获取 orderId 字段
|
||||
const orderId = row.orderId;
|
||||
|
||||
if (!orderId) {
|
||||
relatedOrdersDialog.orders = [];
|
||||
ElMessage.info('该运送清单暂无关联订单');
|
||||
relatedOrdersDialog.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析 orderId(可能是字符串,包含逗号分隔的多个ID)
|
||||
let orderIds = [];
|
||||
if (typeof orderId === 'string') {
|
||||
// 如果是字符串,按逗号分割
|
||||
orderIds = orderId.split(',').map(id => id.trim()).filter(id => id !== '');
|
||||
} else if (typeof orderId === 'number') {
|
||||
// 如果是数字,转换为数组
|
||||
orderIds = [String(orderId)];
|
||||
} else if (Array.isArray(orderId)) {
|
||||
// 如果是数组,直接使用
|
||||
orderIds = orderId.map(id => String(id));
|
||||
} else {
|
||||
// 其他情况,尝试转换为字符串
|
||||
orderIds = [String(orderId)];
|
||||
}
|
||||
|
||||
if (orderIds.length === 0) {
|
||||
relatedOrdersDialog.orders = [];
|
||||
ElMessage.info('该运送清单暂无关联订单');
|
||||
relatedOrdersDialog.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据订单ID列表逐个查询订单详情
|
||||
const orderPromises = orderIds.map(orderId => orderGetDetail(orderId));
|
||||
const orderResults = await Promise.allSettled(orderPromises);
|
||||
|
||||
// 处理查询结果
|
||||
const orders = [];
|
||||
orderResults.forEach((result, index) => {
|
||||
if (result.status === 'fulfilled' && result.value.code === 200) {
|
||||
const orderData = result.value.data || result.value;
|
||||
if (orderData) {
|
||||
orders.push(orderData);
|
||||
}
|
||||
} else {
|
||||
console.warn(`获取订单 ${orderIds[index]} 详情失败:`, result.reason || result.value?.msg);
|
||||
}
|
||||
});
|
||||
|
||||
relatedOrdersDialog.orders = orders;
|
||||
|
||||
if (orders.length === 0) {
|
||||
ElMessage.info('该运送清单暂无关联订单或订单不存在');
|
||||
} else if (orders.length < orderIds.length) {
|
||||
ElMessage.warning(`成功加载 ${orders.length}/${orderIds.length} 个订单`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取相关订单失败:', error);
|
||||
ElMessage.error('获取相关订单失败,请稍后重试');
|
||||
} finally {
|
||||
relatedOrdersDialog.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDataList();
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<el-descriptions-item label="创建时间">{{ data.baseInfo.createTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="司机运费">{{ data.baseInfo.freight ? data.baseInfo.freight + ' 元' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="登记设备数量">{{ totalRegisteredDevices }} 个</el-descriptions-item>
|
||||
<el-descriptions-item label="牛只数量">{{ data.baseInfo.ratedQuantity ||'-' }} 头</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
@@ -123,7 +124,19 @@
|
||||
</div>
|
||||
|
||||
<!-- 照片信息分组 -->
|
||||
<div v-if="hasValue(data.baseInfo.quarantineTickeyUrl) || hasValue(data.baseInfo.poundListImg) || hasValue(data.baseInfo.emptyVehicleFrontPhoto) || hasValue(data.baseInfo.loadedVehicleFrontPhoto) || hasValue(data.baseInfo.loadedVehicleWeightPhoto) || hasValue(data.baseInfo.driverIdCardPhoto) || hasValue(data.baseInfo.destinationPoundListImg) || hasValue(data.baseInfo.destinationVehicleFrontPhoto)" class="info-group">
|
||||
<div
|
||||
v-if="
|
||||
parseMediaList(data.baseInfo.quarantineTickeyUrl).length ||
|
||||
parseMediaList(data.baseInfo.poundListImg).length ||
|
||||
parseMediaList(data.baseInfo.emptyVehicleFrontPhoto).length ||
|
||||
parseMediaList(data.baseInfo.loadedVehicleFrontPhoto).length ||
|
||||
parseMediaList(data.baseInfo.loadedVehicleWeightPhoto).length ||
|
||||
parseMediaList(data.baseInfo.driverIdCardPhoto).length ||
|
||||
parseMediaList(data.baseInfo.destinationPoundListImg).length ||
|
||||
parseMediaList(data.baseInfo.destinationVehicleFrontPhoto).length
|
||||
"
|
||||
class="info-group"
|
||||
>
|
||||
<div class="sub-title">照片信息</div>
|
||||
<div class="media-grid">
|
||||
<div class="media-item" v-if="data.baseInfo.carFrontPhoto || data.baseInfo.carBehindPhoto">
|
||||
@@ -147,83 +160,99 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.quarantineTickeyUrl)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.quarantineTickeyUrl).length">
|
||||
<div class="media-label">检疫票</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.quarantineTickeyUrl)"
|
||||
:key="`quarantine-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.quarantineTickeyUrl"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.quarantineTickeyUrl]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.quarantineTickeyUrl)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.poundListImg)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.poundListImg).length">
|
||||
<div class="media-label">纸质磅单</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.poundListImg)"
|
||||
:key="`pound-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.poundListImg"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.poundListImg]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.poundListImg)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.emptyVehicleFrontPhoto)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.emptyVehicleFrontPhoto).length">
|
||||
<div class="media-label">空磅车头照片</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.emptyVehicleFrontPhoto)"
|
||||
:key="`empty-front-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.emptyVehicleFrontPhoto"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.emptyVehicleFrontPhoto]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.emptyVehicleFrontPhoto)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.loadedVehicleFrontPhoto)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.loadedVehicleFrontPhoto).length">
|
||||
<div class="media-label">过重磅车头照片</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.loadedVehicleFrontPhoto)"
|
||||
:key="`loaded-front-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.loadedVehicleFrontPhoto"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.loadedVehicleFrontPhoto]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.loadedVehicleFrontPhoto)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.loadedVehicleWeightPhoto)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.loadedVehicleWeightPhoto).length">
|
||||
<div class="media-label">车辆重磅照片</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.loadedVehicleWeightPhoto)"
|
||||
:key="`loaded-weight-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.loadedVehicleWeightPhoto"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.loadedVehicleWeightPhoto]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.loadedVehicleWeightPhoto)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.driverIdCardPhoto)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.driverIdCardPhoto).length">
|
||||
<div class="media-label">驾驶员手持身份证</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.driverIdCardPhoto)"
|
||||
:key="`driver-id-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.driverIdCardPhoto"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.driverIdCardPhoto]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.driverIdCardPhoto)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.destinationPoundListImg)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.destinationPoundListImg).length">
|
||||
<div class="media-label">落地纸质磅单</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.destinationPoundListImg)"
|
||||
:key="`dest-pound-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.destinationPoundListImg"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.destinationPoundListImg]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.destinationPoundListImg)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item" v-if="hasValue(data.baseInfo.destinationVehicleFrontPhoto)">
|
||||
<div class="media-item" v-if="parseMediaList(data.baseInfo.destinationVehicleFrontPhoto).length">
|
||||
<div class="media-label">落地过重磅车头</div>
|
||||
<el-image
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.destinationVehicleFrontPhoto)"
|
||||
:key="`dest-front-${idx}`"
|
||||
class="photo-img"
|
||||
:src="data.baseInfo.destinationVehicleFrontPhoto"
|
||||
:src="url"
|
||||
fit="cover"
|
||||
:preview-src-list="[data.baseInfo.destinationVehicleFrontPhoto]"
|
||||
:preview-src-list="parseMediaList(data.baseInfo.destinationVehicleFrontPhoto)"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
@@ -231,36 +260,82 @@
|
||||
</div>
|
||||
|
||||
<!-- 视频信息分组 -->
|
||||
<div v-if="hasValue(data.baseInfo.emptyWeightVideo) || hasValue(data.baseInfo.entruckWeightVideo) || hasValue(data.baseInfo.entruckVideo) || hasValue(data.baseInfo.controlSlotVideo) || hasValue(data.baseInfo.cattleLoadingCircleVideo) || hasValue(data.baseInfo.unloadCattleVideo) || hasValue(data.baseInfo.destinationWeightVideo)" class="info-group">
|
||||
<div
|
||||
v-if="
|
||||
parseMediaList(data.baseInfo.emptyWeightVideo).length ||
|
||||
parseMediaList(data.baseInfo.entruckWeightVideo).length ||
|
||||
parseMediaList(data.baseInfo.entruckVideo).length ||
|
||||
parseMediaList(data.baseInfo.controlSlotVideo).length ||
|
||||
parseMediaList(data.baseInfo.cattleLoadingCircleVideo).length ||
|
||||
parseMediaList(data.baseInfo.unloadCattleVideo).length ||
|
||||
parseMediaList(data.baseInfo.destinationWeightVideo).length
|
||||
"
|
||||
class="info-group"
|
||||
>
|
||||
<div class="sub-title">视频信息</div>
|
||||
<div class="media-grid">
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.emptyWeightVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.emptyWeightVideo).length">
|
||||
<div class="media-label">空车过磅视频</div>
|
||||
<video controls :src="data.baseInfo.emptyWeightVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.emptyWeightVideo)"
|
||||
:key="`emptyWeightVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.entruckWeightVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.entruckWeightVideo).length">
|
||||
<div class="media-label">装车过磅视频</div>
|
||||
<video controls :src="data.baseInfo.entruckWeightVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.entruckWeightVideo)"
|
||||
:key="`entruckWeightVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.entruckVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.entruckVideo).length">
|
||||
<div class="media-label">装车视频</div>
|
||||
<video controls :src="data.baseInfo.entruckVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.entruckVideo)"
|
||||
:key="`entruckVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.controlSlotVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.controlSlotVideo).length">
|
||||
<div class="media-label">控槽视频</div>
|
||||
<video controls :src="data.baseInfo.controlSlotVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.controlSlotVideo)"
|
||||
:key="`controlSlotVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.cattleLoadingCircleVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.cattleLoadingCircleVideo).length">
|
||||
<div class="media-label">装完牛绕车一圈</div>
|
||||
<video controls :src="data.baseInfo.cattleLoadingCircleVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.cattleLoadingCircleVideo)"
|
||||
:key="`cattleLoadingCircleVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.unloadCattleVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.unloadCattleVideo).length">
|
||||
<div class="media-label">卸牛视频</div>
|
||||
<video controls :src="data.baseInfo.unloadCattleVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.unloadCattleVideo)"
|
||||
:key="`unloadCattleVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-item video-item" v-if="hasValue(data.baseInfo.destinationWeightVideo)">
|
||||
<div class="media-item video-item" v-if="parseMediaList(data.baseInfo.destinationWeightVideo).length">
|
||||
<div class="media-label">落地过磅视频</div>
|
||||
<video controls :src="data.baseInfo.destinationWeightVideo" />
|
||||
<video
|
||||
v-for="(url, idx) in parseMediaList(data.baseInfo.destinationWeightVideo)"
|
||||
:key="`destinationWeightVideo-${idx}`"
|
||||
controls
|
||||
:src="url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1193,12 +1268,27 @@ const hasValue = (value) => {
|
||||
if (value === null || value === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.trim() !== '';
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 将逗号分隔的字符串或数组统一为去空后的数组
|
||||
const parseMediaList = (value) => {
|
||||
if (!value) return [];
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((v) => (v || '').trim()).filter(Boolean);
|
||||
}
|
||||
return String(value)
|
||||
.split(',')
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
// 获取卖方名称:如果是从订单页面进入的,使用订单的卖方;否则显示 '-'
|
||||
const getSupplierName = () => {
|
||||
// 检查是否从订单页面进入(通过路由参数 fromOrder 判断)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -164,9 +164,16 @@
|
||||
<el-row :gutter="40">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="约定单价" prop="firmPrice">
|
||||
<el-input v-model="ruleForm.firmPrice" placeholder="请输入约定单价" clearable>
|
||||
<el-input-number
|
||||
v-model="ruleForm.firmPrice"
|
||||
:precision="4"
|
||||
:min="0"
|
||||
:max="999999.9999"
|
||||
placeholder="请输入约定单价"
|
||||
style="width: 100%"
|
||||
>
|
||||
<template #append>元/公斤</template>
|
||||
</el-input>
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -287,7 +294,7 @@ const ruleForm = reactive({
|
||||
buyerId: '', // 采购商
|
||||
buyerPrice: '', // 采购单价
|
||||
salePrice: '', // 销售单价
|
||||
firmPrice: '', // 约定单价
|
||||
firmPrice: null, // 约定单价
|
||||
startLocation: '', // 起始地
|
||||
startLat: '',
|
||||
startLon: '',
|
||||
|
||||
@@ -72,9 +72,9 @@
|
||||
<el-form-item label="约定价格(元/斤)" prop="firmPrice">
|
||||
<el-input-number
|
||||
v-model="ruleForm.firmPrice"
|
||||
:precision="2"
|
||||
:precision="4"
|
||||
:min="0"
|
||||
:max="9999999.99"
|
||||
:max="999999.9999"
|
||||
placeholder="请输入约定价格"
|
||||
style="width: 100%"
|
||||
></el-input-number>
|
||||
@@ -728,36 +728,10 @@ const onShowDialog = async (orderData, deliveryId) => {
|
||||
// 设置deliveryId(如果提供)
|
||||
ruleForm.deliveryId = deliveryId || orderData?.deliveryId || null;
|
||||
|
||||
// 处理预付款自动填充
|
||||
// 1. 如果编辑订单,直接使用订单数据中的预付款
|
||||
// 处理预付款:编辑时使用订单值,新建时保持为空
|
||||
if (orderData?.advancePayment != null) {
|
||||
ruleForm.advancePayment = orderData.advancePayment;
|
||||
}
|
||||
// 2. 如果是创建订单且有deliveryId,尝试从已关联的订单中获取预付款作为默认值
|
||||
else if (!ruleForm.id && ruleForm.deliveryId) {
|
||||
try {
|
||||
const res = await getOrdersByDeliveryId(ruleForm.deliveryId);
|
||||
if (res.code === 200) {
|
||||
const responseData = res.data || res;
|
||||
let orders = [];
|
||||
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
|
||||
orders = responseData.rows || [];
|
||||
} else if (responseData && responseData.data && 'rows' in responseData.data) {
|
||||
orders = responseData.data.rows || [];
|
||||
}
|
||||
|
||||
// 如果有关联的订单,使用第一个订单的预付款作为默认值
|
||||
if (orders.length > 0 && orders[0].advancePayment != null) {
|
||||
ruleForm.advancePayment = orders[0].advancePayment;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取关联订单预付款失败:', error);
|
||||
// 失败不影响继续操作,预付款保持为null
|
||||
}
|
||||
}
|
||||
// 3. 其他情况,预付款为null
|
||||
else {
|
||||
} else {
|
||||
ruleForm.advancePayment = null;
|
||||
}
|
||||
|
||||
|
||||
534
pc-cattle-transportation/src/views/slaughter/entry.vue
Normal file
534
pc-cattle-transportation/src/views/slaughter/entry.vue
Normal file
@@ -0,0 +1,534 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<base-search :formItemList="formItemList" @search="handleSearch" ref="baseSearchRef" />
|
||||
<div class="action-bar">
|
||||
<el-button type="primary" @click="openDialog()">新增进场</el-button>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<el-table :data="data.rows" border v-loading="data.loading" element-loading-text="数据加载中..." style="width: 100%">
|
||||
<el-table-column label="进场编码" prop="entryCode" width="150" />
|
||||
<el-table-column label="屠宰场" prop="slaughterHouseId" min-width="140">
|
||||
<template #default="scope">
|
||||
{{ houseNameMap[scope.row.slaughterHouseId] || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运送清单号" prop="deliveryNumber" width="150" />
|
||||
<el-table-column label="订单" min-width="200">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.orderBuyerName || scope.row.orderSellerName">
|
||||
<div v-if="scope.row.orderBuyerName">买方:{{ scope.row.orderBuyerName }}</div>
|
||||
<div v-if="scope.row.orderSellerName">卖方:{{ scope.row.orderSellerName }}</div>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="起始地" prop="startLocation" min-width="150" />
|
||||
<el-table-column label="目的地" prop="endLocation" min-width="150" />
|
||||
<el-table-column label="司机" prop="driverName" width="120" />
|
||||
<el-table-column label="联系方式" prop="driverMobile" width="140" />
|
||||
<el-table-column label="车牌号" prop="licensePlate" width="120" />
|
||||
<el-table-column label="创建时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="openDialog(scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<div class="dataListOnEmpty">暂无数据</div>
|
||||
</template>
|
||||
</el-table>
|
||||
<pagination v-model:limit="form.pageSize" v-model:page="form.pageNum" :total="data.total" @pagination="getList" />
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dialog.visible" :title="dialog.title" width="600px" :close-on-click-modal="false">
|
||||
<el-form ref="dialogFormRef" :model="dialog.form" :rules="dialog.rules" label-width="120px">
|
||||
<el-form-item label="进场编码" prop="entryCode">
|
||||
<el-input
|
||||
v-model="dialog.form.entryCode"
|
||||
placeholder="请输入进场编码或点击自动生成"
|
||||
style="width: calc(100% - 100px); margin-right: 10px;"
|
||||
/>
|
||||
<el-button type="primary" @click="generateEntryCode">自动生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="屠宰场" prop="slaughterHouseId">
|
||||
<el-select v-model="dialog.form.slaughterHouseId" placeholder="请选择屠宰场" filterable style="width: 100%">
|
||||
<el-option v-for="item in houseOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="运送清单" prop="deliveryId">
|
||||
<el-select
|
||||
v-model="dialog.form.deliveryId"
|
||||
placeholder="请选择运送清单"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
@change="handleDeliveryChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in deliveryList"
|
||||
:key="item.id"
|
||||
:label="`${item.deliveryNumber || '--'} - ${item.licensePlate || '--'}`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单" prop="orderId">
|
||||
<el-select
|
||||
v-model="dialog.form.orderId"
|
||||
placeholder="请选择订单(可选)"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in orderList"
|
||||
:key="item.id"
|
||||
:label="`订单${item.id} -买方${item.buyerName}-卖方${item.sellerName}- 单价: ${item.firmPrice || '--'}元/斤`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="起始地" prop="startLocation">
|
||||
<el-input v-model="dialog.form.startLocation" placeholder="请输入起始地" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="目的地" prop="endLocation">
|
||||
<el-input v-model="dialog.form.endLocation" placeholder="请输入目的地" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="起始经度" prop="startLon">
|
||||
<el-input v-model="dialog.form.startLon" placeholder="请输入起始经度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="起始纬度" prop="startLat">
|
||||
<el-input v-model="dialog.form.startLat" placeholder="请输入起始纬度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="目的地经度" prop="endLon">
|
||||
<el-input v-model="dialog.form.endLon" placeholder="请输入目的地经度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="目的地纬度" prop="endLat">
|
||||
<el-input v-model="dialog.form.endLat" placeholder="请输入目的地纬度" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="司机姓名" prop="driverName">
|
||||
<el-input v-model="dialog.form.driverName" placeholder="请输入司机姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系方式" prop="driverMobile">
|
||||
<el-input v-model="dialog.form.driverMobile" placeholder="请输入联系方式" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="车牌号" prop="licensePlate">
|
||||
<el-input v-model="dialog.form.licensePlate" placeholder="请输入车牌号" />
|
||||
</el-form-item>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="牛只数量" prop="capacity">
|
||||
<el-input-number
|
||||
v-model="dialog.form.capacity"
|
||||
:min="0"
|
||||
:max="9999"
|
||||
placeholder="请输入牛只数量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="剩余牛只数量" prop="remainingCapacity">
|
||||
<el-input-number
|
||||
v-model="dialog.form.remainingCapacity"
|
||||
:min="0"
|
||||
:max="9999"
|
||||
placeholder="请输入剩余牛只数量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="dialog.form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitDialog">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import baseSearch from '@/components/common/searchCustom/index.vue';
|
||||
import {
|
||||
slaughterEntryList,
|
||||
slaughterEntryAdd,
|
||||
slaughterEntryEdit,
|
||||
slaughterEntryDel,
|
||||
} from '@/api/slaughter.js';
|
||||
import { slaughterHouseAll, slaughterHouseList } from '@/api/slaughter.js';
|
||||
import { shippingList, orderPageQuery } from '@/api/shipping.js';
|
||||
|
||||
const baseSearchRef = ref();
|
||||
const dialogFormRef = ref();
|
||||
|
||||
const houseOptions = ref([]);
|
||||
const houseNameMap = reactive({});
|
||||
const deliveryList = ref([]);
|
||||
const orderList = ref([]);
|
||||
|
||||
const formItemList = reactive([
|
||||
{
|
||||
label: '屠宰场',
|
||||
param: 'slaughterHouseId',
|
||||
type: 'select',
|
||||
selectOptions: [],
|
||||
placeholder: '请选择屠宰场',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
labelKey: 'label',
|
||||
valueKey: 'value',
|
||||
},
|
||||
{
|
||||
label: '运送清单号',
|
||||
param: 'deliveryNumber',
|
||||
type: 'input',
|
||||
placeholder: '请输入运送清单号',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
{
|
||||
label: '订单',
|
||||
param: 'orderBuyerName'||'orderSellerName',
|
||||
type: 'input',
|
||||
placeholder: '请输入买方或卖方公司名称',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
]);
|
||||
|
||||
const data = reactive({
|
||||
rows: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '新增进场',
|
||||
form: {
|
||||
id: null,
|
||||
entryCode: '',
|
||||
slaughterHouseId: null,
|
||||
deliveryId: null,
|
||||
orderId: null,
|
||||
startLocation: '',
|
||||
startLon: '',
|
||||
startLat: '',
|
||||
endLocation: '',
|
||||
endLon: '',
|
||||
endLat: '',
|
||||
driverName: '',
|
||||
driverMobile: '',
|
||||
licensePlate: '',
|
||||
capacity: null,
|
||||
remainingCapacity: null,
|
||||
remark: '',
|
||||
},
|
||||
rules: {
|
||||
slaughterHouseId: [{ required: true, message: '请选择屠宰场', trigger: 'change' }],
|
||||
deliveryId: [{ required: true, message: '请选择运送清单', trigger: 'change' }],
|
||||
},
|
||||
});
|
||||
|
||||
const resetDialogForm = () => {
|
||||
dialog.form = {
|
||||
id: null,
|
||||
entryCode: '',
|
||||
slaughterHouseId: null,
|
||||
deliveryId: null,
|
||||
orderId: null,
|
||||
startLocation: '',
|
||||
startLon: '',
|
||||
startLat: '',
|
||||
endLocation: '',
|
||||
endLon: '',
|
||||
endLat: '',
|
||||
driverName: '',
|
||||
driverMobile: '',
|
||||
licensePlate: '',
|
||||
capacity: null,
|
||||
remainingCapacity: null,
|
||||
remark: '',
|
||||
};
|
||||
dialog.title = '新增进场';
|
||||
};
|
||||
|
||||
const loadHouseOptions = () => {
|
||||
// 调用列表接口,支持模糊查询
|
||||
slaughterHouseList({ pageNum: 1, pageSize: 1000 })
|
||||
.then((res) => {
|
||||
let responseData = res.data;
|
||||
if (responseData && responseData.data && typeof responseData.data === 'object') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
const list = responseData?.rows || responseData || [];
|
||||
const options = list.map((item) => ({
|
||||
label: item.house_name || item.houseName,
|
||||
value: item.id,
|
||||
}));
|
||||
houseOptions.value = options;
|
||||
formItemList[0].selectOptions = options;
|
||||
Object.keys(houseNameMap).forEach((key) => delete houseNameMap[key]);
|
||||
options.forEach((opt) => {
|
||||
houseNameMap[opt.value] = opt.label;
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
data.loading = true;
|
||||
const params = { ...form, ...baseSearchRef.value.penetrateParams() };
|
||||
slaughterEntryList(params)
|
||||
.then((res) => {
|
||||
// 处理嵌套的数据结构:res.data.data.rows 或 res.data.rows
|
||||
let responseData = res.data;
|
||||
if (responseData && responseData.data && typeof responseData.data === 'object') {
|
||||
// 嵌套结构:res.data.data
|
||||
responseData = responseData.data;
|
||||
}
|
||||
data.rows = responseData?.rows || [];
|
||||
data.total = responseData?.total || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error('查询失败');
|
||||
})
|
||||
.finally(() => {
|
||||
data.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
form.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
// 加载订单列表
|
||||
const loadOrderList = async () => {
|
||||
try {
|
||||
const res = await orderPageQuery({ pageNum: 1, pageSize: 1000 });
|
||||
if (res.code === 200) {
|
||||
const responseData = res.data || res;
|
||||
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
|
||||
orderList.value = responseData.rows || [];
|
||||
} else if (responseData && responseData.data && 'rows' in responseData.data) {
|
||||
orderList.value = responseData.data.rows || [];
|
||||
} else {
|
||||
orderList.value = [];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载订单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载运送清单列表
|
||||
const loadDeliveryList = async () => {
|
||||
try {
|
||||
const res = await shippingList({ pageNum: 1, pageSize: 1000 });
|
||||
if (res.code === 200) {
|
||||
const responseData = res.data || res;
|
||||
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
|
||||
deliveryList.value = responseData.rows || [];
|
||||
} else if (responseData && responseData.data && 'rows' in responseData.data) {
|
||||
deliveryList.value = responseData.data.rows || [];
|
||||
} else {
|
||||
deliveryList.value = [];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载运送清单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 运送清单选择变化
|
||||
const handleDeliveryChange = (deliveryId) => {
|
||||
if (!deliveryId) {
|
||||
// 清空相关字段
|
||||
dialog.form.startLocation = '';
|
||||
dialog.form.startLon = '';
|
||||
dialog.form.startLat = '';
|
||||
dialog.form.endLocation = '';
|
||||
dialog.form.endLon = '';
|
||||
dialog.form.endLat = '';
|
||||
dialog.form.driverName = '';
|
||||
dialog.form.driverMobile = '';
|
||||
dialog.form.licensePlate = '';
|
||||
dialog.form.capacity = null;
|
||||
dialog.form.remainingCapacity = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 从 deliveryList 中找到对应的运送清单
|
||||
const selectedDelivery = deliveryList.value.find(item => item.id === deliveryId);
|
||||
if (selectedDelivery) {
|
||||
// 自动填充起始地信息
|
||||
if (selectedDelivery.startLocation) {
|
||||
dialog.form.startLocation = selectedDelivery.startLocation;
|
||||
}
|
||||
if (selectedDelivery.startLon) {
|
||||
dialog.form.startLon = selectedDelivery.startLon;
|
||||
}
|
||||
if (selectedDelivery.startLat) {
|
||||
dialog.form.startLat = selectedDelivery.startLat;
|
||||
}
|
||||
|
||||
// 自动填充目的地信息
|
||||
if (selectedDelivery.endLocation) {
|
||||
dialog.form.endLocation = selectedDelivery.endLocation;
|
||||
}
|
||||
if (selectedDelivery.endLon) {
|
||||
dialog.form.endLon = selectedDelivery.endLon;
|
||||
}
|
||||
if (selectedDelivery.endLat) {
|
||||
dialog.form.endLat = selectedDelivery.endLat;
|
||||
}
|
||||
|
||||
// 自动填充司机信息
|
||||
if (selectedDelivery.driverName) {
|
||||
dialog.form.driverName = selectedDelivery.driverName;
|
||||
}
|
||||
// 兼容 driverPhone 和 driverMobile 两种字段名
|
||||
if (selectedDelivery.driverPhone || selectedDelivery.driverMobile) {
|
||||
dialog.form.driverMobile = selectedDelivery.driverPhone || selectedDelivery.driverMobile;
|
||||
}
|
||||
|
||||
// 自动填充车牌号
|
||||
if (selectedDelivery.licensePlate) {
|
||||
dialog.form.licensePlate = selectedDelivery.licensePlate;
|
||||
}
|
||||
|
||||
// 自动填充牛只数量(从运送清单的 ratedQuantity 填充)
|
||||
if (selectedDelivery.ratedQuantity) {
|
||||
dialog.form.capacity = selectedDelivery.ratedQuantity;
|
||||
// 默认剩余牛只数量等于牛只数量
|
||||
dialog.form.remainingCapacity = selectedDelivery.ratedQuantity;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 自动生成进场编码
|
||||
const generateEntryCode = () => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const dateStr = `${year}${month}${day}`;
|
||||
|
||||
// 生成一个简单的编码:SE + yyyyMMdd + 时间戳后4位
|
||||
const timestamp = Date.now().toString();
|
||||
const seq = timestamp.slice(-4);
|
||||
dialog.form.entryCode = `SE${dateStr}${seq}`;
|
||||
};
|
||||
|
||||
const openDialog = (row) => {
|
||||
resetDialogForm();
|
||||
// 加载运送清单列表和订单列表
|
||||
loadDeliveryList();
|
||||
loadOrderList();
|
||||
if (row) {
|
||||
dialog.title = '编辑进场';
|
||||
Object.assign(dialog.form, row);
|
||||
} else {
|
||||
// 新增时,如果没有编码则自动生成
|
||||
if (!dialog.form.entryCode) {
|
||||
generateEntryCode();
|
||||
}
|
||||
}
|
||||
dialog.visible = true;
|
||||
};
|
||||
|
||||
const submitDialog = () => {
|
||||
dialogFormRef.value?.validate((valid) => {
|
||||
if (!valid) return;
|
||||
const payload = { ...dialog.form };
|
||||
const api = payload.id ? slaughterEntryEdit : slaughterEntryAdd;
|
||||
api(payload)
|
||||
.then(() => {
|
||||
ElMessage.success(payload.id ? '更新成功' : '新增成功');
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error(payload.id ? '更新失败' : '新增失败');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (row) => {
|
||||
ElMessageBox.confirm('确认删除该进场记录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => slaughterEntryDel(row.id))
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err !== 'cancel') {
|
||||
console.error(err);
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadHouseOptions();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
padding: 0 0 16px;
|
||||
}
|
||||
.action-bar {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
374
pc-cattle-transportation/src/views/slaughter/house.vue
Normal file
374
pc-cattle-transportation/src/views/slaughter/house.vue
Normal file
@@ -0,0 +1,374 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<base-search :formItemList="formItemList" @search="handleSearch" ref="baseSearchRef" />
|
||||
<div class="action-bar">
|
||||
<el-button type="primary" @click="openDialog()">新增屠宰场</el-button>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<el-table :data="data.rows" border v-loading="data.loading" element-loading-text="数据加载中..." style="width: 100%">
|
||||
<el-table-column label="屠宰场名称" prop="houseName" min-width="150" />
|
||||
<el-table-column label="屠宰场编码" prop="slaughterCode" min-width="150" />
|
||||
<el-table-column label="容量" prop="capacity" width="90" />
|
||||
<el-table-column label="地址" prop="address" min-width="200" />
|
||||
<el-table-column label="负责人" prop="person" min-width="120" />
|
||||
<el-table-column label="联系电话" prop="phone" min-width="140" />
|
||||
<el-table-column label="状态" prop="status" width="90">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="info">停用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="openDialog(scope.row)">编辑</el-button>
|
||||
<el-button link type="primary" @click="locateOnMap(scope.row)">定位</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<div class="dataListOnEmpty">暂无数据</div>
|
||||
</template>
|
||||
</el-table>
|
||||
<pagination v-model:limit="form.pageSize" v-model:page="form.pageNum" :total="data.total" @pagination="getList" />
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dialog.visible" :title="dialog.title" width="520px" :close-on-click-modal="false">
|
||||
<el-form ref="dialogFormRef" :model="dialog.form" :rules="dialog.rules" label-width="110px">
|
||||
<el-form-item label="屠宰场名称" prop="houseName">
|
||||
<el-input v-model="dialog.form.houseName" placeholder="请输入屠宰场名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="屠宰场编码" prop="slaughterCode">
|
||||
<el-input v-model="dialog.form.slaughterCode" placeholder="不填将自动生成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="容量" prop="capacity">
|
||||
<el-input-number v-model="dialog.form.capacity" :min="0" :step="1" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="地址" prop="address">
|
||||
<el-input
|
||||
v-model="dialog.form.address"
|
||||
placeholder="请输入地址"
|
||||
style="width: calc(100% - 100px); margin-right: 10px"
|
||||
/>
|
||||
<el-button type="primary" @click="openLocationMap">选择位置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="经度" prop="longitude">
|
||||
<el-input v-model="dialog.form.longitude" placeholder="经度" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="纬度" prop="latitude">
|
||||
<el-input v-model="dialog.form.latitude" placeholder="纬度" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人姓名" prop="person">
|
||||
<el-input v-model="dialog.form.person" placeholder="请输入负责人姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="dialog.form.phone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-switch v-model="dialog.form.status" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="dialog.form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitDialog">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 地址选择地图 -->
|
||||
<el-dialog v-model="showLocationMap" title="选择地址" width="900px">
|
||||
<baidu-map
|
||||
class="map"
|
||||
:center="mapCenter"
|
||||
:zoom="15"
|
||||
:scroll-wheel-zoom="true"
|
||||
@click="handleLocationClick"
|
||||
style="height: 500px"
|
||||
>
|
||||
<bm-marker
|
||||
v-if="dialog.form.longitude && dialog.form.latitude"
|
||||
:position="{ lng: parseFloat(dialog.form.longitude), lat: parseFloat(dialog.form.latitude) }"
|
||||
:dragging="true"
|
||||
@dragging="handleMarkerDrag"
|
||||
/>
|
||||
<bm-map-type :map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"></bm-map-type>
|
||||
</baidu-map>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showLocationMap = false">取消</el-button>
|
||||
<el-button type="primary" @click="showLocationMap = false">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted, computed } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { BaiduMap, BmMapType, BmMarker } from 'vue-baidu-map-3x';
|
||||
import baseSearch from '@/components/common/searchCustom/index.vue';
|
||||
import { slaughterHouseList, slaughterHouseAdd, slaughterHouseEdit, slaughterHouseDel } from '@/api/slaughter.js';
|
||||
|
||||
const baseSearchRef = ref();
|
||||
const dialogFormRef = ref();
|
||||
const showLocationMap = ref(false);
|
||||
|
||||
const formItemList = reactive([
|
||||
{
|
||||
label: '屠宰场名称',
|
||||
param: 'houseName',
|
||||
type: 'input',
|
||||
placeholder: '请输入屠宰场名称',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
{
|
||||
label: '屠宰场编码',
|
||||
param: 'slaughterCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入屠宰场编码',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
param: 'status',
|
||||
type: 'select',
|
||||
selectOptions: [
|
||||
{ value: 1,text: '启用' },
|
||||
{ value: 0 ,text: '停用' },
|
||||
],
|
||||
placeholder: '请选择状态',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
]);
|
||||
|
||||
const data = reactive({
|
||||
rows: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '新增屠宰场',
|
||||
form: {
|
||||
id: null,
|
||||
houseName: '',
|
||||
slaughterCode: '',
|
||||
capacity: null,
|
||||
address: '',
|
||||
longitude: '',
|
||||
latitude: '',
|
||||
person: '',
|
||||
phone: '',
|
||||
status: 1,
|
||||
remark: '',
|
||||
},
|
||||
rules: {
|
||||
houseName: [{ required: true, message: '请输入屠宰场名称', trigger: 'blur' }],
|
||||
capacity: [{ required: true, message: '请输入容量', trigger: 'change' }],
|
||||
address: [{ required: true, message: '请输入地址', trigger: 'blur' }],
|
||||
phone: [{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效手机号', trigger: 'blur' }],
|
||||
},
|
||||
});
|
||||
|
||||
const resetDialogForm = () => {
|
||||
dialog.form = {
|
||||
id: null,
|
||||
houseName: '',
|
||||
slaughterCode: '',
|
||||
capacity: null,
|
||||
address: '',
|
||||
longitude: '',
|
||||
latitude: '',
|
||||
person: '',
|
||||
phone: '',
|
||||
status: 1,
|
||||
remark: '',
|
||||
};
|
||||
dialog.title = '新增屠宰场';
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
data.loading = true;
|
||||
const params = { ...form, ...baseSearchRef.value.penetrateParams() };
|
||||
slaughterHouseList(params)
|
||||
.then((res) => {
|
||||
// 兼容结构:
|
||||
// axiosRes.data = { code, msg, data: { code, msg, data: { total, rows } } }
|
||||
// 或 axiosRes.data = { code, msg, data: { total, rows } }
|
||||
// 或 axiosRes.data = { total, rows }
|
||||
const resp = res?.data || {};
|
||||
const inner = resp?.data?.data || resp?.data || resp;
|
||||
data.rows = inner.rows || inner.data?.rows || [];
|
||||
data.total = inner.total || inner.data?.total || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error('查询失败');
|
||||
})
|
||||
.finally(() => {
|
||||
data.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
form.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const openDialog = (row) => {
|
||||
resetDialogForm();
|
||||
if (row) {
|
||||
dialog.title = '编辑屠宰场';
|
||||
Object.assign(dialog.form, row);
|
||||
}
|
||||
dialog.visible = true;
|
||||
};
|
||||
|
||||
const locateOnMap = (row) => {
|
||||
if (row && row.longitude && row.latitude) {
|
||||
dialog.form.longitude = row.longitude.toString();
|
||||
dialog.form.latitude = row.latitude.toString();
|
||||
dialog.form.address = row.address || dialog.form.address;
|
||||
showLocationMap.value = true;
|
||||
} else {
|
||||
ElMessage.warning('该记录无有效经纬度');
|
||||
}
|
||||
};
|
||||
|
||||
const openLocationMap = () => {
|
||||
// 如果输入了地址,先尝试地理编码定位
|
||||
if (dialog.form.address && dialog.form.address.trim()) {
|
||||
showLocationMap.value = true;
|
||||
setTimeout(() => {
|
||||
geocodeAddress(dialog.form.address, true);
|
||||
}, 300);
|
||||
} else {
|
||||
showLocationMap.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const geocodeAddress = (address, showToast = false) => {
|
||||
if (!address || !window.BMap || !window.BMap.Geocoder) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const geocoder = new window.BMap.Geocoder();
|
||||
geocoder.getPoint(address, (point) => {
|
||||
if (point) {
|
||||
dialog.form.longitude = point.lng.toFixed(6);
|
||||
dialog.form.latitude = point.lat.toFixed(6);
|
||||
showToast && ElMessage.success('已定位到该地址');
|
||||
} else {
|
||||
showToast && ElMessage.warning('未找到该地址,请在地图上手动选择');
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// ignore geocode errors
|
||||
}
|
||||
};
|
||||
|
||||
const handleLocationClick = (e) => {
|
||||
if (e && e.point) {
|
||||
dialog.form.longitude = e.point.lng.toFixed(6);
|
||||
dialog.form.latitude = e.point.lat.toFixed(6);
|
||||
// 反向地理编码回填地址
|
||||
if (window.BMap && window.BMap.Geocoder) {
|
||||
const geocoder = new window.BMap.Geocoder();
|
||||
geocoder.getLocation(e.point, (res) => {
|
||||
if (res && res.address) {
|
||||
dialog.form.address = res.address;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleMarkerDrag = (e) => {
|
||||
if (e && e.point) {
|
||||
dialog.form.longitude = e.point.lng.toFixed(6);
|
||||
dialog.form.latitude = e.point.lat.toFixed(6);
|
||||
if (window.BMap && window.BMap.Geocoder) {
|
||||
const geocoder = new window.BMap.Geocoder();
|
||||
geocoder.getLocation(e.point, (res) => {
|
||||
if (res && res.address) {
|
||||
dialog.form.address = res.address;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mapCenter = computed(() => {
|
||||
if (dialog.form.longitude && dialog.form.latitude) {
|
||||
return { lng: parseFloat(dialog.form.longitude), lat: parseFloat(dialog.form.latitude) };
|
||||
}
|
||||
return { lng: 116.404, lat: 39.915 };
|
||||
});
|
||||
|
||||
const submitDialog = () => {
|
||||
dialogFormRef.value?.validate((valid) => {
|
||||
if (!valid) return;
|
||||
const payload = { ...dialog.form };
|
||||
const requestApi = payload.id ? slaughterHouseEdit : slaughterHouseAdd;
|
||||
requestApi(payload)
|
||||
.then(() => {
|
||||
ElMessage.success(payload.id ? '更新成功' : '新增成功');
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error(payload.id ? '更新失败' : '新增失败');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (row) => {
|
||||
ElMessageBox.confirm('确认删除该屠宰场吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => slaughterHouseDel(row.id))
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err !== 'cancel') {
|
||||
console.error(err);
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
padding: 0 0 16px;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
364
pc-cattle-transportation/src/views/slaughter/record.vue
Normal file
364
pc-cattle-transportation/src/views/slaughter/record.vue
Normal file
@@ -0,0 +1,364 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<base-search :formItemList="formItemList" @search="handleSearch" ref="baseSearchRef" />
|
||||
<div class="action-bar">
|
||||
<el-button type="primary" @click="openDialog()">新增屠宰记录</el-button>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<el-table :data="data.rows" border v-loading="data.loading" element-loading-text="数据加载中..." style="width: 100%">
|
||||
<el-table-column label="屠宰记录编码" prop="recordCode" min-width="140" />
|
||||
<el-table-column label="进场编码" prop="entryCode" min-width="140" />
|
||||
<el-table-column label="屠宰场" prop="slaughterHouseName" min-width="140">
|
||||
<template #default="scope">
|
||||
{{ scope.row.slaughterHouseName || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="屠宰头数" prop="slaughterCount" width="120" />
|
||||
<el-table-column label="出肉率(%)" prop="yieldRate" width="120">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.yieldRate !== null && scope.row.yieldRate !== undefined">
|
||||
{{ scope.row.yieldRate }}%
|
||||
</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="进场剩余头数" prop="remainingCapacity" width="140">
|
||||
<template #default="scope">
|
||||
{{ scope.row.remainingCapacity ?? '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="openDialog(scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<div class="dataListOnEmpty">暂无数据</div>
|
||||
</template>
|
||||
</el-table>
|
||||
<pagination v-model:limit="form.pageSize" v-model:page="form.pageNum" :total="data.total" @pagination="getList" />
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dialog.visible" :title="dialog.title" width="520px" :close-on-click-modal="false">
|
||||
<el-form ref="dialogFormRef" :model="dialog.form" :rules="dialog.rules" label-width="120px">
|
||||
<el-form-item label="屠宰记录编码" prop="recordCode">
|
||||
<el-input
|
||||
v-model="dialog.form.recordCode"
|
||||
placeholder="请输入屠宰记录编码或点击自动生成"
|
||||
style="width: calc(100% - 100px); margin-right: 10px;"
|
||||
/>
|
||||
<el-button type="primary" @click="generateRecordCode">自动生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="进场记录" prop="entryId">
|
||||
<el-select
|
||||
v-model="dialog.form.entryId"
|
||||
placeholder="请选择进场记录"
|
||||
filterable
|
||||
style="width: 100%"
|
||||
@change="handleEntryChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in entryOptions"
|
||||
:key="item.id"
|
||||
:label="`${item.entryCode || '--'}(剩余${item.remainingCapacity ?? '--'}头)`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="屠宰头数" prop="slaughterCount">
|
||||
<el-input-number
|
||||
v-model="dialog.form.slaughterCount"
|
||||
:min="1"
|
||||
:max="999999"
|
||||
placeholder="请输入屠宰头数"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="出肉率(%)" prop="yieldRate">
|
||||
<el-input-number
|
||||
v-model="dialog.form.yieldRate"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="0.1"
|
||||
placeholder="请输入出肉率(0-100)"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="选中的进场记录"
|
||||
description="进场编码:{{ dialog.state.entryCode || '--' }},当前剩余头数:{{ dialog.state.remaining ?? '--' }}"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitDialog">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import baseSearch from '@/components/common/searchCustom/index.vue';
|
||||
import {
|
||||
slaughterRecordList,
|
||||
slaughterRecordAdd,
|
||||
slaughterRecordEdit,
|
||||
slaughterRecordDel,
|
||||
slaughterRecordDetail,
|
||||
slaughterEntryList,
|
||||
slaughterHouseList,
|
||||
} from '@/api/slaughter.js';
|
||||
|
||||
const baseSearchRef = ref();
|
||||
const dialogFormRef = ref();
|
||||
|
||||
const houseOptions = ref([]);
|
||||
const entryOptions = ref([]);
|
||||
const entryMap = reactive({});
|
||||
|
||||
const formItemList = reactive([
|
||||
{
|
||||
label: '屠宰场',
|
||||
param: 'slaughterHouseId',
|
||||
type: 'select',
|
||||
selectOptions: [],
|
||||
placeholder: '请选择屠宰场',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
labelKey: 'label',
|
||||
valueKey: 'value',
|
||||
},
|
||||
{
|
||||
label: '屠宰记录编码',
|
||||
param: 'recordCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入屠宰记录编码',
|
||||
span: 8,
|
||||
labelWidth: 120,
|
||||
},
|
||||
{
|
||||
label: '进场编码',
|
||||
param: 'entryCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入进场编码',
|
||||
span: 8,
|
||||
labelWidth: 100,
|
||||
},
|
||||
]);
|
||||
|
||||
const data = reactive({
|
||||
rows: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '新增屠宰记录',
|
||||
form: {
|
||||
id: null,
|
||||
recordCode: '',
|
||||
entryId: null,
|
||||
slaughterCount: 1,
|
||||
yieldRate: null,
|
||||
},
|
||||
state: {
|
||||
remaining: null,
|
||||
entryCode: '',
|
||||
},
|
||||
rules: {
|
||||
entryId: [{ required: true, message: '请选择进场记录', trigger: 'change' }],
|
||||
slaughterCount: [{ required: true, message: '请输入屠宰头数', trigger: 'blur' }],
|
||||
},
|
||||
});
|
||||
|
||||
const resetDialogForm = () => {
|
||||
dialog.form = {
|
||||
id: null,
|
||||
recordCode: '',
|
||||
entryId: null,
|
||||
slaughterCount: 1,
|
||||
yieldRate: null,
|
||||
};
|
||||
dialog.state = {
|
||||
remaining: null,
|
||||
entryCode: '',
|
||||
};
|
||||
dialog.title = '新增屠宰记录';
|
||||
};
|
||||
|
||||
const loadHouseOptions = () => {
|
||||
slaughterHouseList({ pageNum: 1, pageSize: 1000 })
|
||||
.then((res) => {
|
||||
let responseData = res.data;
|
||||
if (responseData && responseData.data && typeof responseData.data === 'object') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
const list = responseData?.rows || responseData || [];
|
||||
const options = list.map((item) => ({
|
||||
label: item.house_name || item.houseName,
|
||||
value: item.id,
|
||||
}));
|
||||
houseOptions.value = options;
|
||||
formItemList[0].selectOptions = options;
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
};
|
||||
|
||||
const loadEntryOptions = () => {
|
||||
slaughterEntryList({ pageNum: 1, pageSize: 1000 })
|
||||
.then((res) => {
|
||||
let responseData = res.data;
|
||||
if (responseData && responseData.data && typeof responseData.data === 'object') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
const list = responseData?.rows || responseData || [];
|
||||
entryOptions.value = list;
|
||||
Object.keys(entryMap).forEach((key) => delete entryMap[key]);
|
||||
list.forEach((item) => {
|
||||
entryMap[item.id] = {
|
||||
entryCode: item.entryCode,
|
||||
remainingCapacity: item.remainingCapacity,
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
data.loading = true;
|
||||
const params = { ...form, ...baseSearchRef.value.penetrateParams() };
|
||||
slaughterRecordList(params)
|
||||
.then((res) => {
|
||||
let responseData = res.data;
|
||||
if (responseData && responseData.data && typeof responseData.data === 'object') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
data.rows = responseData?.rows || [];
|
||||
data.total = responseData?.total || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error('查询失败');
|
||||
})
|
||||
.finally(() => {
|
||||
data.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
form.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const generateRecordCode = () => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const dateStr = `${year}${month}${day}`;
|
||||
const seq = Date.now().toString().slice(-3);
|
||||
dialog.form.recordCode = `SL${dateStr}${seq}`;
|
||||
};
|
||||
|
||||
const handleEntryChange = (entryId) => {
|
||||
if (!entryId) {
|
||||
dialog.state.remaining = null;
|
||||
dialog.state.entryCode = '';
|
||||
return;
|
||||
}
|
||||
const info = entryMap[entryId];
|
||||
dialog.state.remaining = info?.remainingCapacity ?? null;
|
||||
dialog.state.entryCode = info?.entryCode || '';
|
||||
};
|
||||
|
||||
const openDialog = (row) => {
|
||||
resetDialogForm();
|
||||
loadEntryOptions();
|
||||
if (row) {
|
||||
dialog.title = '编辑屠宰记录';
|
||||
// 重新获取详情,保证剩余头数为最新
|
||||
slaughterRecordDetail(row.id)
|
||||
.then((res) => {
|
||||
const responseData = res.data?.data || res.data || {};
|
||||
Object.assign(dialog.form, responseData);
|
||||
dialog.state.entryCode = responseData.entryCode;
|
||||
// 可用剩余 = 后端剩余 + 当前记录屠宰头数
|
||||
const remaining = (responseData.remainingCapacity ?? 0) + (responseData.slaughterCount ?? 0);
|
||||
dialog.state.remaining = remaining;
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
} else {
|
||||
if (!dialog.form.recordCode) {
|
||||
generateRecordCode();
|
||||
}
|
||||
}
|
||||
dialog.visible = true;
|
||||
};
|
||||
|
||||
const submitDialog = () => {
|
||||
dialogFormRef.value?.validate((valid) => {
|
||||
if (!valid) return;
|
||||
const payload = { ...dialog.form };
|
||||
const api = payload.id ? slaughterRecordEdit : slaughterRecordAdd;
|
||||
api(payload)
|
||||
.then(() => {
|
||||
ElMessage.success(payload.id ? '更新成功' : '新增成功');
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
loadEntryOptions();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error(payload.id ? '更新失败' : '新增失败');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (row) => {
|
||||
ElMessageBox.confirm('确认删除该屠宰记录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => slaughterRecordDel(row.id))
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
getList();
|
||||
loadEntryOptions();
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err !== 'cancel') {
|
||||
console.error(err);
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadHouseOptions();
|
||||
loadEntryOptions();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.action-bar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
:file-list="ruleForm.driver_license"
|
||||
:headers="importHeaders"
|
||||
:on-exceed="() => handleExceed(2)"
|
||||
@drop.native="(e) => handleDrop(e, 'driver_license', 2)"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -35,6 +40,11 @@
|
||||
:file-list="ruleForm.id_card"
|
||||
:headers="importHeaders"
|
||||
:on-exceed="() => handleExceed(2)"
|
||||
@drop.native="(e) => handleDrop(e, 'id_card', 2)"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -152,6 +162,105 @@ const handleExceed = (number) => {
|
||||
ElMessage.warning(`最多只能上传${number}张图片!`);
|
||||
};
|
||||
|
||||
// 处理拖拽进入
|
||||
const handleDragEnter = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.add('drag-over');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理拖拽离开
|
||||
const handleDragLeave = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.remove('drag-over');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理拖拽上传
|
||||
const handleDrop = (e, type, limit = 2) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// 移除拖拽样式
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.remove('drag-over');
|
||||
}
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
|
||||
// 过滤出图片文件
|
||||
const imageFiles = files.filter(file => file.type.startsWith('image/'));
|
||||
|
||||
if (imageFiles.length === 0) {
|
||||
ElMessage.error('请拖拽图片文件!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查限制:只处理不超过限制的文件
|
||||
const currentCount = ruleForm[type].length;
|
||||
const remainingSlots = limit - currentCount;
|
||||
|
||||
if (remainingSlots <= 0) {
|
||||
ElMessage.warning(`最多只能上传${limit}张图片!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 只处理前 remainingSlots 个文件
|
||||
const filesToUpload = imageFiles.slice(0, remainingSlots);
|
||||
|
||||
// 处理每个文件
|
||||
filesToUpload.forEach((file, index) => {
|
||||
// 验证文件
|
||||
if (!beforeAvatarUpload(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 FormData 并上传
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 使用 fetch 上传文件
|
||||
fetch('/api/common/upload', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': importHeaders.Authorization
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(res => {
|
||||
// 创建文件对象
|
||||
const fileObj = {
|
||||
uid: Date.now() + Math.random() + index,
|
||||
name: file.name,
|
||||
status: 'success',
|
||||
url: ''
|
||||
};
|
||||
|
||||
// 获取当前文件列表并添加新文件
|
||||
const currentFileList = [...ruleForm[type]];
|
||||
currentFileList.push(fileObj);
|
||||
|
||||
// 调用成功处理函数
|
||||
handleAvatarSuccess(res, fileObj, currentFileList, type);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('上传失败:', error);
|
||||
ElMessage.error('上传失败,请稍后重试');
|
||||
});
|
||||
});
|
||||
|
||||
// 如果拖拽的文件超过限制,提示用户
|
||||
if (imageFiles.length > remainingSlots) {
|
||||
ElMessage.warning(`只能上传${remainingSlots}张图片,已忽略多余的${imageFiles.length - remainingSlots}张`);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePreview = (file) => {
|
||||
data.dialogImageUrl = file.url;
|
||||
data.dialogVisibleImg = true;
|
||||
@@ -224,4 +333,39 @@ defineExpose({ onShowDialog });
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* 拖拽上传样式 */
|
||||
:deep(.upload-drag-area) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload--picture-card) {
|
||||
border: 2px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload--picture-card:hover) {
|
||||
border-color: #409eff;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload-list--picture-card) {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 拖拽时的视觉反馈 */
|
||||
:deep(.upload-drag-area.drag-over .el-upload--picture-card) {
|
||||
border-color: #409eff;
|
||||
background-color: #ecf5ff;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area.drag-over .el-upload--picture-card .el-icon) {
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="remark" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime" width="180"></el-table-column>
|
||||
<el-table-column label="创建人" prop="createByName" width="120"></el-table-column>
|
||||
<el-table-column label="操作" width="160">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="showAddDialog(scope.row)">编辑</el-button>
|
||||
@@ -119,6 +120,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Picture } from '@element-plus/icons-vue';
|
||||
import baseSearch from '@/components/common/searchCustom/index.vue';
|
||||
import { vehicleList, vehicleDel } from '@/api/userManage.js';
|
||||
import { sysUserList } from '@/api/sys.js';
|
||||
import VehicleDialog from './vehicleDialog.vue';
|
||||
|
||||
const baseSearchRef = ref();
|
||||
@@ -143,6 +145,7 @@ const data = reactive({
|
||||
rows: [],
|
||||
total: 0,
|
||||
dataListLoading: false,
|
||||
userMap: {}, // 存储用户ID到用户名的映射 {userId: userName}
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
@@ -190,7 +193,9 @@ const getDataList = async () => {
|
||||
const dataInfo = res.data?.data || res.data;
|
||||
data.rows = dataInfo?.rows || [];
|
||||
data.total = dataInfo?.total || 0;
|
||||
|
||||
|
||||
// 映射创建人名称
|
||||
await mapCreatedByName();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '查询失败');
|
||||
}
|
||||
@@ -265,6 +270,94 @@ const getImageCount = (value) => {
|
||||
return 1;
|
||||
};
|
||||
|
||||
// 映射创建人名称
|
||||
const mapCreatedByName = async () => {
|
||||
if (!data.rows || data.rows.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否所有记录都已经有 createByName 字段(后端可能已经返回)
|
||||
const needMapping = data.rows.some(row => !row.createByName && row.createdBy);
|
||||
|
||||
if (!needMapping) {
|
||||
// 如果所有记录都有 createByName,不需要映射
|
||||
return;
|
||||
}
|
||||
|
||||
// 收集所有的 createdBy 字段值(去重)
|
||||
const createdByIds = [...new Set(data.rows
|
||||
.map(row => row.createdBy)
|
||||
.filter(id => id != null && id !== '' && id !== undefined))];
|
||||
|
||||
if (createdByIds.length === 0) {
|
||||
// 如果没有创建人ID,设置默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
row.createByName = '--';
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询用户信息
|
||||
const userRes = await sysUserList({
|
||||
pageNum: 1,
|
||||
pageSize: 1000 // 设置一个较大的值以获取所有用户
|
||||
});
|
||||
|
||||
if (userRes.code === 200) {
|
||||
const userList = userRes.data?.rows || userRes.data || [];
|
||||
|
||||
// 创建用户ID到用户名的映射(只映射需要的用户)
|
||||
const idSet = new Set(createdByIds.map(id => String(id)));
|
||||
userList.forEach(user => {
|
||||
const userId = String(user.id);
|
||||
if (idSet.has(userId) && user.name) {
|
||||
data.userMap[userId] = user.name;
|
||||
// 同时支持数字ID和字符串ID的映射
|
||||
data.userMap[user.id] = user.name;
|
||||
}
|
||||
});
|
||||
|
||||
// 为每条记录设置 createByName(只设置没有值的记录)
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
if (row.createdBy) {
|
||||
const userId = String(row.createdBy);
|
||||
// 尝试多种方式查找用户名
|
||||
row.createByName = data.userMap[row.createdBy]
|
||||
|| data.userMap[userId]
|
||||
|| data.userMap[Number(row.createdBy)]
|
||||
|| '--';
|
||||
} else {
|
||||
row.createByName = '--';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// API返回错误,使用默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
row.createByName = row.createdBy ? String(row.createdBy) : '--';
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
// 如果获取用户信息失败,显示ID或默认值
|
||||
data.rows.forEach(row => {
|
||||
if (!row.createByName) {
|
||||
if (row.createdBy) {
|
||||
row.createByName = String(row.createdBy);
|
||||
} else {
|
||||
row.createByName = '--';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDataList();
|
||||
});
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
:file-list="ruleForm.carFrontPhoto"
|
||||
:headers="importHeaders"
|
||||
:on-exceed="handleExceed"
|
||||
@drop.native="(e) => handleDrop(e, 'carFrontPhoto')"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -32,6 +37,11 @@
|
||||
:file-list="ruleForm.carRearPhoto"
|
||||
:headers="importHeaders"
|
||||
:on-exceed="handleExceed"
|
||||
@drop.native="(e) => handleDrop(e, 'carRearPhoto')"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -46,6 +56,11 @@
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:file-list="ruleForm.drivingLicensePhoto"
|
||||
:headers="importHeaders"
|
||||
@drop.native="(e) => handleDrop(e, 'drivingLicensePhoto')"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -60,6 +75,11 @@
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:file-list="ruleForm.recordCode"
|
||||
:headers="importHeaders"
|
||||
@drop.native="(e) => handleDrop(e, 'recordCode')"
|
||||
@dragover.native.prevent
|
||||
@dragenter.native="(e) => handleDragEnter(e)"
|
||||
@dragleave.native="(e) => handleDragLeave(e)"
|
||||
class="upload-drag-area"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@@ -178,6 +198,132 @@ const handleExceed = () => {
|
||||
// 已移除单图片限制,此方法不再需要
|
||||
};
|
||||
|
||||
// 处理拖拽进入
|
||||
const handleDragEnter = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.add('drag-over');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理拖拽离开
|
||||
const handleDragLeave = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.remove('drag-over');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理拖拽上传
|
||||
const handleDrop = (e, type) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// 移除拖拽样式
|
||||
const target = e.currentTarget;
|
||||
if (target) {
|
||||
target.classList.remove('drag-over');
|
||||
}
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
|
||||
// 过滤出图片文件
|
||||
const imageFiles = files.filter(file => file.type.startsWith('image/'));
|
||||
|
||||
if (imageFiles.length === 0) {
|
||||
ElMessage.error('请拖拽图片文件!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查限制
|
||||
const limit = type === 'carFrontPhoto' || type === 'carRearPhoto' ? 1 : undefined;
|
||||
if (limit) {
|
||||
// 单图片:如果已有图片,先清空
|
||||
if (ruleForm[type].length > 0) {
|
||||
ruleForm[type] = [];
|
||||
}
|
||||
// 只处理第一个文件
|
||||
const file = imageFiles[0];
|
||||
if (!beforeAvatarUpload(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 FormData 并上传
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 使用 fetch 上传文件
|
||||
fetch('/api/common/upload', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': importHeaders.Authorization
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(res => {
|
||||
// 创建文件对象
|
||||
const fileObj = {
|
||||
uid: Date.now() + Math.random(),
|
||||
name: file.name,
|
||||
status: 'success',
|
||||
url: ''
|
||||
};
|
||||
|
||||
// 调用成功处理函数
|
||||
handleAvatarSuccess(res, fileObj, [fileObj], type);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('上传失败:', error);
|
||||
ElMessage.error('上传失败,请稍后重试');
|
||||
});
|
||||
} else {
|
||||
// 多图片:处理所有文件
|
||||
imageFiles.forEach((file, index) => {
|
||||
// 验证文件
|
||||
if (!beforeAvatarUpload(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 FormData 并上传
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 使用 fetch 上传文件
|
||||
fetch('/api/common/upload', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': importHeaders.Authorization
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(res => {
|
||||
// 创建文件对象
|
||||
const fileObj = {
|
||||
uid: Date.now() + Math.random() + index,
|
||||
name: file.name,
|
||||
status: 'success',
|
||||
url: ''
|
||||
};
|
||||
|
||||
// 获取当前文件列表并添加新文件
|
||||
const currentFileList = [...ruleForm[type]];
|
||||
currentFileList.push(fileObj);
|
||||
|
||||
// 调用成功处理函数
|
||||
handleAvatarSuccess(res, fileObj, currentFileList, type);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('上传失败:', error);
|
||||
ElMessage.error('上传失败,请稍后重试');
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onClickSave = async () => {
|
||||
await formDataRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
@@ -334,5 +480,40 @@ defineExpose({ open });
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* 拖拽上传样式 */
|
||||
:deep(.upload-drag-area) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload--picture-card) {
|
||||
border: 2px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload--picture-card:hover) {
|
||||
border-color: #409eff;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area .el-upload-list--picture-card) {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 拖拽时的视觉反馈 */
|
||||
:deep(.upload-drag-area.drag-over .el-upload--picture-card) {
|
||||
border-color: #409eff;
|
||||
background-color: #ecf5ff;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
:deep(.upload-drag-area.drag-over .el-upload--picture-card .el-icon) {
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<el-option
|
||||
v-for="item in orderList"
|
||||
:key="item.id"
|
||||
:label="`订单${item.id} - 单价: ${item.firmPrice || '--'}元/斤`"
|
||||
:label="`订单${item.id} -买方${item.buyerName}-卖方${item.sellerName}- 单价: ${item.firmPrice || '--'}元/斤`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
@@ -35,9 +35,23 @@
|
||||
{{ scope.row.warehouseName || '--' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="进仓单号" prop="warehouseInNumber" min-width="150" width="180">
|
||||
<el-table-column label="关联进仓记录" prop="warehouseInRelations" min-width="200" width="250">
|
||||
<template #default="scope">
|
||||
{{ scope.row.warehouseInNumber || '--' }}
|
||||
<div v-if="scope.row.warehouseInRelations && scope.row.warehouseInRelations.length > 0">
|
||||
<el-tag
|
||||
v-for="(relation, index) in scope.row.warehouseInRelations"
|
||||
:key="index"
|
||||
type="info"
|
||||
size="small"
|
||||
style="margin-right: 5px; margin-bottom: 5px;"
|
||||
>
|
||||
{{ relation.warehouseInNumber || '--' }} ({{ relation.outCount || 0 }}头)
|
||||
</el-tag>
|
||||
</div>
|
||||
<span v-else-if="scope.row.warehouseInNumber">
|
||||
{{ scope.row.warehouseInNumber || '--' }}
|
||||
</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运单号" prop="deliveryNumber" min-width="120" width="150">
|
||||
|
||||
@@ -27,23 +27,120 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="进仓记录" prop="warehouseInId">
|
||||
<el-select
|
||||
v-model="ruleForm.warehouseInId"
|
||||
placeholder="请选择进仓记录(可选)"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
@change="handleWarehouseInChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in warehouseInList"
|
||||
:key="item.id"
|
||||
:label="`${item.inNumber || '--'} - ${item.cattleCount || 0}头`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-row>
|
||||
|
||||
<!-- 进仓记录关联表格 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="关联进仓记录" prop="warehouseInRelations">
|
||||
<div style="width: 100%">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="addWarehouseInRelation"
|
||||
:disabled="data.isDetail || !ruleForm.warehouseId"
|
||||
style="margin-bottom: 10px"
|
||||
>
|
||||
添加进仓记录
|
||||
</el-button>
|
||||
<el-table
|
||||
:data="ruleForm.warehouseInRelations"
|
||||
border
|
||||
style="width: 100%"
|
||||
:max-height="300"
|
||||
:key="`warehouse-in-table-${warehouseInList.length}`"
|
||||
>
|
||||
<el-table-column label="进仓单号" min-width="150">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.warehouseInId"
|
||||
placeholder="请选择进仓记录"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%"
|
||||
:disabled="data.isDetail"
|
||||
:loading="warehouseInList.length === 0 && ruleForm.warehouseId"
|
||||
@change="handleWarehouseInRelationChange(scope.row, scope.$index)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in getAvailableWarehouseInList(scope.$index)"
|
||||
:key="`option-${item.id}-${item.remainingCount}`"
|
||||
:label="`${item.inNumber || '--'} (总:${item.cattleCount || 0}头, 剩余:${item.remainingCount || 0}头)`"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.inNumber || '--' }} (总:{{ item.cattleCount || 0 }}头, 剩余:{{ item.remainingCount || 0 }}头)
|
||||
</el-option>
|
||||
<el-option
|
||||
v-if="getAvailableWarehouseInList(scope.$index).length === 0 && warehouseInList.length === 0 && ruleForm.warehouseId && !data.isDetail"
|
||||
disabled
|
||||
value=""
|
||||
>
|
||||
正在加载进仓记录...
|
||||
</el-option>
|
||||
<el-option
|
||||
v-if="getAvailableWarehouseInList(scope.$index).length === 0 && warehouseInList.length > 0 && !data.isDetail"
|
||||
disabled
|
||||
value=""
|
||||
>
|
||||
暂无可用进仓记录(剩余数量为0或已被选择)
|
||||
</el-option>
|
||||
<el-option
|
||||
v-if="getAvailableWarehouseInList(scope.$index).length === 0 && !ruleForm.warehouseId && !data.isDetail"
|
||||
disabled
|
||||
value=""
|
||||
>
|
||||
请先选择中转仓
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="进仓总数量" prop="totalCount" min-width="100" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.totalCount || '--' }} 头
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已出仓数量" prop="outCount" min-width="100" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.outCount || 0 }} 头
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="剩余数量" prop="remainingCount" min-width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span :style="{ color: (scope.row.remainingCount || 0) <= 0 ? 'red' : 'green' }">
|
||||
{{ scope.row.remainingCount || 0 }} 头
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="本次出仓数量" prop="outCountThisTime" min-width="150">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
:model-value="scope.row.outCountThisTime || null"
|
||||
@update:model-value="(val) => { scope.row.outCountThisTime = val || undefined; handleOutCountChange(); }"
|
||||
:min="Math.min(1, scope.row.remainingCount || 0)"
|
||||
:max="Math.max(scope.row.remainingCount || 0, 0)"
|
||||
:disabled="data.isDetail || !scope.row.warehouseInId || (scope.row.remainingCount || 0) <= 0"
|
||||
placeholder="请输入数量"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center" v-if="!data.isDetail">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="removeWarehouseInRelation(scope.$index)"
|
||||
:disabled="!scope.row.warehouseInId"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top: 10px; color: #666; font-size: 12px;">
|
||||
<span>总出仓数量:<strong style="color: #409EFF;">{{ getTotalOutCount() }}</strong> 头</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -137,9 +234,13 @@
|
||||
v-model="ruleForm.cattleCount"
|
||||
:min="1"
|
||||
:max="9999"
|
||||
placeholder="请输入牛只数量"
|
||||
placeholder="请输入牛只数量(自动计算)"
|
||||
style="width: 100%"
|
||||
:disabled="true"
|
||||
/>
|
||||
<div style="color: #909399; font-size: 12px; margin-top: 5px;">
|
||||
由关联的进仓记录自动计算
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -263,11 +364,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { ref, reactive, watch, nextTick, computed } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { BaiduMap, BmMapType, BmMarker } from 'vue-baidu-map-3x';
|
||||
import { warehouseOutAdd, warehouseOutEdit, warehouseOutDetail } from '@/api/warehouseOut.js';
|
||||
import { warehouseOutAdd, warehouseOutEdit, warehouseOutDetail, warehouseOutList } from '@/api/warehouseOut.js';
|
||||
import { warehouseAll } from '@/api/warehouse.js';
|
||||
import { warehouseInList as warehouseInListApi } from '@/api/warehouseIn.js';
|
||||
import { orderPageQuery, shippingList } from '@/api/shipping.js';
|
||||
@@ -281,7 +382,7 @@ const photoFileList = ref([]);
|
||||
const videoFileList = ref([]);
|
||||
|
||||
const warehouseList = ref([]);
|
||||
const warehouseInList = ref([]);
|
||||
const warehouseInList = ref([]); // 所有可用的进仓记录
|
||||
const orderList = ref([]);
|
||||
const deliveryList = ref([]);
|
||||
|
||||
@@ -295,7 +396,8 @@ const data = reactive({
|
||||
const ruleForm = reactive({
|
||||
id: null,
|
||||
warehouseId: null,
|
||||
warehouseInId: null,
|
||||
warehouseInId: null, // 保留用于兼容,但不再使用
|
||||
warehouseInRelations: [], // 进仓记录关联数组,每个元素包含:warehouseInId, totalCount, outCount, remainingCount, outCountThisTime
|
||||
orderId: [],
|
||||
deliveryId: null,
|
||||
destinationLocation: '',
|
||||
@@ -317,6 +419,30 @@ const rules = reactive({
|
||||
deliveryId: [
|
||||
{ required: true, message: '请选择运送清单', trigger: 'change' },
|
||||
],
|
||||
warehouseInRelations: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (!value || value.length === 0) {
|
||||
callback(new Error('请至少添加一个进仓记录'));
|
||||
} else {
|
||||
// 检查每个关联记录是否都填写了出仓数量
|
||||
const hasEmpty = value.some(item => !item.warehouseInId || !item.outCountThisTime || item.outCountThisTime <= 0);
|
||||
if (hasEmpty) {
|
||||
callback(new Error('请为每个进仓记录填写出仓数量'));
|
||||
} else {
|
||||
// 检查总出仓数量
|
||||
const totalOutCount = value.reduce((sum, item) => sum + (item.outCountThisTime || 0), 0);
|
||||
if (totalOutCount <= 0) {
|
||||
callback(new Error('总出仓数量必须大于0'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
},
|
||||
],
|
||||
cattleCount: [
|
||||
{ required: true, message: '请输入牛只数量', trigger: 'blur' },
|
||||
{ type: 'number', min: 1, message: '牛只数量必须大于0', trigger: 'blur' },
|
||||
@@ -341,23 +467,119 @@ const loadWarehouseList = async () => {
|
||||
// 加载进仓记录列表(不限制状态,避免过滤掉待进仓记录)
|
||||
const loadWarehouseInList = async (warehouseId) => {
|
||||
try {
|
||||
console.log('开始加载进仓记录列表,warehouseId:', warehouseId);
|
||||
const params = { pageNum: 1, pageSize: 1000 };
|
||||
if (warehouseId) {
|
||||
params.warehouseId = warehouseId;
|
||||
}
|
||||
console.log('调用接口参数:', params);
|
||||
const res = await warehouseInListApi(params);
|
||||
console.log('进仓记录接口返回:', res);
|
||||
|
||||
if (res.code === 200) {
|
||||
const responseData = res.data || res;
|
||||
let list = [];
|
||||
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
|
||||
warehouseInList.value = responseData.rows || [];
|
||||
list = responseData.rows || [];
|
||||
} else if (responseData && responseData.data && 'rows' in responseData.data) {
|
||||
warehouseInList.value = responseData.data.rows || [];
|
||||
} else {
|
||||
warehouseInList.value = [];
|
||||
list = responseData.data.rows || [];
|
||||
} else if (Array.isArray(responseData)) {
|
||||
list = responseData;
|
||||
}
|
||||
|
||||
console.log('解析后的进仓记录列表:', list);
|
||||
|
||||
// 直接使用数据库返回的 remainingCount 字段,并过滤掉剩余数量为0的记录
|
||||
// 在编辑模式下,需要将当前编辑的出仓记录关联的进仓记录的剩余数量加回去
|
||||
const currentEditId = data.editId;
|
||||
console.log('当前编辑的出仓记录ID:', currentEditId);
|
||||
|
||||
// 如果正在编辑,需要获取当前编辑的出仓记录详情,以便恢复已关联进仓记录的剩余数量
|
||||
let currentEditOutRelations = new Map(); // key: 进仓记录ID, value: 当前编辑的出仓数量
|
||||
if (currentEditId && ruleForm.warehouseInRelations && ruleForm.warehouseInRelations.length > 0) {
|
||||
// 从表单中获取当前编辑的出仓记录关联的进仓记录和出仓数量
|
||||
ruleForm.warehouseInRelations.forEach(rel => {
|
||||
if (rel.warehouseInId && rel.outCountThisTime) {
|
||||
const currentCount = currentEditOutRelations.get(rel.warehouseInId) || 0;
|
||||
currentEditOutRelations.set(rel.warehouseInId, currentCount + rel.outCountThisTime);
|
||||
}
|
||||
});
|
||||
console.log('当前编辑的出仓记录关联的进仓记录和数量:', Array.from(currentEditOutRelations.entries()));
|
||||
}
|
||||
|
||||
// 处理进仓记录列表,使用数据库的 remainingCount 字段
|
||||
// 如果 remainingCount 字段不存在(数据库未迁移),则使用 cattleCount 作为默认值
|
||||
const processedList = list.map(item => {
|
||||
// 使用数据库返回的 remainingCount,如果没有则使用 cattleCount(兼容旧数据)
|
||||
const totalCount = item.cattleCount || 0;
|
||||
let remainingCount = item.remainingCount;
|
||||
|
||||
// 如果 remainingCount 为 undefined 或 null,说明数据库字段可能不存在,使用 cattleCount
|
||||
if (remainingCount === undefined || remainingCount === null) {
|
||||
remainingCount = totalCount;
|
||||
console.warn(`进仓记录 ${item.inNumber} 没有 remainingCount 字段,使用 cattleCount: ${totalCount}`);
|
||||
}
|
||||
|
||||
// 在编辑模式下,如果这个进仓记录已经被当前编辑的出仓记录关联,需要将当前编辑的出仓数量加回去
|
||||
// 这样用户就可以编辑到进仓总数量(如果没有其他出仓记录关联的话)
|
||||
if (currentEditId && currentEditOutRelations.has(item.id)) {
|
||||
const currentEditOutCount = currentEditOutRelations.get(item.id) || 0;
|
||||
remainingCount = remainingCount + currentEditOutCount;
|
||||
console.log(`编辑模式 - 进仓记录 ${item.inNumber}: 恢复当前编辑的出仓数量 ${currentEditOutCount},剩余数量从 ${item.remainingCount} 调整为 ${remainingCount}`);
|
||||
}
|
||||
|
||||
const outCount = totalCount - remainingCount;
|
||||
|
||||
console.log(`处理进仓记录 ${item.inNumber}: totalCount=${totalCount}, outCount=${outCount}, remainingCount=${remainingCount}`);
|
||||
|
||||
return {
|
||||
...item,
|
||||
outCount: Math.max(0, outCount),
|
||||
remainingCount: Math.max(0, remainingCount),
|
||||
// 标记是否为编辑模式下已关联的记录
|
||||
isCurrentEditRelated: currentEditId && currentEditOutRelations.has(item.id),
|
||||
};
|
||||
});
|
||||
|
||||
// 在编辑模式下,需要保留当前已选择的进仓记录(即使剩余数量为0)
|
||||
// 这样用户可以看到已选择的记录,但无法选择新的剩余数量为0的记录
|
||||
const currentSelectedIds = new Set();
|
||||
if (data.editId && ruleForm.warehouseInRelations) {
|
||||
ruleForm.warehouseInRelations.forEach(rel => {
|
||||
if (rel.warehouseInId) {
|
||||
currentSelectedIds.add(rel.warehouseInId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 过滤进仓记录列表
|
||||
// 1. 保留当前已选择的记录(编辑模式下,不受剩余数量限制)
|
||||
// 2. 过滤掉剩余数量为0的记录(新增模式下或未选择的记录)
|
||||
warehouseInList.value = processedList.filter(item => {
|
||||
// 如果是当前已选择的记录,保留(编辑模式下需要显示,不受剩余数量限制)
|
||||
if (currentSelectedIds.has(item.id)) {
|
||||
return true;
|
||||
}
|
||||
// 否则,只显示剩余数量 > 0 的记录
|
||||
return (item.remainingCount || 0) > 0;
|
||||
});
|
||||
|
||||
console.log('处理后的进仓记录列表:', warehouseInList.value);
|
||||
console.log('当前已选择的进仓记录ID:', Array.from(currentSelectedIds));
|
||||
|
||||
// 强制触发响应式更新
|
||||
nextTick(() => {
|
||||
console.log('nextTick - 进仓记录列表已更新,长度:', warehouseInList.value.length);
|
||||
});
|
||||
} else {
|
||||
console.error('加载进仓记录列表失败,返回码:', res.code, '错误信息:', res.msg);
|
||||
ElMessage.warning('加载进仓记录列表失败:' + (res.msg || '未知错误'));
|
||||
warehouseInList.value = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载进仓记录列表失败', error);
|
||||
console.error('加载进仓记录列表异常:', error);
|
||||
ElMessage.error('加载进仓记录列表失败:' + (error.message || '未知错误'));
|
||||
warehouseInList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -407,6 +629,7 @@ const handleClose = () => {
|
||||
id: null,
|
||||
warehouseId: null,
|
||||
warehouseInId: null,
|
||||
warehouseInRelations: [],
|
||||
orderId: [],
|
||||
deliveryId: null,
|
||||
destinationLocation: '',
|
||||
@@ -448,9 +671,47 @@ const onClickSave = () => {
|
||||
const photosStr = photoFileList.value.map(file => file.url || file.response?.data?.url || '').filter(url => url).join(',');
|
||||
const videosStr = videoFileList.value.map(file => file.url || file.response?.data?.url || '').filter(url => url).join(',');
|
||||
|
||||
// 处理进仓记录关联(多对多关系)
|
||||
console.log('========== 提交前数据检查 ==========');
|
||||
console.log('ruleForm.warehouseInRelations:', ruleForm.warehouseInRelations);
|
||||
console.log('ruleForm.warehouseInId:', ruleForm.warehouseInId);
|
||||
|
||||
const warehouseInRelations = ruleForm.warehouseInRelations
|
||||
.filter(item => item.warehouseInId && item.outCountThisTime > 0)
|
||||
.map(item => ({
|
||||
warehouseInId: item.warehouseInId,
|
||||
outCount: item.outCountThisTime,
|
||||
}));
|
||||
|
||||
console.log('过滤后的 warehouseInRelations:', warehouseInRelations);
|
||||
|
||||
// 如果有关联的进仓记录,将ID用逗号分隔设置到 warehouseInId(用于兼容旧数据格式)
|
||||
// 如果只有一个,直接设置;如果有多个,用逗号分隔
|
||||
let warehouseInIdValue = null;
|
||||
if (warehouseInRelations.length > 0) {
|
||||
if (warehouseInRelations.length === 1) {
|
||||
warehouseInIdValue = String(warehouseInRelations[0].warehouseInId);
|
||||
} else {
|
||||
// 多个ID用逗号分隔
|
||||
warehouseInIdValue = warehouseInRelations.map(item => String(item.warehouseInId)).join(',');
|
||||
}
|
||||
console.log('从 warehouseInRelations 提取 warehouseInIdValue:', warehouseInIdValue);
|
||||
} else if (ruleForm.warehouseInId) {
|
||||
// 如果没有关联记录但有旧的 warehouseInId,使用旧值
|
||||
warehouseInIdValue = String(ruleForm.warehouseInId);
|
||||
console.log('使用旧的 warehouseInId:', warehouseInIdValue);
|
||||
} else {
|
||||
console.warn('警告:warehouseInRelations 为空且 warehouseInId 也为空!');
|
||||
}
|
||||
|
||||
console.log('最终提交参数 - warehouseInRelations:', warehouseInRelations);
|
||||
console.log('最终提交参数 - warehouseInIdValue:', warehouseInIdValue);
|
||||
console.log('==========================================');
|
||||
|
||||
const params = {
|
||||
warehouseId: ruleForm.warehouseId,
|
||||
warehouseInId: ruleForm.warehouseInId,
|
||||
warehouseInId: warehouseInIdValue, // 设置为关联的进仓记录ID(单个或逗号分隔的多个)
|
||||
warehouseInRelations: warehouseInRelations, // 新增:多对多关联数组
|
||||
orderId: orderIdStr,
|
||||
deliveryId: ruleForm.deliveryId,
|
||||
destinationLocation: ruleForm.destinationLocation,
|
||||
@@ -515,13 +776,19 @@ const onShowDialog = (row, isDetail = false) => {
|
||||
// 如果是详情模式,先获取详情数据
|
||||
if (isDetail) {
|
||||
warehouseOutDetail(row.id)
|
||||
.then((res) => {
|
||||
.then(async (res) => {
|
||||
if (res.code === 200 && res.data) {
|
||||
const detailData = res.data;
|
||||
// 先加载进仓记录列表,以便能够正确显示关联的进仓记录
|
||||
if (detailData.warehouseId) {
|
||||
await loadWarehouseInList(detailData.warehouseId);
|
||||
}
|
||||
|
||||
Object.assign(ruleForm, {
|
||||
id: detailData.id,
|
||||
warehouseId: detailData.warehouseId,
|
||||
warehouseInId: detailData.warehouseInId,
|
||||
warehouseInRelations: detailData.warehouseInRelations || [], // 加载关联的进仓记录
|
||||
orderId: detailData.orderId ? detailData.orderId.split(',').map(id => parseInt(id)) : [],
|
||||
deliveryId: detailData.deliveryId,
|
||||
destinationLocation: detailData.destinationLocation || '',
|
||||
@@ -535,6 +802,30 @@ const onShowDialog = (row, isDetail = false) => {
|
||||
remark: detailData.remark || '',
|
||||
status: detailData.status !== undefined ? detailData.status : 1,
|
||||
});
|
||||
// 如果有旧的warehouseInId但没有warehouseInRelations,则转换
|
||||
if (detailData.warehouseInId && (!detailData.warehouseInRelations || detailData.warehouseInRelations.length === 0)) {
|
||||
// 兼容旧数据:将单个warehouseInId转换为关联数组
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === detailData.warehouseInId);
|
||||
ruleForm.warehouseInRelations = [{
|
||||
warehouseInId: detailData.warehouseInId,
|
||||
totalCount: warehouseIn ? warehouseIn.cattleCount : (detailData.warehouseInCattleCount || detailData.cattleCount || 0),
|
||||
outCount: warehouseIn ? warehouseIn.outCount : 0,
|
||||
remainingCount: warehouseIn ? warehouseIn.remainingCount : (detailData.warehouseInCattleCount || detailData.cattleCount || 0),
|
||||
outCountThisTime: detailData.cattleCount || 0,
|
||||
}];
|
||||
} else if (detailData.warehouseInRelations && detailData.warehouseInRelations.length > 0) {
|
||||
// 如果有warehouseInRelations,需要更新每个关联记录的详细信息
|
||||
ruleForm.warehouseInRelations = detailData.warehouseInRelations.map(relation => {
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === relation.warehouseInId);
|
||||
return {
|
||||
warehouseInId: relation.warehouseInId,
|
||||
totalCount: warehouseIn ? warehouseIn.cattleCount : (relation.totalCount || 0),
|
||||
outCount: warehouseIn ? warehouseIn.outCount : (relation.outCount || 0),
|
||||
remainingCount: warehouseIn ? warehouseIn.remainingCount : (relation.remainingCount || 0),
|
||||
outCountThisTime: relation.outCount || relation.outCountThisTime || 0,
|
||||
};
|
||||
});
|
||||
}
|
||||
// 处理照片和视频文件列表
|
||||
if (detailData.photos) {
|
||||
photoFileList.value = detailData.photos.split(',').map(url => ({ url, name: 'photo' }));
|
||||
@@ -548,30 +839,13 @@ const onShowDialog = (row, isDetail = false) => {
|
||||
ElMessage.error('获取详情失败:' + (error.message || '未知错误'));
|
||||
});
|
||||
} else {
|
||||
// 编辑模式,直接使用传入的数据
|
||||
Object.assign(ruleForm, {
|
||||
id: row.id,
|
||||
warehouseId: row.warehouseId,
|
||||
warehouseInId: row.warehouseInId,
|
||||
orderId: row.orderId ? row.orderId.split(',').map(id => parseInt(id)) : [],
|
||||
deliveryId: row.deliveryId,
|
||||
destinationLocation: row.destinationLocation || '',
|
||||
destinationLon: row.destinationLon || '',
|
||||
destinationLat: row.destinationLat || '',
|
||||
cattleCount: row.cattleCount,
|
||||
weight: row.weight,
|
||||
outTime: row.outTime || '',
|
||||
photos: row.photos || '',
|
||||
videos: row.videos || '',
|
||||
remark: row.remark || '',
|
||||
status: row.status !== undefined ? row.status : 1,
|
||||
});
|
||||
// 处理照片和视频文件列表
|
||||
if (row.photos) {
|
||||
photoFileList.value = row.photos.split(',').map(url => ({ url, name: 'photo' }));
|
||||
}
|
||||
if (row.videos) {
|
||||
videoFileList.value = row.videos.split(',').map(url => ({ url, name: 'video' }));
|
||||
// 编辑模式,先加载进仓记录列表,然后设置表单数据
|
||||
if (row.warehouseId) {
|
||||
loadWarehouseInList(row.warehouseId).then(() => {
|
||||
setFormDataForEdit(row);
|
||||
});
|
||||
} else {
|
||||
setFormDataForEdit(row);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -580,6 +854,7 @@ const onShowDialog = (row, isDetail = false) => {
|
||||
id: null,
|
||||
warehouseId: null,
|
||||
warehouseInId: null,
|
||||
warehouseInRelations: [],
|
||||
orderId: [],
|
||||
deliveryId: null,
|
||||
destinationLocation: '',
|
||||
@@ -602,22 +877,139 @@ const onShowDialog = (row, isDetail = false) => {
|
||||
|
||||
// 中转仓选择变化
|
||||
const handleWarehouseChange = (warehouseId) => {
|
||||
// 加载该中转仓的进仓记录
|
||||
loadWarehouseInList(warehouseId);
|
||||
console.log('中转仓选择变化,warehouseId:', warehouseId);
|
||||
// 清空关联记录
|
||||
ruleForm.warehouseInRelations = [];
|
||||
// 清空进仓记录列表
|
||||
warehouseInList.value = [];
|
||||
// 如果选择了中转仓,加载该中转仓的进仓记录
|
||||
if (warehouseId) {
|
||||
loadWarehouseInList(warehouseId);
|
||||
}
|
||||
};
|
||||
|
||||
// 进仓记录选择变化
|
||||
const handleWarehouseInChange = (warehouseInId) => {
|
||||
// 如果选择了进仓记录,可以自动填充一些信息
|
||||
if (warehouseInId) {
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === warehouseInId);
|
||||
if (warehouseIn) {
|
||||
// 可以自动填充牛只数量等信息
|
||||
if (!ruleForm.cattleCount && warehouseIn.cattleCount) {
|
||||
ruleForm.cattleCount = warehouseIn.cattleCount;
|
||||
}
|
||||
}
|
||||
// 添加进仓记录关联
|
||||
const addWarehouseInRelation = async () => {
|
||||
if (!ruleForm.warehouseId) {
|
||||
ElMessage.warning('请先选择中转仓');
|
||||
return;
|
||||
}
|
||||
// 如果进仓记录列表为空,尝试重新加载
|
||||
if (warehouseInList.value.length === 0) {
|
||||
console.log('进仓记录列表为空,重新加载');
|
||||
await loadWarehouseInList(ruleForm.warehouseId);
|
||||
}
|
||||
console.log('添加进仓记录关联行,当前列表长度:', warehouseInList.value.length);
|
||||
ruleForm.warehouseInRelations.push({
|
||||
warehouseInId: null,
|
||||
totalCount: 0,
|
||||
outCount: 0,
|
||||
remainingCount: 0,
|
||||
outCountThisTime: undefined, // 使用 undefined 而不是 null,避免 el-input-number 报错
|
||||
});
|
||||
console.log('添加后的关联行数:', ruleForm.warehouseInRelations.length);
|
||||
console.log('添加后的 warehouseInList:', warehouseInList.value);
|
||||
// 等待 nextTick 确保 computed 重新计算
|
||||
nextTick(() => {
|
||||
console.log('nextTick - availableWarehouseInLists:', availableWarehouseInLists.value);
|
||||
});
|
||||
};
|
||||
|
||||
// 删除进仓记录关联
|
||||
const removeWarehouseInRelation = (index) => {
|
||||
ruleForm.warehouseInRelations.splice(index, 1);
|
||||
handleOutCountChange();
|
||||
};
|
||||
|
||||
// 创建一个计算属性,为每一行生成可用的进仓记录列表
|
||||
// 这样可以避免在模板中重复调用函数,提高性能
|
||||
const availableWarehouseInLists = computed(() => {
|
||||
const result = ruleForm.warehouseInRelations.map((_, currentIndex) => {
|
||||
// 获取已选择的其他行的进仓ID
|
||||
const selectedIds = ruleForm.warehouseInRelations
|
||||
.map((item, index) => index !== currentIndex ? item.warehouseInId : null)
|
||||
.filter(id => id != null);
|
||||
|
||||
// 过滤出可用的进仓记录
|
||||
const available = warehouseInList.value.filter(item => {
|
||||
// 只显示有剩余数量的进仓记录,且未被其他行选择
|
||||
return (item.remainingCount || 0) > 0 && !selectedIds.includes(item.id);
|
||||
});
|
||||
|
||||
console.log(`computed[${currentIndex}]: warehouseInList.length=${warehouseInList.value.length}, selectedIds=${JSON.stringify(selectedIds)}, available.length=${available.length}`);
|
||||
|
||||
return available;
|
||||
});
|
||||
|
||||
console.log('availableWarehouseInLists computed:', result);
|
||||
return result;
|
||||
});
|
||||
|
||||
// 获取可用的进仓记录列表(排除已选择的)
|
||||
// 使用缓存的计算属性,避免重复计算
|
||||
const getAvailableWarehouseInList = (currentIndex) => {
|
||||
// 确保索引有效
|
||||
if (currentIndex < 0 || currentIndex >= availableWarehouseInLists.value.length) {
|
||||
console.warn(`getAvailableWarehouseInList: 无效的索引 ${currentIndex}, 当前关联行数: ${ruleForm.warehouseInRelations.length}`);
|
||||
// 如果索引无效,直接计算返回
|
||||
const selectedIds = ruleForm.warehouseInRelations
|
||||
.map((item, index) => index !== currentIndex ? item.warehouseInId : null)
|
||||
.filter(id => id != null);
|
||||
return warehouseInList.value.filter(item => {
|
||||
return (item.remainingCount || 0) > 0 && !selectedIds.includes(item.id);
|
||||
});
|
||||
}
|
||||
const result = availableWarehouseInLists.value[currentIndex] || [];
|
||||
console.log(`getAvailableWarehouseInList(${currentIndex}):`, result.length, 'items', result);
|
||||
return result;
|
||||
};
|
||||
|
||||
// 进仓记录关联变化
|
||||
const handleWarehouseInRelationChange = (row, index) => {
|
||||
if (row.warehouseInId) {
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === row.warehouseInId);
|
||||
if (warehouseIn) {
|
||||
row.totalCount = warehouseIn.cattleCount || 0;
|
||||
row.outCount = warehouseIn.outCount || 0;
|
||||
// 在编辑模式下,如果这是已关联的记录,使用调整后的剩余数量(已经加回了当前编辑的数量)
|
||||
// 在新增模式下,使用正常的剩余数量
|
||||
row.remainingCount = warehouseIn.remainingCount || 0;
|
||||
|
||||
// 自动设置本次出仓数量为剩余数量(如果剩余数量大于0)
|
||||
// 在编辑模式下,如果这是已关联的记录,可以编辑到剩余数量(包括当前编辑的数量)
|
||||
if (row.remainingCount > 0 && !row.outCountThisTime) {
|
||||
row.outCountThisTime = row.remainingCount;
|
||||
}
|
||||
|
||||
console.log(`进仓记录关联变化 - ${warehouseIn.inNumber}: totalCount=${row.totalCount}, remainingCount=${row.remainingCount}, isCurrentEditRelated=${warehouseIn.isCurrentEditRelated}`);
|
||||
}
|
||||
} else {
|
||||
row.totalCount = 0;
|
||||
row.outCount = 0;
|
||||
row.remainingCount = 0;
|
||||
row.outCountThisTime = undefined;
|
||||
}
|
||||
handleOutCountChange();
|
||||
};
|
||||
|
||||
// 出仓数量变化
|
||||
const handleOutCountChange = () => {
|
||||
// 自动计算总出仓数量
|
||||
const totalOutCount = getTotalOutCount();
|
||||
ruleForm.cattleCount = totalOutCount;
|
||||
|
||||
// 触发表单验证
|
||||
if (formDataRef.value) {
|
||||
formDataRef.value.validateField('warehouseInRelations');
|
||||
formDataRef.value.validateField('cattleCount');
|
||||
}
|
||||
};
|
||||
|
||||
// 计算总出仓数量
|
||||
const getTotalOutCount = () => {
|
||||
return ruleForm.warehouseInRelations.reduce((sum, item) => {
|
||||
return sum + (item.outCountThisTime || 0);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// 运送清单选择变化
|
||||
@@ -725,11 +1117,91 @@ const beforeVideoUpload = (file) => {
|
||||
return false; // 阻止自动上传,手动处理
|
||||
};
|
||||
|
||||
// 设置编辑模式的表单数据
|
||||
const setFormDataForEdit = (row) => {
|
||||
Object.assign(ruleForm, {
|
||||
id: row.id,
|
||||
warehouseId: row.warehouseId,
|
||||
warehouseInId: row.warehouseInId,
|
||||
warehouseInRelations: row.warehouseInRelations || [], // 加载关联的进仓记录
|
||||
orderId: row.orderId ? row.orderId.split(',').map(id => parseInt(id)) : [],
|
||||
deliveryId: row.deliveryId,
|
||||
destinationLocation: row.destinationLocation || '',
|
||||
destinationLon: row.destinationLon || '',
|
||||
destinationLat: row.destinationLat || '',
|
||||
cattleCount: row.cattleCount,
|
||||
weight: row.weight,
|
||||
outTime: row.outTime || '',
|
||||
photos: row.photos || '',
|
||||
videos: row.videos || '',
|
||||
remark: row.remark || '',
|
||||
status: row.status !== undefined ? row.status : 1,
|
||||
});
|
||||
// 如果有旧的warehouseInId但没有warehouseInRelations,则转换
|
||||
// 注意:warehouseInId 现在可能是字符串(多个ID用逗号分隔)
|
||||
if (row.warehouseInId && (!row.warehouseInRelations || row.warehouseInRelations.length === 0)) {
|
||||
console.log('编辑模式 - 检测到 warehouseInId 但没有 warehouseInRelations,开始转换');
|
||||
console.log('row.warehouseInId:', row.warehouseInId, '类型:', typeof row.warehouseInId);
|
||||
|
||||
// 兼容旧数据:将 warehouseInId(可能是单个ID或逗号分隔的多个ID)转换为关联数组
|
||||
const warehouseInIdStr = String(row.warehouseInId);
|
||||
const warehouseInIds = warehouseInIdStr.split(',').map(id => id.trim()).filter(id => id);
|
||||
|
||||
console.log('解析出的进仓记录ID数组:', warehouseInIds);
|
||||
|
||||
ruleForm.warehouseInRelations = warehouseInIds.map(warehouseInIdStr => {
|
||||
const warehouseInId = parseInt(warehouseInIdStr);
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === warehouseInId);
|
||||
|
||||
console.log(`处理进仓记录ID ${warehouseInId}:`, warehouseIn ? '找到' : '未找到');
|
||||
|
||||
// 如果找不到对应的进仓记录,使用默认值
|
||||
return {
|
||||
warehouseInId: warehouseInId,
|
||||
totalCount: warehouseIn ? warehouseIn.cattleCount : 0,
|
||||
outCount: warehouseIn ? warehouseIn.outCount : 0,
|
||||
remainingCount: warehouseIn ? warehouseIn.remainingCount : 0,
|
||||
outCountThisTime: warehouseIn ? Math.min(warehouseIn.remainingCount || 0, row.cattleCount || 0) : (row.cattleCount || 0),
|
||||
};
|
||||
});
|
||||
|
||||
console.log('转换后的 warehouseInRelations:', ruleForm.warehouseInRelations);
|
||||
} else if (row.warehouseInRelations && row.warehouseInRelations.length > 0) {
|
||||
// 如果有warehouseInRelations,需要更新每个关联记录的详细信息
|
||||
ruleForm.warehouseInRelations = row.warehouseInRelations.map(relation => {
|
||||
const warehouseIn = warehouseInList.value.find(item => item.id === relation.warehouseInId);
|
||||
return {
|
||||
warehouseInId: relation.warehouseInId,
|
||||
totalCount: warehouseIn ? warehouseIn.cattleCount : (relation.totalCount || 0),
|
||||
outCount: warehouseIn ? warehouseIn.outCount : (relation.outCount || 0),
|
||||
remainingCount: warehouseIn ? warehouseIn.remainingCount : (relation.remainingCount || 0),
|
||||
outCountThisTime: relation.outCount || relation.outCountThisTime || 0,
|
||||
};
|
||||
});
|
||||
}
|
||||
// 处理照片和视频文件列表
|
||||
if (row.photos) {
|
||||
photoFileList.value = row.photos.split(',').map(url => ({ url, name: 'photo' }));
|
||||
}
|
||||
if (row.videos) {
|
||||
videoFileList.value = row.videos.split(',').map(url => ({ url, name: 'video' }));
|
||||
}
|
||||
};
|
||||
|
||||
// 监听对话框打开,加载数据
|
||||
watch(() => data.dialogVisible, (newVal) => {
|
||||
if (newVal) {
|
||||
console.log('对话框打开,开始加载数据');
|
||||
loadWarehouseList();
|
||||
loadWarehouseInList();
|
||||
// 如果已有中转仓ID,则加载对应的进仓记录;否则等待用户选择中转仓
|
||||
if (ruleForm.warehouseId) {
|
||||
console.log('已有中转仓ID,加载进仓记录:', ruleForm.warehouseId);
|
||||
loadWarehouseInList(ruleForm.warehouseId);
|
||||
} else {
|
||||
console.log('暂无中转仓ID,等待用户选择');
|
||||
// 清空进仓记录列表
|
||||
warehouseInList.value = [];
|
||||
}
|
||||
loadOrderList();
|
||||
loadDeliveryList();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.aiotagro.cattletrade.business.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterEntryService;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 屠宰场进场管理控制器
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/slaughter/entry")
|
||||
public class SlaughterEntryController {
|
||||
|
||||
@Autowired
|
||||
private ISlaughterEntryService slaughterEntryService;
|
||||
|
||||
/**
|
||||
* 分页查询进场记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterEntry:query")
|
||||
@PostMapping("/list")
|
||||
public AjaxResult list(@RequestBody SlaughterEntryDto dto) {
|
||||
try {
|
||||
PageResultResponse<SlaughterEntry> result = slaughterEntryService.pageQuery(dto);
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询进场记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增进场记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterEntry:add")
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@Validated @RequestBody SlaughterEntryCreateDto dto) {
|
||||
try {
|
||||
return slaughterEntryService.addEntry(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("新增进场记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑进场记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterEntry:edit")
|
||||
@PostMapping("/edit")
|
||||
public AjaxResult edit(@Validated @RequestBody SlaughterEntryEditDto dto) {
|
||||
try {
|
||||
return slaughterEntryService.updateEntry(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("编辑进场记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除进场记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterEntry:delete")
|
||||
@GetMapping("/delete")
|
||||
public AjaxResult delete(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterEntryService.deleteEntry(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("删除进场记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
@SaCheckPermission("slaughterEntry:query")
|
||||
@GetMapping("/detail")
|
||||
public AjaxResult detail(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterEntryService.detail(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询进场记录详情失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.aiotagro.cattletrade.business.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterHouseService;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 屠宰场管理控制器
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/slaughter/house")
|
||||
public class SlaughterHouseController {
|
||||
|
||||
@Autowired
|
||||
private ISlaughterHouseService slaughterHouseService;
|
||||
|
||||
/**
|
||||
* 分页查询屠宰场
|
||||
*/
|
||||
@SaCheckPermission("slaughterHouse:query")
|
||||
@PostMapping("/list")
|
||||
public AjaxResult list(@RequestBody SlaughterHouseDto dto) {
|
||||
try {
|
||||
PageResultResponse<SlaughterHouse> result = slaughterHouseService.pageQuery(dto);
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询屠宰场列表失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增屠宰场
|
||||
*/
|
||||
@SaCheckPermission("slaughterHouse:add")
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@Validated @RequestBody SlaughterHouseCreateDto dto) {
|
||||
try {
|
||||
return slaughterHouseService.addHouse(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("新增屠宰场失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑屠宰场
|
||||
*/
|
||||
@SaCheckPermission("slaughterHouse:edit")
|
||||
@PostMapping("/edit")
|
||||
public AjaxResult edit(@Validated @RequestBody SlaughterHouseEditDto dto) {
|
||||
try {
|
||||
return slaughterHouseService.updateHouse(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("编辑屠宰场失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除屠宰场
|
||||
*/
|
||||
@SaCheckPermission("slaughterHouse:delete")
|
||||
@GetMapping("/delete")
|
||||
public AjaxResult delete(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterHouseService.deleteHouse(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("删除屠宰场失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
@SaCheckPermission("slaughterHouse:query")
|
||||
@GetMapping("/detail")
|
||||
public AjaxResult detail(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterHouseService.detail(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询屠宰场详情失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用列表(下拉)
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public AjaxResult allEnabled() {
|
||||
try {
|
||||
List<SlaughterHouse> list = slaughterHouseService.getAllEnabled();
|
||||
return AjaxResult.success("查询成功", list);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询屠宰场列表失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.aiotagro.cattletrade.business.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterRecord;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterRecordService;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 屠宰记录管理控制器
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/slaughter/record")
|
||||
public class SlaughterRecordController {
|
||||
|
||||
@Autowired
|
||||
private ISlaughterRecordService slaughterRecordService;
|
||||
|
||||
/**
|
||||
* 分页查询屠宰记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterRecord:query")
|
||||
@PostMapping("/list")
|
||||
public AjaxResult list(@RequestBody SlaughterRecordDto dto) {
|
||||
try {
|
||||
PageResultResponse<SlaughterRecord> result = slaughterRecordService.pageQuery(dto);
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询屠宰记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增屠宰记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterRecord:add")
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@Validated @RequestBody SlaughterRecordCreateDto dto) {
|
||||
try {
|
||||
return slaughterRecordService.addRecord(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("新增屠宰记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑屠宰记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterRecord:edit")
|
||||
@PostMapping("/edit")
|
||||
public AjaxResult edit(@Validated @RequestBody SlaughterRecordEditDto dto) {
|
||||
try {
|
||||
return slaughterRecordService.updateRecord(dto);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("编辑屠宰记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除屠宰记录
|
||||
*/
|
||||
@SaCheckPermission("slaughterRecord:delete")
|
||||
@GetMapping("/delete")
|
||||
public AjaxResult delete(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterRecordService.deleteRecord(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("删除屠宰记录失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
@SaCheckPermission("slaughterRecord:query")
|
||||
@GetMapping("/detail")
|
||||
public AjaxResult detail(@RequestParam Integer id) {
|
||||
try {
|
||||
return slaughterRecordService.detail(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("查询屠宰记录详情失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.aiotagro.cattletrade.business.service.IWarehouseOutService;
|
||||
import com.aiotagro.cattletrade.business.vo.WarehouseOutVo;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -22,6 +24,8 @@ import org.springframework.web.bind.annotation.*;
|
||||
@RequestMapping("/warehouseOut")
|
||||
public class WarehouseOutController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WarehouseOutController.class);
|
||||
|
||||
@Autowired
|
||||
private IWarehouseOutService warehouseOutService;
|
||||
|
||||
@@ -61,8 +65,20 @@ public class WarehouseOutController {
|
||||
@PostMapping("/edit")
|
||||
public AjaxResult edit(@Validated @RequestBody WarehouseOutEditDto dto) {
|
||||
try {
|
||||
// 记录接收到的编辑参数
|
||||
logger.info("========== 编辑出仓记录 - 接收参数 ==========");
|
||||
logger.info("出仓记录ID: {}", dto.getId());
|
||||
logger.info("中转仓ID: {}", dto.getWarehouseId());
|
||||
logger.info("进仓记录ID (warehouseInId): {}", dto.getWarehouseInId());
|
||||
logger.info("牛只数量: {}", dto.getCattleCount());
|
||||
logger.info("运送清单ID: {}", dto.getDeliveryId());
|
||||
logger.info("订单ID: {}", dto.getOrderId());
|
||||
logger.info("完整DTO对象: {}", dto);
|
||||
logger.info("==========================================");
|
||||
|
||||
return warehouseOutService.updateWarehouseOut(dto);
|
||||
} catch (Exception e) {
|
||||
logger.error("编辑出仓记录失败", e);
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("编辑出仓记录失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 进场记录创建DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class SlaughterEntryCreateDto {
|
||||
|
||||
/**
|
||||
* 进场编码
|
||||
*/
|
||||
private String entryCode;
|
||||
|
||||
/**
|
||||
* 屠宰场ID
|
||||
*/
|
||||
@NotNull(message = "屠宰场ID不能为空")
|
||||
private Integer slaughterHouseId;
|
||||
|
||||
/**
|
||||
* 运送清单ID
|
||||
*/
|
||||
@NotNull(message = "运送清单ID不能为空")
|
||||
private Integer deliveryId;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Integer orderId;
|
||||
|
||||
/**
|
||||
* 起始地
|
||||
*/
|
||||
private String startLocation;
|
||||
|
||||
/**
|
||||
* 起始经度
|
||||
*/
|
||||
private String startLon;
|
||||
|
||||
/**
|
||||
* 起始纬度
|
||||
*/
|
||||
private String startLat;
|
||||
|
||||
/**
|
||||
* 目的地
|
||||
*/
|
||||
private String endLocation;
|
||||
|
||||
/**
|
||||
* 目的地经度
|
||||
*/
|
||||
private String endLon;
|
||||
|
||||
/**
|
||||
* 目的地纬度
|
||||
*/
|
||||
private String endLat;
|
||||
|
||||
/**
|
||||
* 司机姓名
|
||||
*/
|
||||
private String driverName;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
private String driverMobile;
|
||||
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
private String licensePlate;
|
||||
|
||||
/**
|
||||
* 牛只数量
|
||||
*/
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 剩余牛只数量
|
||||
*/
|
||||
private Integer remainingCapacity;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 进场记录查询DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SlaughterEntryDto extends BaseDto {
|
||||
|
||||
/**
|
||||
* 屠宰场ID
|
||||
*/
|
||||
private Integer slaughterHouseId;
|
||||
|
||||
/**
|
||||
* 运送清单ID
|
||||
*/
|
||||
private Integer deliveryId;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Integer orderId;
|
||||
|
||||
/**
|
||||
* 运送清单号(模糊查询)
|
||||
*/
|
||||
private String deliveryNumber;
|
||||
|
||||
/**
|
||||
* 订单关键词(用于查询买方或卖方公司名称)
|
||||
*/
|
||||
private String orderKeyword;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 进场记录编辑DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class SlaughterEntryEditDto {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 进场编码
|
||||
*/
|
||||
private String entryCode;
|
||||
|
||||
/**
|
||||
* 屠宰场ID
|
||||
*/
|
||||
@NotNull(message = "屠宰场ID不能为空")
|
||||
private Integer slaughterHouseId;
|
||||
|
||||
/**
|
||||
* 运送清单ID
|
||||
*/
|
||||
@NotNull(message = "运送清单ID不能为空")
|
||||
private Integer deliveryId;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Integer orderId;
|
||||
|
||||
/**
|
||||
* 起始地
|
||||
*/
|
||||
private String startLocation;
|
||||
|
||||
/**
|
||||
* 起始经度
|
||||
*/
|
||||
private String startLon;
|
||||
|
||||
/**
|
||||
* 起始纬度
|
||||
*/
|
||||
private String startLat;
|
||||
|
||||
/**
|
||||
* 目的地
|
||||
*/
|
||||
private String endLocation;
|
||||
|
||||
/**
|
||||
* 目的地经度
|
||||
*/
|
||||
private String endLon;
|
||||
|
||||
/**
|
||||
* 目的地纬度
|
||||
*/
|
||||
private String endLat;
|
||||
|
||||
/**
|
||||
* 司机姓名
|
||||
*/
|
||||
private String driverName;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
private String driverMobile;
|
||||
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
private String licensePlate;
|
||||
|
||||
/**
|
||||
* 牛只数量
|
||||
*/
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 剩余牛只数量
|
||||
*/
|
||||
private Integer remainingCapacity;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 屠宰场创建DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class SlaughterHouseCreateDto {
|
||||
|
||||
/**
|
||||
* 屠宰场名称
|
||||
*/
|
||||
@NotBlank(message = "屠宰场名称不能为空")
|
||||
private String houseName;
|
||||
|
||||
/**
|
||||
* 屠宰场编码(为空时自动生成)
|
||||
*/
|
||||
private String slaughterCode;
|
||||
|
||||
/**
|
||||
* 容量(头数)
|
||||
*/
|
||||
@NotNull(message = "容量不能为空")
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 负责人
|
||||
*/
|
||||
private String person;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@NotBlank(message = "地址不能为空")
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private String longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private String latitude;
|
||||
|
||||
/**
|
||||
* 状态:1-启用,0-禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 屠宰场查询DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SlaughterHouseDto extends BaseDto {
|
||||
|
||||
/**
|
||||
* 屠宰场名称
|
||||
*/
|
||||
private String houseName;
|
||||
|
||||
/**
|
||||
* 屠宰场编码
|
||||
*/
|
||||
private String slaughterCode;
|
||||
|
||||
/**
|
||||
* 状态:1-启用,0-禁用
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 屠宰场编辑DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class SlaughterHouseEditDto {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 屠宰场名称
|
||||
*/
|
||||
@NotBlank(message = "屠宰场名称不能为空")
|
||||
private String houseName;
|
||||
|
||||
/**
|
||||
* 屠宰场编码
|
||||
*/
|
||||
@NotBlank(message = "屠宰场编码不能为空")
|
||||
private String slaughterCode;
|
||||
|
||||
/**
|
||||
* 容量(头数)
|
||||
*/
|
||||
@NotNull(message = "容量不能为空")
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 负责人
|
||||
*/
|
||||
private String person;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@NotBlank(message = "地址不能为空")
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private String longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private String latitude;
|
||||
|
||||
/**
|
||||
* 状态:1-启用,0-禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 屠宰记录创建DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Data
|
||||
public class SlaughterRecordCreateDto {
|
||||
|
||||
/**
|
||||
* 屠宰记录编码(可选,未填则自动生成)
|
||||
*/
|
||||
private String recordCode;
|
||||
|
||||
/**
|
||||
* 进场记录ID
|
||||
*/
|
||||
@NotNull(message = "进场记录ID不能为空")
|
||||
private Integer entryId;
|
||||
|
||||
/**
|
||||
* 屠宰头数
|
||||
*/
|
||||
@NotNull(message = "屠宰头数不能为空")
|
||||
@Min(value = 1, message = "屠宰头数必须大于0")
|
||||
private Integer slaughterCount;
|
||||
|
||||
/**
|
||||
* 出肉率(0-100,百分比)
|
||||
*/
|
||||
private BigDecimal yieldRate;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 屠宰记录查询DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SlaughterRecordDto extends BaseDto {
|
||||
|
||||
/**
|
||||
* 屠宰记录编码(模糊)
|
||||
*/
|
||||
private String recordCode;
|
||||
|
||||
/**
|
||||
* 进场记录ID
|
||||
*/
|
||||
private Integer entryId;
|
||||
|
||||
/**
|
||||
* 进场编码(模糊)
|
||||
*/
|
||||
private String entryCode;
|
||||
|
||||
/**
|
||||
* 屠宰场ID
|
||||
*/
|
||||
private Integer slaughterHouseId;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 屠宰记录编辑DTO
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SlaughterRecordEditDto extends SlaughterRecordCreateDto {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空")
|
||||
private Integer id;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.aiotagro.cattletrade.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 进仓记录关联DTO(用于多对多关系)
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Data
|
||||
public class WarehouseInRelationDto {
|
||||
|
||||
/**
|
||||
* 进仓记录ID
|
||||
*/
|
||||
private Integer warehouseInId;
|
||||
|
||||
/**
|
||||
* 本次出仓数量
|
||||
*/
|
||||
private Integer outCount;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.Data;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出仓创建DTO
|
||||
@@ -24,9 +25,16 @@ public class WarehouseOutCreateDto {
|
||||
|
||||
/**
|
||||
* 进仓记录ID(可选)
|
||||
* 保留用于兼容旧数据格式
|
||||
*/
|
||||
private Integer warehouseInId;
|
||||
|
||||
/**
|
||||
* 进仓记录关联数组(多对多关系,每个元素包含 warehouseInId 和 outCount)
|
||||
* 优先使用此字段,如果没有则使用 warehouseInId 和 cattleCount 进行平均分配
|
||||
*/
|
||||
private List<WarehouseInRelationDto> warehouseInRelations;
|
||||
|
||||
/**
|
||||
* 订单ID(多个订单用逗号分隔)
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.Data;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 出仓编辑DTO
|
||||
@@ -29,9 +30,16 @@ public class WarehouseOutEditDto {
|
||||
private Integer warehouseId;
|
||||
|
||||
/**
|
||||
* 进仓记录ID(可选)
|
||||
* 进仓记录ID(可选,支持多个ID用逗号分隔,如:1,2,3)
|
||||
* 保留用于兼容旧数据格式
|
||||
*/
|
||||
private Integer warehouseInId;
|
||||
private String warehouseInId;
|
||||
|
||||
/**
|
||||
* 进仓记录关联数组(多对多关系,每个元素包含 warehouseInId 和 outCount)
|
||||
* 优先使用此字段,如果没有则使用 warehouseInId 和 cattleCount 进行平均分配
|
||||
*/
|
||||
private List<WarehouseInRelationDto> warehouseInRelations;
|
||||
|
||||
/**
|
||||
* 订单ID(多个订单用逗号分隔)
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package com.aiotagro.cattletrade.business.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 屠宰场进场记录实体
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
@TableName("slaughter_entry")
|
||||
public class SlaughterEntry implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 进场编码
|
||||
*/
|
||||
@TableField("entry_code")
|
||||
private String entryCode;
|
||||
|
||||
/**
|
||||
* 屠宰场ID
|
||||
*/
|
||||
@TableField("slaughter_house_id")
|
||||
private Integer slaughterHouseId;
|
||||
|
||||
/**
|
||||
* 运送清单ID
|
||||
*/
|
||||
@TableField("delivery_id")
|
||||
private Integer deliveryId;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@TableField("order_id")
|
||||
private Integer orderId;
|
||||
|
||||
/**
|
||||
* 起始地
|
||||
*/
|
||||
@TableField("start_location")
|
||||
private String startLocation;
|
||||
|
||||
/**
|
||||
* 起始经度
|
||||
*/
|
||||
@TableField("start_lon")
|
||||
private String startLon;
|
||||
|
||||
/**
|
||||
* 起始纬度
|
||||
*/
|
||||
@TableField("start_lat")
|
||||
private String startLat;
|
||||
|
||||
/**
|
||||
* 目的地
|
||||
*/
|
||||
@TableField("end_location")
|
||||
private String endLocation;
|
||||
|
||||
/**
|
||||
* 目的地经度
|
||||
*/
|
||||
@TableField("end_lon")
|
||||
private String endLon;
|
||||
|
||||
/**
|
||||
* 目的地纬度
|
||||
*/
|
||||
@TableField("end_lat")
|
||||
private String endLat;
|
||||
|
||||
/**
|
||||
* 司机姓名
|
||||
*/
|
||||
@TableField("driver_name")
|
||||
private String driverName;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
@TableField("driver_mobile")
|
||||
private String driverMobile;
|
||||
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
@TableField("license_plate")
|
||||
private String licensePlate;
|
||||
|
||||
/**
|
||||
* 牛只数量
|
||||
*/
|
||||
@TableField("capacity")
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 剩余牛只数量
|
||||
*/
|
||||
@TableField("remaining_capacity")
|
||||
private Integer remainingCapacity;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 逻辑删除标记(0-正常,1-已删除)
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
@TableField("created_by")
|
||||
private Integer createdBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新人ID
|
||||
*/
|
||||
@TableField("updated_by")
|
||||
private Integer updatedBy;
|
||||
|
||||
/**
|
||||
* 运送清单号(关联查询,不存储在数据库中)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String deliveryNumber;
|
||||
|
||||
/**
|
||||
* 订单买方名称(关联查询,不存储在数据库中)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String orderBuyerName;
|
||||
|
||||
/**
|
||||
* 订单卖方名称(关联查询,不存储在数据库中)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String orderSellerName;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.aiotagro.cattletrade.business.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 屠宰场实体
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
@TableName("slaughter_house")
|
||||
public class SlaughterHouse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 屠宰场名称
|
||||
*/
|
||||
@TableField("house_name")
|
||||
private String houseName;
|
||||
|
||||
/**
|
||||
* 屠宰场编码
|
||||
*/
|
||||
@TableField("slaughter_code")
|
||||
private String slaughterCode;
|
||||
|
||||
/**
|
||||
* 容量(头数)
|
||||
*/
|
||||
@TableField("capacity")
|
||||
private Integer capacity;
|
||||
|
||||
/**
|
||||
* 负责人
|
||||
*/
|
||||
@TableField("person")
|
||||
private String person;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
@TableField("phone")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@TableField("address")
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@TableField("longitude")
|
||||
private String longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
@TableField("latitude")
|
||||
private String latitude;
|
||||
|
||||
/**
|
||||
* 状态:1-启用,0-禁用
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 逻辑删除标记(0-正常,1-已删除)
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
@TableField("created_by")
|
||||
private Integer createdBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新人ID
|
||||
*/
|
||||
@TableField("updated_by")
|
||||
private Integer updatedBy;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.aiotagro.cattletrade.business.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 屠宰记录实体
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Data
|
||||
@TableName("slaughter_record")
|
||||
public class SlaughterRecord implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 屠宰记录编码
|
||||
*/
|
||||
@TableField("record_code")
|
||||
private String recordCode;
|
||||
|
||||
/**
|
||||
* 进场记录ID
|
||||
*/
|
||||
@TableField("entry_id")
|
||||
private Integer entryId;
|
||||
|
||||
/**
|
||||
* 屠宰头数
|
||||
*/
|
||||
@TableField("slaughter_count")
|
||||
private Integer slaughterCount;
|
||||
|
||||
/**
|
||||
* 出肉率(0-100,百分比)
|
||||
*/
|
||||
@TableField("yield_rate")
|
||||
private BigDecimal yieldRate;
|
||||
|
||||
/**
|
||||
* 逻辑删除标记(0-正常,1-已删除)
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField("created_by")
|
||||
private Integer createdBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@TableField("updated_by")
|
||||
private Integer updatedBy;
|
||||
|
||||
/**
|
||||
* 进场编码(关联查询)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String entryCode;
|
||||
|
||||
/**
|
||||
* 屠宰场ID(关联查询)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer slaughterHouseId;
|
||||
|
||||
/**
|
||||
* 屠宰场名称(关联查询)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String slaughterHouseName;
|
||||
|
||||
/**
|
||||
* 进场剩余牛只数量(关联查询)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer remainingCapacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,12 @@ public class WarehouseIn implements Serializable {
|
||||
@TableField("cattle_count")
|
||||
private Integer cattleCount;
|
||||
|
||||
/**
|
||||
* 剩余头数(总数量 - 已出仓数量)
|
||||
*/
|
||||
@TableField("remaining_count")
|
||||
private Integer remainingCount;
|
||||
|
||||
/**
|
||||
* 重量(公斤)
|
||||
*/
|
||||
|
||||
@@ -43,10 +43,10 @@ public class WarehouseOut implements Serializable {
|
||||
private Integer warehouseId;
|
||||
|
||||
/**
|
||||
* 进仓记录ID(可选)
|
||||
* 进仓记录ID(可选,支持多个ID用逗号分隔,如:1,2,3)
|
||||
*/
|
||||
@TableField("warehouse_in_id")
|
||||
private Integer warehouseInId;
|
||||
private String warehouseInId;
|
||||
|
||||
/**
|
||||
* 订单ID(多个订单用逗号分隔)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.aiotagro.cattletrade.business.mapper;
|
||||
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
/**
|
||||
* 进场记录 Mapper
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Mapper
|
||||
public interface SlaughterEntryMapper extends BaseMapper<SlaughterEntry> {
|
||||
|
||||
/**
|
||||
* 根据编码前缀查询最后一个编码(用于生成新编码)
|
||||
* @param prefixPattern 编码前缀模式,如 "SE20251210%"
|
||||
* @return 最后一个进场记录
|
||||
*/
|
||||
@Select("SELECT * FROM slaughter_entry WHERE entry_code LIKE #{prefixPattern} AND is_delete = 0 ORDER BY entry_code DESC LIMIT 1")
|
||||
SlaughterEntry selectLastCode(@Param("prefixPattern") String prefixPattern);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.aiotagro.cattletrade.business.mapper;
|
||||
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 屠宰场管理 Mapper
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Mapper
|
||||
public interface SlaughterHouseMapper extends BaseMapper<SlaughterHouse> {
|
||||
|
||||
/**
|
||||
* 根据编码查询
|
||||
*/
|
||||
@Select("SELECT * FROM slaughter_house WHERE slaughter_code = #{slaughterCode} AND is_delete = 0")
|
||||
SlaughterHouse selectByCode(@Param("slaughterCode") String slaughterCode);
|
||||
|
||||
/**
|
||||
* 查询指定前缀下的最新编码
|
||||
*/
|
||||
@Select("SELECT * FROM slaughter_house WHERE slaughter_code LIKE #{prefixPattern} AND is_delete = 0 ORDER BY slaughter_code DESC LIMIT 1")
|
||||
SlaughterHouse selectLastCode(@Param("prefixPattern") String prefixPattern);
|
||||
|
||||
/**
|
||||
* 查询所有启用的屠宰场
|
||||
*/
|
||||
@Select("SELECT id, house_name, slaughter_code FROM slaughter_house WHERE status = 1 AND is_delete = 0 ORDER BY create_time DESC")
|
||||
List<SlaughterHouse> selectAllEnabled();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.aiotagro.cattletrade.business.mapper;
|
||||
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
/**
|
||||
* 屠宰记录 Mapper
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Mapper
|
||||
public interface SlaughterRecordMapper extends BaseMapper<SlaughterRecord> {
|
||||
|
||||
/**
|
||||
* 根据编码前缀查询最后一个编码(用于生成新编码)
|
||||
*
|
||||
* @param prefixPattern 编码前缀模式,如 "SL20251210%"
|
||||
* @return 最后一个屠宰记录
|
||||
*/
|
||||
@Select("SELECT * FROM slaughter_record WHERE record_code LIKE #{prefixPattern} AND is_delete = 0 ORDER BY record_code DESC LIMIT 1")
|
||||
SlaughterRecord selectLastCode(@Param("prefixPattern") String prefixPattern);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.aiotagro.cattletrade.business.service;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* 进场管理服务接口
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface ISlaughterEntryService extends IService<SlaughterEntry> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
PageResultResponse<SlaughterEntry> pageQuery(SlaughterEntryDto dto);
|
||||
|
||||
/**
|
||||
* 新增进场记录
|
||||
*/
|
||||
AjaxResult addEntry(SlaughterEntryCreateDto dto);
|
||||
|
||||
/**
|
||||
* 编辑进场记录
|
||||
*/
|
||||
AjaxResult updateEntry(SlaughterEntryEditDto dto);
|
||||
|
||||
/**
|
||||
* 删除进场记录(逻辑删除)
|
||||
*/
|
||||
AjaxResult deleteEntry(Integer id);
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
*/
|
||||
AjaxResult detail(Integer id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.aiotagro.cattletrade.business.service;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 屠宰场管理服务接口
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface ISlaughterHouseService extends IService<SlaughterHouse> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
PageResultResponse<SlaughterHouse> pageQuery(SlaughterHouseDto dto);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
AjaxResult addHouse(SlaughterHouseCreateDto dto);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
AjaxResult updateHouse(SlaughterHouseEditDto dto);
|
||||
|
||||
/**
|
||||
* 删除(逻辑)
|
||||
*/
|
||||
AjaxResult deleteHouse(Integer id);
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
AjaxResult detail(Integer id);
|
||||
|
||||
/**
|
||||
* 下拉列表
|
||||
*/
|
||||
List<SlaughterHouse> getAllEnabled();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.aiotagro.cattletrade.business.service;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterRecord;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* 屠宰记录服务接口
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
public interface ISlaughterRecordService extends IService<SlaughterRecord> {
|
||||
|
||||
/**
|
||||
* 分页查询屠宰记录
|
||||
*/
|
||||
PageResultResponse<SlaughterRecord> pageQuery(SlaughterRecordDto dto);
|
||||
|
||||
/**
|
||||
* 新增屠宰记录
|
||||
*/
|
||||
AjaxResult addRecord(SlaughterRecordCreateDto dto);
|
||||
|
||||
/**
|
||||
* 更新屠宰记录
|
||||
*/
|
||||
AjaxResult updateRecord(SlaughterRecordEditDto dto);
|
||||
|
||||
/**
|
||||
* 删除屠宰记录
|
||||
*/
|
||||
AjaxResult deleteRecord(Integer id);
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
AjaxResult detail(Integer id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
package com.aiotagro.cattletrade.business.service.impl;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterEntryEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.Delivery;
|
||||
import com.aiotagro.cattletrade.business.entity.Order;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.aiotagro.cattletrade.business.mapper.DeliveryMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.MemberMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.OrderMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterEntryMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterHouseMapper;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterEntryService;
|
||||
import com.aiotagro.common.core.utils.SecurityUtil;
|
||||
import com.aiotagro.common.core.utils.bean.BeanUtils;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 进场管理服务实现
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Service
|
||||
public class SlaughterEntryServiceImpl extends ServiceImpl<SlaughterEntryMapper, SlaughterEntry> implements ISlaughterEntryService {
|
||||
|
||||
@Autowired
|
||||
private SlaughterEntryMapper slaughterEntryMapper;
|
||||
@Autowired
|
||||
private SlaughterHouseMapper slaughterHouseMapper;
|
||||
@Autowired
|
||||
private DeliveryMapper deliveryMapper;
|
||||
@Autowired
|
||||
private OrderMapper orderMapper;
|
||||
@Autowired
|
||||
private MemberMapper memberMapper;
|
||||
|
||||
@Override
|
||||
public PageResultResponse<SlaughterEntry> pageQuery(SlaughterEntryDto dto) {
|
||||
Integer pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
||||
Integer pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
||||
|
||||
Page<SlaughterEntry> page = PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
LambdaQueryWrapper<SlaughterEntry> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.and(q -> q.eq(SlaughterEntry::getIsDelete, 0).or().isNull(SlaughterEntry::getIsDelete));
|
||||
|
||||
if (dto.getSlaughterHouseId() != null) {
|
||||
wrapper.eq(SlaughterEntry::getSlaughterHouseId, dto.getSlaughterHouseId());
|
||||
}
|
||||
if (dto.getDeliveryId() != null) {
|
||||
wrapper.eq(SlaughterEntry::getDeliveryId, dto.getDeliveryId());
|
||||
}
|
||||
if (dto.getOrderId() != null) {
|
||||
wrapper.eq(SlaughterEntry::getOrderId, dto.getOrderId());
|
||||
}
|
||||
|
||||
// 运送清单号模糊查询
|
||||
if (StringUtils.hasText(dto.getDeliveryNumber())) {
|
||||
// 先查询符合条件的运送清单ID
|
||||
LambdaQueryWrapper<Delivery> deliveryWrapper = new LambdaQueryWrapper<>();
|
||||
deliveryWrapper.like(Delivery::getDeliveryNumber, dto.getDeliveryNumber());
|
||||
List<Delivery> deliveries = deliveryMapper.selectList(deliveryWrapper);
|
||||
if (deliveries != null && !deliveries.isEmpty()) {
|
||||
List<Integer> deliveryIds = deliveries.stream()
|
||||
.map(Delivery::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
wrapper.in(SlaughterEntry::getDeliveryId, deliveryIds);
|
||||
} else {
|
||||
// 如果没有匹配的运送清单,返回空结果
|
||||
wrapper.eq(SlaughterEntry::getId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// 订单关键词查询(买方或卖方公司名称)
|
||||
if (StringUtils.hasText(dto.getOrderKeyword())) {
|
||||
// 先查询符合条件的订单ID
|
||||
// 需要关联查询 Order 表和 Member 表
|
||||
// 由于需要查询 Member 表的用户名,这里先查询所有订单,然后在内存中过滤
|
||||
List<Order> allOrders = orderMapper.selectList(null);
|
||||
List<Integer> matchedOrderIds = new java.util.ArrayList<>();
|
||||
String keyword = dto.getOrderKeyword().trim();
|
||||
|
||||
for (Order order : allOrders) {
|
||||
boolean matched = false;
|
||||
// 检查买方
|
||||
if (order.getBuyerId() != null && !order.getBuyerId().isEmpty()) {
|
||||
String[] buyerIds = order.getBuyerId().split(",");
|
||||
for (String buyerId : buyerIds) {
|
||||
try {
|
||||
Map<String, Object> memberUser = memberMapper.selectMemberUserById(Integer.parseInt(buyerId.trim()));
|
||||
if (memberUser != null && memberUser.get("username") != null) {
|
||||
String username = (String) memberUser.get("username");
|
||||
if (username != null && username.contains(keyword)) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
// 检查卖方
|
||||
if (!matched && order.getSellerId() != null && !order.getSellerId().isEmpty()) {
|
||||
String[] sellerIds = order.getSellerId().split(",");
|
||||
for (String sellerId : sellerIds) {
|
||||
try {
|
||||
Map<String, Object> memberUser = memberMapper.selectMemberUserById(Integer.parseInt(sellerId.trim()));
|
||||
if (memberUser != null && memberUser.get("username") != null) {
|
||||
String username = (String) memberUser.get("username");
|
||||
if (username != null && username.contains(keyword)) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
matchedOrderIds.add(order.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchedOrderIds.isEmpty()) {
|
||||
wrapper.in(SlaughterEntry::getOrderId, matchedOrderIds);
|
||||
} else {
|
||||
// 如果没有匹配的订单,返回空结果
|
||||
wrapper.eq(SlaughterEntry::getId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(SlaughterEntry::getCreateTime);
|
||||
|
||||
List<SlaughterEntry> list = slaughterEntryMapper.selectList(wrapper);
|
||||
|
||||
// 填充关联信息:运送清单号和订单买卖双方
|
||||
fillRelatedInfo(list);
|
||||
|
||||
return new PageResultResponse<>(page.getTotal(), list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充关联信息:运送清单号和订单买卖双方
|
||||
*/
|
||||
private void fillRelatedInfo(List<SlaughterEntry> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (SlaughterEntry entry : list) {
|
||||
// 填充运送清单号
|
||||
if (entry.getDeliveryId() != null) {
|
||||
Delivery delivery = deliveryMapper.selectById(entry.getDeliveryId());
|
||||
if (delivery != null) {
|
||||
entry.setDeliveryNumber(delivery.getDeliveryNumber());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充订单买卖双方信息
|
||||
if (entry.getOrderId() != null) {
|
||||
Order order = orderMapper.selectById(entry.getOrderId());
|
||||
if (order != null) {
|
||||
// 填充买方名称
|
||||
if (order.getBuyerId() != null && !order.getBuyerId().isEmpty()) {
|
||||
String buyerNames = Arrays.stream(order.getBuyerId().split(","))
|
||||
.map(buyerId -> {
|
||||
try {
|
||||
Map<String, Object> memberUser = memberMapper.selectMemberUserById(Integer.parseInt(buyerId.trim()));
|
||||
if (memberUser != null && memberUser.get("username") != null) {
|
||||
return (String) memberUser.get("username");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
return "";
|
||||
})
|
||||
.filter(name -> !name.isEmpty())
|
||||
.collect(Collectors.joining(", "));
|
||||
entry.setOrderBuyerName(buyerNames);
|
||||
}
|
||||
|
||||
// 填充卖方名称
|
||||
if (order.getSellerId() != null && !order.getSellerId().isEmpty()) {
|
||||
String sellerNames = Arrays.stream(order.getSellerId().split(","))
|
||||
.map(sellerId -> {
|
||||
try {
|
||||
Map<String, Object> memberUser = memberMapper.selectMemberUserById(Integer.parseInt(sellerId.trim()));
|
||||
if (memberUser != null && memberUser.get("username") != null) {
|
||||
return (String) memberUser.get("username");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略错误
|
||||
}
|
||||
return "";
|
||||
})
|
||||
.filter(name -> !name.isEmpty())
|
||||
.collect(Collectors.joining(", "));
|
||||
entry.setOrderSellerName(sellerNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult addEntry(SlaughterEntryCreateDto dto) {
|
||||
AjaxResult validateResult = validateRelation(dto.getSlaughterHouseId(), dto.getDeliveryId(), dto.getOrderId());
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
SlaughterEntry entry = new SlaughterEntry();
|
||||
BeanUtils.copyProperties(dto, entry);
|
||||
|
||||
// 如果编码为空,自动生成
|
||||
if (!StringUtils.hasText(entry.getEntryCode())) {
|
||||
entry.setEntryCode(generateEntryCode());
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
entry.setCreatedBy(userId);
|
||||
entry.setCreateTime(new Date());
|
||||
|
||||
int inserted = slaughterEntryMapper.insert(entry);
|
||||
return inserted > 0 ? AjaxResult.success("新增进场记录成功") : AjaxResult.error("新增进场记录失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult updateEntry(SlaughterEntryEditDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return AjaxResult.error("进场记录ID不能为空");
|
||||
}
|
||||
SlaughterEntry existing = slaughterEntryMapper.selectById(dto.getId());
|
||||
if (existing == null || (existing.getIsDelete() != null && existing.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("进场记录不存在");
|
||||
}
|
||||
|
||||
AjaxResult validateResult = validateRelation(dto.getSlaughterHouseId(), dto.getDeliveryId(), dto.getOrderId());
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
SlaughterEntry entry = new SlaughterEntry();
|
||||
BeanUtils.copyProperties(dto, entry);
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
entry.setUpdatedBy(userId);
|
||||
entry.setUpdateTime(new Date());
|
||||
|
||||
int updated = slaughterEntryMapper.updateById(entry);
|
||||
return updated > 0 ? AjaxResult.success("更新进场记录成功") : AjaxResult.error("更新进场记录失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult deleteEntry(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("进场记录ID不能为空");
|
||||
}
|
||||
SlaughterEntry entry = slaughterEntryMapper.selectById(id);
|
||||
if (entry == null || (entry.getIsDelete() != null && entry.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("进场记录不存在");
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
UpdateWrapper<SlaughterEntry> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("id", id).eq("is_delete", 0)
|
||||
.set("is_delete", 1)
|
||||
.set("updated_by", userId)
|
||||
.set("update_time", new Date());
|
||||
|
||||
int result = slaughterEntryMapper.update(null, wrapper);
|
||||
return result > 0 ? AjaxResult.success("删除进场记录成功") : AjaxResult.error("删除进场记录失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult detail(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("进场记录ID不能为空");
|
||||
}
|
||||
SlaughterEntry entry = slaughterEntryMapper.selectById(id);
|
||||
if (entry == null || (entry.getIsDelete() != null && entry.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("进场记录不存在");
|
||||
}
|
||||
|
||||
// 填充关联信息
|
||||
fillRelatedInfo(Arrays.asList(entry));
|
||||
|
||||
return AjaxResult.success("查询成功", entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验关联的屠宰场、运送清单、订单是否存在
|
||||
*/
|
||||
private AjaxResult validateRelation(Integer houseId, Integer deliveryId, Integer orderId) {
|
||||
SlaughterHouse house = slaughterHouseMapper.selectById(houseId);
|
||||
if (house == null || (house.getIsDelete() != null && house.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰场不存在");
|
||||
}
|
||||
|
||||
Delivery delivery = deliveryMapper.selectById(deliveryId);
|
||||
if (delivery == null) {
|
||||
return AjaxResult.error("运送清单不存在");
|
||||
}
|
||||
|
||||
if (orderId != null) {
|
||||
Order order = orderMapper.selectById(orderId);
|
||||
if (order == null || (order.getIsDelete() != null && order.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("订单不存在");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成进场编码:SE + yyyyMMdd + 4位流水号
|
||||
*/
|
||||
private String generateEntryCode() {
|
||||
String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||
String prefix = "SE" + dateStr;
|
||||
SlaughterEntry last = slaughterEntryMapper.selectLastCode(prefix + "%");
|
||||
int next = 1;
|
||||
if (last != null && StringUtils.hasText(last.getEntryCode())) {
|
||||
String lastCode = last.getEntryCode();
|
||||
if (lastCode.startsWith(prefix)) {
|
||||
String seq = lastCode.substring(prefix.length());
|
||||
try {
|
||||
next = Integer.parseInt(seq) + 1;
|
||||
} catch (NumberFormatException ignored) {
|
||||
next = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.format("%s%04d", prefix, next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.aiotagro.cattletrade.business.service.impl;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterHouseEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterHouseMapper;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterHouseService;
|
||||
import com.aiotagro.common.core.utils.SecurityUtil;
|
||||
import com.aiotagro.common.core.utils.bean.BeanUtils;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 屠宰场管理服务实现
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Service
|
||||
public class SlaughterHouseServiceImpl extends ServiceImpl<SlaughterHouseMapper, SlaughterHouse> implements ISlaughterHouseService {
|
||||
|
||||
@Autowired
|
||||
private SlaughterHouseMapper slaughterHouseMapper;
|
||||
|
||||
@Override
|
||||
public PageResultResponse<SlaughterHouse> pageQuery(SlaughterHouseDto dto) {
|
||||
Integer pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
||||
Integer pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
||||
|
||||
Page<SlaughterHouse> page = PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
LambdaQueryWrapper<SlaughterHouse> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.and(wrapper -> wrapper.eq(SlaughterHouse::getIsDelete, 0).or().isNull(SlaughterHouse::getIsDelete));
|
||||
|
||||
if (StringUtils.hasText(dto.getHouseName())) {
|
||||
queryWrapper.like(SlaughterHouse::getHouseName, dto.getHouseName());
|
||||
}
|
||||
if (StringUtils.hasText(dto.getSlaughterCode())) {
|
||||
queryWrapper.like(SlaughterHouse::getSlaughterCode, dto.getSlaughterCode());
|
||||
}
|
||||
if (dto.getStatus() != null) {
|
||||
queryWrapper.eq(SlaughterHouse::getStatus, dto.getStatus());
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc(SlaughterHouse::getCreateTime);
|
||||
|
||||
List<SlaughterHouse> list = slaughterHouseMapper.selectList(queryWrapper);
|
||||
return new PageResultResponse<>(page.getTotal(), list);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult addHouse(SlaughterHouseCreateDto dto) {
|
||||
String code = dto.getSlaughterCode();
|
||||
if (!StringUtils.hasText(code)) {
|
||||
code = generateSlaughterCode();
|
||||
} else {
|
||||
SlaughterHouse exist = slaughterHouseMapper.selectByCode(code);
|
||||
if (exist != null) {
|
||||
return AjaxResult.error("屠宰场编码已存在");
|
||||
}
|
||||
}
|
||||
|
||||
SlaughterHouse house = new SlaughterHouse();
|
||||
BeanUtils.copyProperties(dto, house);
|
||||
house.setSlaughterCode(code);
|
||||
if (house.getStatus() == null) {
|
||||
house.setStatus(1);
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
house.setCreatedBy(userId);
|
||||
house.setCreateTime(new Date());
|
||||
|
||||
try {
|
||||
int inserted = slaughterHouseMapper.insert(house);
|
||||
return inserted > 0 ? AjaxResult.success("新增屠宰场成功") : AjaxResult.error("新增屠宰场失败");
|
||||
} catch (DuplicateKeyException e) {
|
||||
return AjaxResult.error("屠宰场编码已存在,请使用其他编码");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("新增屠宰场失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult updateHouse(SlaughterHouseEditDto dto) {
|
||||
if (dto.getId() == null) {
|
||||
return AjaxResult.error("屠宰场ID不能为空");
|
||||
}
|
||||
|
||||
SlaughterHouse exist = slaughterHouseMapper.selectById(dto.getId());
|
||||
if (exist == null || (exist.getIsDelete() != null && exist.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰场不存在");
|
||||
}
|
||||
|
||||
SlaughterHouse codeHouse = slaughterHouseMapper.selectByCode(dto.getSlaughterCode());
|
||||
if (codeHouse != null && !codeHouse.getId().equals(dto.getId())) {
|
||||
return AjaxResult.error("屠宰场编码已存在");
|
||||
}
|
||||
|
||||
SlaughterHouse house = new SlaughterHouse();
|
||||
BeanUtils.copyProperties(dto, house);
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
house.setUpdatedBy(userId);
|
||||
house.setUpdateTime(new Date());
|
||||
|
||||
try {
|
||||
int updated = slaughterHouseMapper.updateById(house);
|
||||
return updated > 0 ? AjaxResult.success("更新屠宰场成功") : AjaxResult.error("更新屠宰场失败");
|
||||
} catch (DuplicateKeyException e) {
|
||||
return AjaxResult.error("屠宰场编码已存在,请使用其他编码");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("更新屠宰场失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult deleteHouse(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("屠宰场ID不能为空");
|
||||
}
|
||||
SlaughterHouse house = slaughterHouseMapper.selectById(id);
|
||||
if (house == null || (house.getIsDelete() != null && house.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰场不存在");
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
|
||||
UpdateWrapper<SlaughterHouse> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", id).eq("is_delete", 0)
|
||||
.set("is_delete", 1)
|
||||
.set("updated_by", userId)
|
||||
.set("update_time", new Date());
|
||||
|
||||
int result = slaughterHouseMapper.update(null, updateWrapper);
|
||||
return result > 0 ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult detail(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("屠宰场ID不能为空");
|
||||
}
|
||||
SlaughterHouse house = slaughterHouseMapper.selectById(id);
|
||||
if (house == null || (house.getIsDelete() != null && house.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰场不存在");
|
||||
}
|
||||
return AjaxResult.success("查询成功", house);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SlaughterHouse> getAllEnabled() {
|
||||
return slaughterHouseMapper.selectAllEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成屠宰场编码:SLyyyyMMdd + 4位流水
|
||||
*/
|
||||
private String generateSlaughterCode() {
|
||||
String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||
String prefix = "SL" + dateStr;
|
||||
SlaughterHouse last = slaughterHouseMapper.selectLastCode(prefix + "%");
|
||||
int next = 1;
|
||||
if (last != null && StringUtils.hasText(last.getSlaughterCode())) {
|
||||
String lastCode = last.getSlaughterCode();
|
||||
if (lastCode.startsWith(prefix)) {
|
||||
String seq = lastCode.substring(prefix.length());
|
||||
try {
|
||||
next = Integer.parseInt(seq) + 1;
|
||||
} catch (NumberFormatException ignored) {
|
||||
next = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.format("%s%04d", prefix, next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
package com.aiotagro.cattletrade.business.service.impl;
|
||||
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordCreateDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordDto;
|
||||
import com.aiotagro.cattletrade.business.dto.SlaughterRecordEditDto;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
|
||||
import com.aiotagro.cattletrade.business.entity.SlaughterRecord;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterEntryMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterHouseMapper;
|
||||
import com.aiotagro.cattletrade.business.mapper.SlaughterRecordMapper;
|
||||
import com.aiotagro.cattletrade.business.service.ISlaughterRecordService;
|
||||
import com.aiotagro.common.core.utils.SecurityUtil;
|
||||
import com.aiotagro.common.core.utils.bean.BeanUtils;
|
||||
import com.aiotagro.common.core.web.domain.AjaxResult;
|
||||
import com.aiotagro.common.core.web.domain.PageResultResponse;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 屠宰记录服务实现
|
||||
*
|
||||
* @author System
|
||||
* @date 2025-12-10
|
||||
*/
|
||||
@Service
|
||||
public class SlaughterRecordServiceImpl extends ServiceImpl<SlaughterRecordMapper, SlaughterRecord> implements ISlaughterRecordService {
|
||||
|
||||
@Autowired
|
||||
private SlaughterRecordMapper slaughterRecordMapper;
|
||||
@Autowired
|
||||
private SlaughterEntryMapper slaughterEntryMapper;
|
||||
@Autowired
|
||||
private SlaughterHouseMapper slaughterHouseMapper;
|
||||
|
||||
@Override
|
||||
public PageResultResponse<SlaughterRecord> pageQuery(SlaughterRecordDto dto) {
|
||||
Integer pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
|
||||
Integer pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
|
||||
|
||||
Page<SlaughterRecord> page = PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
LambdaQueryWrapper<SlaughterRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.and(q -> q.eq(SlaughterRecord::getIsDelete, 0).or().isNull(SlaughterRecord::getIsDelete));
|
||||
|
||||
if (StringUtils.hasText(dto.getRecordCode())) {
|
||||
wrapper.like(SlaughterRecord::getRecordCode, dto.getRecordCode().trim());
|
||||
}
|
||||
if (dto.getEntryId() != null) {
|
||||
wrapper.eq(SlaughterRecord::getEntryId, dto.getEntryId());
|
||||
}
|
||||
|
||||
// 按进场编码模糊查询
|
||||
if (StringUtils.hasText(dto.getEntryCode())) {
|
||||
List<SlaughterEntry> matchedEntries = slaughterEntryMapper.selectList(new LambdaQueryWrapper<SlaughterEntry>()
|
||||
.like(SlaughterEntry::getEntryCode, dto.getEntryCode().trim())
|
||||
.and(q -> q.eq(SlaughterEntry::getIsDelete, 0).or().isNull(SlaughterEntry::getIsDelete)));
|
||||
if (CollectionUtils.isEmpty(matchedEntries)) {
|
||||
wrapper.eq(SlaughterRecord::getId, -1);
|
||||
} else {
|
||||
Set<Integer> entryIds = matchedEntries.stream().map(SlaughterEntry::getId).collect(Collectors.toSet());
|
||||
wrapper.in(SlaughterRecord::getEntryId, entryIds);
|
||||
}
|
||||
}
|
||||
|
||||
// 按屠宰场过滤
|
||||
if (dto.getSlaughterHouseId() != null) {
|
||||
List<SlaughterEntry> matchedEntries = slaughterEntryMapper.selectList(new LambdaQueryWrapper<SlaughterEntry>()
|
||||
.eq(SlaughterEntry::getSlaughterHouseId, dto.getSlaughterHouseId())
|
||||
.and(q -> q.eq(SlaughterEntry::getIsDelete, 0).or().isNull(SlaughterEntry::getIsDelete)));
|
||||
if (CollectionUtils.isEmpty(matchedEntries)) {
|
||||
wrapper.eq(SlaughterRecord::getId, -1);
|
||||
} else {
|
||||
Set<Integer> entryIds = matchedEntries.stream().map(SlaughterEntry::getId).collect(Collectors.toSet());
|
||||
wrapper.in(SlaughterRecord::getEntryId, entryIds);
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(SlaughterRecord::getCreateTime);
|
||||
|
||||
List<SlaughterRecord> list = slaughterRecordMapper.selectList(wrapper);
|
||||
fillRelatedInfo(list);
|
||||
|
||||
return new PageResultResponse<>(page.getTotal(), list);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult addRecord(SlaughterRecordCreateDto dto) {
|
||||
String yieldCheck = validateYieldRate(dto.getYieldRate());
|
||||
if (yieldCheck != null) {
|
||||
return AjaxResult.error(yieldCheck);
|
||||
}
|
||||
|
||||
SlaughterEntry entry = loadEntry(dto.getEntryId());
|
||||
if (entry == null) {
|
||||
return AjaxResult.error("进场记录不存在");
|
||||
}
|
||||
|
||||
int remaining = entry.getRemainingCapacity() == null ? 0 : entry.getRemainingCapacity();
|
||||
if (dto.getSlaughterCount() > remaining) {
|
||||
return AjaxResult.error("屠宰头数不能超过进场剩余头数,当前剩余:" + remaining);
|
||||
}
|
||||
|
||||
SlaughterRecord record = new SlaughterRecord();
|
||||
BeanUtils.copyProperties(dto, record);
|
||||
|
||||
if (!StringUtils.hasText(record.getRecordCode())) {
|
||||
record.setRecordCode(generateRecordCode());
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
Date now = new Date();
|
||||
|
||||
record.setCreatedBy(userId);
|
||||
record.setCreateTime(now);
|
||||
record.setIsDelete(0);
|
||||
|
||||
int inserted = slaughterRecordMapper.insert(record);
|
||||
if (inserted <= 0) {
|
||||
return AjaxResult.error("新增屠宰记录失败");
|
||||
}
|
||||
|
||||
// 扣减剩余头数
|
||||
if (!updateRemainingCapacity(entry.getId(), -dto.getSlaughterCount(), userId, now)) {
|
||||
throw new RuntimeException("扣减进场剩余头数失败");
|
||||
}
|
||||
|
||||
return AjaxResult.success("新增屠宰记录成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult updateRecord(SlaughterRecordEditDto dto) {
|
||||
String yieldCheck = validateYieldRate(dto.getYieldRate());
|
||||
if (yieldCheck != null) {
|
||||
return AjaxResult.error(yieldCheck);
|
||||
}
|
||||
|
||||
SlaughterRecord existing = slaughterRecordMapper.selectById(dto.getId());
|
||||
if (existing == null || (existing.getIsDelete() != null && existing.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰记录不存在");
|
||||
}
|
||||
|
||||
if (!Objects.equals(existing.getEntryId(), dto.getEntryId())) {
|
||||
return AjaxResult.error("暂不支持变更进场记录,请删除后重新新增");
|
||||
}
|
||||
|
||||
SlaughterEntry entry = loadEntry(existing.getEntryId());
|
||||
if (entry == null) {
|
||||
return AjaxResult.error("进场记录不存在");
|
||||
}
|
||||
|
||||
int remaining = entry.getRemainingCapacity() == null ? 0 : entry.getRemainingCapacity();
|
||||
int available = remaining + (existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount());
|
||||
if (dto.getSlaughterCount() > available) {
|
||||
return AjaxResult.error("屠宰头数不能超过进场剩余头数,当前可用:" + available);
|
||||
}
|
||||
|
||||
SlaughterRecord record = new SlaughterRecord();
|
||||
BeanUtils.copyProperties(dto, record);
|
||||
|
||||
if (!StringUtils.hasText(record.getRecordCode())) {
|
||||
record.setRecordCode(existing.getRecordCode());
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
Date now = new Date();
|
||||
|
||||
record.setUpdatedBy(userId);
|
||||
record.setUpdateTime(now);
|
||||
record.setIsDelete(0);
|
||||
|
||||
int updated = slaughterRecordMapper.updateById(record);
|
||||
if (updated <= 0) {
|
||||
return AjaxResult.error("更新屠宰记录失败");
|
||||
}
|
||||
|
||||
int adjust = (existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount()) - dto.getSlaughterCount();
|
||||
if (adjust != 0 && !updateRemainingCapacity(entry.getId(), adjust, userId, now)) {
|
||||
throw new RuntimeException("调整进场剩余头数失败");
|
||||
}
|
||||
|
||||
return AjaxResult.success("更新屠宰记录成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult deleteRecord(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("屠宰记录ID不能为空");
|
||||
}
|
||||
|
||||
SlaughterRecord existing = slaughterRecordMapper.selectById(id);
|
||||
if (existing == null || (existing.getIsDelete() != null && existing.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰记录不存在");
|
||||
}
|
||||
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
Date now = new Date();
|
||||
|
||||
UpdateWrapper<SlaughterRecord> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("id", id)
|
||||
.eq("is_delete", 0)
|
||||
.set("is_delete", 1)
|
||||
.set("updated_by", userId)
|
||||
.set("update_time", now);
|
||||
|
||||
int result = slaughterRecordMapper.update(null, wrapper);
|
||||
if (result <= 0) {
|
||||
return AjaxResult.error("删除屠宰记录失败");
|
||||
}
|
||||
|
||||
int recover = existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount();
|
||||
if (recover > 0 && !updateRemainingCapacity(existing.getEntryId(), recover, userId, now)) {
|
||||
throw new RuntimeException("回补进场剩余头数失败");
|
||||
}
|
||||
|
||||
return AjaxResult.success("删除屠宰记录成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult detail(Integer id) {
|
||||
if (id == null) {
|
||||
return AjaxResult.error("屠宰记录ID不能为空");
|
||||
}
|
||||
SlaughterRecord record = slaughterRecordMapper.selectById(id);
|
||||
if (record == null || (record.getIsDelete() != null && record.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("屠宰记录不存在");
|
||||
}
|
||||
fillRelatedInfo(record);
|
||||
return AjaxResult.success("查询成功", record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充关联信息
|
||||
*/
|
||||
private void fillRelatedInfo(List<SlaughterRecord> list) {
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
Set<Integer> entryIds = list.stream()
|
||||
.map(SlaughterRecord::getEntryId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (CollectionUtils.isEmpty(entryIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<SlaughterEntry> entries = slaughterEntryMapper.selectBatchIds(entryIds);
|
||||
Map<Integer, SlaughterEntry> entryMap = entries.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(SlaughterEntry::getId, e -> e));
|
||||
|
||||
Set<Integer> houseIds = entries.stream()
|
||||
.map(SlaughterEntry::getSlaughterHouseId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Map<Integer, SlaughterHouse> houseMap = new java.util.HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(houseIds)) {
|
||||
houseMap = slaughterHouseMapper.selectBatchIds(houseIds).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(SlaughterHouse::getId, h -> h));
|
||||
}
|
||||
|
||||
for (SlaughterRecord record : list) {
|
||||
SlaughterEntry entry = entryMap.get(record.getEntryId());
|
||||
if (entry != null) {
|
||||
record.setEntryCode(entry.getEntryCode());
|
||||
record.setSlaughterHouseId(entry.getSlaughterHouseId());
|
||||
record.setRemainingCapacity(entry.getRemainingCapacity());
|
||||
|
||||
SlaughterHouse house = houseMap.get(entry.getSlaughterHouseId());
|
||||
if (house != null) {
|
||||
record.setSlaughterHouseName(house.getHouseName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fillRelatedInfo(SlaughterRecord record) {
|
||||
if (record == null) {
|
||||
return;
|
||||
}
|
||||
fillRelatedInfo(Collections.singletonList(record));
|
||||
}
|
||||
|
||||
private SlaughterEntry loadEntry(Integer entryId) {
|
||||
if (entryId == null) {
|
||||
return null;
|
||||
}
|
||||
SlaughterEntry entry = slaughterEntryMapper.selectById(entryId);
|
||||
if (entry == null || (entry.getIsDelete() != null && entry.getIsDelete() == 1)) {
|
||||
return null;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新进场剩余头数(delta为正表示回补,为负表示扣减)
|
||||
*/
|
||||
private boolean updateRemainingCapacity(Integer entryId, int delta, Integer userId, Date now) {
|
||||
if (delta == 0) {
|
||||
return true;
|
||||
}
|
||||
UpdateWrapper<SlaughterEntry> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("id", entryId)
|
||||
.eq("is_delete", 0)
|
||||
.set("updated_by", userId)
|
||||
.set("update_time", now);
|
||||
|
||||
if (delta < 0) {
|
||||
int decrease = Math.abs(delta);
|
||||
wrapper.ge("remaining_capacity", decrease)
|
||||
.setSql("remaining_capacity = remaining_capacity - " + decrease);
|
||||
} else {
|
||||
wrapper.setSql("remaining_capacity = remaining_capacity + " + delta);
|
||||
}
|
||||
|
||||
int updated = slaughterEntryMapper.update(null, wrapper);
|
||||
return updated > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验出肉率范围
|
||||
*/
|
||||
private String validateYieldRate(BigDecimal yieldRate) {
|
||||
if (yieldRate == null) {
|
||||
return null;
|
||||
}
|
||||
if (yieldRate.compareTo(BigDecimal.ZERO) < 0 || yieldRate.compareTo(new BigDecimal("100")) > 0) {
|
||||
return "出肉率需在0-100之间";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成屠宰记录编码:SL + yyyyMMdd + 3位流水
|
||||
*/
|
||||
private String generateRecordCode() {
|
||||
String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||
String prefix = "SL" + dateStr;
|
||||
SlaughterRecord last = slaughterRecordMapper.selectLastCode(prefix + "%");
|
||||
int next = 1;
|
||||
if (last != null && StringUtils.hasText(last.getRecordCode())) {
|
||||
String lastCode = last.getRecordCode();
|
||||
if (lastCode.startsWith(prefix)) {
|
||||
String seq = lastCode.substring(prefix.length());
|
||||
try {
|
||||
next = Integer.parseInt(seq) + 1;
|
||||
} catch (NumberFormatException ignored) {
|
||||
next = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.format("%s%03d", prefix, next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,8 @@ public class WarehouseInServiceImpl extends ServiceImpl<WarehouseInMapper, Wareh
|
||||
BeanUtils.copyProperties(dto, warehouseIn);
|
||||
warehouseIn.setInNumber(inNumber);
|
||||
warehouseIn.setStatus(1); // 默认待进仓
|
||||
// 初始化剩余头数 = 总数量
|
||||
warehouseIn.setRemainingCount(dto.getCattleCount() != null ? dto.getCattleCount() : 0);
|
||||
|
||||
// 设置创建人和创建时间
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -42,6 +44,8 @@ import java.util.List;
|
||||
@Service
|
||||
public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, WarehouseOut> implements IWarehouseOutService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WarehouseOutServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private WarehouseOutMapper warehouseOutMapper;
|
||||
|
||||
@@ -110,11 +114,23 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
}
|
||||
}
|
||||
|
||||
// 关联查询进仓记录
|
||||
if (warehouseOut.getWarehouseInId() != null) {
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseOut.getWarehouseInId());
|
||||
if (warehouseIn != null) {
|
||||
vo.setWarehouseInNumber(warehouseIn.getInNumber());
|
||||
// 关联查询进仓记录(支持多个ID,用逗号分隔)
|
||||
if (warehouseOut.getWarehouseInId() != null && !warehouseOut.getWarehouseInId().trim().isEmpty()) {
|
||||
String[] warehouseInIds = warehouseOut.getWarehouseInId().split(",");
|
||||
List<String> warehouseInNumbers = new ArrayList<>();
|
||||
for (String warehouseInIdStr : warehouseInIds) {
|
||||
try {
|
||||
Integer warehouseInId = Integer.parseInt(warehouseInIdStr.trim());
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseInId);
|
||||
if (warehouseIn != null) {
|
||||
warehouseInNumbers.add(warehouseIn.getInNumber());
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("进仓记录ID格式错误: {}", warehouseInIdStr);
|
||||
}
|
||||
}
|
||||
if (!warehouseInNumbers.isEmpty()) {
|
||||
vo.setWarehouseInNumber(String.join(",", warehouseInNumbers));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +201,19 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
int result = warehouseOutMapper.insert(warehouseOut);
|
||||
|
||||
if (result > 0) {
|
||||
// 更新相关进仓记录的剩余数量
|
||||
// 优先使用 warehouseInRelations 数组,如果没有则使用 warehouseInId 和 cattleCount 进行平均分配
|
||||
if (dto.getWarehouseInRelations() != null && !dto.getWarehouseInRelations().isEmpty()) {
|
||||
// 使用 warehouseInRelations 数组,精确更新每个进仓记录的剩余数量
|
||||
for (com.aiotagro.cattletrade.business.dto.WarehouseInRelationDto relation : dto.getWarehouseInRelations()) {
|
||||
if (relation.getWarehouseInId() != null && relation.getOutCount() != null && relation.getOutCount() > 0) {
|
||||
updateSingleWarehouseInRemainingCount(relation.getWarehouseInId(), relation.getOutCount(), true);
|
||||
}
|
||||
}
|
||||
} else if (warehouseOut.getWarehouseInId() != null && warehouseOut.getCattleCount() != null) {
|
||||
// 回退到平均分配逻辑(兼容旧数据)
|
||||
updateWarehouseInRemainingCount(warehouseOut.getWarehouseInId(), warehouseOut.getCattleCount(), true);
|
||||
}
|
||||
return AjaxResult.success("新增出仓记录成功", warehouseOut);
|
||||
} else {
|
||||
return AjaxResult.error("新增出仓记录失败");
|
||||
@@ -207,6 +236,9 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult updateWarehouseOut(WarehouseOutEditDto dto) {
|
||||
logger.info("========== 更新出仓记录 - Service层 ==========");
|
||||
logger.info("接收到的DTO - ID: {}, warehouseInId: {}", dto.getId(), dto.getWarehouseInId());
|
||||
|
||||
if (dto.getId() == null) {
|
||||
return AjaxResult.error("出仓记录ID不能为空");
|
||||
}
|
||||
@@ -216,6 +248,8 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
if (existingWarehouseOut == null) {
|
||||
return AjaxResult.error("出仓记录不存在");
|
||||
}
|
||||
|
||||
logger.info("更新前 - 原有记录 warehouse_in_id: {}", existingWarehouseOut.getWarehouseInId());
|
||||
|
||||
// 校验中转仓是否存在且启用
|
||||
Warehouse warehouse = warehouseMapper.selectById(dto.getWarehouseId());
|
||||
@@ -227,36 +261,91 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
}
|
||||
|
||||
// 如果关联了进仓记录,校验进仓记录是否存在
|
||||
if (dto.getWarehouseInId() != null) {
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(dto.getWarehouseInId());
|
||||
if (warehouseIn == null || (warehouseIn.getIsDelete() != null && warehouseIn.getIsDelete() == 1)) {
|
||||
return AjaxResult.error("进仓记录不存在");
|
||||
}
|
||||
// 校验出仓数量不能超过进仓数量
|
||||
if (dto.getCattleCount() > warehouseIn.getCattleCount()) {
|
||||
return AjaxResult.error("出仓数量不能超过进仓数量");
|
||||
// 注意:warehouseInId 现在可能是多个ID(用逗号分隔),需要分别校验
|
||||
if (dto.getWarehouseInId() != null && !dto.getWarehouseInId().trim().isEmpty()) {
|
||||
String[] warehouseInIds = dto.getWarehouseInId().split(",");
|
||||
for (String warehouseInIdStr : warehouseInIds) {
|
||||
try {
|
||||
Integer warehouseInId = Integer.parseInt(warehouseInIdStr.trim());
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseInId);
|
||||
if (warehouseIn == null || (warehouseIn.getIsDelete() != null && warehouseIn.getIsDelete() == 1)) {
|
||||
logger.warn("进仓记录不存在,ID: {}", warehouseInId);
|
||||
return AjaxResult.error("进仓记录不存在,ID: " + warehouseInId);
|
||||
}
|
||||
// 注意:多对多关系时,不能简单比较总数,需要在关联表中校验
|
||||
// 这里暂时保留原有逻辑,后续可以优化
|
||||
logger.info("校验进仓记录 - ID: {}, 进仓数量: {}", warehouseInId, warehouseIn.getCattleCount());
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("进仓记录ID格式错误: {}", warehouseInIdStr, e);
|
||||
return AjaxResult.error("进仓记录ID格式错误: " + warehouseInIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新出仓信息
|
||||
WarehouseOut warehouseOut = new WarehouseOut();
|
||||
BeanUtils.copyProperties(dto, warehouseOut);
|
||||
|
||||
logger.info("BeanUtils.copyProperties 后 - warehouseOut.warehouseInId: {}", warehouseOut.getWarehouseInId());
|
||||
logger.info("DTO中的warehouseInId类型: {}, 值: {}",
|
||||
dto.getWarehouseInId() != null ? dto.getWarehouseInId().getClass().getName() : "null",
|
||||
dto.getWarehouseInId());
|
||||
|
||||
// 设置更新人和更新时间
|
||||
Integer userId = SecurityUtil.getCurrentUserId();
|
||||
warehouseOut.setUpdatedBy(userId);
|
||||
warehouseOut.setUpdateTime(new Date());
|
||||
|
||||
logger.info("准备保存到数据库 - warehouseOut对象详情:");
|
||||
logger.info(" - id: {}", warehouseOut.getId());
|
||||
logger.info(" - warehouseId: {}", warehouseOut.getWarehouseId());
|
||||
logger.info(" - warehouseInId: {} (类型: {})",
|
||||
warehouseOut.getWarehouseInId(),
|
||||
warehouseOut.getWarehouseInId() != null ? warehouseOut.getWarehouseInId().getClass().getName() : "null");
|
||||
logger.info(" - cattleCount: {}", warehouseOut.getCattleCount());
|
||||
logger.info(" - deliveryId: {}", warehouseOut.getDeliveryId());
|
||||
|
||||
try {
|
||||
// 先恢复旧的出仓数量(增加剩余数量)
|
||||
if (existingWarehouseOut.getWarehouseInId() != null && existingWarehouseOut.getCattleCount() != null) {
|
||||
updateWarehouseInRemainingCount(existingWarehouseOut.getWarehouseInId(), existingWarehouseOut.getCattleCount(), false);
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
int result = warehouseOutMapper.updateById(warehouseOut);
|
||||
|
||||
logger.info("数据库更新结果: {}", result > 0 ? "成功" : "失败");
|
||||
|
||||
// 查询更新后的数据,验证是否保存成功
|
||||
if (result > 0) {
|
||||
WarehouseOut updatedRecord = warehouseOutMapper.selectById(dto.getId());
|
||||
if (updatedRecord != null) {
|
||||
logger.info("更新后查询数据库 - warehouse_in_id: {}", updatedRecord.getWarehouseInId());
|
||||
}
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
// 减去新的出仓数量(减少剩余数量)
|
||||
// 优先使用 warehouseInRelations 数组,如果没有则使用 warehouseInId 和 cattleCount 进行平均分配
|
||||
if (dto.getWarehouseInRelations() != null && !dto.getWarehouseInRelations().isEmpty()) {
|
||||
// 使用 warehouseInRelations 数组,精确更新每个进仓记录的剩余数量
|
||||
for (com.aiotagro.cattletrade.business.dto.WarehouseInRelationDto relation : dto.getWarehouseInRelations()) {
|
||||
if (relation.getWarehouseInId() != null && relation.getOutCount() != null && relation.getOutCount() > 0) {
|
||||
updateSingleWarehouseInRemainingCount(relation.getWarehouseInId(), relation.getOutCount(), true);
|
||||
}
|
||||
}
|
||||
} else if (warehouseOut.getWarehouseInId() != null && warehouseOut.getCattleCount() != null) {
|
||||
// 回退到平均分配逻辑(兼容旧数据)
|
||||
updateWarehouseInRemainingCount(warehouseOut.getWarehouseInId(), warehouseOut.getCattleCount(), true);
|
||||
}
|
||||
logger.info("========== 更新出仓记录成功 ==========");
|
||||
return AjaxResult.success("更新出仓记录成功");
|
||||
} else {
|
||||
logger.warn("========== 更新出仓记录失败 - 影响行数为0 ==========");
|
||||
return AjaxResult.error("更新出仓记录失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("========== 更新出仓记录异常 ==========", e);
|
||||
e.printStackTrace();
|
||||
return AjaxResult.error("更新出仓记录失败:" + e.getMessage());
|
||||
}
|
||||
@@ -293,6 +382,10 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
int result = warehouseOutMapper.update(null, updateWrapper);
|
||||
|
||||
if (result > 0) {
|
||||
// 恢复相关进仓记录的剩余数量(增加剩余数量)
|
||||
if (warehouseOut.getWarehouseInId() != null && warehouseOut.getCattleCount() != null) {
|
||||
updateWarehouseInRemainingCount(warehouseOut.getWarehouseInId(), warehouseOut.getCattleCount(), false);
|
||||
}
|
||||
return AjaxResult.success("删除出仓记录成功");
|
||||
} else {
|
||||
return AjaxResult.error("删除出仓记录失败");
|
||||
@@ -325,11 +418,23 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
}
|
||||
}
|
||||
|
||||
// 关联查询进仓记录
|
||||
if (warehouseOut.getWarehouseInId() != null) {
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseOut.getWarehouseInId());
|
||||
if (warehouseIn != null) {
|
||||
vo.setWarehouseInNumber(warehouseIn.getInNumber());
|
||||
// 关联查询进仓记录(支持多个ID,用逗号分隔)
|
||||
if (warehouseOut.getWarehouseInId() != null && !warehouseOut.getWarehouseInId().trim().isEmpty()) {
|
||||
String[] warehouseInIds = warehouseOut.getWarehouseInId().split(",");
|
||||
List<String> warehouseInNumbers = new ArrayList<>();
|
||||
for (String warehouseInIdStr : warehouseInIds) {
|
||||
try {
|
||||
Integer warehouseInId = Integer.parseInt(warehouseInIdStr.trim());
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseInId);
|
||||
if (warehouseIn != null) {
|
||||
warehouseInNumbers.add(warehouseIn.getInNumber());
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("进仓记录ID格式错误: {}", warehouseInIdStr);
|
||||
}
|
||||
}
|
||||
if (!warehouseInNumbers.isEmpty()) {
|
||||
vo.setWarehouseInNumber(String.join(",", warehouseInNumbers));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,6 +474,98 @@ public class WarehouseOutServiceImpl extends ServiceImpl<WarehouseOutMapper, War
|
||||
return String.format("%s%04d", datePrefix, nextSequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个进仓记录的剩余数量
|
||||
* @param warehouseInId 进仓记录ID
|
||||
* @param outCount 出仓数量
|
||||
* @param isSubtract true-减去出仓数量(减少剩余数量),false-增加出仓数量(恢复剩余数量)
|
||||
*/
|
||||
private void updateSingleWarehouseInRemainingCount(Integer warehouseInId, Integer outCount, boolean isSubtract) {
|
||||
if (warehouseInId == null || outCount == null || outCount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseInId);
|
||||
if (warehouseIn != null && warehouseIn.getIsDelete() != null && warehouseIn.getIsDelete() == 0) {
|
||||
int currentRemaining = warehouseIn.getRemainingCount() != null ? warehouseIn.getRemainingCount() : warehouseIn.getCattleCount();
|
||||
|
||||
int newRemaining;
|
||||
if (isSubtract) {
|
||||
// 减去出仓数量
|
||||
newRemaining = Math.max(0, currentRemaining - outCount);
|
||||
} else {
|
||||
// 恢复出仓数量
|
||||
newRemaining = Math.min(warehouseIn.getCattleCount(), currentRemaining + outCount);
|
||||
}
|
||||
|
||||
UpdateWrapper<WarehouseIn> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", warehouseInId)
|
||||
.eq("is_delete", 0)
|
||||
.set("remaining_count", newRemaining)
|
||||
.set("update_time", new Date());
|
||||
warehouseInMapper.update(null, updateWrapper);
|
||||
|
||||
logger.info("更新进仓记录 {} 的剩余数量: {} -> {} (出仓数量: {}, 操作: {})",
|
||||
warehouseInId, currentRemaining, newRemaining, outCount, isSubtract ? "减去" : "恢复");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("更新进仓记录剩余数量失败,进仓记录ID: {}", warehouseInId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新进仓记录的剩余数量(平均分配方式,用于兼容旧数据)
|
||||
* @param warehouseInIdStr 进仓记录ID(可能是单个ID或逗号分隔的多个ID)
|
||||
* @param outCount 出仓数量
|
||||
* @param isSubtract true-减去出仓数量(减少剩余数量),false-增加出仓数量(恢复剩余数量)
|
||||
*/
|
||||
private void updateWarehouseInRemainingCount(String warehouseInIdStr, Integer outCount, boolean isSubtract) {
|
||||
if (warehouseInIdStr == null || warehouseInIdStr.trim().isEmpty() || outCount == null || outCount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String[] warehouseInIds = warehouseInIdStr.split(",");
|
||||
int countPerIn = outCount / warehouseInIds.length; // 平均分配出仓数量
|
||||
int remainder = outCount % warehouseInIds.length; // 余数分配给第一个
|
||||
|
||||
for (int i = 0; i < warehouseInIds.length; i++) {
|
||||
try {
|
||||
Integer warehouseInId = Integer.parseInt(warehouseInIds[i].trim());
|
||||
WarehouseIn warehouseIn = warehouseInMapper.selectById(warehouseInId);
|
||||
if (warehouseIn != null && warehouseIn.getIsDelete() != null && warehouseIn.getIsDelete() == 0) {
|
||||
int currentRemaining = warehouseIn.getRemainingCount() != null ? warehouseIn.getRemainingCount() : warehouseIn.getCattleCount();
|
||||
int outCountForThis = countPerIn + (i == 0 ? remainder : 0); // 第一个分配余数
|
||||
|
||||
int newRemaining;
|
||||
if (isSubtract) {
|
||||
// 减去出仓数量
|
||||
newRemaining = Math.max(0, currentRemaining - outCountForThis);
|
||||
} else {
|
||||
// 恢复出仓数量
|
||||
newRemaining = Math.min(warehouseIn.getCattleCount(), currentRemaining + outCountForThis);
|
||||
}
|
||||
|
||||
UpdateWrapper<WarehouseIn> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", warehouseInId)
|
||||
.eq("is_delete", 0)
|
||||
.set("remaining_count", newRemaining)
|
||||
.set("update_time", new Date());
|
||||
warehouseInMapper.update(null, updateWrapper);
|
||||
|
||||
logger.info("更新进仓记录 {} 的剩余数量: {} -> {} (出仓数量: {}, 操作: {})",
|
||||
warehouseInId, currentRemaining, newRemaining, outCountForThis, isSubtract ? "减去" : "恢复");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("进仓记录ID格式错误: {}", warehouseInIds[i], e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("更新进仓记录剩余数量失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态描述
|
||||
*/
|
||||
|
||||
@@ -85,6 +85,11 @@ public class WarehouseInVo {
|
||||
*/
|
||||
private Integer cattleCount;
|
||||
|
||||
/**
|
||||
* 剩余头数(总数量 - 已出仓数量)
|
||||
*/
|
||||
private Integer remainingCount;
|
||||
|
||||
/**
|
||||
* 重量(公斤)
|
||||
*/
|
||||
|
||||
@@ -36,9 +36,9 @@ public class WarehouseOutVo {
|
||||
private String warehouseName;
|
||||
|
||||
/**
|
||||
* 进仓记录ID(可选)
|
||||
* 进仓记录ID(可选,支持多个ID用逗号分隔,如:1,2,3)
|
||||
*/
|
||||
private Integer warehouseInId;
|
||||
private String warehouseInId;
|
||||
|
||||
/**
|
||||
* 进仓单号(通过warehouse_in_id关联查询)
|
||||
|
||||
@@ -95,3 +95,8 @@ openapi:
|
||||
|
||||
iot:
|
||||
url: http://aiot.aiotagro.com/iotPlateform/iotBusiness/sendCmd
|
||||
|
||||
# 日志等级调整:抑制重复的 NotLoginException 警告,只保留错误级别
|
||||
logging:
|
||||
level:
|
||||
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: error
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# 销售概览菜单配置说明
|
||||
|
||||
## 问题说明
|
||||
|
||||
如果销售概览页面可以访问,但侧边栏菜单中没有显示,通常是因为:
|
||||
1. 菜单已插入数据库,但没有给用户/角色分配权限
|
||||
2. 菜单的 `org_type` 配置与用户不匹配
|
||||
|
||||
## 解决步骤
|
||||
|
||||
### 步骤1:检查菜单是否已插入
|
||||
|
||||
执行检查SQL:
|
||||
```sql
|
||||
-- 文件:check_salesoverview_menu.sql
|
||||
USE cattletrade;
|
||||
SELECT * FROM sys_menu WHERE name = '销售概览' AND is_delete = 0;
|
||||
```
|
||||
|
||||
如果查询结果为空,说明菜单未插入,需要先执行 `insert_salesoverview_menu.sql`。
|
||||
|
||||
### 步骤2:分配菜单权限
|
||||
|
||||
有两种方式分配权限:
|
||||
|
||||
#### 方式A:通过SQL脚本分配(推荐)
|
||||
|
||||
执行权限分配SQL:
|
||||
```sql
|
||||
-- 文件:assign_salesoverview_menu_permission.sql
|
||||
-- 该脚本会为角色ID=1(超级管理员)分配销售概览菜单权限
|
||||
```
|
||||
|
||||
**注意**:如果您的超级管理员角色ID不是1,请先查询:
|
||||
```sql
|
||||
SELECT id, name FROM sys_role WHERE name LIKE '%管理员%' OR name LIKE '%admin%';
|
||||
```
|
||||
|
||||
然后修改SQL脚本中的角色ID。
|
||||
|
||||
#### 方式B:通过系统界面分配
|
||||
|
||||
1. 登录系统管理后台
|
||||
2. 进入 **权限管理** → **操作权限管理**
|
||||
3. 选择需要分配权限的角色
|
||||
4. 勾选销售概览相关的菜单项:
|
||||
- 销售概览(主菜单)
|
||||
- 新增
|
||||
- 编辑
|
||||
- 删除
|
||||
- 计算统计数据
|
||||
5. 点击保存
|
||||
|
||||
### 步骤3:检查菜单的org_type配置
|
||||
|
||||
菜单的 `org_type` 字段:
|
||||
- 1 = 海关端
|
||||
- 2 = 企业端
|
||||
- 3 = 海关企业共用
|
||||
|
||||
如果您的用户是企业端,但菜单的 `org_type` 是1(海关端),菜单也不会显示。
|
||||
|
||||
**检查当前用户的org_type**:
|
||||
```sql
|
||||
-- 查询用户所属机构类型
|
||||
SELECT u.id, u.name, u.mobile, r.name AS role_name, r.org_type
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_role r ON u.role_id = r.id
|
||||
WHERE u.mobile = '15900000000'; -- 替换为实际手机号
|
||||
```
|
||||
|
||||
**如果需要修改菜单的org_type**:
|
||||
```sql
|
||||
-- 将销售概览菜单设置为企业端和海关端共用
|
||||
UPDATE sys_menu
|
||||
SET org_type = 3
|
||||
WHERE name = '销售概览' AND type = 1 AND is_delete = 0;
|
||||
```
|
||||
|
||||
### 步骤4:刷新页面
|
||||
|
||||
执行完SQL或分配权限后:
|
||||
1. 退出登录
|
||||
2. 重新登录系统
|
||||
3. 刷新页面
|
||||
|
||||
菜单应该会出现在侧边栏中。
|
||||
|
||||
## 快速修复SQL(一键执行)
|
||||
|
||||
如果确认菜单已插入,只需要分配权限,可以执行以下SQL:
|
||||
|
||||
```sql
|
||||
USE cattletrade;
|
||||
|
||||
-- 查询销售概览菜单ID
|
||||
SET @menu_id = (SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1);
|
||||
|
||||
-- 为角色ID=1(超级管理员)分配主菜单权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_id
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_id)
|
||||
AND @menu_id IS NOT NULL;
|
||||
|
||||
-- 为角色ID=1分配所有按钮权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, id
|
||||
FROM sys_menu
|
||||
WHERE parent_id = @menu_id AND type = 2 AND is_delete = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = sys_menu.id)
|
||||
AND @menu_id IS NOT NULL;
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
执行以下SQL验证权限是否分配成功:
|
||||
|
||||
```sql
|
||||
USE cattletrade;
|
||||
|
||||
-- 查询销售概览菜单权限分配情况
|
||||
SELECT
|
||||
r.id AS role_id,
|
||||
r.name AS role_name,
|
||||
m.id AS menu_id,
|
||||
m.name AS menu_name,
|
||||
m.type AS menu_type,
|
||||
m.page_url
|
||||
FROM sys_role_menu rm
|
||||
INNER JOIN sys_role r ON rm.role_id = r.id
|
||||
INNER JOIN sys_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name = '销售概览' OR m.parent_id = (SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1)
|
||||
ORDER BY r.id, m.type, m.sort;
|
||||
```
|
||||
|
||||
如果查询结果中有您的角色,说明权限已分配成功。
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
-- 扩展耳标与项圈日志表的经纬度字段长度,避免坐标精度过高导致超长
|
||||
USE cattletrade;
|
||||
|
||||
-- jbq_client_log(智能耳标日志表)
|
||||
ALTER TABLE jbq_client_log
|
||||
MODIFY COLUMN latitude VARCHAR(32) COMMENT '纬度',
|
||||
MODIFY COLUMN longitude VARCHAR(32) COMMENT '经度';
|
||||
|
||||
-- xq_client_log(项圈日志表)
|
||||
ALTER TABLE xq_client_log
|
||||
MODIFY COLUMN latitude VARCHAR(32) COMMENT '纬度',
|
||||
MODIFY COLUMN longitude VARCHAR(32) COMMENT '经度';
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
-- 为 delivery 表添加 estimated_departure_time 字段(预计出发时间)
|
||||
-- 此脚本已手动执行,保留作为参考文档
|
||||
|
||||
USE cattletrade;
|
||||
|
||||
-- 添加预计出发时间字段(如果字段已存在,此语句会报错,可以忽略)
|
||||
-- ALTER TABLE delivery
|
||||
-- ADD COLUMN estimated_departure_time DATETIME COMMENT '预计出发时间'
|
||||
-- AFTER estimated_delivery_time;
|
||||
|
||||
-- 为现有记录设置默认值(使用创建时间作为默认的预计出发时间)
|
||||
-- 如果字段中已有部分数据,可以执行此更新语句为 NULL 值设置默认值
|
||||
UPDATE delivery
|
||||
SET estimated_departure_time = create_time
|
||||
WHERE estimated_departure_time IS NULL;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 为运送清单表新增百度鹰眼同步字段
|
||||
ALTER TABLE `delivery`
|
||||
ADD COLUMN `yingyan_entity_name` VARCHAR(64) NULL DEFAULT NULL COMMENT '百度鹰眼终端名称';
|
||||
|
||||
ALTER TABLE `delivery`
|
||||
ADD COLUMN `yingyan_last_sync_time` DATETIME NULL DEFAULT NULL COMMENT '百度鹰眼最后同步时间';
|
||||
|
||||
ALTER TABLE `delivery`
|
||||
ADD COLUMN `arrival_time` DATETIME NULL DEFAULT NULL COMMENT '自动判定的到达时间';
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 修改 delivery 表的 order_id 字段类型为 VARCHAR,用于存储多个订单ID(逗号分隔)
|
||||
-- 将原来的 INTEGER 类型改为 VARCHAR(500),支持存储多个订单ID,如 "1,2,3"
|
||||
|
||||
-- 注意:如果表中已有数据,需要先将现有的 order_id 值转换为字符串格式
|
||||
-- 例如:如果 order_id = 123,转换后仍为 "123"
|
||||
|
||||
ALTER TABLE `delivery`
|
||||
MODIFY COLUMN `order_id` VARCHAR(500) NULL DEFAULT NULL COMMENT '订单ID(多个订单ID用逗号分隔,如:1,2,3)';
|
||||
|
||||
-- 如果表中已有数据,将现有的整数 order_id 转换为字符串格式
|
||||
-- UPDATE delivery SET order_id = CAST(order_id AS CHAR) WHERE order_id IS NOT NULL;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
-- 修复 vehicle 表 record_code 字段长度问题
|
||||
-- 将 record_code 字段从当前长度扩展为 VARCHAR(1000) 以支持较长的图片URL
|
||||
-- 同时扩展其他图片URL字段以确保一致性
|
||||
|
||||
-- 修改 record_code 字段
|
||||
ALTER TABLE vehicle MODIFY COLUMN record_code VARCHAR(1000) COMMENT '牧运通备案码(图片URL)';
|
||||
|
||||
-- 修改其他图片URL字段(如果需要,建议也一起修改)
|
||||
ALTER TABLE vehicle MODIFY COLUMN car_front_photo VARCHAR(1000) COMMENT '车头照片URL';
|
||||
ALTER TABLE vehicle MODIFY COLUMN car_rear_photo VARCHAR(1000) COMMENT '车尾照片URL';
|
||||
ALTER TABLE vehicle MODIFY COLUMN driving_license_photo VARCHAR(1000) COMMENT '行驶证照片URL';
|
||||
|
||||
-- 如果您的数据库不支持修改字段长度,或者需要更大的容量,可以使用 TEXT 类型:
|
||||
-- ALTER TABLE vehicle MODIFY COLUMN record_code TEXT COMMENT '牧运通备案码(图片URL)';
|
||||
-- ALTER TABLE vehicle MODIFY COLUMN car_front_photo TEXT COMMENT '车头照片URL';
|
||||
-- ALTER TABLE vehicle MODIFY COLUMN car_rear_photo TEXT COMMENT '车尾照片URL';
|
||||
-- ALTER TABLE vehicle MODIFY COLUMN driving_license_photo TEXT COMMENT '行驶证照片URL';
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 为 warning_log 表添加索引以优化预警列表查询性能
|
||||
-- 优化目标:getPageWarningLog 查询中的派生表查询和 JOIN 操作
|
||||
--
|
||||
-- 执行说明:
|
||||
-- 1. 先执行检查脚本查看现有索引:SHOW INDEX FROM warning_log;
|
||||
-- 2. 如果索引已存在,会报错 "Duplicate key name",可以忽略该错误或注释掉对应语句
|
||||
-- 3. 建议按顺序执行,遇到已存在的索引错误时跳过即可
|
||||
|
||||
-- ============================================
|
||||
-- 第一步:检查现有索引(可选)
|
||||
-- ============================================
|
||||
-- 执行以下命令查看 warning_log 表的所有索引:
|
||||
-- SHOW INDEX FROM warning_log;
|
||||
|
||||
-- ============================================
|
||||
-- 第二步:创建索引(所有索引已存在,已全部注释)
|
||||
-- ============================================
|
||||
-- ✅ 状态:所有需要的索引已经存在,无需再次创建
|
||||
-- 如需重新创建,请先删除现有索引:DROP INDEX idx_name ON warning_log;
|
||||
|
||||
-- 1. 添加 delivery_id 和 warning_type 的联合索引(用于派生表的 GROUP BY 查询)
|
||||
-- 这个索引可以大幅提升 "SELECT delivery_id, warning_type, MAX(id) FROM warning_log WHERE warning_type IN (...) GROUP BY delivery_id, warning_type" 的性能
|
||||
-- ✅ 索引已存在:idx_delivery_warning_type
|
||||
-- ALTER TABLE warning_log
|
||||
-- ADD INDEX idx_delivery_warning_type (delivery_id, warning_type, id);
|
||||
|
||||
-- 2. 添加 warning_time 索引(用于 ORDER BY 排序)
|
||||
-- ✅ 索引已存在:idx_warning_time
|
||||
-- ALTER TABLE warning_log
|
||||
-- ADD INDEX idx_warning_time (warning_time DESC);
|
||||
|
||||
-- 3. 如果 delivery_id 还没有单独索引,添加一个(用于 JOIN 操作)
|
||||
-- 注意:如果 delivery_id 已经是主键或唯一索引的一部分,可以跳过
|
||||
-- 检查现有索引:SHOW INDEX FROM warning_log;
|
||||
-- 如果 delivery_id 没有索引,执行下面的语句
|
||||
-- ALTER TABLE warning_log ADD INDEX idx_delivery_id (delivery_id);
|
||||
|
||||
-- ============================================
|
||||
-- 索引说明和性能优化效果
|
||||
-- ============================================
|
||||
--
|
||||
-- 已存在的索引:
|
||||
-- 1. idx_delivery_warning_type: 覆盖索引,支持 WHERE warning_type IN (...) GROUP BY delivery_id, warning_type 的查询
|
||||
-- 2. idx_warning_time: 支持 ORDER BY warning_time DESC 的排序操作
|
||||
--
|
||||
-- 性能提升效果:
|
||||
-- ✅ 派生表查询从全表扫描优化为索引扫描
|
||||
-- ✅ GROUP BY 操作可以使用索引,避免临时表排序
|
||||
-- ✅ ORDER BY 可以使用索引,避免文件排序
|
||||
--
|
||||
-- ============================================
|
||||
-- 验证索引是否生效
|
||||
-- ============================================
|
||||
-- 执行以下 SQL 验证索引:
|
||||
-- SHOW INDEX FROM warning_log WHERE Key_name IN ('idx_delivery_warning_type', 'idx_warning_time');
|
||||
--
|
||||
-- 使用 EXPLAIN 分析查询性能:
|
||||
-- EXPLAIN SELECT ... (使用优化后的 getPageWarningLog SQL)
|
||||
--
|
||||
-- 注意:所有索引已创建完成,脚本保留作为文档参考
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 为角色分配销售概览菜单权限
|
||||
-- 注意:需要根据实际情况修改 role_id
|
||||
|
||||
-- 1. 查询销售概览菜单ID(包括主菜单和按钮权限)
|
||||
SET @salesoverview_menu_id = (SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1);
|
||||
SET @salesoverview_add_id = (SELECT id FROM sys_menu WHERE name = '新增' AND parent_id = @salesoverview_menu_id AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @salesoverview_edit_id = (SELECT id FROM sys_menu WHERE name = '编辑' AND parent_id = @salesoverview_menu_id AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @salesoverview_delete_id = (SELECT id FROM sys_menu WHERE name = '删除' AND parent_id = @salesoverview_menu_id AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @salesoverview_calculate_id = (SELECT id FROM sys_menu WHERE name = '计算统计数据' AND parent_id = @salesoverview_menu_id AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
|
||||
-- 显示查询到的菜单ID(用于调试)
|
||||
SELECT
|
||||
@salesoverview_menu_id AS '主菜单ID',
|
||||
@salesoverview_add_id AS '新增按钮ID',
|
||||
@salesoverview_edit_id AS '编辑按钮ID',
|
||||
@salesoverview_delete_id AS '删除按钮ID',
|
||||
@salesoverview_calculate_id AS '计算按钮ID';
|
||||
|
||||
-- 2. 查询所有角色ID(用于批量分配)
|
||||
-- SELECT id, name FROM sys_role WHERE is_delete = 0;
|
||||
|
||||
-- 3. 为指定角色分配销售概览菜单权限
|
||||
-- 方式1:为单个角色分配(需要替换 @role_id 为实际角色ID)
|
||||
-- SET @role_id = 1; -- 替换为实际角色ID,例如:超级管理员角色ID
|
||||
|
||||
-- 删除该角色原有的销售概览权限(如果存在)
|
||||
-- DELETE FROM sys_role_menu
|
||||
-- WHERE role_id = @role_id
|
||||
-- AND menu_id IN (@salesoverview_menu_id, @salesoverview_add_id, @salesoverview_edit_id, @salesoverview_delete_id, @salesoverview_calculate_id);
|
||||
|
||||
-- 插入新的权限
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- VALUES
|
||||
-- (@role_id, @salesoverview_menu_id),
|
||||
-- (@role_id, @salesoverview_add_id),
|
||||
-- (@role_id, @salesoverview_edit_id),
|
||||
-- (@role_id, @salesoverview_delete_id),
|
||||
-- (@role_id, @salesoverview_calculate_id)
|
||||
-- ON DUPLICATE KEY UPDATE role_id = role_id; -- 如果已存在则忽略
|
||||
|
||||
-- 方式2:为所有角色分配销售概览菜单权限(谨慎使用)
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- SELECT r.id, @salesoverview_menu_id
|
||||
-- FROM sys_role r
|
||||
-- WHERE r.is_delete = 0
|
||||
-- AND NOT EXISTS (
|
||||
-- SELECT 1 FROM sys_role_menu rm
|
||||
-- WHERE rm.role_id = r.id AND rm.menu_id = @salesoverview_menu_id
|
||||
-- );
|
||||
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- SELECT r.id, @salesoverview_add_id
|
||||
-- FROM sys_role r
|
||||
-- WHERE r.is_delete = 0
|
||||
-- AND NOT EXISTS (
|
||||
-- SELECT 1 FROM sys_role_menu rm
|
||||
-- WHERE rm.role_id = r.id AND rm.menu_id = @salesoverview_add_id
|
||||
-- );
|
||||
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- SELECT r.id, @salesoverview_edit_id
|
||||
-- FROM sys_role r
|
||||
-- WHERE r.is_delete = 0
|
||||
-- AND NOT EXISTS (
|
||||
-- SELECT 1 FROM sys_role_menu rm
|
||||
-- WHERE rm.role_id = r.id AND rm.menu_id = @salesoverview_edit_id
|
||||
-- );
|
||||
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- SELECT r.id, @salesoverview_delete_id
|
||||
-- FROM sys_role r
|
||||
-- WHERE r.is_delete = 0
|
||||
-- AND NOT EXISTS (
|
||||
-- SELECT 1 FROM sys_role_menu rm
|
||||
-- WHERE rm.role_id = r.id AND rm.menu_id = @salesoverview_delete_id
|
||||
-- );
|
||||
|
||||
-- INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
-- SELECT r.id, @salesoverview_calculate_id
|
||||
-- FROM sys_role r
|
||||
-- WHERE r.is_delete = 0
|
||||
-- AND NOT EXISTS (
|
||||
-- SELECT 1 FROM sys_role_menu rm
|
||||
-- WHERE rm.role_id = r.id AND rm.menu_id = @salesoverview_calculate_id
|
||||
-- );
|
||||
|
||||
-- 方式3:为超级管理员角色分配(推荐使用)
|
||||
-- 假设超级管理员角色ID为1(需要根据实际情况调整)
|
||||
-- 如果角色ID不是1,请先查询:SELECT id, name FROM sys_role WHERE name LIKE '%管理员%' OR name LIKE '%admin%';
|
||||
|
||||
-- 为角色ID=1分配销售概览菜单权限(请根据实际情况修改角色ID)
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @salesoverview_menu_id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 1 AND rm.menu_id = @salesoverview_menu_id
|
||||
)
|
||||
AND @salesoverview_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @salesoverview_add_id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 1 AND rm.menu_id = @salesoverview_add_id
|
||||
)
|
||||
AND @salesoverview_add_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @salesoverview_edit_id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 1 AND rm.menu_id = @salesoverview_edit_id
|
||||
)
|
||||
AND @salesoverview_edit_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @salesoverview_delete_id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 1 AND rm.menu_id = @salesoverview_delete_id
|
||||
)
|
||||
AND @salesoverview_delete_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @salesoverview_calculate_id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 1 AND rm.menu_id = @salesoverview_calculate_id
|
||||
)
|
||||
AND @salesoverview_calculate_id IS NOT NULL;
|
||||
|
||||
-- 4. 验证权限分配结果
|
||||
SELECT
|
||||
rm.role_id,
|
||||
r.name AS role_name,
|
||||
rm.menu_id,
|
||||
m.name AS menu_name,
|
||||
m.type AS menu_type
|
||||
FROM sys_role_menu rm
|
||||
INNER JOIN sys_role r ON rm.role_id = r.id
|
||||
INNER JOIN sys_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name = '销售概览' OR m.parent_id = (SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1)
|
||||
ORDER BY rm.role_id, m.type, m.sort;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 检查销售概览菜单是否已插入
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
type,
|
||||
icon,
|
||||
name,
|
||||
sort,
|
||||
route_url,
|
||||
page_url,
|
||||
org_type,
|
||||
authority,
|
||||
is_delete,
|
||||
create_time
|
||||
FROM sys_menu
|
||||
WHERE name = '销售概览'
|
||||
ORDER BY type, sort;
|
||||
|
||||
-- 检查是否有重复的销售概览菜单
|
||||
SELECT COUNT(*) as count, name, type
|
||||
FROM sys_menu
|
||||
WHERE name = '销售概览' AND is_delete = 0
|
||||
GROUP BY name, type;
|
||||
|
||||
-- 查询所有顶级菜单(parent_id = 0)用于参考
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
icon,
|
||||
sort,
|
||||
page_url,
|
||||
org_type,
|
||||
authority
|
||||
FROM sys_menu
|
||||
WHERE parent_id = 0 AND is_delete = 0
|
||||
ORDER BY sort;
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 检查 sys_menu 表的字段长度
|
||||
-- 用于诊断字段值被截断的问题
|
||||
|
||||
-- ============================================
|
||||
-- 1. 检查 page_url 和 authority 字段的定义
|
||||
-- ============================================
|
||||
-- 执行以下查询查看字段定义:
|
||||
SHOW COLUMNS FROM sys_menu WHERE Field IN ('page_url', 'authority');
|
||||
|
||||
-- 或者使用以下查询:
|
||||
SELECT
|
||||
COLUMN_NAME,
|
||||
DATA_TYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH,
|
||||
COLUMN_COMMENT
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'cattletrade'
|
||||
AND TABLE_NAME = 'sys_menu'
|
||||
AND COLUMN_NAME IN ('page_url', 'authority');
|
||||
|
||||
-- ============================================
|
||||
-- 2. 检查当前菜单数据的字段长度
|
||||
-- ============================================
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
type,
|
||||
name,
|
||||
route_url,
|
||||
page_url,
|
||||
LENGTH(page_url) as page_url_length,
|
||||
authority,
|
||||
LENGTH(authority) as authority_length
|
||||
FROM sys_menu
|
||||
WHERE (id = 82 OR parent_id = 82)
|
||||
AND is_delete = 0
|
||||
ORDER BY id, sort;
|
||||
|
||||
-- ============================================
|
||||
-- 3. 检查是否有被截断的字段值
|
||||
-- ============================================
|
||||
-- 检查进仓管理菜单
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
LENGTH(page_url) as page_url_length,
|
||||
'warehouse/warehouseIn' as expected_value,
|
||||
LENGTH('warehouse/warehouseIn') as expected_length
|
||||
FROM sys_menu
|
||||
WHERE id = 88
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 检查出仓管理菜单
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
LENGTH(page_url) as page_url_length,
|
||||
authority,
|
||||
LENGTH(authority) as authority_length,
|
||||
'warehouse/warehouseOut' as expected_page_url,
|
||||
LENGTH('warehouse/warehouseOut') as expected_page_url_length,
|
||||
'warehouseout:list' as expected_authority,
|
||||
LENGTH('warehouseout:list') as expected_authority_length
|
||||
FROM sys_menu
|
||||
WHERE id = 93
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 4. 如果需要扩展字段长度,执行以下语句(取消注释)
|
||||
-- ============================================
|
||||
-- 注意:执行前请先备份数据库!
|
||||
|
||||
-- 扩展 page_url 字段长度到 255
|
||||
-- ALTER TABLE sys_menu MODIFY COLUMN page_url VARCHAR(255) COMMENT '前端路由地址';
|
||||
|
||||
-- 扩展 authority 字段长度到 100
|
||||
-- ALTER TABLE sys_menu MODIFY COLUMN authority VARCHAR(100) COMMENT '权限字符串';
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 创建中转仓管理相关表
|
||||
-- 1. 中转仓表(warehouse)
|
||||
-- 2. 进仓表(warehouse_in)
|
||||
-- 3. 出仓表(warehouse_out)
|
||||
|
||||
-- ============================================
|
||||
-- 1. 中转仓表(warehouse)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS `warehouse` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`warehouse_name` VARCHAR(100) NOT NULL COMMENT '中转仓名称',
|
||||
`warehouse_code` VARCHAR(50) NOT NULL COMMENT '中转仓编码',
|
||||
`address` VARCHAR(255) NOT NULL COMMENT '地址',
|
||||
`longitude` VARCHAR(50) DEFAULT NULL COMMENT '经度',
|
||||
`latitude` VARCHAR(50) DEFAULT NULL COMMENT '纬度',
|
||||
`capacity` INT(11) NOT NULL COMMENT '容量(可存储牛只数量)',
|
||||
`manager_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名',
|
||||
`manager_mobile` VARCHAR(20) DEFAULT NULL COMMENT '负责人联系电话',
|
||||
`status` TINYINT(1) DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
|
||||
`remark` TEXT COMMENT '备注',
|
||||
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||
`created_by` INT(11) DEFAULT NULL COMMENT '创建人ID',
|
||||
`updated_by` INT(11) DEFAULT NULL COMMENT '更新人ID',
|
||||
`is_delete` TINYINT(1) DEFAULT 0 COMMENT '逻辑删除:0-未删除,1-已删除',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_warehouse_code` (`warehouse_code`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_is_delete` (`is_delete`),
|
||||
KEY `idx_warehouse_name` (`warehouse_name`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_status_is_delete` (`status`, `is_delete`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='中转仓表';
|
||||
|
||||
-- ============================================
|
||||
-- 2. 进仓表(warehouse_in)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS `warehouse_in` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`in_number` VARCHAR(50) NOT NULL COMMENT '进仓单号',
|
||||
`warehouse_id` INT(11) NOT NULL COMMENT '中转仓ID',
|
||||
`order_id` VARCHAR(100) DEFAULT NULL COMMENT '订单ID(多个订单用逗号分隔)',
|
||||
`delivery_id` INT(11) DEFAULT NULL COMMENT '运送清单ID',
|
||||
`source_location` VARCHAR(255) DEFAULT NULL COMMENT '来源地',
|
||||
`source_lon` VARCHAR(50) DEFAULT NULL COMMENT '来源地经度',
|
||||
`source_lat` VARCHAR(50) DEFAULT NULL COMMENT '来源地纬度',
|
||||
`cattle_count` INT(11) NOT NULL COMMENT '牛只数量',
|
||||
`weight` DECIMAL(10,2) DEFAULT NULL COMMENT '重量(公斤)',
|
||||
`in_time` DATETIME NOT NULL COMMENT '进仓时间',
|
||||
`photos` TEXT COMMENT '照片URL(多个用逗号分隔)',
|
||||
`videos` TEXT COMMENT '视频URL(多个用逗号分隔)',
|
||||
`remark` TEXT COMMENT '备注',
|
||||
`status` TINYINT(1) DEFAULT 1 COMMENT '状态:1-待进仓,2-已进仓,3-已出仓',
|
||||
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||
`created_by` INT(11) DEFAULT NULL COMMENT '创建人ID',
|
||||
`updated_by` INT(11) DEFAULT NULL COMMENT '更新人ID',
|
||||
`is_delete` TINYINT(1) DEFAULT 0 COMMENT '逻辑删除:0-未删除,1-已删除',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_in_number` (`in_number`),
|
||||
KEY `idx_warehouse_id` (`warehouse_id`),
|
||||
KEY `idx_delivery_id` (`delivery_id`),
|
||||
KEY `idx_in_time` (`in_time`),
|
||||
KEY `idx_is_delete` (`is_delete`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_warehouse_id_status` (`warehouse_id`, `status`),
|
||||
KEY `idx_is_delete_create_time` (`is_delete`, `create_time`),
|
||||
CONSTRAINT `fk_warehouse_in_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `warehouse` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='进仓表';
|
||||
|
||||
-- ============================================
|
||||
-- 3. 出仓表(warehouse_out)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS `warehouse_out` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`out_number` VARCHAR(50) NOT NULL COMMENT '出仓单号',
|
||||
`warehouse_id` INT(11) NOT NULL COMMENT '中转仓ID',
|
||||
`warehouse_in_id` INT(11) DEFAULT NULL COMMENT '进仓记录ID(可选)',
|
||||
`order_id` VARCHAR(100) DEFAULT NULL COMMENT '订单ID(多个订单用逗号分隔)',
|
||||
`delivery_id` INT(11) DEFAULT NULL COMMENT '运送清单ID',
|
||||
`destination_location` VARCHAR(255) DEFAULT NULL COMMENT '目的地',
|
||||
`destination_lon` VARCHAR(50) DEFAULT NULL COMMENT '目的地经度',
|
||||
`destination_lat` VARCHAR(50) DEFAULT NULL COMMENT '目的地纬度',
|
||||
`cattle_count` INT(11) NOT NULL COMMENT '牛只数量',
|
||||
`weight` DECIMAL(10,2) DEFAULT NULL COMMENT '重量(公斤)',
|
||||
`out_time` DATETIME NOT NULL COMMENT '出仓时间',
|
||||
`photos` TEXT COMMENT '照片URL(多个用逗号分隔)',
|
||||
`videos` TEXT COMMENT '视频URL(多个用逗号分隔)',
|
||||
`remark` TEXT COMMENT '备注',
|
||||
`status` TINYINT(1) DEFAULT 1 COMMENT '状态:1-待出仓,2-已出仓',
|
||||
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||
`created_by` INT(11) DEFAULT NULL COMMENT '创建人ID',
|
||||
`updated_by` INT(11) DEFAULT NULL COMMENT '更新人ID',
|
||||
`is_delete` TINYINT(1) DEFAULT 0 COMMENT '逻辑删除:0-未删除,1-已删除',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_out_number` (`out_number`),
|
||||
KEY `idx_warehouse_id` (`warehouse_id`),
|
||||
KEY `idx_warehouse_in_id` (`warehouse_in_id`),
|
||||
KEY `idx_delivery_id` (`delivery_id`),
|
||||
KEY `idx_out_time` (`out_time`),
|
||||
KEY `idx_is_delete` (`is_delete`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_warehouse_id_status` (`warehouse_id`, `status`),
|
||||
KEY `idx_is_delete_create_time` (`is_delete`, `create_time`),
|
||||
CONSTRAINT `fk_warehouse_out_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `warehouse` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT `fk_warehouse_out_warehouse_in` FOREIGN KEY (`warehouse_in_id`) REFERENCES `warehouse_in` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出仓表';
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 诊断和修复脚本:检查问题并强制修复
|
||||
-- ============================================
|
||||
|
||||
-- ============================================
|
||||
-- 步骤1:诊断当前状态
|
||||
-- ============================================
|
||||
SELECT
|
||||
'=== 当前状态 ===' as info,
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
HEX(page_url) as page_url_hex,
|
||||
authority,
|
||||
CHAR_LENGTH(authority) as authority_len,
|
||||
HEX(authority) as authority_hex
|
||||
FROM sys_menu
|
||||
WHERE id IN (88, 93);
|
||||
|
||||
-- ============================================
|
||||
-- 步骤2:检查是否有触发器
|
||||
-- ============================================
|
||||
SHOW TRIGGERS FROM cattletrade LIKE 'sys_menu';
|
||||
|
||||
-- ============================================
|
||||
-- 步骤3:检查字段定义和约束
|
||||
-- ============================================
|
||||
SHOW COLUMNS FROM sys_menu WHERE Field IN ('page_url', 'authority');
|
||||
|
||||
-- ============================================
|
||||
-- 步骤4:尝试强制更新(使用不同的方法)
|
||||
-- ============================================
|
||||
|
||||
-- 方法1:直接UPDATE,不检查任何条件
|
||||
UPDATE sys_menu
|
||||
SET page_url = 'warehouse/warehouseIn'
|
||||
WHERE id = 88;
|
||||
|
||||
-- 检查是否成功
|
||||
SELECT
|
||||
'=== 更新 id=88 后 ===' as info,
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len
|
||||
FROM sys_menu
|
||||
WHERE id = 88;
|
||||
|
||||
-- 方法2:更新 id=93
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list'
|
||||
WHERE id = 93;
|
||||
|
||||
-- 检查是否成功
|
||||
SELECT
|
||||
'=== 更新 id=93 后 ===' as info,
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
authority,
|
||||
CHAR_LENGTH(authority) as authority_len
|
||||
FROM sys_menu
|
||||
WHERE id = 93;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤5:如果上述方法失败,尝试使用 REPLACE
|
||||
-- ============================================
|
||||
-- 注意:REPLACE 会删除并重新插入,需要所有字段值
|
||||
|
||||
-- 先查询完整记录
|
||||
SELECT * FROM sys_menu WHERE id = 88;
|
||||
SELECT * FROM sys_menu WHERE id = 93;
|
||||
|
||||
-- 如果 UPDATE 失败,可以使用以下方法(需要根据实际字段值调整):
|
||||
-- REPLACE INTO sys_menu (id, parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
-- SELECT id, parent_id, type, icon, name, sort, route_url, 'warehouse/warehouseIn', org_type, authority, create_time, NOW(), is_delete
|
||||
-- FROM sys_menu WHERE id = 88;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤6:最终验证
|
||||
-- ============================================
|
||||
SELECT
|
||||
'=== 最终验证 ===' as info,
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
CASE
|
||||
WHEN page_url = 'warehouse/warehouseIn' THEN '✓ 正确'
|
||||
ELSE '✗ 错误'
|
||||
END as page_url_status,
|
||||
authority,
|
||||
CHAR_LENGTH(authority) as authority_len,
|
||||
CASE
|
||||
WHEN authority = 'warehouseout:list' THEN '✓ 正确'
|
||||
ELSE '✗ 错误'
|
||||
END as authority_status
|
||||
FROM sys_menu
|
||||
WHERE id IN (88, 93);
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 一键修复:确保销售概览菜单在侧边栏显示
|
||||
-- 该脚本会:
|
||||
-- 1. 检查菜单是否存在,不存在则插入
|
||||
-- 2. 为超级管理员角色(role_id=1)分配菜单权限
|
||||
-- 3. 将菜单的org_type设置为3(海关企业共用),确保所有用户都能看到
|
||||
|
||||
-- ========== 步骤1:确保菜单已插入 ==========
|
||||
-- 如果菜单不存在,则插入
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
0 AS parent_id,
|
||||
1 AS type,
|
||||
'el-icon-data-line' AS icon,
|
||||
'销售概览' AS name,
|
||||
50 AS sort,
|
||||
NULL AS route_url,
|
||||
'/salesOverview/list' AS page_url,
|
||||
3 AS org_type, -- 设置为3(海关企业共用),确保所有用户都能看到
|
||||
'salesoverview:list' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0
|
||||
);
|
||||
|
||||
-- 获取销售概览菜单ID
|
||||
SET @salesoverview_menu_id = (SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1);
|
||||
|
||||
-- 更新菜单的org_type为3(如果已存在)
|
||||
UPDATE sys_menu
|
||||
SET org_type = 3, update_time = NOW()
|
||||
WHERE id = @salesoverview_menu_id AND org_type != 3;
|
||||
|
||||
-- ========== 步骤2:确保按钮权限已插入 ==========
|
||||
-- 插入新增按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@salesoverview_menu_id AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'新增' AS name,
|
||||
2 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
3 AS org_type,
|
||||
'salesoverview:add' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @salesoverview_menu_id AND name = '新增' AND type = 2 AND is_delete = 0
|
||||
)
|
||||
AND @salesoverview_menu_id IS NOT NULL;
|
||||
|
||||
-- 插入编辑按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@salesoverview_menu_id AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'编辑' AS name,
|
||||
3 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
3 AS org_type,
|
||||
'salesoverview:edit' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @salesoverview_menu_id AND name = '编辑' AND type = 2 AND is_delete = 0
|
||||
)
|
||||
AND @salesoverview_menu_id IS NOT NULL;
|
||||
|
||||
-- 插入删除按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@salesoverview_menu_id AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'删除' AS name,
|
||||
4 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
3 AS org_type,
|
||||
'salesoverview:delete' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @salesoverview_menu_id AND name = '删除' AND type = 2 AND is_delete = 0
|
||||
)
|
||||
AND @salesoverview_menu_id IS NOT NULL;
|
||||
|
||||
-- 插入计算统计数据按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@salesoverview_menu_id AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'计算统计数据' AS name,
|
||||
5 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
3 AS org_type,
|
||||
'salesoverview:calculate' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @salesoverview_menu_id AND name = '计算统计数据' AND type = 2 AND is_delete = 0
|
||||
)
|
||||
AND @salesoverview_menu_id IS NOT NULL;
|
||||
|
||||
-- ========== 步骤3:为超级管理员角色分配权限 ==========
|
||||
-- 查询所有销售概览相关的菜单ID
|
||||
SET @menu_main = @salesoverview_menu_id;
|
||||
SET @menu_add = (SELECT id FROM sys_menu WHERE parent_id = @salesoverview_menu_id AND name = '新增' AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @menu_edit = (SELECT id FROM sys_menu WHERE parent_id = @salesoverview_menu_id AND name = '编辑' AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @menu_delete = (SELECT id FROM sys_menu WHERE parent_id = @salesoverview_menu_id AND name = '删除' AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
SET @menu_calculate = (SELECT id FROM sys_menu WHERE parent_id = @salesoverview_menu_id AND name = '计算统计数据' AND type = 2 AND is_delete = 0 LIMIT 1);
|
||||
|
||||
-- 为角色ID=1(超级管理员)分配主菜单权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_main
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_main)
|
||||
AND @menu_main IS NOT NULL;
|
||||
|
||||
-- 为角色ID=1分配新增权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_add
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_add)
|
||||
AND @menu_add IS NOT NULL;
|
||||
|
||||
-- 为角色ID=1分配编辑权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_edit
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_edit)
|
||||
AND @menu_edit IS NOT NULL;
|
||||
|
||||
-- 为角色ID=1分配删除权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_delete
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_delete)
|
||||
AND @menu_delete IS NOT NULL;
|
||||
|
||||
-- 为角色ID=1分配计算权限
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, @menu_calculate
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu WHERE role_id = 1 AND menu_id = @menu_calculate)
|
||||
AND @menu_calculate IS NOT NULL;
|
||||
|
||||
-- ========== 步骤4:验证结果 ==========
|
||||
-- 显示菜单信息
|
||||
SELECT
|
||||
'菜单信息' AS info_type,
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
parent_id,
|
||||
page_url,
|
||||
org_type,
|
||||
authority
|
||||
FROM sys_menu
|
||||
WHERE name = '销售概览' OR parent_id = @salesoverview_menu_id
|
||||
ORDER BY type, sort;
|
||||
|
||||
-- 显示权限分配情况
|
||||
SELECT
|
||||
'权限分配' AS info_type,
|
||||
rm.role_id,
|
||||
r.name AS role_name,
|
||||
rm.menu_id,
|
||||
m.name AS menu_name,
|
||||
m.type AS menu_type
|
||||
FROM sys_role_menu rm
|
||||
INNER JOIN sys_role r ON rm.role_id = r.id
|
||||
INNER JOIN sys_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name = '销售概览' OR m.parent_id = @salesoverview_menu_id
|
||||
ORDER BY rm.role_id, m.type, m.sort;
|
||||
|
||||
-- 提示信息
|
||||
SELECT
|
||||
'提示' AS info_type,
|
||||
CONCAT('销售概览菜单ID: ', @salesoverview_menu_id) AS message
|
||||
UNION ALL
|
||||
SELECT
|
||||
'提示' AS info_type,
|
||||
'请重新登录系统以刷新菜单' AS message;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 修复 salesoverview 表的 id 字段,设置为 AUTO_INCREMENT
|
||||
-- 如果表不存在,先创建表;如果表存在但 id 字段不是自增,则修改字段
|
||||
|
||||
-- 检查表是否存在
|
||||
-- 如果表不存在,创建表
|
||||
CREATE TABLE IF NOT EXISTS `salesoverview` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`toal_procurement_amount` DECIMAL(18,2) DEFAULT 0.00 COMMENT '采购总额(元)',
|
||||
`toal_sales_amount` DECIMAL(18,2) DEFAULT 0.00 COMMENT '销售总额(元)',
|
||||
`profits` DECIMAL(18,2) DEFAULT 0.00 COMMENT '利润(元)',
|
||||
`accounts_receivable` DECIMAL(18,2) DEFAULT 0.00 COMMENT '应收货款(元)',
|
||||
`uncollected_payment` DECIMAL(18,2) DEFAULT 0.00 COMMENT '未收货款(元)',
|
||||
`actual_payment` DECIMAL(18,2) DEFAULT 0.00 COMMENT '实收货款(元)',
|
||||
`total_purchase` INT(11) DEFAULT 0 COMMENT '采购数量(头)',
|
||||
`total_order` INT(11) DEFAULT 0 COMMENT '采购单数(车)',
|
||||
`total_sales` INT(11) DEFAULT 0 COMMENT '销售单数(单)',
|
||||
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||
`up_time` DATETIME DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售概览表';
|
||||
|
||||
-- 如果表已存在,修改 id 字段为 AUTO_INCREMENT
|
||||
-- 注意:如果表中已有数据,需要先备份
|
||||
ALTER TABLE `salesoverview`
|
||||
MODIFY COLUMN `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID';
|
||||
|
||||
-- 验证表结构
|
||||
SHOW CREATE TABLE `salesoverview`;
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 完整修复中转仓管理菜单数据
|
||||
-- 1. 检查并扩展字段长度(如果需要)
|
||||
-- 2. 修复被截断的字段值
|
||||
-- 3. 删除重复的菜单数据
|
||||
|
||||
-- ============================================
|
||||
-- 步骤0:检查并扩展字段长度(如果需要)
|
||||
-- ============================================
|
||||
-- 如果 page_url 或 authority 字段长度不足,先扩展字段长度
|
||||
-- 注意:执行前请先检查当前字段长度,如果已经足够则不需要执行
|
||||
|
||||
-- 扩展 page_url 字段长度(如果需要)
|
||||
-- ALTER TABLE sys_menu MODIFY COLUMN page_url VARCHAR(255) COMMENT '前端路由地址';
|
||||
|
||||
-- 扩展 authority 字段长度(如果需要)
|
||||
-- ALTER TABLE sys_menu MODIFY COLUMN authority VARCHAR(100) COMMENT '权限字符串';
|
||||
|
||||
-- ============================================
|
||||
-- 步骤1:删除重复的菜单数据
|
||||
-- ============================================
|
||||
-- 删除 id=98 的子菜单的按钮权限(如果存在)
|
||||
DELETE FROM sys_menu
|
||||
WHERE parent_id IN (99, 104, 109)
|
||||
AND type = 2
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的子菜单(二级菜单)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id IN (99, 104, 109)
|
||||
AND parent_id = 98
|
||||
AND type = 1
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的父菜单(如果存在)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id = 98
|
||||
AND name = '中转仓管理'
|
||||
AND parent_id = 0
|
||||
AND (type = 0 OR type IS NULL)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤2:修复被截断的字段值(直接通过ID修复)
|
||||
-- ============================================
|
||||
|
||||
-- 修复进仓管理菜单(id=88)的 page_url
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE id = 88
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复出仓管理菜单(id=93)的 page_url 和 authority
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE id = 93
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤3:确保所有字段值正确(通过名称修复,作为后备)
|
||||
-- ============================================
|
||||
|
||||
-- 修复进仓管理菜单的 page_url(通过名称匹配)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE name = '进仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND page_url != 'warehouse/warehouseIn'
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复出仓管理菜单的 page_url 和 authority(通过名称匹配)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE name = '出仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url != 'warehouse/warehouseOut' OR authority != 'warehouseout:list')
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤4:确保父菜单的 type 字段正确
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
type = 0,
|
||||
update_time = NOW()
|
||||
WHERE id = 82
|
||||
AND (type IS NULL OR type != 0)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤5:验证修复结果
|
||||
-- ============================================
|
||||
-- 执行以下查询验证数据是否正确:
|
||||
-- SELECT id, parent_id, type, name, route_url, page_url, authority, LENGTH(page_url) as page_url_len, LENGTH(authority) as authority_len
|
||||
-- FROM sys_menu
|
||||
-- WHERE (id = 82 OR parent_id = 82)
|
||||
-- AND is_delete = 0
|
||||
-- ORDER BY id, sort;
|
||||
--
|
||||
-- 预期结果:
|
||||
-- id=82: type = 0, page_url = NULL, authority = NULL
|
||||
-- id=83: route_url = 'list', page_url = 'warehouse/warehouse', authority = 'warehouse:list'
|
||||
-- id=88: route_url = 'in', page_url = 'warehouse/warehouseIn', authority = 'warehousein:list'
|
||||
-- id=93: route_url = 'out', page_url = 'warehouse/warehouseOut', authority = 'warehouseout:list'
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 修复中转仓管理菜单的组件路径
|
||||
-- 该脚本用于修复已存在的菜单记录,确保组件路径正确
|
||||
|
||||
-- ============================================
|
||||
-- 1. 修复中转仓管理菜单(list)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
route_url = 'list',
|
||||
page_url = 'warehouse/warehouse',
|
||||
update_time = NOW()
|
||||
WHERE name = '中转仓管理'
|
||||
AND parent_id IN (SELECT id FROM (SELECT id FROM sys_menu WHERE name = '中转仓管理' AND type = 0 AND is_delete = 0) AS temp)
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
AND page_url != 'warehouse/warehouse';
|
||||
|
||||
-- ============================================
|
||||
-- 2. 修复进仓管理菜单(in)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
route_url = 'in',
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE name = '进仓管理'
|
||||
AND parent_id IN (SELECT id FROM (SELECT id FROM sys_menu WHERE name = '中转仓管理' AND type = 0 AND is_delete = 0) AS temp)
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
AND page_url != 'warehouse/warehouseIn';
|
||||
|
||||
-- ============================================
|
||||
-- 3. 修复出仓管理菜单(out)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
route_url = 'out',
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
update_time = NOW()
|
||||
WHERE name = '出仓管理'
|
||||
AND parent_id IN (SELECT id FROM (SELECT id FROM sys_menu WHERE name = '中转仓管理' AND type = 0 AND is_delete = 0) AS temp)
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
AND page_url != 'warehouse/warehouseOut';
|
||||
|
||||
-- ============================================
|
||||
-- 4. 修复运输管理菜单中的shippingList(如果存在)
|
||||
-- ============================================
|
||||
-- 注意:如果数据库中存在 shipping/shippinglist 的菜单,需要手动修复
|
||||
-- 实际文件是 shipping/shippingList.vue(注意大小写)
|
||||
-- 修复所有可能的变体:shipping/shippinglist, shipping/ShippingList, shipping/SHIPPINGLIST 等
|
||||
-- 使用 LOWER() 函数进行大小写不敏感匹配
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'shipping/shippingList',
|
||||
update_time = NOW()
|
||||
WHERE LOWER(page_url) = 'shipping/shippinglist'
|
||||
AND page_url != 'shipping/shippingList'
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复其他可能的变体(包含路径的情况,包括带前导斜杠的情况)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'shipping/shippingList',
|
||||
update_time = NOW()
|
||||
WHERE (LOWER(page_url) LIKE '%shipping/shippinglist%'
|
||||
OR LOWER(page_url) LIKE '%/shipping/shippinglist%'
|
||||
OR page_url LIKE '%shipping/ShippingList%'
|
||||
OR page_url LIKE '%shipping/SHIPPINGLIST%')
|
||||
AND page_url != 'shipping/shippingList'
|
||||
AND page_url != '/shipping/shippingList'
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复带前导斜杠的情况(如 /shipping/shippinglist -> shipping/shippingList)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'shipping/shippingList',
|
||||
update_time = NOW()
|
||||
WHERE LOWER(page_url) = '/shipping/shippinglist'
|
||||
AND is_delete = 0;
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 修复中转仓管理菜单数据
|
||||
-- 1. 删除重复的菜单数据(保留较早创建的,删除较晚创建的)
|
||||
-- 2. 修复被截断的字段值
|
||||
|
||||
-- ============================================
|
||||
-- 步骤1:删除重复的菜单数据
|
||||
-- 保留 id=82 的父菜单及其子菜单,删除 id=98 的父菜单及其子菜单
|
||||
-- ============================================
|
||||
|
||||
-- 删除 id=98 的子菜单的按钮权限(如果存在)
|
||||
-- 先删除所有以 id=99, 104, 109 为父菜单的按钮权限
|
||||
DELETE FROM sys_menu
|
||||
WHERE parent_id IN (99, 104, 109)
|
||||
AND type = 2
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的子菜单(二级菜单)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id IN (99, 104, 109)
|
||||
AND parent_id = 98
|
||||
AND type = 1
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的父菜单(如果存在)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id = 98
|
||||
AND name = '中转仓管理'
|
||||
AND parent_id = 0
|
||||
AND (type = 0 OR type IS NULL)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤2:修复被截断的字段值
|
||||
-- ============================================
|
||||
|
||||
-- 修复进仓管理菜单的 page_url(修复所有被截断的情况)
|
||||
-- 包括:warehouse/warehouselr, warehouse/warehouselr* 等
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE name = '进仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url LIKE 'warehouse/warehouselr%'
|
||||
OR page_url = 'warehouse/warehouselr'
|
||||
OR page_url LIKE 'warehouse/warehouseIn%' AND page_url != 'warehouse/warehouseIn'
|
||||
OR page_url IS NULL
|
||||
OR LENGTH(page_url) < 20) -- 如果长度小于20,可能是被截断了
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复出仓管理菜单的 page_url 和 authority(修复所有被截断的情况)
|
||||
-- 包括:warehouse/warehouseO, warehouse/warehouseO* 等
|
||||
-- 以及:warehouseout:li, warehouseout:li* 等
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE name = '出仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url LIKE 'warehouse/warehouseO%' AND page_url != 'warehouse/warehouseOut'
|
||||
OR page_url = 'warehouse/warehouseO'
|
||||
OR page_url LIKE 'warehouse/warehouseOut%' AND page_url != 'warehouse/warehouseOut'
|
||||
OR page_url IS NULL
|
||||
OR LENGTH(page_url) < 20 -- 如果长度小于20,可能是被截断了
|
||||
OR authority LIKE 'warehouseout:li%' AND authority != 'warehouseout:list'
|
||||
OR authority = 'warehouseout:li'
|
||||
OR authority IS NULL
|
||||
OR LENGTH(authority) < 15) -- 如果长度小于15,可能是被截断了
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤3:确保父菜单的 type 字段正确(应该是 0)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
type = 0,
|
||||
update_time = NOW()
|
||||
WHERE id = 82
|
||||
AND (type IS NULL OR type != 0)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤4:验证修复结果
|
||||
-- ============================================
|
||||
-- 执行以下查询验证数据是否正确:
|
||||
-- SELECT id, parent_id, type, name, route_url, page_url, authority
|
||||
-- FROM sys_menu
|
||||
-- WHERE (id = 82 OR parent_id = 82)
|
||||
-- AND is_delete = 0
|
||||
-- ORDER BY id, sort;
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 直接修复脚本:强制更新被截断的字段值
|
||||
-- 使用最直接的方式,确保更新成功
|
||||
|
||||
-- ============================================
|
||||
-- 步骤1:先查看当前值(用于确认)
|
||||
-- ============================================
|
||||
-- SELECT id, name, page_url, authority FROM sys_menu WHERE id IN (88, 93) AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤2:修复进仓管理菜单(id=88)
|
||||
-- ============================================
|
||||
-- 当前错误值:warehouse/warehouselr
|
||||
-- 目标正确值:warehouse/warehouseIn
|
||||
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE id = 88;
|
||||
|
||||
-- 验证更新是否成功
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
'warehouse/warehouseIn' as expected,
|
||||
CHAR_LENGTH('warehouse/warehouseIn') as expected_len
|
||||
FROM sys_menu
|
||||
WHERE id = 88;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤3:修复出仓管理菜单(id=93)
|
||||
-- ============================================
|
||||
-- 当前错误值:page_url = warehouse/warehouseO, authority = warehouseout:li
|
||||
-- 目标正确值:page_url = warehouse/warehouseOut, authority = warehouseout:list
|
||||
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE id = 93;
|
||||
|
||||
-- 验证更新是否成功
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
authority,
|
||||
CHAR_LENGTH(authority) as authority_len,
|
||||
'warehouse/warehouseOut' as expected_page_url,
|
||||
CHAR_LENGTH('warehouse/warehouseOut') as expected_page_url_len,
|
||||
'warehouseout:list' as expected_authority,
|
||||
CHAR_LENGTH('warehouseout:list') as expected_authority_len
|
||||
FROM sys_menu
|
||||
WHERE id = 93;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤4:最终验证(执行后运行此查询)
|
||||
-- ============================================
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
type,
|
||||
name,
|
||||
route_url,
|
||||
page_url,
|
||||
CHAR_LENGTH(page_url) as page_url_len,
|
||||
authority,
|
||||
CHAR_LENGTH(authority) as authority_len
|
||||
FROM sys_menu
|
||||
WHERE id IN (88, 93)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 预期结果:
|
||||
-- id=88: page_url='warehouse/warehouseIn', page_url_len=20
|
||||
-- id=93: page_url='warehouse/warehouseOut', page_url_len=21, authority='warehouseout:list', authority_len=16
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 最终修复中转仓管理菜单数据
|
||||
-- 根据表结构:page_url VARCHAR(100), authority VARCHAR(50)
|
||||
-- 需要存储的值:
|
||||
-- warehouse/warehouseIn = 20 字符(在100以内,足够)
|
||||
-- warehouse/warehouseOut = 21 字符(在100以内,足够)
|
||||
-- warehouseout:list = 16 字符(在50以内,足够)
|
||||
--
|
||||
-- 字段长度足够,问题可能是插入时被截断,直接UPDATE修复即可
|
||||
|
||||
-- ============================================
|
||||
-- 步骤1:删除重复的菜单数据(如果存在)
|
||||
-- ============================================
|
||||
-- 删除 id=98 的子菜单的按钮权限(如果存在)
|
||||
DELETE FROM sys_menu
|
||||
WHERE parent_id IN (99, 104, 109)
|
||||
AND type = 2
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的子菜单(二级菜单)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id IN (99, 104, 109)
|
||||
AND parent_id = 98
|
||||
AND type = 1
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 删除 id=98 的父菜单(如果存在)
|
||||
DELETE FROM sys_menu
|
||||
WHERE id = 98
|
||||
AND name = '中转仓管理'
|
||||
AND parent_id = 0
|
||||
AND (type = 0 OR type IS NULL)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤2:修复被截断的字段值(直接通过ID修复,最可靠)
|
||||
-- ============================================
|
||||
|
||||
-- 修复进仓管理菜单(id=88)的 page_url
|
||||
-- 修复:warehouse/warehouselr -> warehouse/warehouseIn
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE id = 88
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复出仓管理菜单(id=93)的 page_url 和 authority
|
||||
-- 修复:warehouse/warehouseO -> warehouse/warehouseOut
|
||||
-- 修复:warehouseout:li -> warehouseout:list
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE id = 93
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤3:通过名称匹配修复(作为后备方案,确保所有记录都被修复)
|
||||
-- ============================================
|
||||
|
||||
-- 修复进仓管理菜单的 page_url(通过名称匹配)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE name = '进仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND page_url != 'warehouse/warehouseIn'
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 修复出仓管理菜单的 page_url 和 authority(通过名称匹配)
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE name = '出仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url != 'warehouse/warehouseOut' OR authority != 'warehouseout:list')
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤4:确保父菜单的 type 字段正确(应该是 0)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
type = 0,
|
||||
update_time = NOW()
|
||||
WHERE id = 82
|
||||
AND (type IS NULL OR type != 0)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 步骤5:验证修复结果
|
||||
-- ============================================
|
||||
-- 执行以下查询验证数据是否正确:
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
type,
|
||||
name,
|
||||
route_url,
|
||||
page_url,
|
||||
LENGTH(page_url) as page_url_len,
|
||||
authority,
|
||||
LENGTH(authority) as authority_len
|
||||
FROM sys_menu
|
||||
WHERE (id = 82 OR parent_id = 82)
|
||||
AND is_delete = 0
|
||||
ORDER BY id, sort;
|
||||
|
||||
-- 预期结果:
|
||||
-- id=82: type=0, page_url=NULL, authority=NULL
|
||||
-- id=83: route_url='list', page_url='warehouse/warehouse', authority='warehouse:list'
|
||||
-- id=88: route_url='in', page_url='warehouse/warehouseIn' (长度=20), authority='warehousein:list'
|
||||
-- id=93: route_url='out', page_url='warehouse/warehouseOut' (长度=21), authority='warehouseout:list' (长度=16)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 简单直接的修复脚本:修复被截断的字段值
|
||||
-- 直接通过ID更新,确保修复成功
|
||||
|
||||
-- ============================================
|
||||
-- 修复进仓管理菜单(id=88)的 page_url
|
||||
-- 当前值:warehouse/warehouselr (长度21)
|
||||
-- 目标值:warehouse/warehouseIn (长度20)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE id = 88
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 修复出仓管理菜单(id=93)的 page_url 和 authority
|
||||
-- 当前值:page_url = warehouse/warehouseO (长度22), authority = warehouseout:li (长度17)
|
||||
-- 目标值:page_url = warehouse/warehouseOut (长度21), authority = warehouseout:list (长度16)
|
||||
-- ============================================
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE id = 93
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 验证修复结果(执行后运行此查询)
|
||||
-- ============================================
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
type,
|
||||
name,
|
||||
route_url,
|
||||
page_url,
|
||||
LENGTH(page_url) as page_url_len,
|
||||
authority,
|
||||
LENGTH(authority) as authority_len
|
||||
FROM sys_menu
|
||||
WHERE id IN (88, 93)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 预期结果:
|
||||
-- id=88: page_url='warehouse/warehouseIn', page_url_len=20
|
||||
-- id=93: page_url='warehouse/warehouseOut', page_url_len=21, authority='warehouseout:list', authority_len=16
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 修复中转仓管理菜单中被截断的字段值
|
||||
-- 该脚本专门用于修复字段值被截断的问题
|
||||
|
||||
-- ============================================
|
||||
-- 修复进仓管理菜单(id=88)的 page_url
|
||||
-- ============================================
|
||||
-- 修复:warehouse/warehouselr -> warehouse/warehouseIn
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE id = 88
|
||||
AND name = '进仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND page_url != 'warehouse/warehouseIn'
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 如果上面的更新没有生效,尝试更宽泛的条件
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseIn',
|
||||
update_time = NOW()
|
||||
WHERE name = '进仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url LIKE 'warehouse/warehouselr%'
|
||||
OR page_url = 'warehouse/warehouselr'
|
||||
OR page_url LIKE 'warehouse/warehouseIn%' AND page_url != 'warehouse/warehouseIn'
|
||||
OR LENGTH(page_url) < 20)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 修复出仓管理菜单(id=93)的 page_url 和 authority
|
||||
-- ============================================
|
||||
-- 修复:warehouse/warehouseO -> warehouse/warehouseOut
|
||||
-- 修复:warehouseout:li -> warehouseout:list
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE id = 93
|
||||
AND name = '出仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url != 'warehouse/warehouseOut' OR authority != 'warehouseout:list')
|
||||
AND is_delete = 0;
|
||||
|
||||
-- 如果上面的更新没有生效,尝试更宽泛的条件
|
||||
UPDATE sys_menu
|
||||
SET
|
||||
page_url = 'warehouse/warehouseOut',
|
||||
authority = 'warehouseout:list',
|
||||
update_time = NOW()
|
||||
WHERE name = '出仓管理'
|
||||
AND type = 1
|
||||
AND parent_id = 82
|
||||
AND (page_url LIKE 'warehouse/warehouseO%' AND page_url != 'warehouse/warehouseOut'
|
||||
OR page_url = 'warehouse/warehouseO'
|
||||
OR page_url LIKE 'warehouse/warehouseOut%' AND page_url != 'warehouse/warehouseOut'
|
||||
OR LENGTH(page_url) < 20
|
||||
OR authority LIKE 'warehouseout:li%' AND authority != 'warehouseout:list'
|
||||
OR authority = 'warehouseout:li'
|
||||
OR LENGTH(authority) < 15)
|
||||
AND is_delete = 0;
|
||||
|
||||
-- ============================================
|
||||
-- 验证修复结果
|
||||
-- ============================================
|
||||
-- 执行以下查询验证数据是否正确:
|
||||
-- SELECT id, parent_id, type, name, route_url, page_url, authority
|
||||
-- FROM sys_menu
|
||||
-- WHERE (id = 82 OR parent_id = 82)
|
||||
-- AND is_delete = 0
|
||||
-- ORDER BY id, sort;
|
||||
--
|
||||
-- 预期结果:
|
||||
-- id=88: page_url = 'warehouse/warehouseIn'
|
||||
-- id=93: page_url = 'warehouse/warehouseOut', authority = 'warehouseout:list'
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 插入销售概览菜单
|
||||
-- 菜单类型:0-目录,1-菜单,2-按钮
|
||||
-- 排序:数字越小越靠前
|
||||
|
||||
-- 1. 插入销售概览主菜单(type=1,菜单)
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES (
|
||||
0, -- parent_id: 0表示顶级菜单
|
||||
1, -- type: 1-菜单
|
||||
'el-icon-data-line', -- icon: 数据统计图标
|
||||
'销售概览', -- name: 菜单名称
|
||||
50, -- sort: 排序(可以根据实际情况调整)
|
||||
NULL, -- route_url: 后端路由地址(菜单不需要)
|
||||
'/salesOverview/list', -- page_url: 前端路由地址
|
||||
2, -- org_type: 2-企业端(根据实际情况调整)
|
||||
'salesoverview:list', -- authority: 权限字符串
|
||||
NOW(), -- create_time
|
||||
NOW(), -- update_time
|
||||
0 -- is_delete: 0-未删除
|
||||
);
|
||||
|
||||
-- 2. 插入销售概览相关按钮权限(type=2,按钮)
|
||||
-- 使用子查询获取刚插入的菜单ID作为parent_id
|
||||
|
||||
-- 2.1 新增权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
(SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1) AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'新增' AS name,
|
||||
2 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
2 AS org_type,
|
||||
'salesoverview:add' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0);
|
||||
|
||||
-- 2.2 编辑权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
(SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1) AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'编辑' AS name,
|
||||
3 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
2 AS org_type,
|
||||
'salesoverview:edit' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0);
|
||||
|
||||
-- 2.3 删除权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
(SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1) AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'删除' AS name,
|
||||
4 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
2 AS org_type,
|
||||
'salesoverview:delete' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0);
|
||||
|
||||
-- 2.4 计算统计数据权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
(SELECT id FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0 LIMIT 1) AS parent_id,
|
||||
2 AS type,
|
||||
NULL AS icon,
|
||||
'计算统计数据' AS name,
|
||||
5 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
2 AS org_type,
|
||||
'salesoverview:calculate' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE name = '销售概览' AND type = 1 AND is_delete = 0);
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 插入中转仓管理菜单
|
||||
-- 菜单类型:0-目录,1-菜单,2-按钮
|
||||
-- 排序:数字越小越靠前
|
||||
|
||||
-- ============================================
|
||||
-- 1. 插入一级菜单:中转仓管理(type=0,目录)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES (
|
||||
0, -- parent_id: 0表示顶级菜单
|
||||
0, -- type: 0-目录
|
||||
'el-icon-office-building', -- icon: 仓库图标
|
||||
'中转仓管理', -- name: 菜单名称
|
||||
60, -- sort: 排序(可以根据实际情况调整)
|
||||
NULL, -- route_url: 后端路由地址(目录不需要)
|
||||
NULL, -- page_url: 前端路由地址(目录不需要)
|
||||
2, -- org_type: 2-企业端
|
||||
NULL, -- authority: 权限字符串(目录不需要)
|
||||
NOW(), -- create_time
|
||||
NOW(), -- update_time
|
||||
0 -- is_delete: 0-未删除
|
||||
);
|
||||
|
||||
-- 获取刚插入的一级菜单ID
|
||||
SET @warehouse_parent_id = LAST_INSERT_ID();
|
||||
|
||||
-- ============================================
|
||||
-- 2. 插入二级菜单:中转仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES (
|
||||
@warehouse_parent_id, -- parent_id: 一级菜单ID
|
||||
1, -- type: 1-菜单
|
||||
'el-icon-office-building', -- icon: 仓库图标
|
||||
'中转仓管理', -- name: 菜单名称
|
||||
1, -- sort: 排序
|
||||
'list', -- route_url: 路由路径(相对于父菜单)
|
||||
'warehouse/warehouse', -- page_url: 前端组件路径(相对于views目录)
|
||||
2, -- org_type: 2-企业端
|
||||
'warehouse:list', -- authority: 权限字符串
|
||||
NOW(), -- create_time
|
||||
NOW(), -- update_time
|
||||
0 -- is_delete: 0-未删除
|
||||
);
|
||||
|
||||
SET @warehouse_list_menu_id = LAST_INSERT_ID();
|
||||
|
||||
-- 中转仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES
|
||||
(@warehouse_list_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehouse:add', NOW(), NOW(), 0),
|
||||
(@warehouse_list_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehouse:edit', NOW(), NOW(), 0),
|
||||
(@warehouse_list_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehouse:delete', NOW(), NOW(), 0),
|
||||
(@warehouse_list_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehouse:query', NOW(), NOW(), 0);
|
||||
|
||||
-- ============================================
|
||||
-- 3. 插入二级菜单:进仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES (
|
||||
@warehouse_parent_id, -- parent_id: 一级菜单ID
|
||||
1, -- type: 1-菜单
|
||||
'el-icon-upload', -- icon: 上传图标
|
||||
'进仓管理', -- name: 菜单名称
|
||||
2, -- sort: 排序
|
||||
'in', -- route_url: 路由路径(相对于父菜单)
|
||||
'warehouse/warehouseIn', -- page_url: 前端组件路径(相对于views目录)
|
||||
2, -- org_type: 2-企业端
|
||||
'warehousein:list', -- authority: 权限字符串
|
||||
NOW(), -- create_time
|
||||
NOW(), -- update_time
|
||||
0 -- is_delete: 0-未删除
|
||||
);
|
||||
|
||||
SET @warehouse_in_menu_id = LAST_INSERT_ID();
|
||||
|
||||
-- 进仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES
|
||||
(@warehouse_in_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehousein:add', NOW(), NOW(), 0),
|
||||
(@warehouse_in_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehousein:edit', NOW(), NOW(), 0),
|
||||
(@warehouse_in_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehousein:delete', NOW(), NOW(), 0),
|
||||
(@warehouse_in_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehousein:query', NOW(), NOW(), 0);
|
||||
|
||||
-- ============================================
|
||||
-- 4. 插入二级菜单:出仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES (
|
||||
@warehouse_parent_id, -- parent_id: 一级菜单ID
|
||||
1, -- type: 1-菜单
|
||||
'el-icon-download', -- icon: 下载图标
|
||||
'出仓管理', -- name: 菜单名称
|
||||
3, -- sort: 排序
|
||||
'out', -- route_url: 路由路径(相对于父菜单)
|
||||
'warehouse/warehouseOut', -- page_url: 前端组件路径(相对于views目录)
|
||||
2, -- org_type: 2-企业端
|
||||
'warehouseout:list', -- authority: 权限字符串
|
||||
NOW(), -- create_time
|
||||
NOW(), -- update_time
|
||||
0 -- is_delete: 0-未删除
|
||||
);
|
||||
|
||||
SET @warehouse_out_menu_id = LAST_INSERT_ID();
|
||||
|
||||
-- 出仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
VALUES
|
||||
(@warehouse_out_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehouseout:add', NOW(), NOW(), 0),
|
||||
(@warehouse_out_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehouseout:edit', NOW(), NOW(), 0),
|
||||
(@warehouse_out_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehouseout:delete', NOW(), NOW(), 0),
|
||||
(@warehouse_out_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehouseout:query', NOW(), NOW(), 0);
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
USE cattletrade;
|
||||
|
||||
-- 安全插入中转仓管理菜单(可重复执行,不会重复插入)
|
||||
-- 菜单类型:0-目录,1-菜单,2-按钮
|
||||
-- 排序:数字越小越靠前
|
||||
|
||||
-- ============================================
|
||||
-- 1. 插入一级菜单:中转仓管理(type=0,目录)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
0 AS parent_id,
|
||||
0 AS type,
|
||||
'el-icon-office-building' AS icon,
|
||||
'中转仓管理' AS name,
|
||||
60 AS sort,
|
||||
NULL AS route_url,
|
||||
NULL AS page_url,
|
||||
2 AS org_type,
|
||||
NULL AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE name = '中转仓管理' AND type = 0 AND is_delete = 0
|
||||
);
|
||||
|
||||
-- 获取一级菜单ID(如果已存在则查询,否则使用刚插入的ID)
|
||||
SET @warehouse_parent_id = COALESCE(
|
||||
(SELECT id FROM sys_menu WHERE name = '中转仓管理' AND type = 0 AND is_delete = 0 LIMIT 1),
|
||||
LAST_INSERT_ID()
|
||||
);
|
||||
|
||||
-- ============================================
|
||||
-- 2. 插入二级菜单:中转仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@warehouse_parent_id AS parent_id,
|
||||
1 AS type,
|
||||
'el-icon-office-building' AS icon,
|
||||
'中转仓管理' AS name,
|
||||
1 AS sort,
|
||||
'list' AS route_url,
|
||||
'warehouse/warehouse' AS page_url,
|
||||
2 AS org_type,
|
||||
'warehouse:list' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @warehouse_parent_id
|
||||
AND name = '中转仓管理'
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_parent_id IS NOT NULL;
|
||||
|
||||
SET @warehouse_list_menu_id = COALESCE(
|
||||
(SELECT id FROM sys_menu WHERE parent_id = @warehouse_parent_id AND name = '中转仓管理' AND type = 1 AND is_delete = 0 LIMIT 1),
|
||||
LAST_INSERT_ID()
|
||||
);
|
||||
|
||||
-- 中转仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_list_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehouse:add', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_list_menu_id AND name = '新增' AND type = 2 AND authority = 'warehouse:add' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_list_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_list_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehouse:edit', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_list_menu_id AND name = '编辑' AND type = 2 AND authority = 'warehouse:edit' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_list_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_list_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehouse:delete', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_list_menu_id AND name = '删除' AND type = 2 AND authority = 'warehouse:delete' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_list_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_list_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehouse:query', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_list_menu_id AND name = '查询' AND type = 2 AND authority = 'warehouse:query' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_list_menu_id IS NOT NULL;
|
||||
|
||||
-- ============================================
|
||||
-- 3. 插入二级菜单:进仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@warehouse_parent_id AS parent_id,
|
||||
1 AS type,
|
||||
'el-icon-upload' AS icon,
|
||||
'进仓管理' AS name,
|
||||
2 AS sort,
|
||||
'in' AS route_url,
|
||||
'warehouse/warehouseIn' AS page_url,
|
||||
2 AS org_type,
|
||||
'warehousein:list' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @warehouse_parent_id
|
||||
AND name = '进仓管理'
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_parent_id IS NOT NULL;
|
||||
|
||||
SET @warehouse_in_menu_id = COALESCE(
|
||||
(SELECT id FROM sys_menu WHERE parent_id = @warehouse_parent_id AND name = '进仓管理' AND type = 1 AND is_delete = 0 LIMIT 1),
|
||||
LAST_INSERT_ID()
|
||||
);
|
||||
|
||||
-- 进仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_in_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehousein:add', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_in_menu_id AND name = '新增' AND type = 2 AND authority = 'warehousein:add' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_in_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_in_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehousein:edit', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_in_menu_id AND name = '编辑' AND type = 2 AND authority = 'warehousein:edit' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_in_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_in_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehousein:delete', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_in_menu_id AND name = '删除' AND type = 2 AND authority = 'warehousein:delete' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_in_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_in_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehousein:query', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_in_menu_id AND name = '查询' AND type = 2 AND authority = 'warehousein:query' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_in_menu_id IS NOT NULL;
|
||||
|
||||
-- ============================================
|
||||
-- 4. 插入二级菜单:出仓管理(type=1,菜单)
|
||||
-- ============================================
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT
|
||||
@warehouse_parent_id AS parent_id,
|
||||
1 AS type,
|
||||
'el-icon-download' AS icon,
|
||||
'出仓管理' AS name,
|
||||
3 AS sort,
|
||||
'out' AS route_url,
|
||||
'warehouse/warehouseOut' AS page_url,
|
||||
2 AS org_type,
|
||||
'warehouseout:list' AS authority,
|
||||
NOW() AS create_time,
|
||||
NOW() AS update_time,
|
||||
0 AS is_delete
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE parent_id = @warehouse_parent_id
|
||||
AND name = '出仓管理'
|
||||
AND type = 1
|
||||
AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_parent_id IS NOT NULL;
|
||||
|
||||
SET @warehouse_out_menu_id = COALESCE(
|
||||
(SELECT id FROM sys_menu WHERE parent_id = @warehouse_parent_id AND name = '出仓管理' AND type = 1 AND is_delete = 0 LIMIT 1),
|
||||
LAST_INSERT_ID()
|
||||
);
|
||||
|
||||
-- 出仓管理按钮权限
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_out_menu_id, 2, NULL, '新增', 1, NULL, NULL, 2, 'warehouseout:add', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_out_menu_id AND name = '新增' AND type = 2 AND authority = 'warehouseout:add' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_out_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_out_menu_id, 2, NULL, '编辑', 2, NULL, NULL, 2, 'warehouseout:edit', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_out_menu_id AND name = '编辑' AND type = 2 AND authority = 'warehouseout:edit' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_out_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_out_menu_id, 2, NULL, '删除', 3, NULL, NULL, 2, 'warehouseout:delete', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_out_menu_id AND name = '删除' AND type = 2 AND authority = 'warehouseout:delete' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_out_menu_id IS NOT NULL;
|
||||
|
||||
INSERT INTO sys_menu (parent_id, type, icon, name, sort, route_url, page_url, org_type, authority, create_time, update_time, is_delete)
|
||||
SELECT @warehouse_out_menu_id, 2, NULL, '查询', 4, NULL, NULL, 2, 'warehouseout:query', NOW(), NOW(), 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE parent_id = @warehouse_out_menu_id AND name = '查询' AND type = 2 AND authority = 'warehouseout:query' AND is_delete = 0
|
||||
)
|
||||
AND @warehouse_out_menu_id IS NOT NULL;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<result column="source_lon" property="sourceLon" />
|
||||
<result column="source_lat" property="sourceLat" />
|
||||
<result column="cattle_count" property="cattleCount" />
|
||||
<result column="remaining_count" property="remainingCount" />
|
||||
<result column="weight" property="weight" />
|
||||
<result column="in_time" property="inTime" />
|
||||
<result column="photos" property="photos" />
|
||||
@@ -28,7 +29,7 @@
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, in_number, warehouse_id, order_id, delivery_id, source_location, source_lon, source_lat, cattle_count, weight, in_time, photos, videos, remark, status, create_time, update_time, created_by, updated_by, is_delete
|
||||
id, in_number, warehouse_id, order_id, delivery_id, source_location, source_lon, source_lat, cattle_count, remaining_count, weight, in_time, photos, videos, remark, status, create_time, update_time, created_by, updated_by, is_delete
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user