Просмотр исходного кода

refactor: 重构录播图管理页面、图片预览组件抽离、useSearchable 组合式函数使用

IlhamTahir 1 год назад
Родитель
Сommit
0558261ba7

+ 2 - 0
components.d.ts

@@ -8,6 +8,7 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     Copyright: typeof import('./src/components/Copyright.vue')['default']
+    ImagePreviewer: typeof import('./src/components/ImagePreviewer.vue')['default']
     ImageUpload: typeof import('./src/components/ImageUpload.vue')['default']
     RegularPage: typeof import('./src/components/RegularPage.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
@@ -22,6 +23,7 @@ declare module 'vue' {
     TFormItem: typeof import('tdesign-vue-next')['FormItem']
     THeader: typeof import('tdesign-vue-next')['Header']
     TIcon: typeof import('tdesign-vue-next')['Icon']
+    TImage: typeof import('tdesign-vue-next')['Image']
     TImageViewer: typeof import('tdesign-vue-next')['ImageViewer']
     TInput: typeof import('tdesign-vue-next')['Input']
     TInputNumber: typeof import('tdesign-vue-next')['InputNumber']

+ 4 - 4
src/api/carousal.ts

@@ -1,13 +1,13 @@
 import httpClient from './httpClient'
-import type { CarousalResult, CreateCarousalsRequest, GetCarousalsRequest } from '@/model/carousals'
+import type { CarousalResult, CreateCarousalsRequest, SearchCarousalsFilter } from '@/model/carousals'
 import type { PageResult } from '@/model/base'
 
 export const createCarousal = (createCarousalsRequest: CreateCarousalsRequest) => {
   return httpClient.post<PageResult<CarousalResult>>('/carousals', createCarousalsRequest)
 }
 
-export const getCarousalList = (getCarousalsRequest:GetCarousalsRequest) => {
-  return httpClient.get<PageResult<CarousalResult>>('/carousals',getCarousalsRequest)
+export const searchCarousals = (searchCarousalsFilter: SearchCarousalsFilter) => {
+  return httpClient.get<PageResult<CarousalResult>>('/carousals',searchCarousalsFilter)
 }
 export const getCarousalItem = (id:string) => {
   return httpClient.get<CarousalResult>(`/carousals/${id}`)
@@ -27,4 +27,4 @@ export const activeCarousal = (id: string | number) => {
 
 export const inactiveCarousal = (id: string | number ) => {
   return httpClient.put<CarousalResult>(`/carousals/${id}/inactive`)
-}
+}

+ 25 - 0
src/components/ImagePreviewer.vue

@@ -0,0 +1,25 @@
+<template>
+    <TImageViewer :images="[url]">
+      <template #trigger="{ open }">
+        <div class="w-[100px] h-[100px] relative flex justify-center items-center rounded overflow-hidden">
+          <img alt="test" :src="url" class="w-full h-full object-contain" />
+          <div class="transition-all hover:opacity-100 opacity-0 w-full h-full absolute top-0 left-0 bg-[#00000099] text-white flex items-center justify-center" @click="open">
+            <span><BrowseIcon size="1.4em" /> 预览</span>
+          </div>
+        </div>
+      </template>
+    </TImageViewer>
+</template>
+<script setup lang="ts">
+
+import { BrowseIcon } from 'tdesign-icons-vue-next'
+
+defineProps<{
+  url: string,
+}>()
+
+
+</script>
+<style scoped>
+
+</style>

+ 6 - 1
src/components/RegularPage.vue

@@ -42,4 +42,9 @@ const slots = defineSlots<{
   </TCard>
 </template>
 
-<style scoped></style>
+<style scoped>
+:deep(.t-card__body) {
+  flex: 1;
+  min-height: 0;
+}
+</style>

+ 1 - 1
src/model/carousals.ts

@@ -6,7 +6,7 @@ export interface CreateCarousalsRequest {
   targetUrl?:string,
   targetId?:string
 }
-export interface GetCarousalsRequest {
+export interface SearchCarousalsFilter {
   page:number,
   size:number,
   order?:[string]

+ 39 - 115
src/pages/carousal/index.vue

@@ -1,84 +1,70 @@
 <script setup lang="ts">
 import RegularPage from '@/components/RegularPage.vue'
-import { onMounted, ref, reactive } from 'vue'
+import { onMounted,  ref } from 'vue'
 import type { BaseTableColumns } from 'tdesign-vue-next'
 import CarousalDialog from '@/pages/carousal/components/CarousalDialog.vue'
-import { activeCarousal, deleteCarousal, getCarousalList, inactiveCarousal } from '@/api/carousal'
-import { BrowseIcon } from 'tdesign-icons-vue-next'
-import type { CarousalResult } from '@/model/carousals'
+import { activeCarousal, deleteCarousal, searchCarousals, inactiveCarousal } from '@/api/carousal'
+import type { CarousalResult, SearchCarousalsFilter } from '@/model/carousals'
+import ImagePreviewer from '@/components/ImagePreviewer.vue'
+import { useSearchable } from '@/composables/useSearchable'
 
 const columns: BaseTableColumns = [
   {
     title: 'ID',
     colKey: 'id',
-    width: 100,
+    width: 100
   },
   {
     title: '轮播图',
     colKey: 'imageUrl',
-    width: 100,
+    width: 100
   },
   {
     title: '显示状态',
     colKey: 'status',
-    width: 100,
+    width: 100
   },
   {
     title: '操作',
     colKey: 'operation',
-    width: 100,
+    width: 100
   }
 ]
-const loading = ref<boolean>(false)
-const data = ref<CarousalResult[]>([])
-const pagination = reactive<{page:number,size:number,total:number}>({
-  page: 1,
-  size: 10,
-  total:0
-})
-const query = reactive<{page:number,size:number}>({
-  page:1,
-  size:10,
-})
+
+const { loading, data, pagination, fetchData, onPageChange } = useSearchable<CarousalResult, SearchCarousalsFilter>(searchCarousals)
+onMounted(fetchData)
+
+
 const carousalDialogVisible = ref<boolean>(false)
 const isEdit = ref<boolean>(false)
-const currentTableData = ref<CarousalResult | {}>({})
-const fetchSaveCarousalData = async () :Promise<void> => {
-  /* TODO: 获取轮播图表格数据 */
-  query.page = pagination.page
-  query.size = pagination.size
-  const getCarousalListApi = await getCarousalList(query)
-  data.value = getCarousalListApi.data
-  pagination.total = getCarousalListApi.pagination.total
-}
-onMounted(fetchSaveCarousalData)
-const editClick = (row:object):void => {
+const currentTableData = ref<CarousalResult | null>(null)
+
+
+const editClick = (row: object): void => {
   isEdit.value = true
   currentTableData.value = Object.assign({}, row)
   carousalDialogVisible.value = true
 }
-const showClick = async (res:CarousalResult):Promise<void> => {
-  if (res.status === 'active'){
+const showClick = async (res: CarousalResult): Promise<void> => {
+  if (res.status === 'active') {
     await inactiveCarousal(res.id)
   } else {
     await activeCarousal(res.id)
   }
-  await fetchSaveCarousalData()
+  await fetchData()
 }
-const delClick = async (row:CarousalResult) :Promise<void>=> {
+const delClick = async (row: CarousalResult): Promise<void> => {
   await deleteCarousal(row.id)
-  await fetchSaveCarousalData()
+  await fetchData()
 }
-const handleCreateCarousal = () :void => {
+const handleCreateCarousal = (): void => {
   isEdit.value = false
   carousalDialogVisible.value = true
   currentTableData.value = {}
 }
-const onPageChange = ():void => {
-  /* TODO: 分页切换 */
-}
-const handleSuccessDialog = async () :Promise<void> => {
-  await fetchSaveCarousalData()
+
+const handleSuccessDialog = async (): Promise<void> => {
+  await fetchData()
   carousalDialogVisible.value = false
 }
 </script>
@@ -91,8 +77,8 @@ const handleSuccessDialog = async () :Promise<void> => {
     <TTable
       class="w-full h-full"
       row-key="id"
-      height="92%"
       table-layout="auto"
+      height="92%"
       :data="data"
       :loading="loading"
       :columns="columns"
@@ -105,35 +91,28 @@ const handleSuccessDialog = async () :Promise<void> => {
         onChange: onPageChange
       }"
     >
-      <template #imageUrl="{row}">
-        <div class="tdesign-demo-image-viewer__base">
-          <t-image-viewer :images="[row.imageUrl]">
-            <template #trigger="{ open }">
-              <div class="tdesign-demo-image-viewer__ui-image">
-                <img alt="test" :src="row.imageUrl" class="tdesign-demo-image-viewer__ui-image--img" />
-                <div class="tdesign-demo-image-viewer__ui-image--hover" @click="open">
-                  <span><BrowseIcon size="1.4em" /> 预览</span>
-                </div>
-              </div>
-            </template>
-          </t-image-viewer>
-        </div>
+      <template #imageUrl="{ row }">
+        <ImagePreviewer :url="row.imageUrl"/>
       </template>
-      <template #status="{row}">
+      <template #status="{ row }">
         <TSpace>
-          <TTag :theme="row.status === 'active' ? 'success' : 'danger'" variant="light">{{row.status === 'active' ? '显示中' : '已关闭'}}</TTag>
+          <TTag :theme="row.status === 'active' ? 'success' : 'danger'" variant="light">{{
+            row.status === 'active' ? '显示中' : '已关闭'
+          }}</TTag>
         </TSpace>
       </template>
       <template #roles="{ row }">
         <TSpace>
           <TTag v-for="role in row.roles" :key="role.id" theme="success" variant="light">{{
-              role.label
-            }}</TTag>
+            role.label
+          }}</TTag>
         </TSpace>
       </template>
       <template #operation="{ row }">
         <TButton variant="text" size="small" theme="primary" @click="editClick(row)">编辑</TButton>
-        <TButton variant="text" size="small" theme="primary" @click="showClick(row)">{{ row.status === 'active' ? '关闭显示' : '开启显示'}}</TButton>
+        <TButton variant="text" size="small" theme="primary" @click="showClick(row)">{{
+          row.status === 'active' ? '关闭显示' : '开启显示'
+        }}</TButton>
         <TButton variant="text" size="small" theme="danger" @click="delClick(row)">删除</TButton>
       </template>
     </TTable>
@@ -148,60 +127,5 @@ const handleSuccessDialog = async () :Promise<void> => {
 </template>
 
 <style scoped>
-:deep(.t-card__body) {
-  flex: 1;
-  min-height: 0;
-}
-.tdesign-demo-image-viewer__ui-image {
-  width: 100%;
-  height: 100%;
-  display: inline-flex;
-  position: relative;
-  justify-content: center;
-  align-items: center;
-  border-radius: var(--td-radius-small);
-  overflow: hidden;
-}
-
-.tdesign-demo-image-viewer__ui-image--hover {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  position: absolute;
-  left: 0;
-  top: 0;
-  opacity: 0;
-  background-color: rgba(0, 0, 0, 0.6);
-  color: var(--td-text-color-anti);
-  line-height: 22px;
-  transition: 0.2s;
-}
 
-.tdesign-demo-image-viewer__ui-image:hover .tdesign-demo-image-viewer__ui-image--hover {
-  opacity: 1;
-  cursor: pointer;
-}
-
-.tdesign-demo-image-viewer__ui-image--img {
-  width: auto;
-  height: auto;
-  max-width: 100%;
-  max-height: 100%;
-  cursor: pointer;
-  position: absolute;
-}
-
-
-.tdesign-demo-image-viewer__ui-image--icons .tdesign-demo-icon {
-  cursor: pointer;
-}
-
-.tdesign-demo-image-viewer__base {
-  width: 100px;
-  height: 100px;
-  border: 4px solid var(--td-bg-color-secondarycontainer);
-  border-radius: var(--td-radius-medium);
-}
 </style>