2025-08-04 17:22:15 +08:00

733 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="管理耳号" prop="manageTags">
<el-input v-model="queryParams.manageTags" placeholder="请输入耳号" clearable @keyup.enter="handleQuery"
style="width: 150px;" />
</el-form-item>
<el-form-item label="转出羊舍" prop="foldFrom">
<el-select v-model="queryParams.foldFrom" placeholder="请选择转出羊舍" style="min-width:150px" clearable>
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="转入羊舍" prop="foldTo">
<el-select v-model="queryParams.foldTo" placeholder="请选择转入羊舍" style="min-width:150px" clearable>
<el-option v-for="item in sheepfoldOptions" :key="item.id" :label="item.sheepfoldName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="品种" prop="varietyId">
<el-select v-model="queryParams.varietyId" placeholder="请选择品种" style="min-width:150px" clearable>
<el-option v-for="item in varietyOptions" :key="item.id" :label="item.variety" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" style="width: 150px;" placeholder="请选择状态" clearable>
<el-option v-for="dict in status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker v-model="daterangeCreateTime" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['trans_group:trans_group:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['trans_group:trans_group:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['trans_group:trans_group:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['trans_group:trans_group:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="trans_groupList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="管理耳号" align="center" prop="manageTags" />
<el-table-column label="转出羊舍" align="center" prop="foldFromName" />
<el-table-column label="转入羊舍" align="center" prop="foldToName" />
<el-table-column label="品种" align="center" prop="varietyName" />
<el-table-column label="转群原因" align="center" prop="reasonText" />
<el-table-column label="技术员" align="center" prop="technician" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="comment" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="160">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleApprove(scope.row)"
v-hasPermi="['trans_group:trans_group:approve']">
审批
</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['trans_group:trans_group:remove']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改转群记录对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="trans_groupRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="管理耳号" prop="manageTags">
<el-select v-model="form.manageTags" placeholder="请输入或选择耳号" multiple filterable allow-create
style="width: 100%" @change="loadSheepInfo" :disabled="!isAdd">
<el-option v-for="sheep in sheepOptions" :key="sheep.id" :label="sheep.manageTags"
:value="sheep.manageTags" />
</el-select>
</el-form-item>
<!-- 在el-form中新增牧场选择项 -->
<el-form-item label="牧场" prop="ranchId">
<el-select v-model="form.ranchId" placeholder="请选择牧场" clearable @change="handleRanchChange">
<el-option v-for="ranch in ranchOptions" :key="ranch.id" :label="ranch.ranchName" :value="ranch.id" />
</el-select>
</el-form-item>
<!-- 调整转出羊舍的options为当前牧场的羊舍 -->
<el-form-item label="转出羊舍" prop="foldFrom">
<el-select v-model="form.foldFrom" placeholder="请选择转出羊舍" clearable :disabled="!form.ranchId"
@change="handleSheepFilter">
<el-option v-for="fold in currentRanchSheepfolds" :key="fold.id" :label="fold.sheepfoldName"
:value="fold.id" />
</el-select>
</el-form-item>
<!-- 调整转入羊舍的options为当前牧场的羊舍 -->
<el-form-item label="转入羊舍" prop="foldTo">
<el-select v-model="form.foldTo" placeholder="请选择转入羊舍" clearable :disabled="!form.ranchId">
<el-option v-for="fold in currentRanchSheepfolds" :key="fold.id" :label="fold.sheepfoldName"
:value="fold.id" />
</el-select>
</el-form-item>
<el-form-item v-if="isAdd" label="羊只类型" prop="sheepTypeId">
<el-select v-model="form.sheepTypeId" placeholder="请选择羊只类型" clearable @change="handleSheepFilter">
<el-option v-for="type in sheepTypeOptions" :key="type.id" :label="type.name" :value="type.id" />
</el-select>
</el-form-item>
<el-form-item label="转群原因" prop="reason">
<el-select v-model="form.reason" placeholder="请选择转群原因" clearable>
<el-option v-for="dict in trans_group_reason" :key="dict.value" :label="dict.label"
:value="Number(dict.value)" />
</el-select>
</el-form-item>
<el-form-item label="技术员" prop="technician">
<el-input v-model="form.technician" placeholder="请输入技术员" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
<!-- 审批对话框 -->
<el-dialog :title="'审批转群记录'" v-model="approveDialog" width="500px" append-to-body>
<el-form ref="approveFormRef" :model="approveForm" label-width="120px">
<el-form-item label="耳号">
<el-input v-model="displayManageTags" disabled />
</el-form-item>
<el-form-item label="转出羊舍">
<el-input :value="sheepfoldNameMap[approveForm.foldFrom] || approveForm.foldFrom" disabled />
</el-form-item>
<el-form-item label="转入羊舍">
<el-input :value="sheepfoldNameMap[approveForm.foldTo] || approveForm.foldTo" disabled />
</el-form-item>
<el-form-item label="品种">
<el-input :value="approveForm.varietyName" disabled />
</el-form-item>
<el-form-item label="转群原因">
<el-input :value="approveForm.reasonText" disabled />
</el-form-item>
<el-form-item label="状态">
<el-input :value="approveForm.statusText" disabled />
</el-form-item>
<el-form-item label="技术员">
<el-input v-model="approveForm.technician" disabled />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="approveForm.comment" disabled />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleApproveAgree">同意</el-button>
<el-button type="danger" @click="handleApproveReject">驳回</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="Trans_group">
import { listTrans_group, getTrans_group, delTrans_group, addTrans_group, updateTrans_group, approveScTransGroup, listRanch } from '@/api/produce/manage_sheep/trans_group'
import { listSheepfold_management as listSheepfold } from '@/api/fileManagement/sheepfold_management'
import { checkSheepByManageTags, getSheepBySheepfoldId } from '@/api/produce/other/fixHoof'
import request from '@/utils/request'
const { proxy } = getCurrentInstance();
const { trans_group_reason, status } = proxy.useDict('trans_group_reason', 'status');
const trans_groupList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(false);
const total = ref(0);
const title = ref('');
const daterangeCreateTime = ref([]);
const approveDialog = ref(false);
const approveForm = ref({});
const displayManageTags = ref('');
const sheepOptions = ref([]);
const sheepfoldOptions = ref([]);
const sheepfoldNameMap = ref({});
const varietyOptions = ref([]);
const sheepTypeOptions = ref([]);
const isAdd = ref(false);
const ranchOptions = ref([]);
const currentRanchSheepfolds = ref([]);
const data = reactive({
form: {
manageTags: [],
tagDetails: {},
},
queryParams: {
pageNum: 1,
pageSize: 10,
sheepId: null,
manageTags: null,
ranchId: null,
foldTo: null,
foldFrom: null,
varietyId: null,
status: null,
createTime: null,
},
rules: {
manageTags: [{ required: true, message: '请输入耳号', trigger: 'blur' }],
ranchId: [{ required: true, message: '请选择牧场', trigger: 'change' }],
foldTo: [{ required: true, message: '请选择转入羊舍', trigger: 'change' }],
varietyId: [{ required: true, message: '请选择品种', trigger: 'change' }],
reason: [{ required: true, message: '请选择转群原因', trigger: 'change' }],
technician: [{ required: true, message: '请输入技术员', trigger: 'blur' }],
},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询转群记录列表 */
function getList() {
loading.value = true;
queryParams.value.params = {};
if (daterangeCreateTime.value?.length) {
queryParams.value.params.beginCreateTime = daterangeCreateTime.value[0];
queryParams.value.params.endCreateTime = daterangeCreateTime.value[1];
}
listTrans_group(queryParams.value).then((res) => {
trans_groupList.value = res.rows;
total.value = res.total;
loading.value = false;
});
}
//重置按钮
function reset() {
form.value = {
id: null,
sheepId: null,
ranchId: null,
foldFrom: null,
foldTo: null,
varietyId: null,
reason: null,
technician: null,
status: null,
comment: null,
createBy: null,
createTime: null,
manageTags: [],
tagDetails: {},
sheepTypeId: null,
};
proxy.resetForm('trans_groupRef');
}
//新增时判断筛选条件
async function handleSheepFilter() {
const { foldFrom, sheepTypeId, ranchId } = form.value;
let isOnlySheepfold = false;
let isOnlyTypeOrCombined = false;
if (!ranchId) {
form.value.manageTags = [];
sheepOptions.value = [];
proxy.$message.warning("请先选择牧场");
return;
}
if (foldFrom && !sheepTypeId) {
isOnlySheepfold = true;
} else if (!foldFrom && sheepTypeId) {
isOnlyTypeOrCombined = true;
} else if (foldFrom && sheepTypeId) {
isOnlyTypeOrCombined = true;
} else {
form.value.manageTags = [];
sheepOptions.value = [];
return;
}
if (isOnlySheepfold) {
await loadSheepBySheepfoldOnly(foldFrom, ranchId);
} else if (isOnlyTypeOrCombined) {
form.value.manageTags = [];
let loadedSheep = [];
if (foldFrom && sheepTypeId) {
loadedSheep = await loadSheepBySheepfoldAndType(foldFrom, sheepTypeId, ranchId);
} else if (sheepTypeId) {
loadedSheep = await loadSheepByTypeOnly(sheepTypeId, ranchId);
}
if (loadedSheep.length > 0) {
form.value.manageTags = loadedSheep.map((sheep) => sheep.manageTags);
await loadSheepInfo();
} else {
proxy.$message.info("未查询到符合条件的耳号");
}
}
}
//转群类型列表
function getSheepTypeList() {
return new Promise((resolve, reject) => {
request({
url: '/base/base/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 },
}).then((res) => {
sheepTypeOptions.value = res.rows.map(item => ({
id: Number(item.id),
name: item.name || item.typeName
})) || [];
resolve();
}).catch((error) => {
console.error('获取羊只类型失败', error);
proxy.$modal.msgError('加载羊只类型失败,请重试');
reject(error);
});
});
}
//加载所有牧场列表
function loadRanchList() {
listRanch().then(res => {
ranchOptions.value = res.rows.map(ranch => ({
id: ranch.id,
ranchName: ranch.ranch
}));
}).catch(error => {
console.error('加载牧场列表失败', error);
proxy.$modal.msgError('获取牧场数据失败');
});
}
//切换牧场时触发
function handleRanchChange(ranchId) {
form.value.foldFrom = null;
form.value.foldTo = null;
if (!ranchId) {
currentRanchSheepfolds.value = [];
return;
}
request({
url: '/sheepfold_management/sheepfold_management/list',
method: 'get',
params: { ranchId, pageNum: 1, pageSize: 9999 }
}).then(res => {
currentRanchSheepfolds.value = res.rows || [];
if (currentRanchSheepfolds.value.length === 0) {
proxy.$modal.msgWarning(`所选牧场ID:${ranchId})暂无羊舍数据`);
}
}).catch(error => {
console.error('加载牧场羊舍失败', error);
proxy.$modal.msgError('获取羊舍数据失败');
currentRanchSheepfolds.value = [];
});
}
//只通过羊舍
async function loadSheepBySheepfoldOnly(sheepfoldId, ranchId) {
if (!sheepfoldId || isNaN(Number(sheepfoldId))) {
proxy.$message.error('请选择有效的羊舍');
sheepOptions.value = [];
return [];
}
if (!ranchId) {
proxy.$message.error('牧场信息异常,请重新选择');
sheepOptions.value = [];
return [];
}
try {
const res = await getSheepBySheepfoldId(Number(sheepfoldId));
const newSheepList = (res.data || []).map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags || '未知耳号',
sheepfoldId: Number(sheepfoldId),
})).filter(item => item.manageTags);
if (newSheepList.length === 0) {
proxy.$message.info('当前羊舍下暂无羊只数据');
sheepOptions.value = [];
return [];
}
sheepOptions.value = newSheepList;
return newSheepList;
} catch (error) {
console.error('根据羊舍加载耳号失败:', error);
const errorMsg = error.response?.data?.msg || '加载羊舍耳号失败,请重试';
proxy.$modal.msgError(errorMsg);
sheepOptions.value = [];
return [];
}
}
//通过羊舍和羊只类型
async function loadSheepBySheepfoldAndType(sheepfoldId, typeId) {
try {
const res = await request({
url: '/sheep/sheep/listBySheepfoldAndType',
method: 'get',
params: { sheepfoldId, typeId, _t: Date.now() },
});
const sheepList = res.rows || [];
const formattedSheep = sheepList.map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheepfoldId,
}));
sheepOptions.value = formattedSheep;
return formattedSheep;
} catch (error) {
console.error('根据羊舍+类型加载耳号失败', error);
proxy.$modal.msgError('加载耳号失败,请重试');
return [];
}
}
//只通过羊只类型
async function loadSheepByTypeOnly(typeId) {
try {
const res = await request({
url: '/sheep/sheep/listByTypeId',
method: 'get',
params: { typeId },
});
const sheepList = res.rows || [];
const formattedSheep = sheepList.map((sheep) => ({
id: sheep.id,
manageTags: sheep.manageTags,
sheepfoldId: sheep.sheepfoldId,
}));
sheepOptions.value = formattedSheep;
return formattedSheep;
} catch (error) {
console.error('根据类型加载耳号失败', error);
proxy.$modal.msgError('加载耳号失败,请重试');
return [];
}
}
//加载羊只信息
async function loadSheepInfo() {
const tags = form.value.manageTags;
if (!tags || tags.length === 0) return;
const tagDetails = {};
const validResults = [];
let firstSheepfoldId = null;
let firstRanchId = null;
for (const tag of tags) {
try {
const { data: sheepData } = await checkSheepByManageTags(tag.trim());
if (!sheepData) {
validResults.push(false);
proxy.$modal.msgError(`耳号 ${tag} 不存在或信息异常`);
} else {
validResults.push(true);
tagDetails[tag] = {
comment: sheepData.comment || '',
varietyId: sheepData.varietyId,
sheepId: sheepData.id,
sheepfoldId: sheepData.sheepfoldId,
};
if (!firstSheepfoldId) {
firstSheepfoldId = sheepData.sheepfoldId;
firstRanchId = sheepData.ranchId;
}
}
} catch (error) {
console.error('获取耳号信息失败:', error);
proxy.$modal.msgError(`耳号 ${tag} 验证失败,请重试`);
validResults.push(false);
}
}
if (validResults.includes(false)) {
form.value.manageTags = tags.filter((_, index) => validResults[index]);
proxy.$message.warning('部分耳号不合法,已自动过滤');
}
form.value.tagDetails = tagDetails;
if (firstRanchId && isAdd.value) {
form.value.ranchId = firstRanchId;
handleRanchChange(firstRanchId);
}
if (firstSheepfoldId && isAdd.value) {
form.value.foldFrom = Number(firstSheepfoldId);
}
}
//取消按钮
function cancel() {
open.value = false;
reset();
}
//搜索按钮
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
//重置搜索框
function resetQuery() {
daterangeCreateTime.value = [];
proxy.resetForm('queryRef');
handleQuery();
}
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
//新增
function handleAdd() {
reset();
open.value = true;
title.value = '添加转群记录';
isAdd.value = true;
sheepOptions.value = [];
form.value.manageTags = [];
}
//修改
async function handleUpdate(row) {
reset();
const _id = row.id || ids.value;
loading.value = true;
isAdd.value = false;
const { data: d } = await getTrans_group(_id);
try {
await Promise.all([
sheepfoldOptions.value.length === 0 ? loadSheepfold() : Promise.resolve(),
sheepTypeOptions.value.length === 0 ? getSheepTypeList() : Promise.resolve()
]);
const { data: d } = await getTrans_group(_id);
const manageTags = Array.isArray(d.manageTags)
? d.manageTags
: d.manageTags ? [d.manageTags] : [];
const formData = {
...d,
manageTags: manageTags,
foldFrom: Number(d.foldFrom || 0),
foldTo: Number(d.foldTo || 0),
sheepTypeId: Number(d.sheepTypeId || 0),
reason: Number(d.reason || 0),
status: Number(d.status || 0),
varietyId: Number(d.varietyId || 0),
isEdit: true
};
form.value = formData;
form.value.ranchId = row.ranchId;
handleRanchChange(row.ranchId);
isAdd.value = false;
if (manageTags.length > 0) {
await loadSheepInfo();
}
open.value = true;
title.value = '修改转群记录';
} catch (error) {
console.error('修改加载失败:', error);
proxy.$modal.msgError('加载数据失败');
} finally {
loading.value = false;
}
}
//提交
function submitForm() {
proxy.$refs.trans_groupRef.validate((valid) => {
if (!valid) return;
const allTags = form.value.manageTags;
const tagDetails = form.value.tagDetails || {};
if (!allTags || allTags.length === 0) {
proxy.$modal.msgError('请选择或输入至少一个耳号');
return;
}
const requests = allTags.map(async (tag) => {
const formData = { ...form.value };
const details = tagDetails[tag] || {};
formData.manageTags = tag;
formData.sheepId = details.sheepId;
formData.foldFrom = details.sheepfoldId;
formData.comment = details.comment || '';
formData.varietyId = details.varietyId || formData.varietyId;
if (formData.id) {
return updateTrans_group(formData);
} else {
return addTrans_group(formData);
}
});
Promise.all(requests)
.then(() => {
proxy.$modal.msgSuccess('操作成功');
open.value = false;
getList();
})
.catch((error) => {
proxy.$modal.msgError(`处理失败:${error.message}`);
});
});
}
//删除
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm(`是否确认删除转群记录编号为“${_ids}”的数据项?`)
.then(() => delTrans_group(_ids))
.then(() => {
getList();
proxy.$modal.msgSuccess('删除成功');
});
}
//导出
function handleExport() {
proxy.download(
'/produce/manage_sheep/trans_group/export',
{ ...queryParams.value },
`trans_group_${Date.now()}.xlsx`
);
}
// 审核
function handleApprove(row) {
approveForm.value = { ...row };
approveDialog.value = true;
displayManageTags.value = row.manageTags;
}
// 审批同意
function handleApproveAgree() {
if (typeof approveForm.value.foldTo !== 'number') {
approveForm.value.foldTo = Number(approveForm.value.foldTo);
}
approveForm.value.status = 1;
approveScTransGroup(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批通过,羊只所在羊舍已更新');
getList();
}).catch(error => {
proxy.$modal.msgError(`审批失败:${error.message}`);
});
}
function handleApproveReject() {
approveForm.value.status = 2;
approveScTransGroup(approveForm.value).then(() => {
approveDialog.value = false;
proxy.$modal.msgSuccess('审批已驳回');
getList();
}).catch(error => {
proxy.$modal.msgError(`审批失败:${error.message}`);
});
}
//加载羊舍数据
function loadSheepfold() {
listSheepfold({ pageNum: 1, pageSize: 9999 }).then((res) => {
sheepfoldOptions.value = res.rows;
sheepfoldNameMap.value = res.rows.reduce((acc, item) => {
acc[item.id] = item.sheepfoldName;
return acc;
}, {});
});
}
//获取品种数据
function getVarietyOptions() {
request({
url: '/base/variety/list',
method: 'get',
params: { pageNum: 1, pageSize: 9999 },
}).then((res) => {
varietyOptions.value = res.rows || [];
});
}
onMounted(() => {
loadSheepfold();
loadRanchList();
getVarietyOptions();
getSheepTypeList();
getList();
});
</script>