|
|
@@ -12,6 +12,8 @@
|
|
|
lazy
|
|
|
scrollable
|
|
|
class="fish-table"
|
|
|
+ v-model:selection="selectedFish"
|
|
|
+ dataKey="id"
|
|
|
>
|
|
|
<template #header>
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
|
@@ -66,10 +68,19 @@
|
|
|
/>
|
|
|
<Button icon="pi pi-search" @click="handleSearch" label="搜索" size="small" severity="secondary" />
|
|
|
<Button icon="pi pi-refresh" @click="handleRefresh" label="刷新" size="small" />
|
|
|
+ <Button
|
|
|
+ v-if="isAdmin"
|
|
|
+ icon="pi pi-users"
|
|
|
+ @click="openBatchUpdateDialog"
|
|
|
+ label="批量更新所有者"
|
|
|
+ size="small"
|
|
|
+ severity="info"
|
|
|
+ />
|
|
|
<div class="flex-1"></div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
+ <Column selectionMode="multiple" headerStyle="width: 3rem" frozen></Column>
|
|
|
<Column field="id" header="ID" style="width: 80px" frozen>
|
|
|
<template #body="slotProps">
|
|
|
<span
|
|
|
@@ -231,7 +242,7 @@
|
|
|
aria-label="编辑"
|
|
|
@click="openEditDialog(slotProps.data)"
|
|
|
/>
|
|
|
- <Button
|
|
|
+ <!-- <Button
|
|
|
icon="pi pi-trash"
|
|
|
severity="danger"
|
|
|
size="small"
|
|
|
@@ -239,7 +250,7 @@
|
|
|
rounded
|
|
|
aria-label="删除"
|
|
|
@click="confirmDelete(slotProps.data)"
|
|
|
- />
|
|
|
+ /> -->
|
|
|
</div>
|
|
|
</template>
|
|
|
</Column>
|
|
|
@@ -378,11 +389,59 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</Dialog>
|
|
|
+
|
|
|
+ <!-- 批量更新所有者弹窗 -->
|
|
|
+ <Dialog
|
|
|
+ v-model:visible="batchUpdateDialog"
|
|
|
+ :modal="true"
|
|
|
+ header="批量更新所有者"
|
|
|
+ :style="{ width: '500px' }"
|
|
|
+ position="center"
|
|
|
+ >
|
|
|
+ <div class="p-fluid">
|
|
|
+ <div class="mb-4">
|
|
|
+ <p class="text-sm text-gray-600 mb-2">已选择 {{ selectedFish.length }} 条鱼苗记录</p>
|
|
|
+ <div class="max-h-32 overflow-y-auto bg-gray-50 p-3 rounded">
|
|
|
+ <div v-for="fish in selectedFish" :key="fish.id" class="text-sm mb-1">
|
|
|
+ <span class="font-medium">{{ fish.name }}</span>
|
|
|
+ <span class="text-gray-500 ml-2">({{ fish.id }})</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="field">
|
|
|
+ <label for="batch-owner" class="font-medium text-sm mb-2 block">选择新所有者</label>
|
|
|
+ <Dropdown
|
|
|
+ id="batch-owner"
|
|
|
+ v-model="batchUpdateForm.ownerId"
|
|
|
+ :options="ownerStore.owners"
|
|
|
+ optionLabel="name"
|
|
|
+ optionValue="value"
|
|
|
+ placeholder="选择所有者"
|
|
|
+ class="w-full"
|
|
|
+ @change="handleBatchOwnerChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="flex justify-end gap-3">
|
|
|
+ <Button label="取消" severity="secondary" @click="batchUpdateDialog = false" />
|
|
|
+ <Button
|
|
|
+ label="确认更新"
|
|
|
+ severity="success"
|
|
|
+ @click="saveBatchUpdate"
|
|
|
+ :loading="batchUpdateLoading"
|
|
|
+ :disabled="!batchUpdateForm.ownerId"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </Dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { listFish, deleteFish, updateFish, exportFishFriends } from '@/services/api'
|
|
|
+import { listFish, deleteFish, updateFish, exportFishFriends, batchUpdateFishOwner } from '@/services/api'
|
|
|
import { useDateFormat } from '@vueuse/core'
|
|
|
import Button from 'primevue/button'
|
|
|
import Column from 'primevue/column'
|
|
|
@@ -414,6 +473,9 @@ const tableData = ref({
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+// 选中的鱼苗
|
|
|
+const selectedFish = ref([])
|
|
|
+
|
|
|
// 加载状态
|
|
|
const loading = ref(false)
|
|
|
|
|
|
@@ -435,6 +497,14 @@ const editForm = ref({
|
|
|
result: null
|
|
|
})
|
|
|
|
|
|
+// 批量更新相关
|
|
|
+const batchUpdateDialog = ref(false)
|
|
|
+const batchUpdateLoading = ref(false)
|
|
|
+const batchUpdateForm = ref({
|
|
|
+ ownerId: null,
|
|
|
+ ownerName: null
|
|
|
+})
|
|
|
+
|
|
|
// 搜索表单
|
|
|
const searchForm = ref({
|
|
|
id: null,
|
|
|
@@ -799,6 +869,90 @@ const handleExportFriends = async (fish) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 打开批量更新弹窗
|
|
|
+const openBatchUpdateDialog = () => {
|
|
|
+ if (selectedFish.value.length === 0) {
|
|
|
+ toast.add({
|
|
|
+ severity: 'warn',
|
|
|
+ summary: '警告',
|
|
|
+ detail: '请先选择要更新的鱼苗记录',
|
|
|
+ life: 3000
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ batchUpdateForm.value = {
|
|
|
+ ownerId: null,
|
|
|
+ ownerName: null
|
|
|
+ }
|
|
|
+ batchUpdateDialog.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 处理批量更新所有者变化
|
|
|
+const handleBatchOwnerChange = (event) => {
|
|
|
+ const selectedUserId = event.value
|
|
|
+ if (selectedUserId) {
|
|
|
+ const selectedOwner = ownerStore.owners.find((owner) => owner.value === selectedUserId)
|
|
|
+ if (selectedOwner) {
|
|
|
+ batchUpdateForm.value.ownerId = selectedOwner.value
|
|
|
+ batchUpdateForm.value.ownerName = selectedOwner.name
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ batchUpdateForm.value.ownerId = null
|
|
|
+ batchUpdateForm.value.ownerName = null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 保存批量更新
|
|
|
+const saveBatchUpdate = async () => {
|
|
|
+ if (selectedFish.value.length === 0) {
|
|
|
+ toast.add({
|
|
|
+ severity: 'warn',
|
|
|
+ summary: '警告',
|
|
|
+ detail: '请先选择要更新的鱼苗记录',
|
|
|
+ life: 3000
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!batchUpdateForm.value.ownerId) {
|
|
|
+ toast.add({
|
|
|
+ severity: 'warn',
|
|
|
+ summary: '警告',
|
|
|
+ detail: '请选择新的所有者',
|
|
|
+ life: 3000
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ batchUpdateLoading.value = true
|
|
|
+ try {
|
|
|
+ const ids = selectedFish.value.map(fish => fish.id)
|
|
|
+ await batchUpdateFishOwner(ids, batchUpdateForm.value.ownerId, batchUpdateForm.value.ownerName)
|
|
|
+
|
|
|
+ toast.add({
|
|
|
+ severity: 'success',
|
|
|
+ summary: '成功',
|
|
|
+ detail: `已成功更新 ${selectedFish.value.length} 条鱼苗的所有者`,
|
|
|
+ life: 3000
|
|
|
+ })
|
|
|
+
|
|
|
+ batchUpdateDialog.value = false
|
|
|
+ selectedFish.value = []
|
|
|
+ fetchData()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('批量更新失败:', error)
|
|
|
+ toast.add({
|
|
|
+ severity: 'error',
|
|
|
+ summary: '错误',
|
|
|
+ detail: '批量更新失败,请重试',
|
|
|
+ life: 3000
|
|
|
+ })
|
|
|
+ } finally {
|
|
|
+ batchUpdateLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 初始化
|
|
|
onMounted(async () => {
|
|
|
if (isAdmin.value) {
|