Ver código fonte

优化视图的滚动方法

icssoa 1 ano atrás
pai
commit
eb452189ea

+ 6 - 28
src/modules/base/pages/main/components/views.vue

@@ -1,13 +1,11 @@
 <template>
 	<div class="app-views">
 		<router-view v-slot="{ Component }">
-			<el-scrollbar :ref="setRefs('scrollbar')" :key="key">
-				<transition :name="app.info.router.transition || 'none'">
-					<keep-alive :include="caches">
-						<component :is="Component" />
-					</keep-alive>
-				</transition>
-			</el-scrollbar>
+			<transition :name="app.info.router.transition || 'none'">
+				<keep-alive :include="caches" :key="key">
+					<component :is="Component" />
+				</keep-alive>
+			</transition>
 		</router-view>
 	</div>
 </template>
@@ -17,7 +15,7 @@ import { computed, onMounted, onUnmounted, ref } from "vue";
 import { useBase } from "/$/base";
 import { useCool } from "/@/cool";
 
-const { refs, setRefs, mitt } = useCool();
+const { mitt } = useCool();
 const { process, app } = useBase();
 
 // 缓存数
@@ -37,27 +35,11 @@ function refresh() {
 	key.value += 1;
 }
 
-// 滚动到
-function scrollTo({ el, top }: { el?: string; top?: number }) {
-	const scrollbar = refs.scrollbar.wrapRef;
-
-	if (el) {
-		top = scrollbar.querySelector(el).offsetTop;
-	}
-
-	scrollbar.scrollTo({
-		top,
-		behavior: "smooth"
-	});
-}
-
 onMounted(() => {
-	mitt.on("view.scrollTo", scrollTo);
 	mitt.on("view.refresh", refresh);
 });
 
 onUnmounted(() => {
-	mitt.off("view.scrollTo");
 	mitt.off("view.refresh");
 });
 </script>
