Browse Source

素材列表页面

Alex 9 months ago
parent
commit
e6b36fd2c7

+ 24 - 13
src/views/marketing/dialog/components/DialogEdit.vue

@@ -12,9 +12,9 @@
         <el-input v-model="form.name" placeholder="请输入"></el-input>
       </el-form-item>
 
-      <el-form-item label="弹窗图片:" prop="imageUrl">
+      <el-form-item label="弹窗图片:" prop="img">
         <ImageUpload
-          v-model="form.imageUrl"
+          v-model="form.img"
           :limit="1"
           :drag="true"
           accept="image/*"
@@ -54,8 +54,8 @@
             >用户手动关闭</el-checkbox
           >
           <div class="auto-close-section">
-            <el-radio v-model="form.autoClose" :true-value="1" :false-value="2"
-              >显示</el-radio
+            <el-checkbox v-model="form.autoClose" true-value="1" false-value="2"
+              >显示</el-checkbox
             >
             <el-select
               v-model="form.autoCloseTime"
@@ -76,9 +76,9 @@
       <el-form-item label="出现频次:" prop="frequency">
         <el-radio-group v-model="form.frequency">
           <div class="frequency-settings">
-            <el-radio :value="1">首次访问时出现,之后不出现</el-radio>
+            <el-radio value="1">首次访问时出现,之后不出现</el-radio>
             <div class="interval-section">
-              <el-radio :value="2">间隔</el-radio>
+              <el-radio value="2">间隔</el-radio>
 
               <div style="display: flex; align-items: center">
                 <el-select
@@ -146,13 +146,13 @@
     plat: '',
     deliveryPage: '',
     userClose: '1',
-    autoClose: 2,
+    autoClose: '2',
     autoCloseTime: 5,
-    frequency: 1,
+    frequency: '1',
     frequencyTime: 24,
     status: 1,
     timeRange: [],
-    imageUrl: ''
+    img: ''
   };
 
   // 表单数据
@@ -169,9 +169,7 @@
     timeRange: [
       { required: true, message: '请选择起止时间', trigger: 'change' }
     ],
-    imageUrl: [
-      { required: true, message: '请上传弹窗图片', trigger: 'change' }
-    ],
+    img: [{ required: true, message: '请上传弹窗图片', trigger: 'change' }],
     frequency: [
       { required: true, message: '请选择出现频次', trigger: 'change' }
     ]
@@ -183,9 +181,22 @@
     Object.assign(form, defaultForm);
 
     // 如果有数据,则填充表单
+    console.log(data,'data');
     if (data) {
       // 设置基本字段
-      Object.assign(form, data);
+      form.id = data.id;
+      form.img = data.img;
+      form.name = data.name;
+      form.jumpPage = data.jumpPage;
+      form.plat = data.plat;
+      form.deliveryPage = data.deliveryPage;
+      form.userClose = data.userClose;
+      form.autoClose = data.autoClose;
+      form.autoCloseTime = data.autoCloseTime;
+      form.frequency = data.frequency;
+      form.frequencyTime = data.frequencyTime;
+      console.log(form,'xxx');
+
 
       // 设置时间范围
       if (data.startTime && data.endTime) {

+ 16 - 36
src/views/marketing/dialog/index.vue

@@ -41,11 +41,17 @@
       </template>
 
       <template #afterCloseType="{ row }">
-        <el-tag
-          :type="row.autoClose === '用户手动关闭' ? 'primary' : 'warning'"
-        >
-          {{ row.autoClose }}
-        </el-tag>
+        <div class="flex flex-col">
+            <el-text v-if="row.userClose == 1">用户手动关闭</el-text>
+            <el-text v-if="row.autoClose == 1">显示{{row.autoCloseTime}}秒后自动关闭</el-text>
+        </div>
+      </template>
+
+      <template #frequency="{ row }">
+        <div>
+          <el-text v-if="row.frequency == 1">首次访问时出现,之后不出现</el-text>
+          <el-text v-if="row.frequency == 2">间隔{{row.frequencyTime}}小时后再次出现</el-text>
+        </div>
       </template>
 
       <template #time="{ row }">
@@ -118,7 +124,7 @@
       label: '跳转页面',
       prop: 'jumpPage',
       align: 'center',
-      minWidth: 160
+      minWidth: 200
     },
     {
       label: '投放端',
@@ -143,14 +149,14 @@
       label: '出现频次',
       prop: 'frequency',
       align: 'center',
-      minWidth: 100
+      minWidth: 150,
+      slot: 'frequency'
     },
     {
       label: '状态',
       prop: 'status',
       align: 'center',
       minWidth: 100,
-      slot: 'status'
     },
     {
       label: '起止时间',
@@ -199,40 +205,14 @@
       request.get(`/sys/dialogInfo/getInfo/${row.id}`).then((res) => {
         if (res.data.code === 200) {
           const data = res.data.data;
-          // 转换API返回的数据格式为表单需要的格式
-          const formData = {
-            id: data.id,
-            name: data.name,
-            jumpPage: data.jumpPage,
-            plat: data.plat,
-            deliveryPage: data.deliveryPage,
-            autoClose: data.userClose ? '用户手动关闭' : '自动关闭',
-            frequency: data.frequency,
-            status: data.status === 1 ? '进行中' : '已结束',
-            startTime: data.startTime,
-            endTime: data.endTime,
-            imageUrl: data.img
-          };
-          dialogEditRef.value.handleOpen(formData);
+          dialogEditRef.value.handleOpen(data);
         } else {
           EleMessage.error(res.data.msg || '获取弹窗详情失败');
         }
       });
     } else {
       // 新建模式
-      dialogEditRef.value.handleOpen({
-        id: '',
-        name: '',
-        jumpPage: '',
-        plat: '',
-        deliveryPage: '',
-        autoClose: '用户手动关闭',
-        frequency: '',
-        status: '进行中',
-        startTime: '',
-        endTime: '',
-        imageUrl: ''
-      });
+      dialogEditRef.value.handleOpen();
     }
   }
 

