stock-image-modal.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <!-- 库存图片查看弹窗 -->
  2. <template>
  3. <ele-modal form :width="900" v-model="visible" title="库存图片">
  4. <div class="stock-image-container">
  5. <!-- 图片网格 -->
  6. <div v-if="imageList.length > 0" class="image-grid">
  7. <div v-for="(imageUrl, index) in imageList" :key="index" class="image-item"
  8. @click="handleImageClick(imageUrl, index)">
  9. <el-image :src="imageUrl" fit="cover" class="stock-image" :preview-src-list="imageList"
  10. :initial-index="index" :preview-teleported="true" @error="handleImageError" />
  11. </div>
  12. </div>
  13. <!-- 空状态 -->
  14. <div v-else-if="!loading" class="empty-state">
  15. <el-empty description="暂无库存图片" />
  16. </div>
  17. <!-- 加载状态 -->
  18. <div v-if="loading" class="loading-state">
  19. <el-skeleton :rows="3" animated />
  20. </div>
  21. </div>
  22. <template #footer>
  23. <!-- 分页 -->
  24. <div class="pagination-container" v-if="total > 10">
  25. <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize"
  26. :page-sizes="[10, 20, 30, 40, 50, 100]" :total="total"
  27. layout="total, sizes, prev, pager, next" @size-change="handleSizeChange"
  28. @current-change="handleCurrentChange" />
  29. </div>
  30. <el-button @click="handleCancel">关闭</el-button>
  31. </template>
  32. </ele-modal>
  33. </template>
  34. <script setup>
  35. import { ref, reactive, watch, nextTick } from 'vue';
  36. import { EleMessage } from 'ele-admin-plus/es';
  37. import request from '@/utils/request';
  38. /** 弹窗是否打开 */
  39. const visible = defineModel({ type: Boolean });
  40. /** 当前ISBN */
  41. const currentIsbn = ref('');
  42. /** 加载状态 */
  43. const loading = ref(false);
  44. /** 图片列表 */
  45. const imageList = ref([]);
  46. /** 分页信息 */
  47. const currentPage = ref(1);
  48. const pageSize = ref(10);
  49. const total = ref(0);
  50. /** 关闭弹窗 */
  51. const handleCancel = () => {
  52. visible.value = false;
  53. };
  54. /** 图片点击处理 */
  55. const handleImageClick = (imageUrl, index) => {
  56. // Element Plus 的 el-image 组件会自动处理预览
  57. console.log('点击图片:', imageUrl, '索引:', index);
  58. };
  59. /** 图片加载错误处理 */
  60. const handleImageError = (e) => {
  61. console.warn('图片加载失败:', e);
  62. };
  63. /** 分页大小改变 */
  64. const handleSizeChange = (newSize) => {
  65. pageSize.value = newSize;
  66. currentPage.value = 1;
  67. fetchStockImages();
  68. };
  69. /** 当前页改变 */
  70. const handleCurrentChange = (newPage) => {
  71. currentPage.value = newPage;
  72. fetchStockImages();
  73. };
  74. /** 获取库存图片 */
  75. const fetchStockImages = async () => {
  76. if (!currentIsbn.value) return;
  77. loading.value = true;
  78. try {
  79. const response = await request.get(`/activation/bookActivationInfo/stockImgPage/${currentIsbn.value}`, {
  80. params: {
  81. pageNum: currentPage.value,
  82. pageSize: pageSize.value
  83. }
  84. });
  85. if (response.data.code === 200) {
  86. const data = response.data;
  87. imageList.value = data.rows || [];
  88. total.value = data.total || 0;
  89. } else {
  90. EleMessage.error(response.data.msg || '获取库存图片失败');
  91. imageList.value = [];
  92. total.value = 0;
  93. }
  94. } catch (error) {
  95. console.error('获取库存图片失败:', error);
  96. EleMessage.error('获取库存图片失败');
  97. imageList.value = [];
  98. total.value = 0;
  99. } finally {
  100. loading.value = false;
  101. }
  102. };
  103. /** 弹窗打开事件 */
  104. const handleOpen = (isbn) => {
  105. if (isbn) {
  106. currentIsbn.value = isbn;
  107. visible.value = true;
  108. currentPage.value = 1;
  109. pageSize.value = 24;
  110. total.value = 0;
  111. imageList.value = [];
  112. nextTick(() => {
  113. fetchStockImages();
  114. });
  115. }
  116. };
  117. /** 监听弹窗关闭,清理数据 */
  118. watch(visible, (newVal) => {
  119. if (!newVal) {
  120. currentIsbn.value = '';
  121. imageList.value = [];
  122. total.value = 0;
  123. currentPage.value = 1;
  124. loading.value = false;
  125. }
  126. });
  127. defineExpose({
  128. handleOpen
  129. });
  130. </script>
  131. <style scoped>
  132. .stock-image-container {
  133. height: 400px;
  134. overflow: auto;
  135. }
  136. .image-grid {
  137. display: grid;
  138. grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  139. height: 150px;
  140. gap: 16px;
  141. margin-bottom: 20px;
  142. }
  143. .image-item {
  144. position: relative;
  145. cursor: pointer;
  146. border-radius: 8px;
  147. overflow: hidden;
  148. transition: transform 0.2s ease;
  149. height: 150px;
  150. }
  151. .image-item:hover {
  152. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  153. }
  154. .stock-image {
  155. width: 100%;
  156. height: 150px;
  157. border-radius: 8px;
  158. }
  159. .empty-state {
  160. display: flex;
  161. justify-content: center;
  162. align-items: center;
  163. min-height: 300px;
  164. }
  165. .loading-state {
  166. padding: 20px;
  167. }
  168. .pagination-container {
  169. background: white;
  170. display: flex;
  171. justify-content: center;
  172. padding: 0 0;
  173. z-index: 10;
  174. }
  175. </style>