@@ -72,10 +54,6 @@ onUnmounted(() => {
 	border-radius: 4px;
 	position: relative;
 
-	:deep(.el-scrollbar__view) {
-		height: 100%;
-	}
-
 	.none-enter-active {
 		position: absolute;
 	}

+ 0 - 13
src/modules/base/static/css/index.scss

@@ -1,16 +1,3 @@
-*::-webkit-scrollbar {
-	width: 10px;
-	height: 10px;
-}
-
-*::-webkit-scrollbar-thumb {
-	background-color: rgba(144, 147, 153, 0.3);
-}
-
-*::-webkit-scrollbar-track {
-	background: transparent;
-}
-
 #app {
 	height: 100vh;
 	width: 100vw;

+ 50 - 48
src/modules/demo/views/home/index.vue

@@ -1,54 +1,56 @@
 <template>
-	<div class="view-home">
-		<el-row :gutter="15">
-			<el-col :lg="6" :md="12" :xs="24">
-				<div class="card">
-					<count-user />
-				</div>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<div class="card">
-					<count-views />
-				</div>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<div class="card">
-					<count-paid />
-				</div>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<div class="card">
-					<count-effect />
-				</div>
-			</el-col>
-		</el-row>
+	<el-scrollbar>
+		<div class="view-home">
+			<el-row :gutter="15">
+				<el-col :lg="6" :md="12" :xs="24">
+					<div class="card">
+						<count-user />
+					</div>
+				</el-col>
+				<el-col :lg="6" :md="12" :xs="24">
+					<div class="card">
+						<count-views />
+					</div>
+				</el-col>
+				<el-col :lg="6" :md="12" :xs="24">
+					<div class="card">
+						<count-paid />
+					</div>
+				</el-col>
+				<el-col :lg="6" :md="12" :xs="24">
+					<div class="card">
+						<count-effect />
+					</div>
+				</el-col>
+			</el-row>
 
-		<el-row :gutter="15">
-			<el-col :lg="14" :xs="24">
-				<div class="card">
-					<tab-chart />
-				</div>
-			</el-col>
-			<el-col :lg="10" :xs="24">
-				<div class="card">
-					<sales-rank />
-				</div>
-			</el-col>
-		</el-row>
+			<el-row :gutter="15">
+				<el-col :lg="14" :xs="24">
+					<div class="card">
+						<tab-chart />
+					</div>
+				</el-col>
+				<el-col :lg="10" :xs="24">
+					<div class="card">
+						<sales-rank />
+					</div>
+				</el-col>
+			</el-row>
 
-		<el-row :gutter="15">
-			<el-col :lg="14" :sm="24">
-				<div class="card card--last">
-					<hot-search />
-				</div>
-			</el-col>
-			<el-col :lg="10" :sm="24">
-				<div class="card card--last">
-					<category-ratio />
-				</div>
-			</el-col>
-		</el-row>
-	</div>
+			<el-row :gutter="15">
+				<el-col :lg="14" :sm="24">
+					<div class="card card--last">
+						<hot-search />
+					</div>
+				</el-col>
+				<el-col :lg="10" :sm="24">
+					<div class="card card--last">
+						<category-ratio />
+					</div>
+				</el-col>
+			</el-row>
+		</div>
+	</el-scrollbar>
 </template>
 
 <script lang="ts" name="home" setup>

+ 4 - 3
src/modules/design/views/page.vue

@@ -7,10 +7,11 @@
 		<div class="footer">
 			<el-button @click="clear">清空</el-button>
 			<el-button type="info" @click="save">保存草稿</el-button>
-			<el-button type="success" @click="create">生成代码</el-button>
-		</div>
 
-		<cl-editor-preview title="代码预览" name="monaco" :ref="setRefs('preview')" />
+			<cl-editor-preview title="代码预览" name="monaco" :ref="setRefs('preview')">
+				<el-button type="success" @click="create">生成代码</el-button>
+			</cl-editor-preview>
+		</div>
 	</div>
 </template>
 

+ 0 - 25
src/modules/helper/hooks/ai.ts

@@ -142,28 +142,3 @@ export function useAi() {
 		matchType
 	};
 }
-
-export function useScroll() {
-	const { mitt } = useCool();
-
-	let timer: any;
-
-	function start() {
-		stop();
-
-		timer = setInterval(() => {
-			mitt.emit("view.scrollTo", { top: Math.random() + 10000 });
-		}, 100);
-	}
-
-	function stop() {
-		if (timer) {
-			clearInterval(timer);
-		}
-	}
-
-	return {
-		start,
-		stop
-	};
-}

+ 5 - 4
src/modules/helper/static/index.scss

@@ -1,9 +1,10 @@
 .plugins {
-	overflow-x: hidden;
-	background-color: var(--el-bg-color);
 	padding: 10px;
-	height: 100%;
-	box-sizing: border-box;
+
+	&__wrapper {
+		background-color: var(--el-bg-color);
+		height: 100%;
+	}
 
 	.scope {
 		border-radius: 8px;

+ 198 - 159
src/modules/helper/views/ai-code.vue

@@ -1,176 +1,180 @@
 <template>
-	<div class="ai-code">
-		<div class="container">
-			<div class="head">
-				<text2 model-value="Cool Ai 极速编码" />
-			</div>
+	<el-scrollbar :ref="setRefs('scrollbar')">
+		<div class="ai-code">
+			<div class="container">
+				<div class="head">
+					<text2 model-value="Cool Ai 极速编码" />
+				</div>
 
-			<div class="form">
-				<el-form :disabled="temp.disabled" size="large">
-					<div class="label required">CRUD</div>
-
-					<el-row :gutter="10">
-						<el-col :lg="6" :xs="24" :sm="12">
-							<cl-select
-								class="module"
-								placeholder="请选择模块"
-								v-model="form.module"
-								:options="module.dirs"
-								label-key="name"
-								value-key="name"
-								allow-create
-							/>
-						</el-col>
-
-						<el-col :lg="6" :xs="24" :sm="12">
-							<el-input
-								class="name"
-								v-model="form.name"
-								placeholder="实体名称,如:收货地址"
-							/>
-						</el-col>
-
-						<el-col :lg="12" :xs="24" :sm="24">
-							<el-input
-								class="columns"
-								v-model="form.columns"
-								placeholder="请填写字段,如:姓名、年龄、状态"
-							/>
-						</el-col>
-					</el-row>
-
-					<div class="label">其他你想做的事?</div>
-
-					<el-input
-						type="textarea"
-						v-model="form.other"
-						:rows="5"
-						placeholder="如:分页查询时姓名、手机号字段设置成可模糊搜索"
-					/>
-				</el-form>
-			</div>
+				<div class="form">
+					<el-form :disabled="temp.disabled" size="large">
+						<div class="label required">CRUD</div>
+
+						<el-row :gutter="10">
+							<el-col :lg="6" :xs="24" :sm="12">
+								<cl-select
+									class="module"
+									placeholder="请选择模块"
+									v-model="form.module"
+									:options="module.dirs"
+									label-key="name"
+									value-key="name"
+									allow-create
+								/>
+							</el-col>
+
+							<el-col :lg="6" :xs="24" :sm="12">
+								<el-input
+									class="name"
+									v-model="form.name"
+									placeholder="实体名称,如:收货地址"
+								/>
+							</el-col>
+
+							<el-col :lg="12" :xs="24" :sm="24">
+								<el-input
+									class="columns"
+									v-model="form.columns"
+									placeholder="请填写字段,如:姓名、年龄、状态"
+								/>
+							</el-col>
+						</el-row>
+
+						<div class="label">其他你想做的事?</div>
+
+						<el-input
+							type="textarea"
+							v-model="form.other"
+							:rows="5"
+							placeholder="如:分页查询时姓名、手机号字段设置成可模糊搜索"
+						/>
+					</el-form>
+				</div>
 
-			<div class="btns">
-				<el-button
-					round
-					size="large"
-					type="primary"
-					:icon="Promotion"
-					:disabled="temp.disabled"
-					:loading="temp.disabled"
-					@click="next"
-				>
-					{{ temp.disabled ? "思考中" : codes.entity.length ? "重新生成" : "下一步" }}
-				</el-button>
-			</div>
+				<div class="btns">
+					<el-button
+						round
+						size="large"
+						type="primary"
+						:icon="Promotion"
+						:disabled="temp.disabled"
+						:loading="temp.disabled"
+						@click="next"
+					>
+						{{ temp.disabled ? "思考中" : codes.entity.length ? "重新生成" : "下一步" }}
+					</el-button>
+				</div>
 
-			<div class="tips">如遇见 “代码缺失”、“请求超时”,请尝试「刷新」吧</div>
-
-			<!-- 代码 -->
-			<div class="codes">
-				<div class="item is-entity" v-show="codes.entity">
-					<div class="label">
-						<div class="name">
-							<span>Entity(实体类)</span>
-							<el-icon class="is-loading" v-show="temp.coding == 'entity'">
-								<loading />
-							</el-icon>
+				<div class="tips">如遇见 “代码缺失”、“请求超时”,请尝试「刷新」吧</div>
+
+				<!-- 代码 -->
+				<div class="codes">
+					<div class="item is-entity" v-show="codes.entity">
+						<div class="label">
+							<div class="name">
+								<span>Entity(实体类)</span>
+								<el-icon class="is-loading" v-show="temp.coding == 'entity'">
+									<loading />
+								</el-icon>
+							</div>
+
+							<template v-if="!temp.disabled">
+								<el-button round size="small" @click="copyCode('entity')"
+									>Copy</el-button
+								>
+								<el-button
+									round
+									type="success"
+									size="small"
+									:loading="!codes.vue"
+									@click="createVue()"
+								>
+									生成Vue代码
+								</el-button>
+							</template>
 						</div>
 
-						<template v-if="!temp.disabled">
-							<el-button round size="small" @click="copyCode('entity')"
-								>Copy</el-button
-							>
-							<el-button
-								round
-								type="success"
-								size="small"
-								:loading="!codes.vue"
-								@click="createVue()"
-							>
-								生成Vue代码
-							</el-button>
-						</template>
+						<cl-editor
+							name="cl-editor-monaco"
+							:ref="setRefs('codeEntity')"
+							:options="editor.options"
+							height="auto"
+							autofocus
+							autosize
+							language="typescript"
+							v-model="codes.entity"
+						/>
 					</div>
 
-					<cl-editor
-						name="cl-editor-monaco"
-						:ref="setRefs('codeEntity')"
-						:options="editor.options"
-						height="auto"
-						autofocus
-						autosize
-						language="typescript"
-						v-model="codes.entity"
-					/>
-				</div>
-
-				<div class="item is-controller" v-show="codes.controller">
-					<div class="label">
-						<div class="name">
-							<span>Controller(控制层)</span>
-							<el-icon class="is-loading" v-show="temp.coding == 'controller'">
-								<loading />
-							</el-icon>
+					<div class="item is-controller" v-show="codes.controller">
+						<div class="label">
+							<div class="name">
+								<span>Controller(控制层)</span>
+								<el-icon class="is-loading" v-show="temp.coding == 'controller'">
+									<loading />
+								</el-icon>
+							</div>
+
+							<template v-if="!temp.disabled">
+								<el-button round size="small" @click="copyCode('controller')"
+									>Copy</el-button
+								>
+							</template>
 						</div>
 
-						<template v-if="!temp.disabled">
-							<el-button round size="small" @click="copyCode('controller')"
-								>Copy</el-button
-							>
-						</template>
+						<cl-editor
+							name="cl-editor-monaco"
+							:ref="setRefs('codeController')"
+							:options="editor.options"
+							height="auto"
+							autosize
+							language="typescript"
+							v-model="codes.controller"
+						/>
 					</div>
 
-					<cl-editor
-						name="cl-editor-monaco"
-						:ref="setRefs('codeController')"
-						:options="editor.options"
-						height="auto"
-						autosize
-						language="typescript"
-						v-model="codes.controller"
-					/>
-				</div>
-
-				<div class="item is-vue" v-show="codes.vue">
-					<div class="label">
-						<div class="name">
-							<span>Vue(页面)</span>
-							<el-icon class="is-loading" v-show="temp.coding == 'vue'">
-								<loading />
-							</el-icon>
+					<div class="item is-vue" v-show="codes.vue">
+						<div class="label">
+							<div class="name">
+								<span>Vue(页面)</span>
+								<el-icon class="is-loading" v-show="temp.coding == 'vue'">
+									<loading />
+								</el-icon>
+							</div>
+
+							<template v-if="!temp.disabled">
+								<el-button round size="small" @click="copyCode('vue')"
+									>Copy</el-button
+								>
+							</template>
 						</div>
 
-						<template v-if="!temp.disabled">
-							<el-button round size="small" @click="copyCode('vue')">Copy</el-button>
-						</template>
+						<cl-editor
+							name="cl-editor-monaco"
+							:ref="setRefs('codeVue')"
+							:options="editor.options"
+							height="auto"
+							autosize
+							language="html"
+							v-model="codes.vue"
+						/>
 					</div>
+				</div>
 
-					<cl-editor
-						name="cl-editor-monaco"
-						:ref="setRefs('codeVue')"
-						:options="editor.options"
-						height="auto"
-						autosize
-						language="html"
-						v-model="codes.vue"
-					/>
+				<div class="op" v-show="!temp.disabled && codes.entity.length">
+					<el-button :icon="Close" round size="large" @click="reset"> 取消 </el-button>
+					<el-button :icon="Check" round size="large" type="success" @click="createFile">
+						创建文件
+					</el-button>
 				</div>
-			</div>
 
-			<div class="op" v-show="!temp.disabled && codes.entity.length">
-				<el-button :icon="Close" round size="large" @click="reset"> 取消 </el-button>
-				<el-button :icon="Check" round size="large" type="success" @click="createFile">
-					创建文件
-				</el-button>
+				<div class="bottom"></div>
 			</div>
 
-			<div class="bottom"></div>
+			<!-- 创建菜单 -->
+			<cl-form ref="Form" />
 		</div>
-
-		<!-- 创建菜单 -->
-		<cl-form ref="Form" />
-	</div>
+	</el-scrollbar>
 </template>
 
 <script lang="tsx" setup name="helper-ai-code">
@@ -180,19 +184,54 @@ import { Promotion, Loading, Close, Check } from "@element-plus/icons-vue";
 import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
 import { debounce, isEmpty } from "lodash-es";
 import { useClipboard } from "@vueuse/core";
-import { useMenu, useAi, useScroll } from "../hooks";
+import { useMenu, useAi } from "../hooks";
 import { isDev } from "/@/config";
 import { useForm } from "@cool-vue/crud";
 import type { CodeType } from "../types";
 import Text2 from "../components/text.vue";
 
-const { service, mitt, refs, setRefs } = useCool();
+const { service, refs, setRefs } = useCool();
 const { copy } = useClipboard();
 const menu = useMenu();
 const ai = useAi();
-const scroll = useScroll();
 const Form = useForm();
 
+// 滚动条
+const scroller = {
+	timer: null as any,
+
+	scrollTo({ el, top }: { el?: string; top?: number }) {
+		const scrollbar = refs.scrollbar.wrapRef;
+
+		if (el) {
+			top = scrollbar.querySelector(el).offsetTop;
+		}
+
+		scrollbar.scrollTo({
+			top,
+			behavior: "smooth"
+		});
+	},
+
+	start() {
+		this.stop();
+
+		this.timer = setInterval(() => {
+			if (codes.entity) {
+				this.scrollTo({
+					top: Math.random() + 10000
+				});
+			}
+		}, 100);
+	},
+
+	stop() {
+		if (this.timer) {
+			clearInterval(this.timer);
+		}
+	}
+};
+
 // 编辑器
 const editor = reactive({
 	options: {
@@ -275,14 +314,14 @@ function send(type: CodeType = "entity", data: any) {
 	});
 
 	// 开始滚动
-	scroll.start();
+	scroller.start();
 }
 
 // 结束
 function stop() {
 	temp.disabled = false;
 	temp.coding = "";
-	scroll.stop();
+	scroller.stop();
 }
 
 // 重置
@@ -454,7 +493,7 @@ const createVue = debounce((auto?: boolean) => {
 			stop();
 
 			setTimeout(() => {
-				mitt.emit("view.scrollTo", { el: `.codes .is-vue` });
+				scroller.scrollTo({ el: `.codes .is-vue` });
 				refs.codeVue.formatCode();
 			}, 300);
 		}
@@ -629,7 +668,7 @@ onMounted(() => {
 	}
 
 	.bottom {
-		height: 100px;
+		height: 10vh;
 	}
 }
 </style>

+ 107 - 85
src/modules/helper/views/plugins/serve.vue

@@ -1,95 +1,113 @@
 <template>
-	<div class="plugins" @dragover="onDragover" @drop="onDrop">
-		<el-tabs v-model="tab.active" type="card" @tab-change="tab.onChange">
-			<el-tab-pane label="已安装插件" name="installed"> </el-tab-pane>
-			<el-tab-pane label="插件市场" name="shop"> </el-tab-pane>
-		</el-tabs>
-
-		<el-row :gutter="10">
-			<el-col v-for="(item, index) in list" :key="index" :xs="24" :sm="12" :md="8" :lg="6">
-				<div class="scope">
-					<div class="c">
-						<el-icon class="set" @click="toSet(item)">
-							<setting />
-						</el-icon>
-
-						<img class="logo" :src="'data:image/jpg;base64,' + item.logo" />
-
-						<div class="det">
-							<div class="tag">
-								<el-tag size="small" effect="dark">{{ item.keyName }}</el-tag>
-								<el-tag size="small" effect="dark" type="success"
-									>v{{ item.version }}</el-tag
-								>
+	<div class="plugins__wrapper">
+		<el-scrollbar>
+			<div class="plugins" @dragover="onDragover" @drop="onDrop">
+				<el-tabs v-model="tab.active" type="card" @tab-change="tab.onChange">
+					<el-tab-pane label="已安装插件" name="installed"> </el-tab-pane>
+					<el-tab-pane label="插件市场" name="shop"> </el-tab-pane>
+				</el-tabs>
+
+				<el-row :gutter="10">
+					<el-col
+						v-for="(item, index) in list"
+						:key="index"
+						:xs="24"
+						:sm="12"
+						:md="8"
+						:lg="6"
+					>
+						<div class="scope">
+							<div class="c">
+								<el-icon class="set" @click="toSet(item)">
+									<setting />
+								</el-icon>
+
+								<img class="logo" :src="'data:image/jpg;base64,' + item.logo" />
+
+								<div class="det">
+									<div class="tag">
+										<el-tag size="small" effect="dark">{{
+											item.keyName
+										}}</el-tag>
+										<el-tag size="small" effect="dark" type="success"
+											>v{{ item.version }}</el-tag
+										>
+									</div>
+
+									<p class="title">
+										{{ item.name || "未知" }}
+									</p>
+
+									<p class="desc">{{ item.description || "暂无描述" }}</p>
+
+									<div class="author">
+										<span>{{ item.author }}:</span>
+										<span>{{ item.updateTime }}</span>
+									</div>
+								</div>
 							</div>
 
-							<p class="title">
-								{{ item.name || "未知" }}
-							</p>
+							<div class="f">
+								<el-button round @click="toDetail(item)">详情</el-button>
+								<el-button type="danger" round @click="toDel(item, index)"
+									>卸载</el-button
+								>
 
-							<p class="desc">{{ item.description || "暂无描述" }}</p>
+								<cl-flex1 />
 
-							<div class="author">
-								<span>{{ item.author }}:</span>
-								<span>{{ item.updateTime }}</span>
+								<cl-switch
+									v-model="item.status"
+									@change="onStatusChange(item)"
+								></cl-switch>
 							</div>
 						</div>
-					</div>
-
-					<div class="f">
-						<el-button round @click="toDetail(item)">详情</el-button>
-						<el-button type="danger" round @click="toDel(item, index)">卸载</el-button>
-
-						<cl-flex1 />
-
-						<cl-switch v-model="item.status" @change="onStatusChange(item)"></cl-switch>
-					</div>
-				</div>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :md="8" :lg="6">
-				<cl-upload :before-upload="onBeforeUpload" accept=".cool">
-					<div class="scope is-add">
-						<el-icon>
-							<plus />
-						</el-icon>
-					</div>
-				</cl-upload>
-			</el-col>
-		</el-row>
-
-		<!-- 详情预览 -->
-		<cl-editor-preview
-			:ref="setRefs('editorPreview')"
-			name="wang"
-			:show-btn="false"
-			:title="`${info?.name} v${info?.version} 说明文档`"
-		>
-			<template #prepend>
-				<div class="info-header">
-					<span>作者:{{ info?.author }}</span>
-					<span>更新时间:{{ info?.updateTime }}</span>
-				</div>
-			</template>
-		</cl-editor-preview>
-
-		<!-- 设置 -->
-		<cl-form ref="Form">
-			<template #slot-upload>
-				<cl-row>
-					<cl-upload-space
-						:show-list="false"
-						:multiple="false"
-						text="选择文件"
-						@confirm="onFileConfirm"
-					/>
-
-					<el-text type="warning" :style="{ marginLeft: '10px' }"
-						>选择后会在光标后插入文件链接</el-text
-					>
-				</cl-row>
-			</template>
-		</cl-form>
+					</el-col>
+
+					<el-col :xs="24" :sm="12" :md="8" :lg="6">
+						<cl-upload :before-upload="onBeforeUpload" accept=".cool">
+							<div class="scope is-add">
+								<el-icon>
+									<plus />
+								</el-icon>
+							</div>
+						</cl-upload>
+					</el-col>
+				</el-row>
+
+				<!-- 详情预览 -->
+				<cl-editor-preview
+					:ref="setRefs('editorPreview')"
+					name="wang"
+					:show-btn="false"
+					:title="`${info?.name} v${info?.version} 说明文档`"
+				>
+					<template #prepend>
+						<div class="info-header">
+							<span>作者:{{ info?.author }}</span>
+							<span>更新时间:{{ info?.updateTime }}</span>
+						</div>
+					</template>
+				</cl-editor-preview>
+
+				<!-- 设置 -->
+				<cl-form ref="Form">
+					<template #slot-upload>
+						<cl-row>
+							<cl-upload-space
+								:show-list="false"
+								:multiple="false"
+								text="选择文件"
+								@confirm="onFileConfirm"
+							/>
+
+							<el-text type="warning" :style="{ marginLeft: '10px' }"
+								>选择后会在光标后插入文件链接</el-text
+							>
+						</cl-row>
+					</template>
+				</cl-form>
+			</div>
+		</el-scrollbar>
 	</div>
 </template>
 
@@ -137,6 +155,10 @@ function toSet(item: Eps.PluginInfoEntity) {
 	Form.value?.open({
 		title: "设置",
 
+		props: {
+			labelWidth: "60px"
+		},
+
 		form: {
 			...item
 		},

+ 72 - 55
src/modules/helper/views/plugins/vue.vue

@@ -1,62 +1,79 @@
 <template>
-	<div class="plugins">
-		<el-tabs v-model="tab.active" type="card" @tab-change="tab.onChange">
-			<el-tab-pane label="已安装插件" name="installed"> </el-tab-pane>
-			<el-tab-pane label="插件市场" name="shop"> </el-tab-pane>
-		</el-tabs>
-
-		<el-row :gutter="10">
-			<el-col v-for="(item, index) in list" :key="index" :xs="24" :sm="12" :md="8" :lg="6">
-				<div class="scope">
-					<div class="c">
-						<img class="logo" :src="item.logo" />
-
-						<div class="det">
-							<div class="tag">
-								<el-tag size="small" effect="dark">{{ item.name }}</el-tag>
-								<el-tag size="small" effect="dark" type="success"
-									>v{{ item.version || "1.0.0" }}</el-tag
-								>
-							</div>
-
-							<p class="title">
-								{{ item.label || "未知" }}
-							</p>
-
-							<p class="desc">{{ item.description || "暂无描述" }}</p>
+	<div class="plugins__wrapper">
+		<el-scrollbar>
+			<div class="plugins">
+				<div class="header">
+					<el-tabs v-model="tab.active" type="card" @tab-change="tab.onChange">
+						<el-tab-pane label="已安装插件" name="installed"> </el-tab-pane>
+						<el-tab-pane label="插件市场" name="shop"> </el-tab-pane>
+					</el-tabs>
+				</div>
 
-							<div class="author">
-								<span>{{ item.author || "Ta" }}:</span>
-								<span>{{ item.updateTime || "2024-01-01" }}</span>
-							</div>
-						</div>
-					</div>
-
-					<div class="f">
-						<cl-flex1 />
-						<el-button
-							round
-							@click="det.open(item)"
-							v-if="item.demo && !isEmpty(item.demo)"
-							>示例</el-button
+				<div class="container">
+					<el-row :gutter="10">
+						<el-col
+							v-for="(item, index) in list"
+							:key="index"
+							:xs="24"
+							:sm="12"
+							:md="8"
+							:lg="6"
 						>
-					</div>
+							<div class="scope">
+								<div class="c">
+									<img class="logo" :src="item.logo" />
+
+									<div class="det">
+										<div class="tag">
+											<el-tag size="small" effect="dark">{{
+												item.name
+											}}</el-tag>
+											<el-tag size="small" effect="dark" type="success"
+												>v{{ item.version || "1.0.0" }}</el-tag
+											>
+										</div>
+
+										<p class="title">
+											{{ item.label || "未知" }}
+										</p>
+
+										<p class="desc">{{ item.description || "暂无描述" }}</p>
+
+										<div class="author">
+											<span>{{ item.author || "Ta" }}:</span>
+											<span>{{ item.updateTime || "2024-01-01" }}</span>
+										</div>
+									</div>
+								</div>
+
+								<div class="f">
+									<cl-flex1 />
+									<el-button
+										round
+										@click="det.open(item)"
+										v-if="item.demo && !isEmpty(item.demo)"
+										>示例</el-button
+									>
+								</div>
+							</div>
+						</el-col>
+					</el-row>
 				</div>
-			</el-col>
-		</el-row>
-
-		<cl-dialog v-model="det.visible" :title="det.title" width="60%">
-			<el-tabs v-model="det.active" type="card" @tab-change="tab.onChange">
-				<el-tab-pane
-					v-for="(item, index) in det.tabs"
-					:key="index"
-					:label="item.name"
-					:name="index"
-				>
-					<component :is="item.component" />
-				</el-tab-pane>
-			</el-tabs>
-		</cl-dialog>
+
+				<cl-dialog v-model="det.visible" :title="det.title" width="60%">
+					<el-tabs v-model="det.active" type="card" @tab-change="tab.onChange">
+						<el-tab-pane
+							v-for="(item, index) in det.tabs"
+							:key="index"
+							:label="item.name"
+							:name="index"
+						>
+							<component :is="item.component" />
+						</el-tab-pane>
+					</el-tabs>
+				</cl-dialog>
+			</div>
+		</el-scrollbar>
 	</div>
 </template>
 

+ 1 - 1
src/modules/space/views/list.vue

@@ -2,6 +2,6 @@
 	<space-inner />
 </template>
 
-<script lang="ts" setup name="space-list">
+<script lang="ts" setup name="upload-list">
 import SpaceInner from "../components/space-inner.vue";
 </script>