+ 2 - 2
src/views/marketing/material/components/file-group.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="file-group-container">
-    <el-tabs v-model="materialType" class="file-picker-tabs">
+    <!-- <el-tabs v-model="materialType" class="file-picker-tabs">
       <el-tab-pane label="图片" name="1"></el-tab-pane>
       <el-tab-pane label="视频" name="2"></el-tab-pane>
-    </el-tabs>
+    </el-tabs> -->
 
     <div
       v-for="item in groupData"

+ 0 - 471
src/views/marketing/material/components/file-list.vue

@@ -1,471 +0,0 @@
-<template>
-  <div class="file-picker-main">
-    <div class="file-picker-body">
-      <div class="file-picker-toolbar">
-        <ElUpload
-          action=""
-          :accept="accept"
-          :showFileList="false"
-          :beforeUpload="handleUpload"
-        >
-          <ElButton type="primary" class="ele-btn-icon" :icon="UploadOutlined">
-            上传
-          </ElButton>
-        </ElUpload>
-        <div class="file-picker-search">
-          <ElInput
-            :clearable="true"
-            v-model="searchKeyword"
-            placeholder="请输入文件名"
-            @clear="handleSearch"
-            @change="handleSearch"
-          />
-          <ElButton type="primary" @click="handleSearch">搜索</ElButton>
-        </div>
-        <EleSegmented v-model="isGridMode" :items="modeSegmentedItems" />
-      </div>
-      <template v-if="fileData.length">
-        <div class="file-picker-file-list" @scroll="handleFileListScroll">
-          <EleFileList
-            :boxChoose="true"
-            :icons="localIcons"
-            :smallIcons="localSmallIcons"
-            :contextMenuProps="contextMenuProps"
-            v-bind="fileListProps || {}"
-            :data="fileData"
-            :grid="isGridMode === 1"
-            :selectionType="limit === 1 ? 'radio' : 'checkbox'"
-            :selections="fileSelections"
-            v-model:current="fileCurrent"
-            :contextMenus="fileContextMenus"
-            :class="[{ 'is-ping-top': isPingTop }]"
-            @itemClick="handleFileItemClick"
-            @itemContextMenu="handleFileCtxMenuClick"
-            @update:selections="updateSelections"
-            @itemContextOpen="handleFileCtxMenuOpen"
-          />
-        </div>
-        <ElePagination
-          size="small"
-          :teleported="false"
-          :pageSizes="[18, 24, 30, 36, 40, 42]"
-          layout="total,prev,pager,next,sizes"
-          v-bind="paginationProps || {}"
-          :currentPage="currentPage"
-          :pageSize="pageSize"
-          :total="total"
-          @update:currentPage="handleCurrentPageChange"
-          @update:pageSize="handlePageSizeChange"
-        />
-      </template>
-      <ElEmpty
-        v-else
-        :imageSize="80"
-        description="无数据"
-        v-bind="emptyProps || {}"
-      />
-    </div>
-  </div>
-</template>
-
-<script setup>
-  import { ref, reactive, watch, markRaw } from 'vue';
-  import {
-    localIcons,
-    localSmallIcons
-  } from 'ele-admin-plus/es/ele-file-list/icons';
-  import {
-    UploadOutlined,
-    MenuOutlined,
-    AppstoreOutlined,
-    EditOutlined,
-    DeleteOutlined
-  } from '@/components/icons';
-  import { uploadFile, fetchSourcePageList } from '@/api/system/file';
-  import request from '@/utils/request';
-
-  const props = defineProps({
-    /** 最大选择数量 */
-    limit: Number,
-    /** 文件大小限制, 单位MB */
-    fileLimit: Number,
-    /** 接受上传的文件类型 */
-    accept: String,
-    /** 接口查询参数 */
-    params: Object,
-    /** 文件列表自定义属性 */
-    fileListProps: Object,
-    /** 空组件属性 */
-    emptyProps: Object,
-    /** 分页组件属性 */
-    paginationProps: Object,
-    /** 统一设置层级 */
-    baseIndex: Number,
-    /** 消息提示组件 */
-    messageIns: [Object, Function],
-    /** 文件分类 */
-    sourceCate: String,
-    /** 文件类型 */
-    sourceType: String
-  });
-
-  const emit = defineEmits([
-    'queryStart',
-    'queryDone',
-    'renameFile',
-    'moveFile',
-    'removeFile',
-    'fileItemContextOpen'
-  ]);
-
-  /** 当前分组id */
-  const fileParentId = ref();
-
-  /** 文件数据 */
-  const fileData = ref([]);
-
-  /** 选中的文件数据 */
-  const fileSelections = ref([]);
-
-  /** 单选选中的文件数据 */
-  const fileCurrent = ref();
-
-  /** 是否网格模式 */
-  const isGridMode = ref(1);
-
-  /** 搜索关键字 */
-  const searchKeyword = ref('');
-
-  /** 当前页码 */
-  const currentPage = ref(1);
-
-  /** 每页显示数量 */
-  const pageSize = ref(40);
-
-  /** 总数量 */
-  const total = ref(0);
-
-  /** 文件列表是否固定表头 */
-  const isPingTop = ref(false);
-
-  /** 视图模式分段器数据 */
-  const modeSegmentedItems = [
-    { icon: MenuOutlined, value: 0, iconStyle: { transform: 'scale(0.9)' } },
-    { icon: AppstoreOutlined, value: 1 }
-  ];
-
-  /** 文件列表右键菜单属性 */
-  const contextMenuProps = reactive({
-    menuStyle: { minWidth: '120px' },
-    iconProps: { size: 15 },
-    popperOptions: { strategy: 'fixed' },
-    zIndex: props.baseIndex
-  });
-
-  /** 校验最大选择数量 */
-  const checkLimit = (selections, isAdd) => {
-    if (
-      props.limit &&
-      props.limit > 1 &&
-      (isAdd
-        ? selections.length >= props.limit
-        : selections.length > props.limit)
-    ) {
-      props.messageIns?.error?.(`最多只能选择 ${props.limit} 个`);
-      return false;
-    }
-  };
-
-  /** 更新选中数据 */
-  const updateSelections = (selections) => {
-    if (checkLimit(selections) !== false) {
-      fileSelections.value = selections;
-      return;
-    }
-    if (props.limit && props.limit > 1) {
-      fileSelections.value = selections.slice(0, props.limit);
-    }
-  };
-
-  /** 清空选中 */
-  const clearSelections = () => {
-    fileSelections.value = [];
-    fileCurrent.value = void 0;
-  };
-
-  /** 搜索 */
-  const handleSearch = () => {
-    queryData({ pageNum: 1 });
-  };
-
-  /** 切换当前页码 */
-  const handleCurrentPageChange = (page) => {
-    if (currentPage.value !== page) {
-      currentPage.value = page;
-      queryData();
-    }
-  };
-
-  /** 切换每页显示数量 */
-  const handlePageSizeChange = (limit) => {
-    if (pageSize.value !== limit) {
-      currentPage.value = 1;
-      pageSize.value = limit;
-      const maxPage = Math.ceil(total.value / limit);
-      if (maxPage && currentPage.value > maxPage) {
-        currentPage.value = maxPage;
-      }
-      queryData();
-    }
-  };
-
-  /** 文件列表点击事件 */
-  const handleFileItemClick = (item) => {
-    if (props.limit === 1) {
-      fileCurrent.value = item;
-      return;
-    }
-    const index = fileSelections.value.findIndex((d) => d.key === item.key);
-    if (index !== -1) {
-      fileSelections.value.splice(index, 1);
-      return;
-    }
-    if (checkLimit(fileSelections.value, true) !== false) {
-      fileSelections.value.push(item);
-    }
-  };
-
-  /** 文件列表右键菜单点击事件 */
-  const handleFileCtxMenuClick = (option) => {
-    const { key, item } = option;
-    const userFileItem = item.userFile;
-    if (key === 'preview') {
-      if (!item.thumbnail) {
-        window.open(item.url);
-        return;
-      }
-      const data = fileData.value.filter((d) => !!d.thumbnail);
-      const urls = data.map((d) => d.url);
-      const index = data.indexOf(item);
-      if (index !== -1) {
-        window.open(item.url);
-      }
-    } else if (key === 'rename') {
-      emit('renameFile', userFileItem, true);
-    } else if (key === 'move') {
-      emit('moveFile', userFileItem, true);
-    } else if (key === 'remove') {
-      emit('removeFile', userFileItem, true);
-    }
-  };
-
-  /** 文件列表右键菜单数据 */
-  const fileContextMenus = (item) => {
-    const menus = [
-      {
-        title: '重命名',
-        command: 'rename',
-        icon: markRaw(EditOutlined)
-      },
-      {
-        title: '删除',
-        command: 'remove',
-        icon: markRaw(DeleteOutlined),
-        divided: true,
-        danger: true
-      }
-    ];
-    if (item.thumbnail) {
-      menus[0].divided = true;
-      menus.unshift({ title: '预览', command: 'preview' });
-    } else {
-      menus[0].divided = true;
-      menus.unshift({ title: '打开', command: 'preview' });
-    }
-    return menus;
-  };
-
-  /** 文件列表右键菜单打开事件 */
-  const handleFileCtxMenuOpen = () => {
-    emit('fileItemContextOpen');
-  };
-
-  /** 校验选择的文件 */
-  const checkFile = (file) => {
-    if (!file) {
-      return;
-    }
-    if (props.accept === 'image/*') {
-      if (!file.type.startsWith('image')) {
-        props.messageIns?.error?.('只能选择图片');
-        return;
-      }
-    } else if (props.accept === '.xls,.xlsx') {
-      if (
-        ![
-          'application/vnd.ms-excel',
-          'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
-        ].includes(file.type)
-      ) {
-        props.messageIns?.error?.('只能选择 excel 文件');
-        return;
-      }
-    }
-    if (props.fileLimit && file.size / 1024 / 1024 > props.fileLimit) {
-      props.messageIns?.error?.(`大小不能超过 ${props.fileLimit}MB`);
-      return;
-    }
-    return true;
-  };
-
-  /** 文件上传事件 */
-  const handleUpload = (file) => {
-    if (checkFile(file)) {
-      const loading = props.messageIns?.loading?.({
-        message: '上传中..',
-        plain: true,
-        mask: true
-      });
-      uploadFile(file).then((res) => {
-        if (res.code === 200) {
-          file.url = res.url;
-          addFileToDir(file);
-          props.messageIns?.success?.('上传成功');
-        } else {
-          props.messageIns?.error?.(res.msg);
-        }
-      }).finally(() => {
-        loading?.close?.();
-      });
-    }
-    return false;
-  };
-  //新增文件到指定目录
-  const addFileToDir = (file) => {
-    let data = {
-      sourceName: file.name,
-      sourceUrl: file.url,
-      sourceType: props.sourceType,
-      sourceCate: props.sourceCate
-    };
-    request
-      .post('/baseinfo/source/add', data)
-      .then((res) => {
-        if (res.data.code === 200) {
-          props.messageIns?.success?.('上传成功');
-          queryData();
-        } else {
-          props.messageIns?.error?.(res.data.msg);
-        }
-      })
-  };
-
-  /** 文件列表滚动事件 */
-  const handleFileListScroll = (e) => {
-    const wrapEl = e.currentTarget;
-    const scrollTop = wrapEl.scrollTop;
-    isPingTop.value = scrollTop > 1;
-  };
-
-  /** 触发文件数据请求完成 */
-  const handleQueryDone = () => {
-    emit('queryDone');
-  };
-
-  /** 判断是否是图片文件 */
-  const isImageFile = (item) => {
-    // 根据sourceType判断是否为图片,1为图片
-    if (item.sourceType === '1') {
-      return true;
-    }
-    return (
-      typeof item.contentType === 'string' &&
-      item.contentType.startsWith('image/') &&
-      item.sourceUrl
-    );
-  };
-
-  /** 格式化文件大小 */
-  const formatLength = (length) => {
-    if (length == null) {
-      return '-';
-    }
-    if (length < 1024) {
-      return length + 'B';
-    } else if (length < 1024 * 1024) {
-      return (length / 1024).toFixed(1) + 'KB';
-    } else if (length < 1024 * 1024 * 1024) {
-      return (length / 1024 / 1024).toFixed(1) + 'M';
-    } else {
-      return (length / 1024 / 1024 / 1024).toFixed(1) + 'G';
-    }
-  };
-
-  /** 查询文件数据 */
-  const queryData = (params) => {
-    emit('queryStart');
-
-    // 构建请求参数
-    const requestParams = {
-      sourceNameLike: searchKeyword.value,
-      sourceType: props.sourceType,
-      sourceCate: props.sourceCate,
-      pageNum: currentPage.value,
-      pageSize: pageSize.value,
-    };
-
-    // 使用新的API
-    fetchSourcePageList(requestParams)
-      .then((result) => {
-        console.log('result:', result);
-        if (!result?.rows?.length && result?.total) {
-          const maxPage = Math.ceil(result.total / pageSize.value);
-          if (maxPage && currentPage.value > maxPage) {
-            queryData({ pageNum: maxPage });
-            return;
-          }
-        }
-        total.value = result?.total || 0;
-        fileData.value =
-          result?.rows?.map?.((d) => {
-            return {
-              key: d.id,
-              name: d.sourceName,
-              url: d.sourceUrl,
-              thumbnail: isImageFile(d) ? d.sourceUrl : void 0,
-              length: formatLength(d.length),
-              updateTime: d.createTime,
-              isDirectory: false,
-              userFile: {
-                ...d,
-                name: d.sourceName,
-                url: d.sourceUrl
-              }
-            };
-          }) || [];
-        console.log('fileData:', fileData.value);
-        handleQueryDone();
-      })
-      .catch((e) => {
-        fileData.value = [];
-        props.messageIns?.error?.(e.message);
-        handleQueryDone();
-      });
-  };
-
-  watch(
-    () => props.limit,
-    () => {
-      clearSelections();
-    }
-  );
-
-  watch(
-    () => props.baseIndex,
-    (baseIndex) => {
-      contextMenuProps.zIndex = baseIndex;
-    }
-  );
-
-  defineExpose({ queryData, clearSelections });
-</script>

