|
|
@@ -14,6 +14,7 @@
|
|
|
<el-select v-model="searchForm.type" placeholder="类型" clearable style="width:100px">
|
|
|
<el-option label="图片" value="image" />
|
|
|
<el-option label="视频" value="video" />
|
|
|
+ <el-option label="文字" value="text" />
|
|
|
<el-option label="音频" value="audio" />
|
|
|
<el-option label="文档" value="document" />
|
|
|
</el-select>
|
|
|
@@ -58,13 +59,25 @@
|
|
|
<el-icon><VideoPlay /></el-icon>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <el-popover v-else-if="row.type === 'text'" placement="top" :width="300" trigger="hover">
|
|
|
+ <template #reference>
|
|
|
+ <el-icon size="24" color="#409eff"><Document /></el-icon>
|
|
|
+ </template>
|
|
|
+ <div class="text-preview-popover">{{ row.content }}</div>
|
|
|
+ </el-popover>
|
|
|
<el-button v-else type="primary" link @click="viewUrl(row.url)">查看</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="url" label="URL" align="center" min-width="200" show-overflow-tooltip>
|
|
|
+ <el-table-column prop="url" label="URL/内容" align="center" min-width="200" show-overflow-tooltip>
|
|
|
<template #default="{ row }">
|
|
|
- <el-button type="primary" link size="small" @click="copyUrl(row.url)">复制</el-button>
|
|
|
- {{ row.url }}
|
|
|
+ <template v-if="row.type === 'text'">
|
|
|
+ <el-button type="primary" link size="small" @click="copyUrl(row.content)">复制</el-button>
|
|
|
+ {{ row.content }}
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-button type="primary" link size="small" @click="copyUrl(row.url)">复制</el-button>
|
|
|
+ {{ row.url }}
|
|
|
+ </template>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column prop="size" label="大小" align="center" width="100">
|
|
|
@@ -105,10 +118,27 @@
|
|
|
<el-option v-for="item in groupOptions" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="素材类型" prop="type">
|
|
|
+ <el-radio-group v-model="formData.type" @change="handleTypeChange">
|
|
|
+ <el-radio value="image">图片</el-radio>
|
|
|
+ <el-radio value="video">视频</el-radio>
|
|
|
+ <el-radio value="text">文字</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="名称" prop="name">
|
|
|
<el-input v-model="formData.name" placeholder="请输入名称" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="上传文件" prop="url">
|
|
|
+ <!-- 文字类型:文本内容输入 -->
|
|
|
+ <el-form-item v-if="formData.type === 'text'" label="文字内容" prop="content">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.content"
|
|
|
+ type="textarea"
|
|
|
+ :rows="6"
|
|
|
+ placeholder="请输入文字内容"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <!-- 文件类型:上传文件 -->
|
|
|
+ <el-form-item v-else label="上传文件" prop="url">
|
|
|
<div class="upload-container">
|
|
|
<el-upload
|
|
|
ref="uploadRef"
|
|
|
@@ -218,10 +248,10 @@ const tableData = ref([]);
|
|
|
const pageable = reactive({ pageNum: 1, pageSize: 30, total: 0 });
|
|
|
const groupOptions = ref([]);
|
|
|
|
|
|
-const typeMap = { image: "图片", video: "视频", audio: "音频", document: "文档" };
|
|
|
+const typeMap = { image: "图片", video: "视频", audio: "音频", document: "文档", text: "文字" };
|
|
|
|
|
|
const getTypeColor = (type) => {
|
|
|
- const colors = { image: "success", video: "primary", audio: "warning", document: "info" };
|
|
|
+ const colors = { image: "success", video: "primary", audio: "warning", document: "info", text: "" };
|
|
|
return colors[type] || "default";
|
|
|
};
|
|
|
|
|
|
@@ -246,19 +276,36 @@ const formData = ref({
|
|
|
name: "",
|
|
|
type: "image",
|
|
|
url: "",
|
|
|
+ content: "",
|
|
|
cover: "",
|
|
|
size: 0,
|
|
|
sort: 0,
|
|
|
status: 1
|
|
|
});
|
|
|
|
|
|
+// 动态表单验证规则
|
|
|
const formRules = ref({
|
|
|
groupId: [{ required: true, message: "请选择分组", trigger: "change" }],
|
|
|
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
|
|
- url: [{ required: true, message: "请上传文件", trigger: "change" }],
|
|
|
status: [{ required: true, message: "请选择状态", trigger: "change" }]
|
|
|
});
|
|
|
|
|
|
+// 类型切换时清空相关数据
|
|
|
+const handleTypeChange = (type) => {
|
|
|
+ if (type === 'text') {
|
|
|
+ formData.value.url = "";
|
|
|
+ formData.value.cover = "";
|
|
|
+ formData.value.size = 0;
|
|
|
+ previewUrl.value = "";
|
|
|
+ } else {
|
|
|
+ formData.value.content = "";
|
|
|
+ }
|
|
|
+ // 清除验证
|
|
|
+ if (formRef.value) {
|
|
|
+ formRef.value.clearValidate();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
const formatUnix = (val) => {
|
|
|
if (!val) return "";
|
|
|
return dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss");
|
|
|
@@ -343,7 +390,7 @@ const openDialog = (row) => {
|
|
|
previewUrl.value = "";
|
|
|
pendingFile.value = null;
|
|
|
if (row) {
|
|
|
- formData.value = { ...row };
|
|
|
+ formData.value = { ...row, content: row.content || "" };
|
|
|
} else {
|
|
|
formData.value = {
|
|
|
id: null,
|
|
|
@@ -351,6 +398,7 @@ const openDialog = (row) => {
|
|
|
name: "",
|
|
|
type: "image",
|
|
|
url: "",
|
|
|
+ content: "",
|
|
|
cover: "",
|
|
|
size: 0,
|
|
|
sort: 0,
|
|
|
@@ -477,6 +525,20 @@ const handleCoverUpload = async (options) => {
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
if (!formRef.value) return;
|
|
|
+
|
|
|
+ // 验证:文字类型需要内容,其他类型需要URL
|
|
|
+ if (formData.value.type === 'text') {
|
|
|
+ if (!formData.value.content || !formData.value.content.trim()) {
|
|
|
+ ElNotification.warning("请输入文字内容");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!formData.value.url) {
|
|
|
+ ElNotification.warning("请上传文件");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
await formRef.value.validate(async (valid) => {
|
|
|
if (!valid) return;
|
|
|
submitLoading.value = true;
|
|
|
@@ -488,7 +550,8 @@ const handleSubmit = async () => {
|
|
|
group_id: formData.value.groupId,
|
|
|
name: formData.value.name,
|
|
|
type: formData.value.type,
|
|
|
- url: formData.value.url,
|
|
|
+ url: formData.value.type === 'text' ? "" : formData.value.url,
|
|
|
+ content: formData.value.type === 'text' ? formData.value.content : "",
|
|
|
cover: formData.value.cover || "",
|
|
|
size: formData.value.size,
|
|
|
sort: formData.value.sort,
|