更新树形结构
This commit is contained in:
@@ -6,10 +6,15 @@ export interface CreationListParams {
|
||||
keyword?: string;
|
||||
}
|
||||
|
||||
export interface CreationImageItem {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface CreationTitleItem {
|
||||
title: string;
|
||||
htmlFileUrl: string;
|
||||
jsonFileUrl: string[];
|
||||
imageUrls: CreationImageItem[] | null;
|
||||
}
|
||||
|
||||
export interface CreationThemeItem {
|
||||
@@ -17,9 +22,14 @@ export interface CreationThemeItem {
|
||||
titles: CreationTitleItem[];
|
||||
}
|
||||
|
||||
export interface CreationContentTypeItem {
|
||||
contentType: string;
|
||||
themes: CreationThemeItem[];
|
||||
}
|
||||
|
||||
export interface CreationTreeItem {
|
||||
createdDate: string;
|
||||
themes: CreationThemeItem[];
|
||||
contentTypes: CreationContentTypeItem[];
|
||||
}
|
||||
|
||||
export interface CreationListData {
|
||||
|
||||
@@ -18,69 +18,63 @@
|
||||
<div class="tree-node">
|
||||
<div class="tree-node-main">
|
||||
<el-icon v-if="data.nodeType === 'date'"><ele-Calendar /></el-icon>
|
||||
<el-icon v-else-if="data.nodeType === 'contentType'"><ele-Collection /></el-icon>
|
||||
<el-icon v-else-if="data.nodeType === 'theme'"><ele-CollectionTag /></el-icon>
|
||||
<el-icon v-else-if="data.nodeType === 'title'"><ele-FolderOpened /></el-icon>
|
||||
<el-icon v-else-if="data.nodeType === 'html'"><ele-Document /></el-icon>
|
||||
<el-icon v-else><ele-Picture /></el-icon>
|
||||
<span class="ellipsis">{{ data.label }}</span>
|
||||
</div>
|
||||
<el-button v-if="data.nodeType === 'html' || data.nodeType === 'image'" type="primary" link class="tree-download" @click.stop="downloadNode(data)">
|
||||
<el-icon><ele-Download /></el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="data.nodeType === 'html' || data.nodeType === 'image'"
|
||||
type="primary"
|
||||
link
|
||||
class="tree-download"
|
||||
@click.stop="downloadNode(data)"
|
||||
><el-icon><ele-Download /></el-icon
|
||||
></el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel center">
|
||||
<div class="title">内容创建参数配置</div>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-position="top" class="compact-form">
|
||||
<div class="form-grid">
|
||||
<el-form-item label="1. 创作模式" prop="mode" class="span-1">
|
||||
<el-select v-model="formData.mode">
|
||||
<el-option v-for="item in modeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="2. 内容类型" prop="content_type" class="span-1">
|
||||
<el-select v-model="formData.content_type">
|
||||
<el-option v-for="item in contentTypeOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="3. 主题(系列名)" prop="theme" class="span-1">
|
||||
<el-input v-model="formData.theme" placeholder="例如:春季通勤穿搭、小个子显高技巧" />
|
||||
</el-form-item>
|
||||
<el-form-item label="4. 标题(具体标题)" prop="title" class="span-1">
|
||||
<el-input v-model="formData.title" placeholder="例如:通勤穿搭技巧、5个显高穿搭法则" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="5. 内容风格" prop="style" class="span-1">
|
||||
<el-select v-model="formData.style">
|
||||
<el-option v-for="item in styleOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="6. 生成条数" prop="count" class="span-1">
|
||||
<el-input-number v-model="formData.count" :min="1" :max="20" controls-position="right" class="w100" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="7. 配图数量" prop="image_per_post" class="span-1">
|
||||
<el-input-number v-model="formData.image_per_post" :min="1" :max="20" controls-position="right" class="w100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="8. 图片比例" prop="image_ratio" class="span-1">
|
||||
<el-select v-model="formData.image_ratio">
|
||||
<el-option v-for="item in imageRatioOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="9. 描述" prop="description" class="span-2 description-item">
|
||||
<el-input v-model="formData.description" type="textarea" :rows="4" placeholder="请输入内容补充描述、重点要求或限制条件" />
|
||||
</el-form-item>
|
||||
<el-form-item label="1. 创作模式" prop="mode" class="span-1"
|
||||
><el-select v-model="formData.mode"><el-option v-for="item in modeOptions" :key="item" :label="item" :value="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="2. 内容类型" prop="content_type" class="span-1"
|
||||
><el-select v-model="formData.content_type"
|
||||
><el-option v-for="item in contentTypeOptions" :key="item" :label="item" :value="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="3. 主题(系列名)" prop="theme" class="span-1"
|
||||
><el-input v-model="formData.theme" placeholder="例如:春季通勤穿搭、小个子显高技巧"
|
||||
/></el-form-item>
|
||||
<el-form-item label="4. 标题(具体标题)" prop="title" class="span-1"
|
||||
><el-input v-model="formData.title" placeholder="例如:通勤穿搭技巧、5个显高穿搭法则"
|
||||
/></el-form-item>
|
||||
<el-form-item label="5. 内容风格" prop="style" class="span-1"
|
||||
><el-select v-model="formData.style"><el-option v-for="item in styleOptions" :key="item" :label="item" :value="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="6. 生成条数" prop="count" class="span-1"
|
||||
><el-input-number v-model="formData.count" :min="1" :max="20" controls-position="right" class="w100"
|
||||
/></el-form-item>
|
||||
<el-form-item label="7. 配图数量" prop="image_per_post" class="span-1"
|
||||
><el-input-number v-model="formData.image_per_post" :min="1" :max="20" controls-position="right" class="w100"
|
||||
/></el-form-item>
|
||||
<el-form-item label="8. 图片比例" prop="image_ratio" class="span-1"
|
||||
><el-select v-model="formData.image_ratio"
|
||||
><el-option v-for="item in imageRatioOptions" :key="item" :label="item" :value="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="9. 描述" prop="description" class="span-2 description-item"
|
||||
><el-input v-model="formData.description" type="textarea" :rows="4" placeholder="请输入内容补充描述、重点要求或限制条件"
|
||||
/></el-form-item>
|
||||
</div>
|
||||
<el-button type="primary" class="submit-btn" :loading="submitLoading" @click="handleSubmit">告诉我你的选择,我马上开始创作!</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="panel right" v-loading="previewLoading">
|
||||
<div class="title preview-title">预览区域</div>
|
||||
<div class="preview-main">
|
||||
@@ -97,15 +91,23 @@
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
||||
import { createCreation, downloadToFile, getCreationList, type CreationListParams, type CreationSubmitParams, type CreationTreeItem } from '/@/api/digitalHuman/creation';
|
||||
import {
|
||||
createCreation,
|
||||
downloadToFile,
|
||||
getCreationList,
|
||||
type CreationListParams,
|
||||
type CreationSubmitParams,
|
||||
type CreationTreeItem,
|
||||
} from '/@/api/digitalHuman/creation';
|
||||
|
||||
type NodeType = 'date' | 'theme' | 'title' | 'html' | 'image';
|
||||
type NodeType = 'date' | 'contentType' | 'theme' | 'title' | 'html' | 'image';
|
||||
interface TreeNode {
|
||||
id: string;
|
||||
label: string;
|
||||
nodeType: NodeType;
|
||||
children?: TreeNode[];
|
||||
createdDate?: string;
|
||||
contentType?: string;
|
||||
theme?: string;
|
||||
creationTitle?: string;
|
||||
fileUrl?: string;
|
||||
@@ -114,7 +116,6 @@ interface PreviewState {
|
||||
url: string;
|
||||
nodeType: 'html' | 'image';
|
||||
}
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const treeLoading = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
@@ -125,10 +126,25 @@ const selectedPreview = ref<PreviewState | null>(null);
|
||||
const apiBaseUrl = (import.meta.env.VITE_API_URL || '').replace(/\/$/, '');
|
||||
const treeProps = { children: 'children', label: 'label' };
|
||||
const queryParams = reactive<CreationListParams>({ keyword: '', pageNum: 1, pageSize: 10 });
|
||||
const formData = reactive<CreationSubmitParams>({ mode: '混合模式(文案 + 图片)', content_type: '穿搭分享', theme: '', title: '', description: '', style: '生活分享 — 亲切自然,像朋友聊天', count: 3, image_per_post: 1, image_ratio: '3:4 — 小红书' });
|
||||
const formData = reactive<CreationSubmitParams>({
|
||||
mode: '混合模式(文案 + 图片)',
|
||||
content_type: '穿搭分享',
|
||||
theme: '',
|
||||
title: '',
|
||||
description: '',
|
||||
style: '生活分享 — 亲切自然,像朋友聊天',
|
||||
count: 3,
|
||||
image_per_post: 1,
|
||||
image_ratio: '3:4 — 小红书',
|
||||
});
|
||||
const modeOptions = ['混合模式(文案 + 图片)', '纯文案模式', '纯图片模式'];
|
||||
const contentTypeOptions = ['穿搭分享', '好物推荐', '美妆护肤', '探店分享', '旅行日常', '美食分享'];
|
||||
const styleOptions = ['生活分享 — 亲切自然,像朋友聊天', '专业测评 — 深度分析,数据支撑', '种草推荐 — 强调亮点,感染力强', '干货教学 — 条理清晰,步骤明确'];
|
||||
const styleOptions = [
|
||||
'生活分享 — 亲切自然,像朋友聊天',
|
||||
'专业测评 — 深度分析,数据支撑',
|
||||
'种草推荐 — 强调亮点,感染力强',
|
||||
'干货教学 — 条理清晰,步骤明确',
|
||||
];
|
||||
const imageRatioOptions = ['3:4 — 小红书', '1:1 — 方图', '16:9 — 横版'];
|
||||
const rules: FormRules = {
|
||||
mode: [{ required: true, message: '请选择创作模式', trigger: 'change' }],
|
||||
@@ -140,13 +156,7 @@ const rules: FormRules = {
|
||||
image_per_post: [{ required: true, message: '请输入配图数量', trigger: 'change' }],
|
||||
image_ratio: [{ required: true, message: '请选择图片比例', trigger: 'change' }],
|
||||
};
|
||||
|
||||
const joinUrl = (base: string, path: string) => {
|
||||
const cleanBase = base.replace(/\/$/, '');
|
||||
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
||||
return `${cleanBase}${cleanPath}`;
|
||||
};
|
||||
|
||||
const joinUrl = (base: string, path: string) => `${base.replace(/\/$/, '')}${path.startsWith('/') ? path : `/${path}`}`;
|
||||
const buildAssetUrl = (path?: string) => {
|
||||
if (!path) return '';
|
||||
if (/^https?:\/\//i.test(path)) return path;
|
||||
@@ -155,33 +165,66 @@ const buildAssetUrl = (path?: string) => {
|
||||
if (prefix) return joinUrl(joinUrl(apiBaseUrl, prefix), path);
|
||||
return joinUrl(apiBaseUrl, path);
|
||||
};
|
||||
|
||||
const buildTreeNodes = (tree: CreationTreeItem[]) => tree.map((dateGroup, dIndex) => ({
|
||||
id: `date-${dIndex}`,
|
||||
label: dateGroup.createdDate,
|
||||
nodeType: 'date' as const,
|
||||
children: (dateGroup.themes || []).map((themeGroup, tIndex) => ({
|
||||
id: `theme-${dIndex}-${tIndex}`,
|
||||
label: themeGroup.theme,
|
||||
nodeType: 'theme' as const,
|
||||
children: (themeGroup.titles || []).map((titleItem, i) => ({
|
||||
id: `title-${dIndex}-${tIndex}-${i}`,
|
||||
label: titleItem.title || `作品${i + 1}`,
|
||||
nodeType: 'title' as const,
|
||||
const buildTreeNodes = (tree: CreationTreeItem[]): TreeNode[] =>
|
||||
tree.map((dateGroup, dIndex) => ({
|
||||
id: `date-${dIndex}`,
|
||||
label: dateGroup.createdDate,
|
||||
nodeType: 'date' as const,
|
||||
children: (dateGroup.contentTypes || []).map((contentTypeGroup, cIndex) => ({
|
||||
id: `content-type-${dIndex}-${cIndex}`,
|
||||
label: contentTypeGroup.contentType,
|
||||
nodeType: 'contentType' as const,
|
||||
createdDate: dateGroup.createdDate,
|
||||
theme: themeGroup.theme,
|
||||
creationTitle: titleItem.title || `作品${i + 1}`,
|
||||
children: [
|
||||
...(titleItem.htmlFileUrl ? [{ id: `html-${dIndex}-${tIndex}-${i}`, label: 'HTML', nodeType: 'html' as const, createdDate: dateGroup.createdDate, theme: themeGroup.theme, creationTitle: titleItem.title || `作品${i + 1}`, fileUrl: titleItem.htmlFileUrl }] : []),
|
||||
...(titleItem.jsonFileUrl || []).map((img, imgIndex) => ({ id: `img-${dIndex}-${tIndex}-${i}-${imgIndex}`, label: `图片 ${imgIndex + 1}`, nodeType: 'image' as const, createdDate: dateGroup.createdDate, theme: themeGroup.theme, creationTitle: titleItem.title || `作品${i + 1}`, fileUrl: img })),
|
||||
],
|
||||
contentType: contentTypeGroup.contentType,
|
||||
children: (contentTypeGroup.themes || []).map((themeGroup, tIndex) => ({
|
||||
id: `theme-${dIndex}-${cIndex}-${tIndex}`,
|
||||
label: themeGroup.theme,
|
||||
nodeType: 'theme' as const,
|
||||
createdDate: dateGroup.createdDate,
|
||||
contentType: contentTypeGroup.contentType,
|
||||
theme: themeGroup.theme,
|
||||
children: (themeGroup.titles || []).map((titleItem, i) => ({
|
||||
id: `title-${dIndex}-${cIndex}-${tIndex}-${i}`,
|
||||
label: titleItem.title || `作品${i + 1}`,
|
||||
nodeType: 'title' as const,
|
||||
createdDate: dateGroup.createdDate,
|
||||
contentType: contentTypeGroup.contentType,
|
||||
theme: themeGroup.theme,
|
||||
creationTitle: titleItem.title || `作品${i + 1}`,
|
||||
children: [
|
||||
...(titleItem.htmlFileUrl
|
||||
? [
|
||||
{
|
||||
id: `html-${dIndex}-${cIndex}-${tIndex}-${i}`,
|
||||
label: 'HTML',
|
||||
nodeType: 'html' as const,
|
||||
createdDate: dateGroup.createdDate,
|
||||
contentType: contentTypeGroup.contentType,
|
||||
theme: themeGroup.theme,
|
||||
creationTitle: titleItem.title || `作品${i + 1}`,
|
||||
fileUrl: titleItem.htmlFileUrl,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(titleItem.imageUrls || []).map((img, imgIndex) => ({
|
||||
id: `img-${dIndex}-${cIndex}-${tIndex}-${i}-${imgIndex}`,
|
||||
label: img.name || `图片 ${imgIndex + 1}`,
|
||||
nodeType: 'image' as const,
|
||||
createdDate: dateGroup.createdDate,
|
||||
contentType: contentTypeGroup.contentType,
|
||||
theme: themeGroup.theme,
|
||||
creationTitle: titleItem.title || `作品${i + 1}`,
|
||||
fileUrl: img.url,
|
||||
})),
|
||||
],
|
||||
})),
|
||||
})),
|
||||
})),
|
||||
})),
|
||||
}));
|
||||
|
||||
}));
|
||||
const handleNodeClick = (data: TreeNode) => {
|
||||
if (data.contentType) formData.content_type = data.contentType;
|
||||
if (data.theme) formData.theme = data.theme;
|
||||
if (data.nodeType === 'title') {
|
||||
formData.theme = data.theme || formData.theme;
|
||||
formData.title = data.creationTitle || data.label || formData.title;
|
||||
return;
|
||||
}
|
||||
@@ -189,32 +232,37 @@ const handleNodeClick = (data: TreeNode) => {
|
||||
const url = buildAssetUrl(data.fileUrl);
|
||||
if (!url) return ElMessage.warning('当前节点没有可预览地址');
|
||||
selectedPreview.value = { url, nodeType: data.nodeType };
|
||||
formData.theme = data.theme || formData.theme;
|
||||
formData.title = data.creationTitle || formData.title;
|
||||
};
|
||||
|
||||
const downloadNode = async (data: TreeNode) => {
|
||||
if (data.nodeType !== 'html' && data.nodeType !== 'image') return;
|
||||
if (!data.fileUrl) return ElMessage.warning('当前节点没有可下载地址');
|
||||
try {
|
||||
await downloadToFile({
|
||||
fileURL: data.fileUrl,
|
||||
localPath: 'C:/Users/AI/Desktop',
|
||||
});
|
||||
await downloadToFile({ fileURL: data.fileUrl, localPath: 'C:/Users/AI/Desktop' });
|
||||
ElMessage.success('已提交下载到本地');
|
||||
} catch {
|
||||
ElMessage.error('下载失败');
|
||||
}
|
||||
};
|
||||
|
||||
const findFirstPreviewNode = (nodes: TreeNode[]): TreeNode | null => {
|
||||
for (const node of nodes) {
|
||||
if (node.nodeType === 'html' || node.nodeType === 'image') return node;
|
||||
if (node.children?.length) {
|
||||
const matched = findFirstPreviewNode(node.children);
|
||||
if (matched) return matched;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const getList = async () => {
|
||||
treeLoading.value = true;
|
||||
try {
|
||||
const res = await getCreationList({ ...queryParams, keyword: queryParams.keyword || undefined });
|
||||
imgAddressPrefix.value = res.data?.imgAddressPrefix || '';
|
||||
treeNodes.value = buildTreeNodes(res.data?.Tree || []);
|
||||
selectedPreview.value = null;
|
||||
await nextTick();
|
||||
const firstLeaf = treeNodes.value[0]?.children?.[0]?.children?.[0]?.children?.[0];
|
||||
const firstLeaf = findFirstPreviewNode(treeNodes.value);
|
||||
if (firstLeaf) handleNodeClick(firstLeaf);
|
||||
} catch {
|
||||
treeNodes.value = [];
|
||||
@@ -225,7 +273,6 @@ const getList = async () => {
|
||||
treeLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
try {
|
||||
@@ -245,34 +292,148 @@ const handleSubmit = async () => {
|
||||
submitLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(getList);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.creation-page { height: calc(100vh - 100px); display: grid; grid-template-columns: 292px minmax(470px, 1fr) minmax(500px, 1.02fr); gap: 14px; padding: 14px; background: #f6f8fb; box-sizing: border-box; }
|
||||
.panel { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 2px 10px rgba(15,23,42,.05); overflow: hidden; display: flex; flex-direction: column; }
|
||||
.title { font-size: 18px; font-weight: 700; color: #303133; margin-bottom: 12px; }
|
||||
.preview-title { margin-bottom: 0; }
|
||||
.tree-wrap, .center, .preview-main { overflow: auto; }
|
||||
.tree-node { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; }
|
||||
.tree-node-main { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; }
|
||||
.tree-download { flex-shrink: 0; padding: 2px; }
|
||||
.ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.compact-form { flex: 1; display: flex; flex-direction: column; }
|
||||
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
|
||||
.span-1 { grid-column: span 1; }
|
||||
.span-2 { grid-column: span 2; }
|
||||
.description-item { margin-bottom: 8px; }
|
||||
.w100 { width: 100%; }
|
||||
.submit-btn { width: 100%; height: 40px; margin-top: auto; border-radius: 8px; }
|
||||
.preview-main { flex: 1; min-height: 0; background: #f8fafc; border: 1px solid #edf1f7; border-radius: 10px; padding: 10px; }
|
||||
.iframe { width: 100%; height: 100%; min-height: 520px; border: 1px solid #ebeef5; border-radius: 8px; background: #fff; }
|
||||
.img-wrap { height: 100%; min-height: 520px; border: 1px solid #ebeef5; border-radius: 8px; padding: 10px; display: flex; align-items: center; justify-content: center; background: #fff; }
|
||||
.img { width: 100%; height: 100%; min-height: 480px; }
|
||||
:deep(.el-form-item) { margin-bottom: 12px; }
|
||||
:deep(.el-form-item__label) { padding-bottom: 4px; font-size: 13px; color: #606266; }
|
||||
:deep(.el-input__wrapper), :deep(.el-select__wrapper), :deep(.el-textarea__inner), :deep(.el-input-number) { border-radius: 8px; }
|
||||
:deep(.el-select), :deep(.el-input), :deep(.el-input-number), :deep(.el-textarea) { width: 100%; }
|
||||
@media (max-width: 1800px) { .creation-page { grid-template-columns: 280px minmax(430px, 1fr) minmax(460px, 0.98fr); } }
|
||||
.creation-page {
|
||||
height: calc(100vh - 100px);
|
||||
display: grid;
|
||||
grid-template-columns: 292px minmax(470px, 1fr) minmax(500px, 1.02fr);
|
||||
gap: 14px;
|
||||
padding: 14px;
|
||||
background: #f6f8fb;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.panel {
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 14px;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.preview-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.tree-wrap,
|
||||
.center,
|
||||
.preview-main {
|
||||
overflow: auto;
|
||||
}
|
||||
.tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
.tree-node-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
.tree-download {
|
||||
flex-shrink: 0;
|
||||
padding: 2px;
|
||||
}
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.compact-form {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.form-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0 12px;
|
||||
}
|
||||
.span-1 {
|
||||
grid-column: span 1;
|
||||
}
|
||||
.span-2 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
.description-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.w100 {
|
||||
width: 100%;
|
||||
}
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
margin-top: auto;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.preview-main {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #edf1f7;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
.iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 520px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
.img-wrap {
|
||||
height: 100%;
|
||||
min-height: 520px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
}
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 480px;
|
||||
}
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
:deep(.el-form-item__label) {
|
||||
padding-bottom: 4px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
:deep(.el-input__wrapper),
|
||||
:deep(.el-select__wrapper),
|
||||
:deep(.el-textarea__inner),
|
||||
:deep(.el-input-number) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
:deep(.el-select),
|
||||
:deep(.el-input),
|
||||
:deep(.el-input-number),
|
||||
:deep(.el-textarea) {
|
||||
width: 100%;
|
||||
}
|
||||
@media (max-width: 1800px) {
|
||||
.creation-page {
|
||||
grid-template-columns: 280px minmax(430px, 1fr) minmax(460px, 0.98fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user