+ 46 - 35
src/views/marketing/material/index.vue

@@ -7,7 +7,11 @@
           :source-type="searchParams.sourceType"
           @groupSelect="handleGroupSelect"
         />
-        <div class="flex-1 ml-4" v-loading="loading" element-loading-text="上传中...">
+        <div
+          class="flex-1 ml-4"
+          v-loading="loading"
+          element-loading-text="上传中..."
+        >
           <div class="flex items-center">
             <el-button
               type="primary"
@@ -77,11 +81,8 @@
                 fit="cover"
               />
 
-              <div
-                class="mask-error flex items-center justify-center"
-                v-if="item.defaultUse == 1"
-              >
-                <el-text type="primary" size="small">默认图片</el-text>
+              <div class="mask-error">
+                <span>{{ item.sourceName }}</span>
               </div>
             </div>
           </el-checkbox-group>
@@ -119,17 +120,16 @@
     sourceType: '1', //1图片 2视频
     sourceCate: '-1' //-1全部 1素材
   });
-  const selectedGroupId = ref('-1');
   const handleGroupSelect = (item) => {
-    selectedGroupId.value = item.id;
-    getImageList();
+    searchParams.value.sourceCate = item.id;
+    getImageList(searchParams.value);
   };
 
-  const pageParams = ref({ pageNum: 1, pageSize: 50, ...searchParams.value });
+  const pageParams = ref({ pageNum: 1, pageSize: 50 });
   const getImageList = (data = {}) => {
     request
       .get('/baseinfo/source/pagelist', {
-        params: { ...pageParams.value, ...data }
+        params: { ...pageParams.value, ...searchParams.value, ...data }
       })
       .then((res) => {
         if (res.data.code == 200) {
@@ -138,7 +138,9 @@
         }
       });
   };
