Files
fishery-web/src/views/fishery/pond/index.vue

1027 lines
32 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="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="塘口名称" prop="pondName">
<el-input v-model="queryParams.pondName" placeholder="请输入塘口名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="用户信息" prop="params.userKeyword">
<el-input v-model="queryParams.params.userKeyword" placeholder="请输入用户名或手机号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="投苗日期" prop="time">
<el-date-picker
v-model="queryParams.time"
type="daterange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-form-item>
<!-- <el-form-item label="夜间防止误关" prop="keepNightOpen">
<el-input v-model="queryParams.keepNightOpen" placeholder="请输入夜间防止误关" clearable @keyup.enter="handleQuery" />
</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-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['fishery:pond:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['fishery:pond:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['fishery:pond:remove']"
>删除</el-button
>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['fishery:pond:export']">导出</el-button>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="pondList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="塘口名称" align="center" prop="pondName" />
<el-table-column label="用户名" align="center" prop="userName" />
<el-table-column label="手机号" align="center" prop="mobilePhone" />
<el-table-column label="鱼品种列表" align="center" prop="fishKindNames" />
<el-table-column label="面积(亩)" align="center" prop="area" />
<el-table-column label="密度(尾/亩)" align="center" prop="density" />
<el-table-column label="投苗日期" align="center" prop="placeTime" width="120">
<template #default="scope">
<span>{{ parseTime(scope.row.placeTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="夜间防止误关" align="center" prop="keepNightOpen">
<template #default="scope">
<dict-tag :options="open_close" :value="scope.row.keepNightOpen" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="160"/>
<el-table-column label="更新时间" align="center" prop="updateTime" width="160"/>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['fishery:pond:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['fishery:pond:remove']"></el-button>
</el-tooltip>
</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-card>
<!-- 添加或修改塘口对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="550px" append-to-body>
<el-form ref="pondFormRef" :model="form" :rules="rules" label-width="110px">
<el-form-item label="用户" prop="userId">
<el-input
:value="selectedUser ? `${selectedUser.userName} (${selectedUser.mobilePhone})` : ''"
placeholder="请选择用户"
readonly
@click="openUserSelect"
style="cursor: pointer;"
>
<template #append>
<el-button icon="Search" @click="openUserSelect">选择</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="塘口名称" prop="pondName">
<el-input v-model="form.pondName" placeholder="请输入塘口名称" />
</el-form-item>
<el-form-item label="鱼品种列表" prop="fishKindIds">
<div class="fish-selector">
<el-input
v-model="selectedFishNames"
placeholder="请选择鱼品种"
readonly
@click="openFishSelect"
style="cursor: pointer;"
>
<template #suffix>
<div class="input-suffix">
<span v-if="selectedFishList.length > 0" class="count-badge">
{{ selectedFishList.length }}
</span>
<el-icon class="select-icon"><ArrowDown /></el-icon>
</div>
</template>
</el-input>
<!-- 简洁的已选择项目展示 -->
<div v-if="selectedFishList.length > 0" class="selected-items">
<div class="selected-summary">
<span class="summary-text">已选择 {{ selectedFishList.length }} 个品种</span>
<el-button
type="text"
size="small"
@click="clearAllFish"
class="clear-btn"
>
清空
</el-button>
</div>
<div class="selected-list-compact">
<span
v-for="(fish, index) in selectedFishList.slice(0, 5)"
:key="fish.id"
class="fish-item"
>
{{ fish.fishName }}<span v-if="index < Math.min(4, selectedFishList.length - 1)"></span>
</span>
<span v-if="selectedFishList.length > 5" class="more-indicator">
... 及另外{{ selectedFishList.length - 5 }}个品种
</span>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="面积" prop="area">
<el-input v-model="form.area" placeholder="请输入面积">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="密度" prop="density">
<el-input v-model="form.density" placeholder="请输入密度">
<template #append>/</template>
</el-input>
</el-form-item>
<el-form-item label="投苗日期" prop="placeTime">
<el-date-picker clearable v-model="form.placeTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择投苗日期">
</el-date-picker>
</el-form-item>
<el-form-item label="夜间防止误关" prop="keepNightOpen">
<el-select v-model="form.keepNightOpen" placeholder="请选择夜间防止误关">
<el-option
v-for="dict in open_close"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 鱼品种选择对话框 -->
<el-dialog title="选择鱼品种" v-model="fishSelectVisible" width="1200px" append-to-body>
<el-row :gutter="20">
<!-- 左侧鱼类搜索和列表 -->
<el-col :span="16">
<!-- Tab页签 -->
<el-tabs v-model="activeTab" @tab-change="handleTabChange" class="mb-4">
<el-tab-pane label="全部" name="all"></el-tab-pane>
<el-tab-pane
v-for="dict in fish_type"
:key="dict.value"
:label="dict.label"
:name="dict.value"
></el-tab-pane>
</el-tabs>
<!-- 搜索条件 -->
<el-form :model="fishQueryParams" :inline="true" class="mb-4">
<el-form-item label="鱼类名称">
<el-input
v-model="fishQueryParams.fishName"
placeholder="请输入鱼类名称"
clearable
style="width: 200px"
@keyup.enter="handleFishQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleFishQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetFishQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 鱼品种表格 -->
<el-table
ref="fishTableRef"
:data="fishList"
@selection-change="handleSelectAllFish"
height="350px"
border
v-loading="loading"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="鱼类名称" align="center" prop="fishName" />
<el-table-column label="鱼类类型" align="center" prop="fishType" width="100">
<template #default="scope">
<dict-tag :options="fish_type" :value="scope.row.fishType" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="80">
<template #default="scope">
<el-button
type="primary"
size="small"
@click="quickAddFish(scope.row)"
:disabled="selectedFishList.some(item => item.id === scope.row.id)"
>
添加
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 数据统计 -->
<div class="mt-2 text-sm text-gray-500">
当前显示 {{ fishList.length }} 条数据
</div>
</el-col>
<!-- 右侧已选择的鱼类 -->
<el-col :span="8">
<div class="selected-fish-panel">
<div class="panel-header">
<h4>已选择的鱼类 ({{ selectedFishList.length }})</h4>
<el-button
type="danger"
size="small"
@click="clearAllFish"
v-show="selectedFishList.length > 0"
>
清空
</el-button>
</div>
<div class="selected-list">
<div
v-for="fish in selectedFishList"
:key="fish.id"
class="selected-item"
>
<span class="fish-name">{{ fish.fishName }}</span>
<dict-tag :options="fish_type" :value="fish.fishType" size="small" class="ml-2" />
<el-button
type="danger"
size="small"
icon="Close"
circle
@click="removeFish(fish.id)"
class="ml-2"
/>
</div>
<el-empty
v-if="selectedFishList.length === 0"
description="请选择鱼类"
:image-size="100"
/>
</div>
</div>
</el-col>
</el-row>
<template #footer>
<div class="dialog-footer">
<span class="selected-count">已选择 {{ selectedFishList.length }} 个鱼类</span>
<el-button type="primary" @click="confirmFishSelect" :disabled="selectedFishList.length === 0"> </el-button>
<el-button @click="cancelFishSelect"> </el-button>
</div>
</template>
</el-dialog>
<!-- 用户选择对话框 -->
<el-dialog title="选择用户" v-model="userSelectVisible" width="900px" append-to-body>
<!-- 搜索条件 -->
<el-form :model="userQueryParams" :inline="true" class="mb-4">
<el-form-item label="用户名">
<el-input
v-model="userQueryParams.userName"
placeholder="请输入用户名"
clearable
style="width: 180px"
@keyup.enter="handleUserQuery"
/>
</el-form-item>
<el-form-item label="手机号">
<el-input
v-model="userQueryParams.mobilePhone"
placeholder="请输入手机号"
clearable
style="width: 180px"
@keyup.enter="handleUserQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleUserQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetUserQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 用户表格 -->
<el-table
:data="aquUserList"
highlight-current-row
height="400px"
border
>
<el-table-column label="用户名" align="center" prop="userName" />
<el-table-column label="手机号" align="center" prop="mobilePhone" />
<el-table-column label="省份" align="center" prop="province" />
<el-table-column label="城市" align="center" prop="city" />
<el-table-column label="区县" align="center" prop="district" />
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleUserSelect(scope.row)"
>
选择
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="userTotal > 0"
:total="userTotal"
v-model:page="userQueryParams.pageNum"
v-model:limit="userQueryParams.pageSize"
@pagination="handleUserPaginationChange"
class="mt-4"
/>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelUserSelect"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Pond" lang="ts">
import { listPond, getPond, delPond, addPond, updatePond } from '@/api/fishery/pond';
import { listFish, getFish } from '@/api/fishery/fish';
import { listAquUser } from '@/api/fishery/aquUser';
import { PondVO, PondQuery, PondForm } from '@/api/fishery/pond/types';
import { FishVO } from '@/api/fishery/fish/types';
import { AquUserVO } from '@/api/fishery/aquUser/types';
import dayjs from 'dayjs';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { fish_type,open_close } = toRefs<any>(proxy?.useDict('fish_type','open_close'));
const pondList = ref<PondVO[]>([]);
const fishList = ref<FishVO[]>([]);
const selectedFishList = ref<FishVO[]>([]);
const originalSelectedFishList = ref<FishVO[]>([]); // 备份的选择列表,用于取消操作
const fishSelectVisible = ref(false);
// 用户选择相关
const aquUserList = ref<AquUserVO[]>([]);
const selectedUser = ref<AquUserVO | null>(null);
const userSelectVisible = ref(false);
const userQueryParams = reactive<{
pageNum: number;
pageSize: number;
userName?: string;
mobilePhone?: string;
}>({
pageNum: 1,
pageSize: 10,
userName: undefined,
mobilePhone: undefined
});
const userTotal = ref(0);
const fishQueryParams = reactive<{
fishType?: number;
fishName?: string;
}>({
fishType: undefined,
fishName: undefined
});
const fishTotal = ref(0); // 鱼类数据总数
const activeTab = ref<string>('all'); // 当前激活的tab
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const pondFormRef = ref<ElFormInstance>();
const fishTableRef = ref<ElTableInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: PondForm = {
id: undefined,
userId: undefined,
pondName: undefined,
fishKindIds: undefined,
area: undefined,
density: undefined,
placeTime: undefined,
keepNightOpen: undefined,
remark: undefined
};
const data = reactive<PageData<PondForm, PondQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
time: '',
userId: undefined,
pondName: undefined,
fishKindIds: undefined,
placeTime: undefined,
keepNightOpen: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '用户id不能为空', trigger: 'blur' }],
pondName: [{ required: true, message: '塘口名称不能为空', trigger: 'blur' }],
fishKindIds: [{ required: true, message: '鱼品种列表不能为空', trigger: 'blur' }],
area: [{ required: true, message: '面积不能为空', trigger: 'blur' }],
density: [{ required: true, message: '密度不能为空', trigger: 'blur' }],
keepNightOpen: [{ required: true, message: '夜间防止误关不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
// 鱼品种相关状态
const selectedFishNames = computed(() => {
const count = selectedFishList.value.length;
if (count === 0) return '';
// 简洁显示,不显示具体名称
return `已选择 ${count} 个鱼类品种`;
});
// 获取完整的鱼类名称列表用于tooltip显示
const fullFishNames = computed(() => {
return selectedFishList.value.map(fish => fish.fishName).join('、');
});
const parseFishIds = (fishKindIds: any): string[] => {
if (!fishKindIds) return [];
try {
// 解析JSON数组格式"[29,31,34,4,2]"
const parsed = JSON.parse(fishKindIds.toString());
if (Array.isArray(parsed)) {
return parsed.map(id => id.toString());
}
} catch (error) {
console.warn('fishKindIds格式错误:', fishKindIds);
}
return [];
};
// 获取当前页面中已选中的项目
const getCurrentPageSelection = () => {
return fishList.value.filter(fish =>
selectedFishList.value.some(selected => selected.id === fish.id)
);
};
/** 根据ID列表获取鱼类信息 */
const getFishByIds = async (fishIds: string[]) => {
if (fishIds.length === 0) return [];
try {
// 方案1如果鱼类数量不多使用并发单个查询
if (fishIds.length <= 20) {
const promises = fishIds.map(id => getFish(id).catch(() => null));
const results = await Promise.all(promises);
return results.filter(res => res !== null).map(res => res.data);
}
// 方案2鱼类数量较多时使用分批查询
const allFishList: FishVO[] = [];
let pageNum = 1;
let hasMore = true;
const foundIds = new Set<string>();
// 分批获取所有鱼类数据,直到找齐所需的鱼类
while (hasMore && foundIds.size < fishIds.length) {
const res = await listFish({
pageNum: pageNum,
pageSize: 100, // 每次获取100条
fishType: undefined,
fishName: undefined
});
const fishData = res.rows || res.data || [];
// 筛选出需要的鱼类
const neededFish = fishData.filter(fish => {
const fishIdStr = fish.id.toString();
if (fishIds.includes(fishIdStr) && !foundIds.has(fishIdStr)) {
foundIds.add(fishIdStr);
return true;
}
return false;
});
allFishList.push(...neededFish);
// 判断是否还需要继续获取
hasMore = fishData.length === 100 && foundIds.size < fishIds.length;
pageNum++;
// 安全限制,避免无限循环
if (pageNum > 50) break;
}
return allFishList;
} catch (error) {
console.error('获取鱼类信息失败:', error);
return [];
}
};
const getFishList = async () => {
const res = await listFish({
pageNum: 1,
pageSize: 1000, // 获取所有数据
fishType: fishQueryParams.fishType,
fishName: fishQueryParams.fishName
});
fishList.value = res.rows || res.data || [];
fishTotal.value = res.total || 0;
// 数据加载完成后,设置当前页面的选中状态
await nextTick();
const currentPageSelection = getCurrentPageSelection();
if (fishTableRef.value && currentPageSelection.length > 0) {
// 清空当前选中状态
fishTableRef.value.clearSelection();
// 设置已选择的项目
currentPageSelection.forEach(fish => {
fishTableRef.value!.toggleRowSelection(fish, true);
});
}
};
/** 鱼类分页改变 */
const handleFishPaginationChange = () => {
getFishList();
};
/** 搜索鱼品种 */
const handleFishQuery = () => {
getFishList();
};
/** 重置鱼品种搜索 */
const resetFishQuery = () => {
fishQueryParams.fishType = undefined;
fishQueryParams.fishName = undefined;
activeTab.value = 'all';
getFishList();
};
/** 切换tab */
const handleTabChange = (tabName: string) => {
activeTab.value = tabName;
if (tabName === 'all') {
fishQueryParams.fishType = undefined;
} else {
fishQueryParams.fishType = parseInt(tabName);
}
fishQueryParams.fishName = undefined; // 切换tab时清空名称搜索
getFishList();
};
/** 全选/反选鱼类 */
const handleSelectAllFish = (selection: FishVO[]) => {
// 先移除当前页面中的所有项目
const currentPageIds = fishList.value.map(fish => fish.id);
selectedFishList.value = selectedFishList.value.filter(fish => !currentPageIds.includes(fish.id));
// 再添加当前页面选中的项目
selectedFishList.value.push(...selection);
};
/** 快速添加单个鱼类 */
const quickAddFish = (fish: FishVO) => {
if (!selectedFishList.value.find(item => item.id === fish.id)) {
selectedFishList.value.push(fish);
}
};
/** 移除已选择的鱼类 */
const removeFish = (fishId: string | number) => {
selectedFishList.value = selectedFishList.value.filter(fish => fish.id !== fishId);
};
/** 清空所有已选择的鱼类 */
const clearAllFish = async () => {
selectedFishList.value = [];
// 清空表格选中状态
if (fishTableRef.value) {
fishTableRef.value.clearSelection();
}
};
/** 打开鱼品种选择对话框 */
const openFishSelect = () => {
// 备份当前选择状态,用于取消操作
originalSelectedFishList.value = [...selectedFishList.value];
// 仅重置搜索条件,不清空已选择的鱼类
fishQueryParams.fishType = undefined;
fishQueryParams.fishName = undefined;
activeTab.value = 'all';
getFishList();
fishSelectVisible.value = true;
};
/** 确认选择鱼品种 */
const confirmFishSelect = () => {
// 统一保存为JSON数组格式新增和编辑都使用此格式
const fishIds = selectedFishList.value.map(fish => fish.id);
form.value.fishKindIds = JSON.stringify(fishIds);
fishSelectVisible.value = false;
};
/** 取消选择鱼品种 */
const cancelFishSelect = () => {
// 取消时恢复到原有选择状态
selectedFishList.value = [...originalSelectedFishList.value];
fishSelectVisible.value = false;
};
/** 获取用户列表 */
const getAquUserList = async () => {
const res = await listAquUser(userQueryParams);
aquUserList.value = res.rows || res.data || [];
userTotal.value = res.total || 0;
};
/** 打开用户选择对话框 */
const openUserSelect = () => {
// 重置搜索条件
userQueryParams.pageNum = 1;
userQueryParams.userName = undefined;
userQueryParams.mobilePhone = undefined;
getAquUserList();
userSelectVisible.value = true;
};
/** 搜索用户 */
const handleUserQuery = () => {
userQueryParams.pageNum = 1;
getAquUserList();
};
/** 重置用户搜索 */
const resetUserQuery = () => {
userQueryParams.pageNum = 1;
userQueryParams.userName = undefined;
userQueryParams.mobilePhone = undefined;
getAquUserList();
};
/** 用户分页改变 */
const handleUserPaginationChange = () => {
getAquUserList();
};
/** 选择用户 */
const handleUserSelect = (user: AquUserVO) => {
selectedUser.value = user;
form.value.userId = user.id;
userSelectVisible.value = false;
};
/** 取消选择用户 */
const cancelUserSelect = () => {
userSelectVisible.value = false;
};
/** 查询塘口列表 */
const getList = async () => {
loading.value = true;
const timeRange = queryParams.value.time;
let st = '';
let et = '';
if (timeRange && timeRange.length === 2) {
st = dayjs(timeRange[0]).format('YYYY-MM-DD');
et = dayjs(timeRange[1]).format('YYYY-MM-DD');
}
queryParams.value.params.startTime = st;
queryParams.value.params.endTime = et;
const res = await listPond(queryParams.value);
pondList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
// 注释掉清空选择列表,保持弹窗独立性
// selectedFishList.value = [];
pondFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: PondVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
selectedFishList.value = []; // 新增时清空选择列表
selectedUser.value = null; // 清空用户选择
dialog.visible = true;
dialog.title = '添加塘口';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: PondVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getPond(_id);
Object.assign(form.value, res.data);
// 解析JSON数组格式的鱼类ID
if (form.value.fishKindIds) {
const fishIds = parseFishIds(form.value.fishKindIds);
selectedFishList.value = await getFishByIds(fishIds);
} else {
selectedFishList.value = [];
}
// 回显用户信息 - 优化加载逻辑
if (form.value.userId) {
try {
// 先加载用户列表使用较大的pageSize确保包含目标用户
const userRes = await listAquUser({
pageNum: 1,
pageSize: 1000
});
const userList = userRes.rows || userRes.data || [];
const user = userList.find(u => u.id.toString() === form.value.userId.toString());
if (user) {
selectedUser.value = user;
} else {
console.warn('未找到用户ID:', form.value.userId);
selectedUser.value = null;
}
} catch (error) {
console.error('加载用户信息失败:', error);
selectedUser.value = null;
}
} else {
selectedUser.value = null;
}
dialog.visible = true;
dialog.title = '修改塘口';
};
/** 提交按钮 */
const submitForm = () => {
pondFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updatePond(form.value).finally(() => (buttonLoading.value = false));
} else {
await addPond(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: PondVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除塘口编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delPond(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'fishery/pond/export',
{
...queryParams.value
},
`pond_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>
<style scoped>
.selected-fish-panel {
border: 1px solid #dcdfe6;
border-radius: 4px;
height: 450px;
display: flex;
flex-direction: column;
}
.panel-header {
padding: 12px 16px;
border-bottom: 1px solid #ebeef5;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f5f7fa;
}
.panel-header h4 {
margin: 0;
font-size: 14px;
color: #303133;
}
.selected-list {
flex: 1;
overflow-y: auto;
padding: 8px;
}
.selected-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
margin-bottom: 6px;
background-color: #f0f9ff;
border: 1px solid #b3d8ff;
border-radius: 4px;
font-size: 13px;
}
.fish-name {
flex: 1;
color: #303133;
}
.selected-count {
color: #606266;
margin-right: auto;
font-size: 14px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 10px;
}
/* 鱼品种选择器样式 */
.fish-selector {
width: 100%;
}
.input-suffix {
display: flex;
align-items: center;
gap: 8px;
padding-right: 8px;
}
.count-badge {
background: #409eff;
color: white;
border-radius: 10px;
padding: 2px 8px;
font-size: 12px;
min-width: 16px;
text-align: center;
}
.select-icon {
color: #c0c4cc;
font-size: 14px;
}
.selected-items {
margin-top: 8px;
border: 1px solid #e4e7ed;
border-radius: 4px;
background: #f9f9f9;
}
.selected-summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid #ebeef5;
background: #f5f7fa;
}
.summary-text {
font-size: 13px;
color: #606266;
font-weight: 500;
}
.clear-btn {
color: #f56c6c;
padding: 0;
font-size: 12px;
}
.clear-btn:hover {
color: #f78989;
}
.selected-list-compact {
padding: 10px 12px;
line-height: 1.5;
color: #303133;
font-size: 14px;
}
.fish-item {
color: #409eff;
font-weight: 500;
}
.more-indicator {
color: #909399;
font-style: italic;
}
.selected-fish-tags {
max-height: 100px;
overflow-y: auto;
padding: 8px;
border: 1px solid #dcdfe6;
border-radius: 4px;
background-color: #f5f7fa;
}
.selected-fish-tags .el-tag {
margin-right: 6px;
margin-bottom: 4px;
}
</style>