PhotosIndex.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <ContentWrap>
  3. <!-- 搜索工作栏-->
  4. <el-form
  5. class="-mb-15px"
  6. :model="queryParams"
  7. ref="queryFormRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item label="照片id" prop="Id" label-width="100px" >
  12. <el-input
  13. v-model="queryParams.id"
  14. placeholder="照片id"
  15. clearable
  16. @keyup.enter="handleQuery"
  17. class="!w-240px"
  18. />
  19. </el-form-item>
  20. <!-- <el-form-item label="照片存储路径" prop="photoUrl">-->
  21. <!-- <el-input-->
  22. <!-- v-model="queryParams.photoUrl"-->
  23. <!-- placeholder="请输入照片存储路径"-->
  24. <!-- clearable-->
  25. <!-- @keyup.enter="handleQuery"-->
  26. <!-- class="!w-240px"-->
  27. <!-- />-->
  28. <!-- </el-form-item>-->
  29. <el-form-item label="上传时间" prop="createdAt">
  30. <el-date-picker
  31. v-model="queryParams.createdAt"
  32. value-format="YYYY-MM-DD"
  33. type="date"
  34. placeholder="选择上传时间"
  35. clearable
  36. class="!w-240px"
  37. />
  38. </el-form-item>
  39. <el-form-item label="创建时间" prop="createTime">
  40. <el-date-picker
  41. v-model="queryParams.createTime"
  42. value-format="YYYY-MM-DD HH:mm:ss"
  43. type="daterange"
  44. start-placeholder="开始日期"
  45. end-placeholder="结束日期"
  46. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  47. class="!w-220px"
  48. />
  49. </el-form-item>
  50. <el-form-item>
  51. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  52. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  53. <el-button
  54. type="primary"
  55. plain
  56. @click="openForm('create',zuid)"
  57. v-hasPermi="['museums:photos:create']"
  58. >
  59. <Icon icon="ep:plus" class="mr-5px" /> 新增照片
  60. </el-button>
  61. <el-button
  62. type="success"
  63. plain
  64. @click="handleExport"
  65. :loading="exportLoading"
  66. v-hasPermi="['museums:photos:export']"
  67. >
  68. <Icon icon="ep:download" class="mr-5px" /> 批量导出照片
  69. </el-button>
  70. </el-form-item>
  71. </el-form>
  72. </ContentWrap>
  73. <!-- 列表 -->
  74. <ContentWrap>
  75. <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange">
  76. <el-table-column type="selection" width="55" />
  77. <el-table-column label="id" align="center" prop="id" width="55" />
  78. <!-- <el-table-column label="照片id" align="center" prop="groupId" />-->
  79. <el-table-column label="照片" align="center" prop="photoUrl" >
  80. <template #default="{ row }">
  81. <el-image
  82. lazy
  83. class="h-80px w-80px"
  84. :src="row.photoUrl"
  85. :preview-src-list="[row.photoUrl]"
  86. preview-teleported
  87. :zoom-rate="1.2"
  88. :max-scale="7"
  89. :min-scale="0.2"
  90. :initial-index="4"
  91. fit="cover"
  92. />
  93. </template>
  94. </el-table-column>
  95. <el-table-column
  96. label="上传时间"
  97. align="center"
  98. prop="createdAt"
  99. :formatter="dateFormatter"
  100. width="180px"
  101. />
  102. <el-table-column
  103. label="创建时间"
  104. align="center"
  105. prop="createTime"
  106. :formatter="dateFormatter"
  107. width="180px"
  108. />
  109. <el-table-column label="操作" align="center" min-width="120px">
  110. <template #default="scope">
  111. <el-button
  112. link
  113. type="success"
  114. @click="handleDownload(scope.row.photoUrl)"
  115. >
  116. 下载
  117. </el-button>
  118. <el-button
  119. link
  120. type="danger"
  121. @click="handleDelete(scope.row.id)"
  122. v-hasPermi="['museums:photos:delete']"
  123. >
  124. 删除
  125. </el-button>
  126. </template>
  127. </el-table-column>
  128. </el-table>
  129. <!-- 分页 -->
  130. <Pagination
  131. :total="total"
  132. v-model:page="queryParams.pageNo"
  133. v-model:limit="queryParams.pageSize"
  134. @pagination="getList"
  135. />
  136. </ContentWrap>
  137. <!-- 表单弹窗:添加/修改 -->
  138. <PhotosForm ref="formRef" @success="getList" />
  139. </template>
  140. <script setup lang="ts">
  141. import { dateFormatter } from '@/utils/formatTime'
  142. import download from '@/utils/download'
  143. import { PhotosApi, } from '@/api/museums/photos'
  144. import PhotosForm from './PhotosForm.vue'
  145. import {ref} from "vue";
  146. import { useRoute} from 'vue-router';
  147. import JSZip from 'jszip';
  148. import { saveAs } from 'file-saver';
  149. /** 博物馆照片 列表 */
  150. defineOptions({ name: 'Photos' })
  151. const {query} = useRoute() // 查询参数
  152. const message = useMessage() // 消息弹窗
  153. const { t } = useI18n() // 国际化
  154. const loading = ref(true) // 列表的加载中
  155. const list = ref<any>([]) // 列表的数据
  156. const total = ref(0) // 列表的总页数
  157. const queryParams = reactive({
  158. id: undefined ,
  159. pageNo: 1,
  160. pageSize: 10,
  161. groupId: query.groupId,
  162. photoUrl: undefined,
  163. createdAt: undefined,
  164. createTime: []
  165. })
  166. const zuid =ref( queryParams.groupId)
  167. const queryFormRef = ref() // 搜索的表单
  168. const exportLoading = ref(false) // 导出的加载中
  169. const selectedPhotos = ref<any[]>([]) // 选中的照片
  170. /** 查询列表 */
  171. const getList = async () => {
  172. loading.value = true
  173. try {
  174. const data = await PhotosApi.getPhotosPage(queryParams)
  175. list.value = data.list
  176. total.value = data.total
  177. } finally {
  178. loading.value = false
  179. }
  180. }
  181. /** 搜索按钮操作 */
  182. const handleQuery = () => {
  183. queryParams.pageNo = 1
  184. getList()
  185. }
  186. /** 重置按钮操作 */
  187. const resetQuery = () => {
  188. queryFormRef.value.resetFields()
  189. handleQuery()
  190. }
  191. /** 添加/修改操作 */
  192. const formRef = ref()
  193. const openForm = (type: string, id?: number) => {
  194. console.log('id',id)
  195. formRef.value.open(type, id)
  196. }
  197. /** 删除按钮操作 */
  198. const handleDelete = async (id: number) => {
  199. try {
  200. // 删除的二次确认
  201. await message.delConfirm()
  202. // 发起删除
  203. await PhotosApi.deletePhotos(id)
  204. message.success(t('common.delSuccess'))
  205. // 刷新列表
  206. await getList()
  207. } catch {}
  208. }
  209. /** 处理选中变化 */
  210. const handleSelectionChange = (selection: any[]) => {
  211. selectedPhotos.value = selection
  212. }
  213. /** 导出按钮操作 */
  214. const handleExport = async () => {
  215. try {
  216. // 导出的二次确认
  217. await message.exportConfirm()
  218. // 发起导出
  219. exportLoading.value = true
  220. if (selectedPhotos.value.length === 0) {
  221. message.warning('请选择要导出的照片')
  222. return
  223. }
  224. const zip = new JSZip();
  225. const promises = selectedPhotos.value.map(async (photo) => {
  226. const response = await fetch(photo.photoUrl);
  227. const blob = await response.blob();
  228. zip.file(`${photo.id}.jpg`, blob);
  229. });
  230. await Promise.all(promises);
  231. const content = await zip.generateAsync({ type: 'blob' });
  232. saveAs(content, '选中的照片.zip');
  233. } catch {
  234. message.error('导出失败')
  235. } finally {
  236. exportLoading.value = false
  237. }
  238. }
  239. /** 下载图片 */
  240. const handleDownload = async (photoUrl: string) => {
  241. try {
  242. const response = await fetch(photoUrl)
  243. const blob = await response.blob()
  244. saveAs(blob, '照片.jpg')
  245. } catch {
  246. message.error('下载失败')
  247. }
  248. }
  249. /** 初始化 **/
  250. onMounted(() => {
  251. getList()
  252. })
  253. </script>
  254. <style scoped>
  255. .demo-image__error .image-slot {
  256. font-size: 30px;
  257. }
  258. .demo-image__error .image-slot .el-icon {
  259. font-size: 30px;
  260. }
  261. .demo-image__error .el-image {
  262. width: 100%;
  263. height: 200px;
  264. }
  265. </style>