-  getImageList();
+  onMounted(() => {
+    getImageList();
+  });
   //重置
   const handleReset = () => {
     searchParams.value.sourceNameLike = '';
@@ -190,27 +192,14 @@
 
   //选中图片
   const handlecheckboxChange = (value) => {
-    let last = value[value.length - 1];
-    checkList.value = [last];
-  };
-
-  const handleSetDefault = () => {
-    if (checkList.value.length == 0) {
-      ElMessage({ type: 'warning', message: '请选择图片' });
-      return;
-    }
-    ElMessageBox.confirm('是否将该图片设置默认图片?', '提示').then(() => {
-      request
-        .post('/baseinfo/img/setDefault?id=' + checkList.value[0])
-        .then((res) => {
-          if (res.data.code == 200) {
-            ElMessage({ type: 'success', message: '设置成功' });
-            getImageList();
-          }
-        });
-    });
+    //单选
+    // let last = value[value.length - 1];
+    // checkList.value = [last];
+    //多选
+    checkList.value = value;
   };
 
+  //删除图片
   const handleDelete = () => {
     if (checkList.value.length == 0) {
       ElMessage({ type: 'warning', message: '请选择图片' });
@@ -221,6 +210,7 @@
         .post('/baseinfo/source/deleteBatch', { idList: checkList.value })
         .then((res) => {
           if (res.data.code == 200) {
+            ElMessage({ type: 'success', message: '删除成功' });
             getImageList();
           }
         });
@@ -232,7 +222,11 @@
       ElMessage({ type: 'warning', message: '请选择图片' });
       return;
     }
-    window.open(imageList.value[0].imgUrl);
+    // Find the selected image from the imageList
+    const selectedImage = imageList.value.find(img => img.id === checkList.value[0]);
+    if (selectedImage) {
+      window.open(selectedImage.sourceUrl);
+    }
   };
 </script>
 
@@ -260,12 +254,29 @@
     }
     .mask-error {
       width: 100%;
-      height: 26px;
-      background-color: rgba(0, 0, 0, 0.1);
+      height: 30px;
+      background-color: rgba(0, 0, 0, 0.2);
       position: absolute;
-      overflow: hidden;
       bottom: 0;
       left: 0;
+      color: #fff;
+      padding: 0 5px;
+      box-sizing: border-box;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-bottom-left-radius: 6px;
+      border-bottom-right-radius: 6px;
+
+      span {
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        text-align: center;
+        font-size: 12px;
+        font-weight: 500;
+      }
     }
   }
 </style>

