|
@@ -1,157 +1,241 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <div id="mt-left-aside" class="pt-10px h-1/1 box-border p-x-10px">
|
|
|
|
|
- <el-input v-model="search_str" class="pb-10px pr-10px" placeholder="请输入关键字进行搜索" />
|
|
|
|
|
- <div class="h-85/100">
|
|
|
|
|
- <el-scrollbar class="pr-10px" :view-style="{ height: '100%' }">
|
|
|
|
|
- <el-collapse v-model="active_names">
|
|
|
|
|
|
|
+ <div id="mt-left-aside" class="component-library">
|
|
|
|
|
+ <header class="component-library__header">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h2>组件库</h2>
|
|
|
|
|
+ <p>拖拽组件到画布中使用</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <span class="component-library__count">{{ filtered_component_count }} 个</span>
|
|
|
|
|
+ </header>
|
|
|
|
|
+
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="search_str"
|
|
|
|
|
+ class="component-library__search"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="搜索组件名称">
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <el-icon><Search /></el-icon>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+
|
|
|
|
|
+ <main class="component-library__content">
|
|
|
|
|
+ <el-scrollbar :view-style="{ minHeight: '100%' }">
|
|
|
|
|
+ <el-collapse v-if="checked_keys.length" v-model="active_names" class="category-list">
|
|
|
<el-collapse-item
|
|
<el-collapse-item
|
|
|
v-for="config_item_key in checked_keys"
|
|
v-for="config_item_key in checked_keys"
|
|
|
:key="config_item_key"
|
|
:key="config_item_key"
|
|
|
- :title="config_item_key"
|
|
|
|
|
:name="config_item_key">
|
|
:name="config_item_key">
|
|
|
- <div class="flex flex-wrap">
|
|
|
|
|
- <div
|
|
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ <div class="category-title">
|
|
|
|
|
+ <span class="category-title__icon"><CollectionTag /></span>
|
|
|
|
|
+ <span class="category-title__name">{{ config_item_key }}</span>
|
|
|
|
|
+ <span class="category-title__count">
|
|
|
|
|
+ {{ getFilteritems(leftAsideProps.leftAsideConfig.get(config_item_key)).length }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="getFilteritems(leftAsideProps.leftAsideConfig.get(config_item_key)).length"
|
|
|
|
|
+ class="component-grid">
|
|
|
|
|
+ <article
|
|
|
|
|
+ v-for="item in getFilteritems(leftAsideProps.leftAsideConfig.get(config_item_key))"
|
|
|
|
|
+ :key="item.id"
|
|
|
draggable="true"
|
|
draggable="true"
|
|
|
|
|
+ class="component-card"
|
|
|
@dragstart="onDragStart(config_item_key, item.id)"
|
|
@dragstart="onDragStart(config_item_key, item.id)"
|
|
|
- @touchstart.passive="onDragStart(config_item_key, item.id)"
|
|
|
|
|
- class="w-40px h-40px"
|
|
|
|
|
- v-for="(item, index) in getFilteritems(
|
|
|
|
|
- leftAsideProps.leftAsideConfig.get(config_item_key)
|
|
|
|
|
- )"
|
|
|
|
|
- :key="item.id">
|
|
|
|
|
- <el-tooltip
|
|
|
|
|
- v-model:visible="is_show_tooltip[`${config_item_key}${item.id}`]"
|
|
|
|
|
- placement="right"
|
|
|
|
|
- :width="200"
|
|
|
|
|
- :effect="isDark ? 'dark' : 'light'"
|
|
|
|
|
- :show-arrow="false"
|
|
|
|
|
- :hide-after="0"
|
|
|
|
|
- trigger="hover"
|
|
|
|
|
- :enterable="false"
|
|
|
|
|
- :offset="getOffset(index + 1)">
|
|
|
|
|
|
|
+ @touchstart.passive="onDragStart(config_item_key, item.id)">
|
|
|
|
|
+ <div class="component-card__preview">
|
|
|
<el-image
|
|
<el-image
|
|
|
draggable="false"
|
|
draggable="false"
|
|
|
- class="w-30px h-30px select-none"
|
|
|
|
|
|
|
+ fit="contain"
|
|
|
|
|
+ class="component-card__image"
|
|
|
:class="isDark ? 'bg-amber-50' : ''"
|
|
:class="isDark ? 'bg-amber-50' : ''"
|
|
|
:src="item.thumbnail" />
|
|
:src="item.thumbnail" />
|
|
|
- <template #content>
|
|
|
|
|
- <div class="flex justify-center items-center">
|
|
|
|
|
- <div class="flex flex-col">
|
|
|
|
|
- <el-text>{{ item.title }}</el-text>
|
|
|
|
|
- <el-image
|
|
|
|
|
- class="w-100px h-100px pt-5px"
|
|
|
|
|
- :class="isDark ? 'bg-amber-50' : ''"
|
|
|
|
|
- :src="item.thumbnail" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-tooltip
|
|
|
|
|
+ :content="item.title"
|
|
|
|
|
+ placement="top"
|
|
|
|
|
+ :show-after="300"
|
|
|
|
|
+ :effect="isDark ? 'dark' : 'light'">
|
|
|
|
|
+ <span class="component-card__name">{{ item.title }}</span>
|
|
|
</el-tooltip>
|
|
</el-tooltip>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </article>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <el-empty v-else :image-size="44" description="暂无匹配组件" />
|
|
|
</el-collapse-item>
|
|
</el-collapse-item>
|
|
|
</el-collapse>
|
|
</el-collapse>
|
|
|
|
|
+ <el-empty v-else :image-size="64" description="暂无可用分类" />
|
|
|
</el-scrollbar>
|
|
</el-scrollbar>
|
|
|
- </div>
|
|
|
|
|
- <div class="h-[calc(10%-1px)] flex justify-center items-center ct-border">
|
|
|
|
|
- <el-button class="w-80/100" @click="onManageClick">管理</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-dialog v-model="manage_dialog_visiable" title="图库管理" width="80%" destroy-on-close>
|
|
|
|
|
- <div class="flex">
|
|
|
|
|
- <div>
|
|
|
|
|
|
|
+ </main>
|
|
|
|
|
+
|
|
|
|
|
+ <footer class="component-library__footer">
|
|
|
|
|
+ <el-button type="primary" plain @click="onManageClick">
|
|
|
|
|
+ <el-icon><Setting /></el-icon>
|
|
|
|
|
+ 组件管理
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <span>管理分类与本地素材</span>
|
|
|
|
|
+ </footer>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ v-model="manage_dialog_visiable"
|
|
|
|
|
+ width="960px"
|
|
|
|
|
+ class="component-manage-dialog"
|
|
|
|
|
+ align-center
|
|
|
|
|
+ destroy-on-close
|
|
|
|
|
+ @opened="onManageOpened">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <div class="manage-dialog__header">
|
|
|
|
|
+ <span class="manage-dialog__header-icon"><CollectionTag /></span>
|
|
|
<div>
|
|
<div>
|
|
|
- <div class="flex justify-center">
|
|
|
|
|
- <el-checkbox v-model="check_all" :indeterminate="is_indeterminate">全选</el-checkbox>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-scrollbar height="50vh">
|
|
|
|
|
- <el-tree
|
|
|
|
|
- ref="treeRef"
|
|
|
|
|
- :data="classify_list"
|
|
|
|
|
- :highlight-current="true"
|
|
|
|
|
- show-checkbox
|
|
|
|
|
- @check-change="handleCheckChange"
|
|
|
|
|
- node-key="label"
|
|
|
|
|
- :default-checked-keys="checked_keys"
|
|
|
|
|
- @node-click="onNodeClick" />
|
|
|
|
|
- </el-scrollbar>
|
|
|
|
|
- <el-upload
|
|
|
|
|
- ref="uploadRef"
|
|
|
|
|
- class="w-24px h-24px"
|
|
|
|
|
- v-model:file-list="up_img_list"
|
|
|
|
|
- :auto-upload="false"
|
|
|
|
|
- :limit="1"
|
|
|
|
|
- :show-file-list="false"
|
|
|
|
|
- :on-change="onUpLoadChange"
|
|
|
|
|
- accept="image/*">
|
|
|
|
|
- <el-button type="primary">本地上传</el-button>
|
|
|
|
|
- </el-upload>
|
|
|
|
|
|
|
+ <h2>组件管理</h2>
|
|
|
|
|
+ <p>选择侧栏中显示的分类,并管理本地上传素材</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </template>
|
|
|
|
|
|
|
|
- <el-divider direction="vertical" class="h-50vh ml-40px" />
|
|
|
|
|
- <div v-if="selected_node_key">
|
|
|
|
|
- <el-scrollbar height="50vh">
|
|
|
|
|
- <div class="flex flex-wrap">
|
|
|
|
|
- <div
|
|
|
|
|
- v-for="item in leftAsideProps.leftAsideConfig.get(selected_node_key)"
|
|
|
|
|
|
|
+ <div class="manage-dialog__layout">
|
|
|
|
|
+ <aside class="manage-categories">
|
|
|
|
|
+ <div class="manage-categories__header">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <strong>组件分类</strong>
|
|
|
|
|
+ <span>{{ checked_keys.length }}/{{ classify_list.length }} 个已启用</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-checkbox v-model="check_all" :indeterminate="is_indeterminate">全选</el-checkbox>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-scrollbar class="manage-categories__scrollbar">
|
|
|
|
|
+ <el-tree
|
|
|
|
|
+ ref="treeRef"
|
|
|
|
|
+ class="manage-category-tree"
|
|
|
|
|
+ :data="classify_list"
|
|
|
|
|
+ :highlight-current="true"
|
|
|
|
|
+ :check-on-click-node="false"
|
|
|
|
|
+ :check-on-click-leaf="false"
|
|
|
|
|
+ show-checkbox
|
|
|
|
|
+ node-key="label"
|
|
|
|
|
+ :current-node-key="selected_node_key"
|
|
|
|
|
+ :default-checked-keys="checked_keys"
|
|
|
|
|
+ @check-change="handleCheckChange"
|
|
|
|
|
+ @node-click="onNodeClick">
|
|
|
|
|
+ <template #default="{ data }">
|
|
|
|
|
+ <div class="manage-category-node">
|
|
|
|
|
+ <span>{{ data.label }}</span>
|
|
|
|
|
+ <span>{{ leftAsideProps.leftAsideConfig.get(data.label)?.length || 0 }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-tree>
|
|
|
|
|
+ </el-scrollbar>
|
|
|
|
|
+ </aside>
|
|
|
|
|
+
|
|
|
|
|
+ <main class="manage-components">
|
|
|
|
|
+ <header class="manage-components__header">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <h3>{{ selected_node_key || '请选择分类' }}</h3>
|
|
|
|
|
+ <p>共 {{ selected_category_items.length }} 个组件</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="manage-components__actions">
|
|
|
|
|
+ <el-input v-model="manage_search_str" clearable placeholder="搜索当前分类">
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <el-icon><Search /></el-icon>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <el-upload
|
|
|
|
|
+ v-if="selected_node_key === '本地文件'"
|
|
|
|
|
+ ref="uploadRef"
|
|
|
|
|
+ v-model:file-list="up_img_list"
|
|
|
|
|
+ :auto-upload="false"
|
|
|
|
|
+ :limit="1"
|
|
|
|
|
+ :show-file-list="false"
|
|
|
|
|
+ :on-change="onUpLoadChange"
|
|
|
|
|
+ accept="image/*">
|
|
|
|
|
+ <el-button type="primary">
|
|
|
|
|
+ <el-icon><UploadFilled /></el-icon>
|
|
|
|
|
+ 上传素材
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-upload>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </header>
|
|
|
|
|
+
|
|
|
|
|
+ <el-scrollbar class="manage-components__scrollbar">
|
|
|
|
|
+ <div v-if="managed_category_items.length" class="manage-component-grid">
|
|
|
|
|
+ <article
|
|
|
|
|
+ v-for="item in managed_category_items"
|
|
|
:key="item.id"
|
|
:key="item.id"
|
|
|
- class="w-160px h-160px flex flex-wrap justify-center items-center cursor-pointer relative"
|
|
|
|
|
- @mouseenter="show_del_local_file = item.id"
|
|
|
|
|
- @mouseleave="show_del_local_file = null">
|
|
|
|
|
- <el-tooltip
|
|
|
|
|
- :effect="isDark ? 'dark' : 'light'"
|
|
|
|
|
- :content="item.title"
|
|
|
|
|
- placement="top">
|
|
|
|
|
- <div>
|
|
|
|
|
- <el-image
|
|
|
|
|
- class="w-60px h-60px"
|
|
|
|
|
- :class="isDark ? 'bg-amber-50' : ''"
|
|
|
|
|
- :src="item.thumbnail" />
|
|
|
|
|
- <div class="w-60px h-60px flex justify-center items-center">
|
|
|
|
|
- <el-text truncated>{{ item.title }}</el-text>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div
|
|
|
|
|
- v-if="selected_node_key == '本地文件' && show_del_local_file == item.id"
|
|
|
|
|
- class="absolute w-160px h-160px left-0 top-0 opacity-80 bg-light-300 flex justify-center items-center">
|
|
|
|
|
- <el-button type="danger" @click="onDelLocalFile(item)">删除</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ class="manage-component-card">
|
|
|
|
|
+ <div class="manage-component-card__preview">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ fit="contain"
|
|
|
|
|
+ class="manage-component-card__image"
|
|
|
|
|
+ :class="isDark ? 'bg-amber-50' : ''"
|
|
|
|
|
+ :src="item.thumbnail" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-tooltip :content="item.title" placement="top" :show-after="300">
|
|
|
|
|
+ <span class="manage-component-card__name">{{ item.title }}</span>
|
|
|
</el-tooltip>
|
|
</el-tooltip>
|
|
|
- </div>
|
|
|
|
|
|
|
+ <el-popconfirm
|
|
|
|
|
+ v-if="selected_node_key === '本地文件'"
|
|
|
|
|
+ width="210"
|
|
|
|
|
+ title="确认删除这个本地素材吗?"
|
|
|
|
|
+ confirm-button-text="删除"
|
|
|
|
|
+ cancel-button-text="取消"
|
|
|
|
|
+ @confirm="onDelLocalFile(item)">
|
|
|
|
|
+ <template #reference>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ class="manage-component-card__delete"
|
|
|
|
|
+ type="danger"
|
|
|
|
|
+ text
|
|
|
|
|
+ circle
|
|
|
|
|
+ @click.stop>
|
|
|
|
|
+ <el-icon><Delete /></el-icon>
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-popconfirm>
|
|
|
|
|
+ </article>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <el-empty v-else :image-size="84" :description="manage_empty_description" />
|
|
|
</el-scrollbar>
|
|
</el-scrollbar>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </main>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <div class="manage-dialog__footer">
|
|
|
|
|
+ <span>分类显示设置会自动保存</span>
|
|
|
|
|
+ <el-button type="primary" @click="manage_dialog_visiable = false">完成</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { computed, reactive, ref } from 'vue'
|
|
|
|
|
|
|
+import { globalStore } from '@/components/mt-edit/store/global'
|
|
|
|
|
+import type {
|
|
|
|
|
+ ILeftAsideConfig,
|
|
|
|
|
+ ILeftAsideConfigItem,
|
|
|
|
|
+ ILeftAsideConfigItemPublic
|
|
|
|
|
+} from '@/components/mt-edit/store/types'
|
|
|
|
|
+import { blobToBase64 } from '@/components/mt-edit/utils'
|
|
|
|
|
+import { CollectionTag, Delete, Search, Setting, UploadFilled } from '@element-plus/icons-vue'
|
|
|
|
|
+import { useDark, useLocalStorage } from '@vueuse/core'
|
|
|
import {
|
|
import {
|
|
|
- ElInput,
|
|
|
|
|
|
|
+ ElButton,
|
|
|
|
|
+ ElCheckbox,
|
|
|
ElCollapse,
|
|
ElCollapse,
|
|
|
ElCollapseItem,
|
|
ElCollapseItem,
|
|
|
- ElButton,
|
|
|
|
|
- ElScrollbar,
|
|
|
|
|
- ElImage,
|
|
|
|
|
- ElTooltip,
|
|
|
|
|
- ElText,
|
|
|
|
|
ElDialog,
|
|
ElDialog,
|
|
|
- ElCheckbox,
|
|
|
|
|
- ElDivider,
|
|
|
|
|
|
|
+ ElEmpty,
|
|
|
|
|
+ ElIcon,
|
|
|
|
|
+ ElImage,
|
|
|
|
|
+ ElInput,
|
|
|
|
|
+ ElMessage,
|
|
|
|
|
+ ElPopconfirm,
|
|
|
|
|
+ ElScrollbar,
|
|
|
ElTree,
|
|
ElTree,
|
|
|
|
|
+ ElTooltip,
|
|
|
ElUpload,
|
|
ElUpload,
|
|
|
- type UploadUserFile,
|
|
|
|
|
- ElMessage,
|
|
|
|
|
- type UploadFile
|
|
|
|
|
|
|
+ type UploadFile,
|
|
|
|
|
+ type UploadUserFile
|
|
|
} from 'element-plus'
|
|
} from 'element-plus'
|
|
|
-import { useDark, useLocalStorage } from '@vueuse/core'
|
|
|
|
|
-import type {
|
|
|
|
|
- ILeftAsideConfig,
|
|
|
|
|
- ILeftAsideConfigItem,
|
|
|
|
|
- ILeftAsideConfigItemPublic
|
|
|
|
|
-} from '@/components/mt-edit/store/types'
|
|
|
|
|
-import { globalStore } from '@/components/mt-edit/store/global'
|
|
|
|
|
-import { blobToBase64 } from '@/components/mt-edit/utils'
|
|
|
|
|
|
|
+import { computed, nextTick, ref, watch } from 'vue'
|
|
|
type LeftAsideProps = {
|
|
type LeftAsideProps = {
|
|
|
leftAsideConfig: ILeftAsideConfig
|
|
leftAsideConfig: ILeftAsideConfig
|
|
|
}
|
|
}
|
|
@@ -168,12 +252,11 @@ const disable_classify = useLocalStorage<string[]>('mt-disable-classify', [])
|
|
|
const local_file = useLocalStorage<ILeftAsideConfigItem[]>('mt-local-file', [])
|
|
const local_file = useLocalStorage<ILeftAsideConfigItem[]>('mt-local-file', [])
|
|
|
leftAsideProps.leftAsideConfig.set('本地文件', local_file.value)
|
|
leftAsideProps.leftAsideConfig.set('本地文件', local_file.value)
|
|
|
const treeRef = ref()
|
|
const treeRef = ref()
|
|
|
-const is_show_tooltip: Record<string, boolean> = reactive({})
|
|
|
|
|
-const active_names = ref([])
|
|
|
|
|
-const search_str = ref()
|
|
|
|
|
|
|
+const active_names = ref<string[]>([])
|
|
|
|
|
+const search_str = ref('')
|
|
|
const manage_dialog_visiable = ref(false)
|
|
const manage_dialog_visiable = ref(false)
|
|
|
const up_img_list = ref<UploadUserFile[]>([])
|
|
const up_img_list = ref<UploadUserFile[]>([])
|
|
|
-const show_del_local_file = ref<null | string>(null)
|
|
|
|
|
|
|
+const manage_search_str = ref('')
|
|
|
const classify_list = computed(() =>
|
|
const classify_list = computed(() =>
|
|
|
[...leftAsideProps.leftAsideConfig.keys()].map((m) => {
|
|
[...leftAsideProps.leftAsideConfig.keys()].map((m) => {
|
|
|
return { label: m }
|
|
return { label: m }
|
|
@@ -182,34 +265,56 @@ const classify_list = computed(() =>
|
|
|
const checked_keys = ref<string[]>(
|
|
const checked_keys = ref<string[]>(
|
|
|
classify_list.value.filter((f) => !disable_classify.value.includes(f.label)).map((m) => m.label)
|
|
classify_list.value.filter((f) => !disable_classify.value.includes(f.label)).map((m) => m.label)
|
|
|
)
|
|
)
|
|
|
-const selected_node_key = ref()
|
|
|
|
|
|
|
+const filtered_component_count = computed(() =>
|
|
|
|
|
+ checked_keys.value.reduce(
|
|
|
|
|
+ (count, key) => count + getFilteritems(leftAsideProps.leftAsideConfig.get(key)).length,
|
|
|
|
|
+ 0
|
|
|
|
|
+ )
|
|
|
|
|
+)
|
|
|
|
|
+const selected_node_key = ref<string>()
|
|
|
|
|
+const selected_category_items = computed<ILeftAsideConfigItemPublic[]>(() => {
|
|
|
|
|
+ if (!selected_node_key.value) {
|
|
|
|
|
+ return []
|
|
|
|
|
+ }
|
|
|
|
|
+ return leftAsideProps.leftAsideConfig.get(selected_node_key.value) || []
|
|
|
|
|
+})
|
|
|
|
|
+const managed_category_items = computed(() => {
|
|
|
|
|
+ const keyword = manage_search_str.value.trim().toLocaleLowerCase()
|
|
|
|
|
+ if (!keyword) {
|
|
|
|
|
+ return selected_category_items.value
|
|
|
|
|
+ }
|
|
|
|
|
+ return selected_category_items.value.filter((item) =>
|
|
|
|
|
+ item.title.toLocaleLowerCase().includes(keyword)
|
|
|
|
|
+ )
|
|
|
|
|
+})
|
|
|
|
|
+const manage_empty_description = computed(() => {
|
|
|
|
|
+ if (!selected_node_key.value) {
|
|
|
|
|
+ return '请先选择一个组件分类'
|
|
|
|
|
+ }
|
|
|
|
|
+ return manage_search_str.value.trim() ? '没有找到匹配的组件' : '当前分类暂无组件'
|
|
|
|
|
+})
|
|
|
const check_all = computed({
|
|
const check_all = computed({
|
|
|
get: () => {
|
|
get: () => {
|
|
|
return classify_list.value.length == checked_keys.value.length
|
|
return classify_list.value.length == checked_keys.value.length
|
|
|
},
|
|
},
|
|
|
set: (val) => {
|
|
set: (val) => {
|
|
|
- if (val) {
|
|
|
|
|
- checked_keys.value = classify_list.value.map((m) => m.label)
|
|
|
|
|
- } else {
|
|
|
|
|
- checked_keys.value = []
|
|
|
|
|
- treeRef.value?.setCheckedNodes([])
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const keys = val ? classify_list.value.map((m) => m.label) : []
|
|
|
|
|
+ checked_keys.value = keys
|
|
|
|
|
+ treeRef.value?.setCheckedKeys(keys)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
const is_indeterminate = computed(() => {
|
|
const is_indeterminate = computed(() => {
|
|
|
return checked_keys.value.length > 0 && checked_keys.value.length < classify_list.value.length
|
|
return checked_keys.value.length > 0 && checked_keys.value.length < classify_list.value.length
|
|
|
})
|
|
})
|
|
|
-const getOffset = (index: number) => {
|
|
|
|
|
- return index % 4 == 0 ? 40 : index % 4 == 3 ? 80 : index % 4 == 2 ? 120 : 160
|
|
|
|
|
-}
|
|
|
|
|
const getFilteritems = (
|
|
const getFilteritems = (
|
|
|
arr: ILeftAsideConfigItemPublic[] | undefined
|
|
arr: ILeftAsideConfigItemPublic[] | undefined
|
|
|
): ILeftAsideConfigItemPublic[] => {
|
|
): ILeftAsideConfigItemPublic[] => {
|
|
|
if (!arr) {
|
|
if (!arr) {
|
|
|
return []
|
|
return []
|
|
|
}
|
|
}
|
|
|
- if (search_str.value) {
|
|
|
|
|
- return arr.filter((f) => f.title.includes(search_str.value))
|
|
|
|
|
|
|
+ const keyword = search_str.value.trim()
|
|
|
|
|
+ if (keyword) {
|
|
|
|
|
+ return arr.filter((f) => f.title.toLocaleLowerCase().includes(keyword.toLocaleLowerCase()))
|
|
|
}
|
|
}
|
|
|
return arr
|
|
return arr
|
|
|
}
|
|
}
|
|
@@ -218,7 +323,6 @@ const onDragStart = (config_item_key: string, item_id: string) => {
|
|
|
console.error('拖拽初始化失败', config_item_key, item_id)
|
|
console.error('拖拽初始化失败', config_item_key, item_id)
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- is_show_tooltip[`${config_item_key}${item_id}`] = false
|
|
|
|
|
globalStore.setIntention('create')
|
|
globalStore.setIntention('create')
|
|
|
globalStore.setCreateItemInfo({
|
|
globalStore.setCreateItemInfo({
|
|
|
config_key: config_item_key,
|
|
config_key: config_item_key,
|
|
@@ -226,9 +330,31 @@ const onDragStart = (config_item_key: string, item_id: string) => {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
const onManageClick = () => {
|
|
const onManageClick = () => {
|
|
|
|
|
+ const selectedExists = classify_list.value.some((item) => item.label === selected_node_key.value)
|
|
|
|
|
+ if (!selectedExists) {
|
|
|
|
|
+ selected_node_key.value =
|
|
|
|
|
+ classify_list.value.find((item) => item.label === '本地文件')?.label ||
|
|
|
|
|
+ classify_list.value[0]?.label
|
|
|
|
|
+ }
|
|
|
|
|
+ manage_search_str.value = ''
|
|
|
manage_dialog_visiable.value = true
|
|
manage_dialog_visiable.value = true
|
|
|
}
|
|
}
|
|
|
-const handleCheckChange = (data: { label: string }, checked: boolean, indeterminate: boolean) => {
|
|
|
|
|
|
|
+const onManageOpened = () => {
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ treeRef.value?.setCurrentKey(selected_node_key.value)
|
|
|
|
|
+ treeRef.value?.setCheckedKeys(checked_keys.value)
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+watch(search_str, (keyword) => {
|
|
|
|
|
+ if (!keyword.trim()) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ active_names.value = checked_keys.value.filter(
|
|
|
|
|
+ (key) => getFilteritems(leftAsideProps.leftAsideConfig.get(key)).length > 0
|
|
|
|
|
+ )
|
|
|
|
|
+})
|
|
|
|
|
+const handleCheckChange = (data: { label: string }, checked: boolean) => {
|
|
|
if (checked && !checked_keys.value.includes(data.label)) {
|
|
if (checked && !checked_keys.value.includes(data.label)) {
|
|
|
checked_keys.value.push(data.label)
|
|
checked_keys.value.push(data.label)
|
|
|
} else if (!checked) {
|
|
} else if (!checked) {
|
|
@@ -240,6 +366,7 @@ const handleCheckChange = (data: { label: string }, checked: boolean, indetermin
|
|
|
}
|
|
}
|
|
|
const onNodeClick = ({ label }: { label: string }) => {
|
|
const onNodeClick = ({ label }: { label: string }) => {
|
|
|
selected_node_key.value = label
|
|
selected_node_key.value = label
|
|
|
|
|
+ manage_search_str.value = ''
|
|
|
}
|
|
}
|
|
|
const onUpLoadChange = (e: UploadFile) => {
|
|
const onUpLoadChange = (e: UploadFile) => {
|
|
|
if (!e.raw!.type.includes('image/')) {
|
|
if (!e.raw!.type.includes('image/')) {
|
|
@@ -279,6 +406,7 @@ const onUpLoadChange = (e: UploadFile) => {
|
|
|
up_img_list.value = []
|
|
up_img_list.value = []
|
|
|
selected_node_key.value = '本地文件'
|
|
selected_node_key.value = '本地文件'
|
|
|
treeRef.value?.setCurrentKey('本地文件')
|
|
treeRef.value?.setCurrentKey('本地文件')
|
|
|
|
|
+ ElMessage.success('素材上传成功')
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
const onDelLocalFile = ({ id }: ILeftAsideConfigItem) => {
|
|
const onDelLocalFile = ({ id }: ILeftAsideConfigItem) => {
|
|
@@ -287,11 +415,636 @@ const onDelLocalFile = ({ id }: ILeftAsideConfigItem) => {
|
|
|
local_file.value.splice(find_index, 1)
|
|
local_file.value.splice(find_index, 1)
|
|
|
}
|
|
}
|
|
|
leftAsideProps.leftAsideConfig.set('本地文件', local_file.value)
|
|
leftAsideProps.leftAsideConfig.set('本地文件', local_file.value)
|
|
|
|
|
+ ElMessage.success('本地素材已删除')
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.component-library {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ padding: 14px 12px 0;
|
|
|
|
|
+ background: rgb(255 255 255 / 96%);
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ padding: 0 4px;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__header h2 {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 22px;
|
|
|
|
|
+ color: #172033;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__header p {
|
|
|
|
|
+ margin: 3px 0 0;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: #7a8699;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__count {
|
|
|
|
|
+ padding: 3px 8px;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__search {
|
|
|
|
|
+ margin: 13px 0 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__search :deep(.el-input__wrapper) {
|
|
|
|
|
+ padding: 0 11px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+ box-shadow: 0 0 0 1px #dbe1ea inset;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__search :deep(.el-input__wrapper:hover),
|
|
|
|
|
+.component-library__search :deep(.el-input__wrapper.is-focus) {
|
|
|
|
|
+ box-shadow: 0 0 0 1px var(--el-color-primary) inset;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__content {
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__content :deep(.el-scrollbar__view) {
|
|
|
|
|
+ padding-right: 3px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list {
|
|
|
|
|
+ border: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item) {
|
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 1px solid #e2e7ef;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ transition:
|
|
|
|
|
+ border-color 0.2s ease,
|
|
|
|
|
+ box-shadow 0.2s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item:hover),
|
|
|
|
|
+.category-list :deep(.el-collapse-item.is-active) {
|
|
|
|
|
+ border-color: var(--el-color-primary-light-7);
|
|
|
|
|
+ box-shadow: 0 4px 12px rgb(31 45 61 / 6%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item__header) {
|
|
|
|
|
+ height: 44px;
|
|
|
|
|
+ padding: 0 11px;
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ border: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item__arrow) {
|
|
|
|
|
+ margin-left: 8px;
|
|
|
|
|
+ color: #7d899b;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item__wrap) {
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ border: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-collapse-item__content) {
|
|
|
|
|
+ padding: 0 10px 11px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-title__icon {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ width: 26px;
|
|
|
|
|
+ height: 26px;
|
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
|
|
+ border-radius: 7px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-title__icon svg {
|
|
|
|
|
+ width: 15px;
|
|
|
|
|
+ height: 15px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-title__name {
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #344054;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-title__count {
|
|
|
|
|
+ min-width: 20px;
|
|
|
|
|
+ padding: 1px 6px;
|
|
|
|
|
+ margin-left: auto;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: #667085;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ background: #f1f4f8;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
|
|
+ gap: 7px;
|
|
|
|
|
+ margin-top: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card {
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ padding: 5px;
|
|
|
|
|
+ cursor: grab;
|
|
|
|
|
+ background: #f8fafc;
|
|
|
|
|
+ border: 1px solid #e4e9f0;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+ transition:
|
|
|
|
|
+ border-color 0.18s ease,
|
|
|
|
|
+ background 0.18s ease,
|
|
|
|
|
+ box-shadow 0.18s ease,
|
|
|
|
|
+ transform 0.18s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card:hover {
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-color: var(--el-color-primary-light-5);
|
|
|
|
|
+ transform: translateY(-1px);
|
|
|
|
|
+ box-shadow: 0 5px 14px rgb(64 158 255 / 13%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card:active {
|
|
|
|
|
+ cursor: grabbing;
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card__preview {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ height: 38px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background:
|
|
|
|
|
+ linear-gradient(45deg, #f2f5f8 25%, transparent 25%) 0 0 / 12px 12px,
|
|
|
|
|
+ linear-gradient(45deg, transparent 75%, #f2f5f8 75%) 0 0 / 12px 12px,
|
|
|
|
|
+ linear-gradient(45deg, transparent 75%, #f2f5f8 75%) 6px -6px / 12px 12px,
|
|
|
|
|
+ linear-gradient(45deg, #f2f5f8 25%, #fff 25%) 6px -6px / 12px 12px;
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card__image {
|
|
|
|
|
+ width: 32px;
|
|
|
|
|
+ height: 32px;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-card__name {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-top: 4px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: #475467;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-empty) {
|
|
|
|
|
+ padding: 12px 0 6px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-empty__description) {
|
|
|
|
|
+ margin-top: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-list :deep(.el-empty__description p) {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__footer {
|
|
|
|
|
+ padding: 12px 2px 14px;
|
|
|
|
|
+ border-top: 1px solid #dfe4eb;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__footer :deep(.el-button) {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__footer :deep(.el-button > span) {
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-library__footer > span {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ line-height: 16px;
|
|
|
|
|
+ color: #98a2b3;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header-icon {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ width: 38px;
|
|
|
|
|
+ height: 38px;
|
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header-icon svg {
|
|
|
|
|
+ width: 20px;
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header h2,
|
|
|
|
|
+.manage-components__header h3 {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ color: #172033;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header h2 {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 22px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__header p,
|
|
|
|
|
+.manage-components__header p {
|
|
|
|
|
+ margin: 3px 0 0;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: #7a8699;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__layout {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ height: min(560px, calc(100vh - 210px));
|
|
|
|
|
+ min-height: 420px;
|
|
|
|
|
+ grid-template-columns: 220px minmax(0, 1fr);
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories,
|
|
|
|
|
+.manage-components {
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 1px solid #e1e7ef;
|
|
|
|
|
+ border-radius: 11px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header,
|
|
|
|
|
+.manage-components__header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ border-bottom: 1px solid #e8ecf2;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header {
|
|
|
|
|
+ min-height: 64px;
|
|
|
|
|
+ padding: 0 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header > div {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 3px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header strong {
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ color: #263245;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header span {
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ color: #8a95a6;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__header :deep(.el-checkbox) {
|
|
|
|
|
+ height: 28px;
|
|
|
|
|
+ margin-left: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-categories__scrollbar,
|
|
|
|
|
+.manage-components__scrollbar {
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-tree {
|
|
|
|
|
+ padding: 8px;
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-tree :deep(.el-tree-node__content) {
|
|
|
|
|
+ height: 38px;
|
|
|
|
|
+ padding-right: 8px;
|
|
|
|
|
+ margin-bottom: 3px;
|
|
|
|
|
+ border-radius: 7px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-tree :deep(.el-tree-node__content:hover) {
|
|
|
|
|
+ background: #f4f7fb;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-tree :deep(.el-tree-node.is-current > .el-tree-node__content) {
|
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-node {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-node > span:first-child {
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-category-node > span:last-child {
|
|
|
|
|
+ min-width: 22px;
|
|
|
|
|
+ padding: 0 6px;
|
|
|
|
|
+ margin-left: auto;
|
|
|
|
|
+ font-size: 10px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: #718096;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ background: #eef2f7;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__header {
|
|
|
|
|
+ min-height: 64px;
|
|
|
|
|
+ padding: 0 16px;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__header h3 {
|
|
|
|
|
+ font-size: 15px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ line-height: 21px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__actions {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__actions > :deep(.el-input) {
|
|
|
|
|
+ width: 190px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__actions :deep(.el-input__wrapper) {
|
|
|
|
|
+ border-radius: 7px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__actions :deep(.el-button > span) {
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ padding: 14px;
|
|
|
|
|
+ grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ padding: 8px;
|
|
|
|
|
+ background: #f8fafc;
|
|
|
|
|
+ border: 1px solid #e3e8f0;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+ transition:
|
|
|
|
|
+ border-color 0.18s ease,
|
|
|
|
|
+ box-shadow 0.18s ease,
|
|
|
|
|
+ transform 0.18s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card:hover {
|
|
|
|
|
+ border-color: var(--el-color-primary-light-5);
|
|
|
|
|
+ transform: translateY(-1px);
|
|
|
|
|
+ box-shadow: 0 5px 14px rgb(31 45 61 / 8%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card__preview {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ height: 74px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background:
|
|
|
|
|
+ linear-gradient(45deg, #eef2f6 25%, transparent 25%) 0 0 / 14px 14px,
|
|
|
|
|
+ linear-gradient(45deg, transparent 75%, #eef2f6 75%) 0 0 / 14px 14px,
|
|
|
|
|
+ linear-gradient(45deg, transparent 75%, #eef2f6 75%) 7px -7px / 14px 14px,
|
|
|
|
|
+ linear-gradient(45deg, #eef2f6 25%, #fff 25%) 7px -7px / 14px 14px;
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card__image {
|
|
|
|
|
+ width: 64px;
|
|
|
|
|
+ height: 64px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card__name {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ color: #475467;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card__delete {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 5px;
|
|
|
|
|
+ right: 5px;
|
|
|
|
|
+ width: 26px;
|
|
|
|
|
+ height: 26px;
|
|
|
|
|
+ color: var(--el-color-danger);
|
|
|
|
|
+ background: rgb(255 255 255 / 92%);
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+ box-shadow: 0 2px 7px rgb(31 45 61 / 12%);
|
|
|
|
|
+ transition:
|
|
|
|
|
+ opacity 0.18s ease,
|
|
|
|
|
+ transform 0.18s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-component-card:hover .manage-component-card__delete,
|
|
|
|
|
+.manage-component-card__delete:focus-visible {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-components__scrollbar :deep(.el-empty) {
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ padding: 30px 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__footer {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__footer > span {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #8a95a6;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.manage-dialog__footer :deep(.el-button) {
|
|
|
|
|
+ min-width: 82px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-library {
|
|
|
|
|
+ background: rgb(24 31 43 / 97%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-library__header h2,
|
|
|
|
|
+.dark .category-title__name {
|
|
|
|
|
+ color: #edf2f8;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-library__header p,
|
|
|
|
|
+.dark .component-library__footer > span {
|
|
|
|
|
+ color: #8d99aa;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-library__search :deep(.el-input__wrapper),
|
|
|
|
|
+.dark .category-list :deep(.el-collapse-item) {
|
|
|
|
|
+ background: #202735;
|
|
|
|
|
+ border-color: #303949;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .category-title__count {
|
|
|
|
|
+ color: #aeb8c7;
|
|
|
|
|
+ background: #2b3444;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-card {
|
|
|
|
|
+ background: #252d3b;
|
|
|
|
|
+ border-color: #354052;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-card:hover {
|
|
|
|
|
+ background: #2a3445;
|
|
|
|
|
+ border-color: var(--el-color-primary-dark-2);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-card__name {
|
|
|
|
|
+ color: #cad3df;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dark .component-library__footer {
|
|
|
|
|
+ border-color: #303949;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+
|
|
|
<style>
|
|
<style>
|
|
|
-#mt-left-aside .el-collapse-item__header,
|
|
|
|
|
-#mt-left-aside .el-collapse-item__wrap {
|
|
|
|
|
- background-color: transparent !important;
|
|
|
|
|
|
|
+.component-manage-dialog {
|
|
|
|
|
+ max-width: calc(100vw - 40px);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ border-radius: 14px;
|
|
|
|
|
+ box-shadow: 0 20px 60px rgb(15 23 42 / 20%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-manage-dialog .el-dialog__header {
|
|
|
|
|
+ padding: 17px 20px;
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ border-bottom: 1px solid #e4e9f0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-manage-dialog .el-dialog__headerbtn {
|
|
|
|
|
+ top: 16px;
|
|
|
|
|
+ right: 16px;
|
|
|
|
|
+ width: 32px;
|
|
|
|
|
+ height: 32px;
|
|
|
|
|
+ border-radius: 7px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-manage-dialog .el-dialog__headerbtn:hover {
|
|
|
|
|
+ background: #f1f4f8;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-manage-dialog .el-dialog__body {
|
|
|
|
|
+ padding: 14px 18px;
|
|
|
|
|
+ background: #f6f8fb;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.component-manage-dialog .el-dialog__footer {
|
|
|
|
|
+ padding: 12px 18px;
|
|
|
|
|
+ border-top: 1px solid #e4e9f0;
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|