|
@@ -35,18 +35,28 @@
|
|
|
<div class="flex justify-between items-end mb-4">
|
|
<div class="flex justify-between items-end mb-4">
|
|
|
<!-- Tabs -->
|
|
<!-- Tabs -->
|
|
|
<div class="flex space-x-6 border-b border-gray-200 w-64 mr-4">
|
|
<div class="flex space-x-6 border-b border-gray-200 w-64 mr-4">
|
|
|
- <div
|
|
|
|
|
|
|
+ <div
|
|
|
class="cursor-pointer pb-2 px-2 whitespace-nowrap"
|
|
class="cursor-pointer pb-2 px-2 whitespace-nowrap"
|
|
|
- :class="activeTab === 'all' ? 'text-primary border-b-2 border-primary font-medium' : 'text-gray-600'"
|
|
|
|
|
|
|
+ :class="
|
|
|
|
|
+ activeTab === 'all'
|
|
|
|
|
+ ? 'text-primary border-b-2 border-primary font-medium'
|
|
|
|
|
+ : 'text-gray-600'
|
|
|
|
|
+ "
|
|
|
@click="activeTab = 'all'"
|
|
@click="activeTab = 'all'"
|
|
|
- >全部</div>
|
|
|
|
|
- <div
|
|
|
|
|
|
|
+ >全部</div
|
|
|
|
|
+ >
|
|
|
|
|
+ <div
|
|
|
class="cursor-pointer pb-2 px-2 whitespace-nowrap"
|
|
class="cursor-pointer pb-2 px-2 whitespace-nowrap"
|
|
|
- :class="activeTab === 'selected' ? 'text-primary border-b-2 border-primary font-medium' : 'text-gray-600'"
|
|
|
|
|
|
|
+ :class="
|
|
|
|
|
+ activeTab === 'selected'
|
|
|
|
|
+ ? 'text-primary border-b-2 border-primary font-medium'
|
|
|
|
|
+ : 'text-gray-600'
|
|
|
|
|
+ "
|
|
|
@click="activeTab = 'selected'"
|
|
@click="activeTab = 'selected'"
|
|
|
- >已选择 ({{ selectedCount }})</div>
|
|
|
|
|
|
|
+ >已选择 ({{ selectedCount }})</div
|
|
|
|
|
+ >
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<!-- Pagination -->
|
|
<!-- Pagination -->
|
|
|
<el-pagination
|
|
<el-pagination
|
|
|
v-if="activeTab === 'all'"
|
|
v-if="activeTab === 'all'"
|
|
@@ -74,7 +84,12 @@
|
|
|
border
|
|
border
|
|
|
height="400px"
|
|
height="400px"
|
|
|
>
|
|
>
|
|
|
- <el-table-column type="selection" width="55" align="center" :reserve-selection="true" />
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ type="selection"
|
|
|
|
|
+ width="55"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ :reserve-selection="true"
|
|
|
|
|
+ />
|
|
|
<el-table-column label="图示" width="80" align="center">
|
|
<el-table-column label="图示" width="80" align="center">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<el-image
|
|
<el-image
|
|
@@ -84,22 +99,44 @@
|
|
|
preview-teleported
|
|
preview-teleported
|
|
|
>
|
|
>
|
|
|
<template #error>
|
|
<template #error>
|
|
|
- <div class="w-10 h-10 bg-gray-100 flex items-center justify-center text-gray-400">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="w-10 h-10 bg-gray-100 flex items-center justify-center text-gray-400"
|
|
|
|
|
+ >
|
|
|
<el-icon><Picture /></el-icon>
|
|
<el-icon><Picture /></el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-image>
|
|
</el-image>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column prop="isbn" label="ISBN" width="140" align="center" />
|
|
|
|
|
- <el-table-column prop="bookName" label="书名" min-width="200" show-overflow-tooltip />
|
|
|
|
|
-
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="isbn"
|
|
|
|
|
+ label="ISBN"
|
|
|
|
|
+ width="140"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="bookName"
|
|
|
|
|
+ label="书名"
|
|
|
|
|
+ min-width="200"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<template v-if="showDescription">
|
|
<template v-if="showDescription">
|
|
|
<el-table-column label="商品描述" min-width="200">
|
|
<el-table-column label="商品描述" min-width="200">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <div v-if="!row._editingDesc" class="cursor-pointer flex items-center" @click="row._editingDesc = true">
|
|
|
|
|
- <span class="truncate flex-1" :title="row.bookDesc || '点击输入描述'">{{ row.bookDesc || '点击输入描述' }}</span>
|
|
|
|
|
- <el-icon class="ml-1 text-gray-400"><Edit /></el-icon>
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="!row._editingDesc"
|
|
|
|
|
+ class="cursor-pointer flex items-center"
|
|
|
|
|
+ @click="row._editingDesc = true"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span
|
|
|
|
|
+ class="truncate flex-1"
|
|
|
|
|
+ :title="row.bookDesc || '点击输入描述'"
|
|
|
|
|
+ >{{ row.bookDesc || '点击输入描述' }}</span
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-icon class="ml-1 text-gray-400"
|
|
|
|
|
+ ><Edit
|
|
|
|
|
+ /></el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
<el-input
|
|
<el-input
|
|
|
v-else
|
|
v-else
|
|
@@ -108,15 +145,25 @@
|
|
|
size="small"
|
|
size="small"
|
|
|
@blur="row._editingDesc = false"
|
|
@blur="row._editingDesc = false"
|
|
|
@keyup.enter="row._editingDesc = false"
|
|
@keyup.enter="row._editingDesc = false"
|
|
|
- @input="val => updateSelectionDesc(row, val)"
|
|
|
|
|
|
|
+ @input="(val) => updateSelectionDesc(row, val)"
|
|
|
autofocus
|
|
autofocus
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <el-table-column prop="author" label="作者" width="120" show-overflow-tooltip />
|
|
|
|
|
- <el-table-column prop="price" label="价格" width="100" align="center" />
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="author"
|
|
|
|
|
+ label="作者"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="price"
|
|
|
|
|
+ label="价格"
|
|
|
|
|
+ width="100"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
|
|
|
|
@@ -130,10 +177,16 @@
|
|
|
>
|
|
>
|
|
|
<el-table-column width="55" align="center">
|
|
<el-table-column width="55" align="center">
|
|
|
<template #header>
|
|
<template #header>
|
|
|
- <el-checkbox :model-value="true" @change="handleClearAllSelections" />
|
|
|
|
|
|
|
+ <el-checkbox
|
|
|
|
|
+ :model-value="true"
|
|
|
|
|
+ @change="handleClearAllSelections"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <el-checkbox :model-value="true" @change="() => handleRemoveSelection(row)" />
|
|
|
|
|
|
|
+ <el-checkbox
|
|
|
|
|
+ :model-value="true"
|
|
|
|
|
+ @change="() => handleRemoveSelection(row)"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="图示" width="80" align="center">
|
|
<el-table-column label="图示" width="80" align="center">
|
|
@@ -145,22 +198,44 @@
|
|
|
preview-teleported
|
|
preview-teleported
|
|
|
>
|
|
>
|
|
|
<template #error>
|
|
<template #error>
|
|
|
- <div class="w-10 h-10 bg-gray-100 flex items-center justify-center text-gray-400">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="w-10 h-10 bg-gray-100 flex items-center justify-center text-gray-400"
|
|
|
|
|
+ >
|
|
|
<el-icon><Picture /></el-icon>
|
|
<el-icon><Picture /></el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-image>
|
|
</el-image>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column prop="isbn" label="ISBN" width="140" align="center" />
|
|
|
|
|
- <el-table-column prop="bookName" label="书名" min-width="200" show-overflow-tooltip />
|
|
|
|
|
-
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="isbn"
|
|
|
|
|
+ label="ISBN"
|
|
|
|
|
+ width="140"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="bookName"
|
|
|
|
|
+ label="书名"
|
|
|
|
|
+ min-width="200"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<template v-if="showDescription">
|
|
<template v-if="showDescription">
|
|
|
<el-table-column label="商品描述" min-width="200">
|
|
<el-table-column label="商品描述" min-width="200">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <div v-if="!row._editingDesc" class="cursor-pointer flex items-center" @click="row._editingDesc = true">
|
|
|
|
|
- <span class="truncate flex-1" :title="row.bookDesc || '点击输入描述'">{{ row.bookDesc || '点击输入描述' }}</span>
|
|
|
|
|
- <el-icon class="ml-1 text-gray-400"><Edit /></el-icon>
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="!row._editingDesc"
|
|
|
|
|
+ class="cursor-pointer flex items-center"
|
|
|
|
|
+ @click="row._editingDesc = true"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span
|
|
|
|
|
+ class="truncate flex-1"
|
|
|
|
|
+ :title="row.bookDesc || '点击输入描述'"
|
|
|
|
|
+ >{{ row.bookDesc || '点击输入描述' }}</span
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-icon class="ml-1 text-gray-400"
|
|
|
|
|
+ ><Edit
|
|
|
|
|
+ /></el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
<el-input
|
|
<el-input
|
|
|
v-else
|
|
v-else
|
|
@@ -169,15 +244,25 @@
|
|
|
size="small"
|
|
size="small"
|
|
|
@blur="row._editingDesc = false"
|
|
@blur="row._editingDesc = false"
|
|
|
@keyup.enter="row._editingDesc = false"
|
|
@keyup.enter="row._editingDesc = false"
|
|
|
- @input="val => updateSelectionDesc(row, val)"
|
|
|
|
|
|
|
+ @input="(val) => updateSelectionDesc(row, val)"
|
|
|
autofocus
|
|
autofocus
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <el-table-column prop="author" label="作者" width="120" show-overflow-tooltip />
|
|
|
|
|
- <el-table-column prop="price" label="价格" width="100" align="center" />
|
|
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="author"
|
|
|
|
|
+ label="作者"
|
|
|
|
|
+ width="120"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ prop="price"
|
|
|
|
|
+ label="价格"
|
|
|
|
|
+ width="100"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
|
|
|
|
@@ -228,7 +313,7 @@
|
|
|
if (activeTab.value === 'selected') {
|
|
if (activeTab.value === 'selected') {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
try {
|
|
try {
|
|
|
const params = {
|
|
const params = {
|
|
@@ -242,14 +327,18 @@
|
|
|
if (res.data.code === 200) {
|
|
if (res.data.code === 200) {
|
|
|
const data = res.data.data || res.data;
|
|
const data = res.data.data || res.data;
|
|
|
const rows = data.rows || data;
|
|
const rows = data.rows || data;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const updateRowDesc = (row) => {
|
|
const updateRowDesc = (row) => {
|
|
|
- const selectedItem = currentSelections.value.find(s => s.isbn === row.isbn);
|
|
|
|
|
|
|
+ const selectedItem = currentSelections.value.find(
|
|
|
|
|
+ (s) => s.isbn === row.isbn
|
|
|
|
|
+ );
|
|
|
if (selectedItem && selectedItem.bookDesc !== undefined) {
|
|
if (selectedItem && selectedItem.bookDesc !== undefined) {
|
|
|
row.bookDesc = selectedItem.bookDesc;
|
|
row.bookDesc = selectedItem.bookDesc;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- const defaultItem = props.defaultSelected.find(d => d.isbn === row.isbn);
|
|
|
|
|
|
|
+ const defaultItem = props.defaultSelected.find(
|
|
|
|
|
+ (d) => d.isbn === row.isbn
|
|
|
|
|
+ );
|
|
|
if (defaultItem) {
|
|
if (defaultItem) {
|
|
|
row.bookDesc = defaultItem.bookDesc;
|
|
row.bookDesc = defaultItem.bookDesc;
|
|
|
}
|
|
}
|
|
@@ -258,14 +347,21 @@
|
|
|
rows.forEach(updateRowDesc);
|
|
rows.forEach(updateRowDesc);
|
|
|
tableData.value = rows;
|
|
tableData.value = rows;
|
|
|
total.value = data.total || rows.length;
|
|
total.value = data.total || rows.length;
|
|
|
- console.log('Updated tableData:', tableData.value.length, 'rows, total:', total.value);
|
|
|
|
|
|
|
+ console.log(
|
|
|
|
|
+ 'Updated tableData:',
|
|
|
|
|
+ tableData.value.length,
|
|
|
|
|
+ 'rows, total:',
|
|
|
|
|
+ total.value
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Sync selections to table
|
|
// Sync selections to table
|
|
|
nextTick(() => {
|
|
nextTick(() => {
|
|
|
if (tableRef.value) {
|
|
if (tableRef.value) {
|
|
|
tableRef.value.clearSelection();
|
|
tableRef.value.clearSelection();
|
|
|
- rows.forEach(row => {
|
|
|
|
|
- const isSelected = currentSelections.value.some(s => s.isbn === row.isbn);
|
|
|
|
|
|
|
+ rows.forEach((row) => {
|
|
|
|
|
+ const isSelected = currentSelections.value.some(
|
|
|
|
|
+ (s) => s.isbn === row.isbn
|
|
|
|
|
+ );
|
|
|
if (isSelected) {
|
|
if (isSelected) {
|
|
|
tableRef.value.toggleRowSelection(row, true);
|
|
tableRef.value.toggleRowSelection(row, true);
|
|
|
}
|
|
}
|
|
@@ -311,24 +407,26 @@
|
|
|
|
|
|
|
|
const handleSelectionChange = (rows) => {
|
|
const handleSelectionChange = (rows) => {
|
|
|
// Get all selected rows from the table (only current page)
|
|
// Get all selected rows from the table (only current page)
|
|
|
- const currentPageSelectedIsbns = new Set(rows.map(row => row.isbn));
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const currentPageSelectedIsbns = new Set(rows.map((row) => row.isbn));
|
|
|
|
|
+
|
|
|
// Remove rows that are no longer selected on current page
|
|
// Remove rows that are no longer selected on current page
|
|
|
- currentSelections.value = currentSelections.value.filter(s =>
|
|
|
|
|
- currentPageSelectedIsbns.has(s.isbn) ||
|
|
|
|
|
- !tableData.value.some(r => r.isbn === s.isbn)
|
|
|
|
|
|
|
+ currentSelections.value = currentSelections.value.filter(
|
|
|
|
|
+ (s) =>
|
|
|
|
|
+ currentPageSelectedIsbns.has(s.isbn) ||
|
|
|
|
|
+ !tableData.value.some((r) => r.isbn === s.isbn)
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Add newly selected rows from current page
|
|
// Add newly selected rows from current page
|
|
|
- rows.forEach(row => {
|
|
|
|
|
- if (!currentSelections.value.some(s => s.isbn === row.isbn)) {
|
|
|
|
|
|
|
+ rows.forEach((row) => {
|
|
|
|
|
+ if (!currentSelections.value.some((s) => s.isbn === row.isbn)) {
|
|
|
currentSelections.value.push({ ...row });
|
|
currentSelections.value.push({ ...row });
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleClearAllSelections = (val) => {
|
|
const handleClearAllSelections = (val) => {
|
|
|
- if (!val) { // User clicked to uncheck
|
|
|
|
|
|
|
+ if (!val) {
|
|
|
|
|
+ // User clicked to uncheck
|
|
|
currentSelections.value = [];
|
|
currentSelections.value = [];
|
|
|
if (tableRef.value) {
|
|
if (tableRef.value) {
|
|
|
tableRef.value.clearSelection();
|
|
tableRef.value.clearSelection();
|
|
@@ -337,13 +435,15 @@
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleRemoveSelection = (row) => {
|
|
const handleRemoveSelection = (row) => {
|
|
|
- const idx = currentSelections.value.findIndex(s => s.isbn === row.isbn);
|
|
|
|
|
|
|
+ const idx = currentSelections.value.findIndex(
|
|
|
|
|
+ (s) => s.isbn === row.isbn
|
|
|
|
|
+ );
|
|
|
if (idx !== -1) {
|
|
if (idx !== -1) {
|
|
|
currentSelections.value.splice(idx, 1);
|
|
currentSelections.value.splice(idx, 1);
|
|
|
}
|
|
}
|
|
|
// Also untoggle in table if it's currently loaded
|
|
// Also untoggle in table if it's currently loaded
|
|
|
if (tableRef.value) {
|
|
if (tableRef.value) {
|
|
|
- const tableRow = tableData.value.find(r => r.isbn === row.isbn);
|
|
|
|
|
|
|
+ const tableRow = tableData.value.find((r) => r.isbn === row.isbn);
|
|
|
if (tableRow) {
|
|
if (tableRow) {
|
|
|
tableRef.value.toggleRowSelection(tableRow, false);
|
|
tableRef.value.toggleRowSelection(tableRow, false);
|
|
|
}
|
|
}
|
|
@@ -351,12 +451,14 @@
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const updateSelectionDesc = (row, val) => {
|
|
const updateSelectionDesc = (row, val) => {
|
|
|
- const selected = currentSelections.value.find(s => s.isbn === row.isbn);
|
|
|
|
|
|
|
+ const selected = currentSelections.value.find(
|
|
|
|
|
+ (s) => s.isbn === row.isbn
|
|
|
|
|
+ );
|
|
|
if (selected) {
|
|
if (selected) {
|
|
|
selected.bookDesc = val;
|
|
selected.bookDesc = val;
|
|
|
}
|
|
}
|
|
|
// Also update the row in tableData if it exists
|
|
// Also update the row in tableData if it exists
|
|
|
- const tableRow = tableData.value.find(r => r.isbn === row.isbn);
|
|
|
|
|
|
|
+ const tableRow = tableData.value.find((r) => r.isbn === row.isbn);
|
|
|
if (tableRow) {
|
|
if (tableRow) {
|
|
|
tableRow.bookDesc = val;
|
|
tableRow.bookDesc = val;
|
|
|
}
|
|
}
|
|
@@ -375,7 +477,9 @@
|
|
|
if (val) {
|
|
if (val) {
|
|
|
nextTick(() => {
|
|
nextTick(() => {
|
|
|
if (props.defaultSelected && props.defaultSelected.length > 0) {
|
|
if (props.defaultSelected && props.defaultSelected.length > 0) {
|
|
|
- currentSelections.value = JSON.parse(JSON.stringify(props.defaultSelected));
|
|
|
|
|
|
|
+ currentSelections.value = JSON.parse(
|
|
|
|
|
+ JSON.stringify(props.defaultSelected)
|
|
|
|
|
+ );
|
|
|
} else {
|
|
} else {
|
|
|
currentSelections.value = [];
|
|
currentSelections.value = [];
|
|
|
}
|
|
}
|
|
@@ -384,7 +488,7 @@
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
defineExpose({
|
|
defineExpose({
|
|
|
reset
|
|
reset
|
|
|
});
|
|
});
|