+ 0 - 301
src/views/marketing/material/index1.vue

@@ -1,301 +0,0 @@
-<!-- 文件选择器 -->
-<template>
-  <div class="file-picker-container">
-    <el-tabs v-model="searchParams.sourceType" class="file-picker-tabs">
-      <el-tab-pane label="图片" name="1"></el-tab-pane>
-      <el-tab-pane label="视频" name="2"></el-tab-pane>
-    </el-tabs>
-
-    <EleSplitPanel
-      ref="splitRef"
-      space="0px"
-      size="186px"
-      :flexTable="true"
-      :allowCollapse="mobile"
-      :customStyle="{ borderWidth: '0 1px 0 0' }"
-      class="file-picker-wrapper"
-    >
-      <FileGroup
-        ref="fileGroupRef"
-        :groupData="groupData"
-        :selectedId="groupSelected?.id"
-        @groupSelect="handleGroupSelect"
-      />
-      <template #body>
-        <FileList
-          ref="fileListRef"
-          :limit="limit"
-          :sourceType="searchParams.sourceType"
-          :sourceCate="searchParams.sourceCate"
-          :fileLimit="fileLimit"
-          :accept="searchParams.sourceType == 1 ? 'image/*' : '.mp4'"
-          :fileListProps="fileListProps"
-          :selectionListProps="selectionListProps"
-          :emptyProps="emptyProps"
-          :paginationProps="paginationProps"
-          :baseIndex="componentIndex"
-          :messageIns="messageIns"
-          @queryStart="showLoading"
-          @queryDone="hideLoading"
-        />
-      </template>
-    </EleSplitPanel>
-    <EleLoading :loading="loading" class="file-picker-loading" />
-    <!-- 消息提示容器 -->
-    <div
-      ref="messageWrapRef"
-      class="ele-message-wrapper"
-      :style="{ position: 'fixed', zIndex: messageIndex }"
-    ></div>
-    <div
-      ref="messageBoxWrapRef"
-      class="ele-message-box-wrapper"
-      :style="{ position: 'fixed', zIndex: messageIndex }"
-    ></div>
-  </div>
-</template>
-
-<script setup>
-  import { ref, computed, nextTick, onMounted, getCurrentInstance } from 'vue';
-  import { useMessage, useMessageBox } from 'ele-admin-plus/es';
-  import { useMobile } from '@/utils/use-mobile';
-  import FileGroup from './components/file-group.vue';
-  import FileList from './components/file-list.vue';
-  import { listUserFiles } from '@/api/system/file';
-
-  const { proxy } = getCurrentInstance();
-
-  defineOptions({ name: 'FilePicker' });
-
-  const props = defineProps({
-    /** 标题 */
-    title: {
-      type: String,
-      default: '文件选择'
-    },
-    /** 弹窗参数 */
-    modalProps: Object,
-    /** 最大选择数量 */
-    limit: Number,
-    /** 文件大小限制, 单位MB */
-    fileLimit: {
-      type: Number,
-      default: 100
-    },
-    /** 接受上传的文件类型 */
-    accept: String,
-    /** 接口查询参数 */
-    params: Object,
-    /** 文件列表自定义属性 */
-    fileListProps: Object,
-    /** 已选列表自定义属性 */
-    selectionListProps: Object,
-    /** 空组件属性 */
-    emptyProps: Object,
-    /** 分页组件属性 */
-    paginationProps: Object,
-    /** 统一设置层级 */
-    baseIndex: Number
-  });
-
-  const emit = defineEmits(['done', 'close']);
-
-  /** 是否是移动端 */
-  const { mobile } = useMobile();
-
-  /** 分割面板组件 */
-  const splitRef = ref(null);
-
-  /** 文件分组组件 */
-  const fileGroupRef = ref(null);
-
-  /** 文件列表组件 */
-  const fileListRef = ref(null);
-
-  /** 数据请求状态 */
-  const loading = ref(false);
-
-  /** 分组数据 */
-  const groupData = ref([]);
-
-  /** 选中分组数据 */
-  const groupSelected = ref(null);
-
-  /** 组件统一层级 */
-  const componentIndex = computed(() => {
-    if (props.baseIndex == null) {
-      return;
-    }
-    return props.baseIndex + 100;
-  });
-
-  /** 消息提示组件层级 */
-  const messageIndex = computed(() => {
-    if (componentIndex.value == null) {
-      return 3000;
-    }
-    return componentIndex.value + 100;
-  });
-
-  /** 消息提示容器 */
-  const messageWrapRef = ref();
-
-  /** 消息弹出框容器 */
-  const messageBoxWrapRef = ref();
-
-  /** 消息提示框 */
-  const messageIns = useMessage({
-    inner: true,
-    appendTo: messageWrapRef
-  });
-
-  /** 分组选中 */
-  const handleGroupSelect = (item, isTreeClick) => {
-    if (groupSelected.value != null && mobile.value) {
-      splitRef.value?.toggleCollapse?.(true);
-    }
-    if (item && item.id != null) {
-      if (!isTreeClick) {
-        fileGroupRef.value?.setSelectedGroup?.(item);
-      }
-      if (groupSelected.value == null || groupSelected.value.id !== item.id) {
-        groupSelected.value = item;
-        queryData({ sourceCate: item.id });
-      }
-    }
-  };
-
-  /** 关闭请求加载图标 */
-  const hideLoading = () => {
-    loading.value = false;
-  };
-
-  /** 打开请求加载图标 */
-  const showLoading = () => {
-    loading.value = true;
-  };
-
-  //获取分组数据
-  const getGroupData = () => {
-    proxy.$http.get(`/system/dict/data/type/material_file`).then((res) => {
-      if (res.data.code === 200) {
-        groupData.value = res.data.data.map((item) => ({
-          ...item,
-          name: item.dictLabel,
-          id: item.dictValue
-        }));
-      }
-    });
-  };
-
-  const searchParams = ref({
-    sourceNameLike: '',
-    sourceType: '1',
-    sourceCate: '-1'
-  });
-
-  /** 查询分组数据 */
-  const queryGroup = (sourceCate) => {
-    showLoading();
-    listUserFiles({ isDirectory: 1, sourceCate })
-      .then((list) => {
-        const oldSelected =
-          groupSelected.value == null
-            ? void 0
-            : findTree(result, (d) => d.id === groupSelected.value?.id);
-        groupSelected.value = null;
-        nextTick(() => {
-          handleGroupSelect(oldSelected || result[0]);
-        });
-      })
-      .catch((e) => {
-        messageIns.error(e.message);
-        hideLoading();
-      });
-  };
-
-  /** 刷新文件数据 */
-  const queryData = (params) => {
-    showLoading();
-    const queryParams =
-      params == null
-        ? void 0
-        : { page: 1, sourceNameLike: '', sourceCate: params.sourceCate };
-    fileListRef.value && fileListRef.value.queryData(queryParams);
-  };
-
-  /** 清空文件选中 */
-  const clearSelections = () => {
-    fileListRef.value && fileListRef.value.clearSelections();
-  };
-
-  /** 初始化数据 */
-  const initData = () => {
-    clearSelections();
-    queryGroup();
-  };
-
-  /** 弹窗打开事件 */
-  const handleOpen = () => {
-    clearSelections();
-    queryGroup();
-  };
-
-  /** 弹窗关闭事件 */
-  const handleClose = () => {
-    clearSelections();
-    emit('close');
-  };
-
-  /** 确定按钮点击事件 */
-  const handleConfirm = () => {
-    showLoading();
-    emit('done', fileListRef.value?.getSelections?.() || []);
-  };
-
-  // 组件挂载时初始化数据
-  onMounted(() => {
-    getGroupData();
-  });
-
-  defineExpose({ hideLoading });
-</script>
-
-<style lang="scss">
-  @use './style/index.scss';
-
-  .file-picker-container {
-    display: flex;
-    flex-direction: column;
-    height: 100%;
-    width: calc(100% - 24px);
-    position: relative;
-    background-color: #fff;
-    margin: 12px;
-
-    .file-picker-tabs {
-      width: 100%;
-      padding: 0 12px;
-    }
-
-    .file-picker-wrapper {
-      flex: 1;
-      overflow: hidden;
-    }
-
-    .file-picker-footer {
-      padding: 12px 16px;
-      text-align: right;
-      border-top: 1px solid #ebeef5;
-    }
-
-    .file-picker-loading {
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      z-index: 100;
-    }
-  }
-</style>

