|
@@ -56,18 +56,18 @@
|
|
|
<van-list
|
|
<van-list
|
|
|
v-model:loading="loading"
|
|
v-model:loading="loading"
|
|
|
:finished="finished"
|
|
:finished="finished"
|
|
|
- :finished-text="$t('common.noData')"
|
|
|
|
|
|
|
+ :finished-text="materialList.length ? '' : $t('common.noData')"
|
|
|
@load="loadMore"
|
|
@load="loadMore"
|
|
|
>
|
|
>
|
|
|
<!-- 图片素材 -->
|
|
<!-- 图片素材 -->
|
|
|
- <div class="image-grid" v-if="type === 'image' || type === ''">
|
|
|
|
|
|
|
+ <div class="image-grid" v-if="(type === 'image' || type === '') && imageList.length">
|
|
|
<div
|
|
<div
|
|
|
class="image-item"
|
|
class="image-item"
|
|
|
v-for="item in imageList"
|
|
v-for="item in imageList"
|
|
|
:key="item.id"
|
|
:key="item.id"
|
|
|
@click="previewImage(item)"
|
|
@click="previewImage(item)"
|
|
|
>
|
|
>
|
|
|
- <img :src="item.url" />
|
|
|
|
|
|
|
+ <img :src="getMediaUrl(item)" />
|
|
|
<div class="image-actions">
|
|
<div class="image-actions">
|
|
|
<van-icon name="eye-o" @click.stop="previewImage(item)" />
|
|
<van-icon name="eye-o" @click.stop="previewImage(item)" />
|
|
|
<van-icon name="down" @click.stop="downloadImage(item)" />
|
|
<van-icon name="down" @click.stop="downloadImage(item)" />
|
|
@@ -76,16 +76,16 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 文本素材 -->
|
|
<!-- 文本素材 -->
|
|
|
- <div class="text-list" v-if="type === 'text' || type === ''">
|
|
|
|
|
|
|
+ <div class="text-list" v-if="(type === 'text' || type === '') && textList.length">
|
|
|
<div
|
|
<div
|
|
|
class="text-item"
|
|
class="text-item"
|
|
|
v-for="item in textList"
|
|
v-for="item in textList"
|
|
|
:key="item.id"
|
|
:key="item.id"
|
|
|
>
|
|
>
|
|
|
- <div class="text-title">{{ item.title }}</div>
|
|
|
|
|
|
|
+ <div class="text-title">{{ getName(item) }}</div>
|
|
|
<div class="text-content">{{ item.content }}</div>
|
|
<div class="text-content">{{ item.content }}</div>
|
|
|
<div class="text-actions">
|
|
<div class="text-actions">
|
|
|
- <van-button size="small" @click="copyText(item.content)">
|
|
|
|
|
|
|
+ <van-button size="small" @click="copyText(item.content || '')">
|
|
|
{{ $t('common.copy') }}
|
|
{{ $t('common.copy') }}
|
|
|
</van-button>
|
|
</van-button>
|
|
|
</div>
|
|
</div>
|
|
@@ -93,14 +93,14 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 视频素材 -->
|
|
<!-- 视频素材 -->
|
|
|
- <div class="video-list" v-if="type === 'video' || type === ''">
|
|
|
|
|
|
|
+ <div class="video-list" v-if="(type === 'video' || type === '') && videoList.length">
|
|
|
<div
|
|
<div
|
|
|
class="video-item"
|
|
class="video-item"
|
|
|
v-for="item in videoList"
|
|
v-for="item in videoList"
|
|
|
:key="item.id"
|
|
:key="item.id"
|
|
|
>
|
|
>
|
|
|
- <video :src="item.url" controls></video>
|
|
|
|
|
- <div class="video-title">{{ item.title }}</div>
|
|
|
|
|
|
|
+ <video :src="getMediaUrl(item)" controls></video>
|
|
|
|
|
+ <div class="video-title">{{ getName(item) }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</van-list>
|
|
</van-list>
|
|
@@ -114,6 +114,7 @@ import { ref, computed, watch, onMounted } from "vue";
|
|
|
import { useRouter } from "vue-router";
|
|
import { useRouter } from "vue-router";
|
|
|
import { useI18n } from "vue-i18n";
|
|
import { useI18n } from "vue-i18n";
|
|
|
import { showToast, showImagePreview } from "vant";
|
|
import { showToast, showImagePreview } from "vant";
|
|
|
|
|
+import { requestGetMaterialList, type MaterialInfo } from "@/api/material";
|
|
|
|
|
|
|
|
const { t } = useI18n();
|
|
const { t } = useI18n();
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
@@ -127,6 +128,16 @@ const refreshing = ref(false);
|
|
|
const page = ref(1);
|
|
const page = ref(1);
|
|
|
const pageSize = 20;
|
|
const pageSize = 20;
|
|
|
|
|
|
|
|
|
|
+// 获取素材的URL (图片/视频)
|
|
|
|
|
+const getMediaUrl = (item: MaterialInfo): string => {
|
|
|
|
|
+ return item.url || '';
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 获取素材名称
|
|
|
|
|
+const getName = (item: MaterialInfo): string => {
|
|
|
|
|
+ return item.name || '';
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const imageList = computed(() =>
|
|
const imageList = computed(() =>
|
|
|
materialList.value.filter(m => m.type === 'image')
|
|
materialList.value.filter(m => m.type === 'image')
|
|
|
);
|
|
);
|
|
@@ -146,33 +157,44 @@ const getMaterials = async (isRefresh = false) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 模拟数据
|
|
|
|
|
- const types = type.value ? [type.value] : ['image', 'text', 'video'];
|
|
|
|
|
- const mockList = Array(pageSize).fill(null).map((_, i) => {
|
|
|
|
|
- const itemType = types[i % types.length];
|
|
|
|
|
- return {
|
|
|
|
|
- id: (page.value - 1) * pageSize + i + 1,
|
|
|
|
|
- type: itemType,
|
|
|
|
|
- title: `Material ${(page.value - 1) * pageSize + i + 1}`,
|
|
|
|
|
- content: itemType === 'text' ? 'This is sample promotional text that can be copied and used for marketing purposes. Feel free to customize it according to your needs.' : undefined,
|
|
|
|
|
- url: itemType === 'image'
|
|
|
|
|
- ? `https://picsum.photos/300/200?random=${(page.value - 1) * pageSize + i}`
|
|
|
|
|
- : itemType === 'video'
|
|
|
|
|
- ? 'https://www.w3schools.com/html/mov_bbb.mp4'
|
|
|
|
|
- : undefined
|
|
|
|
|
- };
|
|
|
|
|
- }) as MaterialInfo[];
|
|
|
|
|
-
|
|
|
|
|
- if (isRefresh) {
|
|
|
|
|
- materialList.value = mockList;
|
|
|
|
|
- } else {
|
|
|
|
|
- materialList.value = [...materialList.value, ...mockList];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const res = await requestGetMaterialList({
|
|
|
|
|
+ current: page.value,
|
|
|
|
|
+ size: pageSize
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ let list = res.data?.list || [];
|
|
|
|
|
|
|
|
- if (page.value >= 2) {
|
|
|
|
|
|
|
+ // 前端过滤类型
|
|
|
|
|
+ if (type.value) {
|
|
|
|
|
+ list = list.filter(m => m.type === type.value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 前端过滤关键词
|
|
|
|
|
+ if (keyword.value) {
|
|
|
|
|
+ const kw = keyword.value.toLowerCase();
|
|
|
|
|
+ list = list.filter(m =>
|
|
|
|
|
+ m.name?.toLowerCase().includes(kw) ||
|
|
|
|
|
+ m.content?.toLowerCase().includes(kw)
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isRefresh) {
|
|
|
|
|
+ materialList.value = list;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ materialList.value = [...materialList.value, ...list];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 判断是否还有更多数据
|
|
|
|
|
+ const total = res.data?.paging?.total || 0;
|
|
|
|
|
+ if (materialList.value.length >= total || list.length < pageSize) {
|
|
|
|
|
+ finished.value = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
finished.value = true;
|
|
finished.value = true;
|
|
|
}
|
|
}
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
|
|
+ console.error('获取素材列表失败', e);
|
|
|
finished.value = true;
|
|
finished.value = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -194,19 +216,22 @@ const loadMore = () => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const previewImage = (item: MaterialInfo) => {
|
|
const previewImage = (item: MaterialInfo) => {
|
|
|
- if (item.url) {
|
|
|
|
|
|
|
+ const url = getMediaUrl(item);
|
|
|
|
|
+ if (url) {
|
|
|
showImagePreview({
|
|
showImagePreview({
|
|
|
- images: imageList.value.map(i => i.url!),
|
|
|
|
|
- startPosition: imageList.value.findIndex(i => i.id === item.id)
|
|
|
|
|
|
|
+ images: [url],
|
|
|
|
|
+ startPosition: 0
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const downloadImage = (item: MaterialInfo) => {
|
|
const downloadImage = (item: MaterialInfo) => {
|
|
|
- if (item.url) {
|
|
|
|
|
|
|
+ const url = getMediaUrl(item);
|
|
|
|
|
+ if (url) {
|
|
|
const link = document.createElement('a');
|
|
const link = document.createElement('a');
|
|
|
- link.href = item.url;
|
|
|
|
|
- link.download = `material_${item.id}.jpg`;
|
|
|
|
|
|
|
+ link.href = url;
|
|
|
|
|
+ link.download = item.name || `material_${item.id}.jpg`;
|
|
|
|
|
+ link.target = '_blank';
|
|
|
link.click();
|
|
link.click();
|
|
|
showToast(t('material.download') + ' started');
|
|
showToast(t('material.download') + ' started');
|
|
|
}
|
|
}
|