+ 0 - 407
src/views/marketing/material/style/index.scss

@@ -1,407 +0,0 @@
-.file-picker-modal {
-  max-height: 94vh;
-  max-height: 94dvh;
-  min-height: 434px;
-  display: flex;
-  flex-direction: column;
-
-  & > .el-dialog__body {
-    flex: 1;
-    overflow: hidden;
-
-    & > .ele-modal-body {
-      height: 100%;
-      overflow: hidden;
-      padding: 0;
-    }
-  }
-}
-
-.file-picker-wrapper {
-  height: 580px;
-  max-height: 100%;
-  overflow: hidden !important;
-
-  .ele-split-collapse-button {
-    top: auto;
-    bottom: 124px;
-    margin-top: 0;
-  }
-
-  &.is-collapse .ele-split-collapse-button {
-    margin-left: 6px;
-  }
-}
-
-.file-picker-loading {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  pointer-events: none;
-
-  & > .ele-loading-spinner {
-    background: none;
-    border-radius: var(--el-border-radius-base);
-    pointer-events: auto;
-  }
-}
-
-.file-picker-tree-icon {
-  width: 18px;
-  height: 18px;
-  margin-right: 6px;
-  user-select: none;
-}
-
-.file-picker-wrapper .file-picker-left {
-  flex: 1;
-  padding-top: 8px;
-  padding-bottom: 8px;
-  padding-left: calc(var(--ele-tree-item-radius) * 2);
-  padding-right: calc(var(--ele-tree-item-radius) * 2);
-  box-sizing: border-box;
-  overflow-x: hidden;
-  overflow-y: auto;
-  user-select: none;
-  --ele-tree-item-height: 36px;
-
-  .el-tree-node__content {
-    position: relative;
-
-    & > .el-tree-node__label::before {
-      content: '';
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      z-index: 2;
-    }
-
-    & > .file-picker-tree-more {
-      flex-shrink: 0;
-      width: 20px;
-      height: 20px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      margin: 0 -8px 0 0;
-      color: var(--el-text-color-placeholder);
-      font-size: 12px;
-      border-radius: var(--el-border-radius-base);
-      transition: all 0.2s;
-      z-index: 3;
-
-      &:hover {
-        color: var(--el-text-color-regular);
-        background: hsla(0, 0%, 60%, 0.15);
-      }
-    }
-  }
-}
-
-.file-picker-left-add {
-  flex-shrink: 0;
-  padding: 0 6px;
-  margin: 2px 12px 8px 12px;
-  border-radius: var(--el-border-radius-base);
-  border: 1px dashed var(--el-color-primary);
-  box-sizing: border-box;
-  font-size: 12px;
-  line-height: 20px;
-  user-select: none;
-
-  &:hover {
-    border-color: var(--el-color-primary-light-5);
-  }
-}
-
-.file-picker-main {
-  flex: 1;
-  display: flex;
-  overflow: auto;
-}
-
-.file-picker-body {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  overflow: auto;
-}
-
-.file-picker-toolbar {
-  flex-shrink: 0;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 8px 12px;
-  border-bottom: 1px solid var(--el-border-color-light);
-  box-sizing: border-box;
-}
-
-.file-picker-search {
-  flex: 1;
-  display: flex;
-  max-width: 220px;
-  margin: 0 8px;
-
-  & > .el-input {
-    flex: 1;
-
-    & > .el-input__wrapper {
-      border-top-right-radius: 0;
-      border-bottom-right-radius: 0;
-    }
-  }
-
-  & > .el-button {
-    flex-shrink: 0;
-    margin-left: -1px;
-    position: relative;
-    border-top-left-radius: 0;
-    border-bottom-left-radius: 0;
-  }
-}
-
-.file-picker-toolbar > .ele-segmented {
-  --ele-segmented-height: 26px;
-  --ele-segmented-font-size: 16px;
-  --ele-segmented-item-padding: 8px;
-}
-
-.file-picker-file-list {
-  flex: 1;
-  overflow: auto;
-}
-
-.file-picker-file-list > .ele-file-list-group {
-  --ele-file-item-width: 102px;
-  --ele-file-item-padding: 4px 2px 2px 2px;
-
-  & > .ele-file-list {
-    & > .ele-file-list-header {
-      display: none;
-    }
-
-    & > .ele-file-list-body {
-      display: grid;
-      grid-gap: 14px 0px;
-      grid-template-columns: repeat(6, 1fr);
-      padding: 6px 1px 1px 1px;
-
-      & > .ele-file-list-item {
-        margin: 0 auto;
-
-        .ele-file-list-item-title {
-          font-size: 12px;
-          margin-top: 0;
-        }
-      }
-    }
-  }
-
-  & > .ele-file-list-table {
-    min-width: 528px;
-
-    & > .ele-file-list-header {
-      position: sticky;
-      top: 0;
-      background: var(--el-bg-color-overlay);
-    }
-  }
-
-  &.is-ping-top > .ele-file-list-table > .ele-file-list-header {
-    z-index: 2;
-  }
-}
-
-.file-picker-body > .el-empty {
-  padding: 0;
-  flex: 1;
-}
-
-.file-picker-body > .el-pagination {
-  padding-bottom: 8px;
-}
-
-.file-picker-right {
-  flex-shrink: 0;
-  width: 128px;
-  border-left: 1px solid var(--el-border-color-light);
-  box-sizing: border-box;
-  display: flex;
-  flex-direction: column;
-  position: relative;
-}
-
-.file-picker-right-header {
-  flex-shrink: 0;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 6px 12px 8px 12px;
-  box-sizing: border-box;
-}
-
-.file-picker-right-title {
-  flex: 1;
-  width: 100%;
-  overflow: hidden;
-  padding-right: 8px;
-  box-sizing: border-box;
-  font-size: 13px;
-}
-
-.file-picker-right-clear {
-  width: 100%;
-  padding: 0 6px;
-  margin-top: 6px;
-  border-radius: var(--el-border-radius-base);
-  border: 1px dashed var(--el-color-danger);
-  box-sizing: border-box;
-  font-size: 12px;
-  line-height: 20px;
-  user-select: none;
-
-  &:hover {
-    border-color: var(--el-color-danger-light-5);
-  }
-}
-
-.file-picker-right > .ele-upload-list {
-  flex: 1;
-  overflow: auto;
-  padding: 6px 0 8px 0;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  flex-wrap: nowrap;
-  gap: 0;
-
-  & > .ele-upload-item {
-    flex-shrink: 0;
-    margin: 0;
-
-    & + .ele-upload-item {
-      margin-top: 8px;
-    }
-  }
-}
-
-@media screen and (max-width: 980px) {
-  .file-picker-file-list {
-    & > .ele-file-list-group > .ele-file-list > .ele-file-list-body {
-      grid-template-columns: repeat(5, 1fr);
-    }
-  }
-}
-
-@media screen and (max-width: 888px) {
-  .file-picker-file-list {
-    & > .ele-file-list-group > .ele-file-list > .ele-file-list-body {
-      grid-template-columns: repeat(4, 1fr);
-    }
-  }
-}
-
-@media screen and (max-width: 788px) {
-  .file-picker-main {
-    flex-direction: column;
-  }
-
-  .file-picker-right {
-    width: auto;
-    height: 156px;
-    border-left: none;
-    border-top: 1px solid var(--el-border-color-light);
-
-    & > .file-picker-right-header {
-      padding-top: 8px;
-      padding-bottom: 0;
-      flex-direction: row;
-
-      & > .file-picker-right-title,
-      & > .file-picker-right-clear {
-        width: auto;
-        margin: 0;
-      }
-    }
-
-    & > .ele-upload-list {
-      flex-direction: row;
-      padding: 0 8px;
-
-      & > .ele-upload-item + .ele-upload-item {
-        margin-top: 0;
-        margin-left: 8px;
-      }
-    }
-  }
-}
-
-@media screen and (max-width: 768px) {
-  .file-picker-right-title {
-    text-align: right;
-  }
-}
-
-@media screen and (max-width: 460px) {
-  .file-picker-file-list {
-    & > .ele-file-list-group > .ele-file-list > .ele-file-list-body {
-      grid-template-columns: repeat(3, 1fr);
-    }
-  }
-}
-
-@media screen and (max-width: 358px) {
-  .file-picker-file-list {
-    & > .ele-file-list-group > .ele-file-list > .ele-file-list-body {
-      grid-template-columns: repeat(2, 1fr);
-    }
-  }
-}
-
-.file-picker-move-wrapper {
-  border: 1px solid var(--el-border-color-light);
-  border-radius: var(--el-border-radius-base);
-
-  & > .file-picker-move-tree {
-    padding-top: 8px;
-    padding-bottom: 8px;
-    padding-left: calc(var(--ele-tree-item-radius) * 2);
-    padding-right: calc(var(--ele-tree-item-radius) * 2);
-    box-sizing: border-box;
-    overflow-x: hidden;
-    overflow-y: auto;
-    user-select: none;
-    --ele-tree-item-height: 36px;
-
-    .el-tree-node__content {
-      position: relative;
-      z-index: 1;
-
-      & > .el-tree-node__label.is-active {
-        color: var(--el-color-primary);
-        font-weight: bold;
-
-        &::before {
-          content: '';
-          position: absolute;
-          top: 0;
-          left: 0;
-          right: 0;
-          bottom: 0;
-          z-index: -1;
-          background: var(--el-color-primary-light-9);
-          border-radius: var(--ele-tree-item-radius);
-        }
-      }
-
-      & > .el-radio {
-        margin: 0 -12px 0 0;
-      }
-    }
-  }
-}