Просмотр исходного кода

😁1、优化打印模板、动态插件功能 2、升级所有依赖

zuohuaijun 2 лет назад
Родитель
Сommit
c8b1bc1d3b

+ 3 - 3
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -21,9 +21,9 @@
     <PackageReference Include="DotNetCore.Compile.Environment" Version="3.2.0" />
     <PackageReference Include="DotNetCore.Natasha.CSharp" Version="5.2.2.1" />
     <PackageReference Include="FluentEmail.Smtp" Version="3.0.2" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.8.17" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.8.17" />
-    <PackageReference Include="Furion.Pure" Version="4.8.8.17" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.8.18" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.8.18" />
+    <PackageReference Include="Furion.Pure" Version="4.8.8.18" />
     <PackageReference Include="IPTools.China" Version="1.6.0" />
     <PackageReference Include="Lazy.Captcha.Core" Version="2.0.3" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.4" />

+ 7 - 7
Admin.NET/Admin.NET.Core/Entity/SysPlugin.cs

@@ -14,13 +14,6 @@ public class SysPlugin : EntityTenant
     [Required, MaxLength(64)]
     public virtual string Name { get; set; }
 
-    /// <summary>
-    /// 程序集名称
-    /// </summary>
-    [SugarColumn(ColumnDescription = "程序集名称", Length = 512)]
-    [Required, MaxLength(512)]
-    public virtual string AssemblyName { get; set; }
-
     /// <summary>
     /// C#代码
     /// </summary>
@@ -28,6 +21,13 @@ public class SysPlugin : EntityTenant
     [Required]
     public virtual string CsharpCode { get; set; }
 
+    /// <summary>
+    /// 程序集名称
+    /// </summary>
+    [SugarColumn(ColumnDescription = "程序集名称", Length = 512)]
+    [MaxLength(512)]
+    public string? AssemblyName { get; set; }
+
     /// <summary>
     /// 排序
     /// </summary>

+ 2 - 2
Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs

@@ -518,9 +518,9 @@ public enum ErrorCodeEnum
     D1800,
 
     /// <summary>
-    /// 已存在同名功能插件
+    /// 已存在同名功能或同名程序及插件
     /// </summary>
-    [ErrorCodeItemMetadata("已存在同名功能插件")]
+    [ErrorCodeItemMetadata("已存在同名功能或同名程序及插件")]
     D1900,
 
     /// <summary>

+ 19 - 5
Admin.NET/Admin.NET.Core/Service/Plugin/SysPluginService.cs

@@ -37,13 +37,17 @@ public class SysPluginService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Add"), HttpPost]
     [DisplayName("增加动态插件")]
-    public async Task AddPos(AddPluginInput input)
+    public async Task AddPlugin(AddPluginInput input)
     {
-        var isExist = await _sysPluginRep.IsAnyAsync(u => u.Name == input.Name);
+        var isExist = await _sysPluginRep.IsAnyAsync(u => u.Name == input.Name || u.AssemblyName == input.AssemblyName);
         if (isExist)
             throw Oops.Oh(ErrorCodeEnum.D1900);
 
+        // 添加动态程序集/接口
+        input.AssemblyName = CompileAssembly(input.CsharpCode, input.AssemblyName);
+
         await _sysPluginRep.InsertAsync(input.Adapt<SysPlugin>());
+
     }
 
     /// <summary>
@@ -53,12 +57,16 @@ public class SysPluginService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Update"), HttpPost]
     [DisplayName("更新动态插件")]
-    public async Task UpdatePos(UpdatePluginInput input)
+    public async Task UpdatePlugin(UpdatePluginInput input)
     {
-        var isExist = await _sysPluginRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id);
+        var isExist = await _sysPluginRep.IsAnyAsync(u => (u.Name == input.Name || u.AssemblyName == input.AssemblyName) && u.Id != input.Id);
         if (isExist)
             throw Oops.Oh(ErrorCodeEnum.D1900);
 
+        // 先移除再添加动态程序集/接口
+        RemoveAssembly(input.AssemblyName);
+        input.AssemblyName = CompileAssembly(input.CsharpCode);
+
         await _sysPluginRep.AsUpdateable(input.Adapt<SysPlugin>()).IgnoreColumns(true).ExecuteCommandAsync();
     }
 
@@ -69,8 +77,14 @@ public class SysPluginService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Delete"), HttpPost]
     [DisplayName("删除动态插件")]
-    public async Task DeletePos(DeletePluginInput input)
+    public async Task DeletePlugin(DeletePluginInput input)
     {
+        var plugin = await _sysPluginRep.GetByIdAsync(input.Id);
+        if (plugin == null) return;
+
+        // 移除动态程序集/接口
+        RemoveAssembly(plugin.AssemblyName);
+
         await _sysPluginRep.DeleteAsync(u => u.Id == input.Id);
     }
 

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/Print/SysPrintService.cs

@@ -34,7 +34,7 @@ public class SysPrintService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Add"), HttpPost]
     [DisplayName("增加打印模板")]
-    public async Task AddPos(AddPrintInput input)
+    public async Task AddPrint(AddPrintInput input)
     {
         var isExist = await _sysPrintRep.IsAnyAsync(u => u.Name == input.Name);
         if (isExist)
@@ -50,7 +50,7 @@ public class SysPrintService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Update"), HttpPost]
     [DisplayName("更新打印模板")]
-    public async Task UpdatePos(UpdatePrintInput input)
+    public async Task UpdatePrint(UpdatePrintInput input)
     {
         var isExist = await _sysPrintRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id);
         if (isExist)
@@ -66,7 +66,7 @@ public class SysPrintService : IDynamicApiController, ITransient
     /// <returns></returns>
     [ApiDescriptionSettings(Name = "Delete"), HttpPost]
     [DisplayName("删除打印模板")]
-    public async Task DeletePos(DeletePrintInput input)
+    public async Task DeletePrint(DeletePrintInput input)
     {
         await _sysPrintRep.DeleteAsync(u => u.Id == input.Id);
     }

+ 1 - 0
README.md

@@ -127,3 +127,4 @@
 - 👉 AspNet.Security.OAuth.Providers:[https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers)
 - 👉 System.Linq.Dynamic.Core:[https://github.com/zzzprojects/System.Linq.Dynamic.Core](https://github.com/zzzprojects/System.Linq.Dynamic.Core)
 - 👉 APIJSON.NET:[https://github.com/liaozb/APIJSON.NET](https://github.com/liaozb/APIJSON.NET)
+- 👉 vue-plugin-hiprint:[https://gitee.com/CcSimple/vue-plugin-hiprint](https://gitee.com/CcSimple/vue-plugin-hiprint)

+ 1 - 1
Web/package.json

@@ -27,7 +27,7 @@
 		"jsplumb": "^2.15.6",
 		"lodash-es": "^4.17.21",
 		"mitt": "^3.0.0",
-		"monaco-editor": "^0.34.1",
+		"monaco-editor": "^0.38.0",
 		"nprogress": "^0.2.0",
 		"pinia": "^2.0.34",
 		"print-js": "^1.6.0",

+ 5 - 5
Web/pnpm-lock.yaml

@@ -30,7 +30,7 @@ specifiers:
   jsplumb: ^2.15.6
   lodash-es: ^4.17.21
   mitt: ^3.0.0
-  monaco-editor: ^0.34.1
+  monaco-editor: ^0.38.0
   nprogress: ^0.2.0
   pinia: ^2.0.34
   prettier: ^2.8.7
@@ -80,7 +80,7 @@ dependencies:
   jsplumb: registry.npmmirror.com/jsplumb/2.15.6
   lodash-es: registry.npmmirror.com/lodash-es/4.17.21
   mitt: registry.npmmirror.com/mitt/3.0.0
-  monaco-editor: registry.npmmirror.com/monaco-editor/0.34.1
+  monaco-editor: registry.npmmirror.com/monaco-editor/0.38.0
   nprogress: registry.npmmirror.com/nprogress/0.2.0
   pinia: registry.npmmirror.com/pinia/2.0.36_typescript@5.0.4+vue@3.3.2
   print-js: registry.npmmirror.com/print-js/1.6.0
@@ -3395,10 +3395,10 @@ packages:
     version: 3.0.0
     dev: false
 
-  registry.npmmirror.com/monaco-editor/0.34.1:
-    resolution: {integrity: sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.34.1.tgz}
+  registry.npmmirror.com/monaco-editor/0.38.0:
+    resolution: {integrity: sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.38.0.tgz}
     name: monaco-editor
-    version: 0.34.1
+    version: 0.38.0
     dev: false
 
   registry.npmmirror.com/ms/2.1.2:

+ 0 - 1
Web/src/views/system/job/component/editJobDetail.vue

@@ -129,7 +129,6 @@ const state = reactive({
 	isShowDialog: false,
 	selectedTabName: '0', // 选中的 tab 页
 	ruleForm: {} as UpdateJobDetailInput,
-	monacoEditor: null as any,
 	httpJobMessage: { requestUri: '', httpMethod: httpMethodDef.get, body: '' } as HttpJobMessage,
 });
 

+ 89 - 137
Web/src/views/system/plugin/component/editPlugin.vue

@@ -1,141 +1,51 @@
 <template>
 	<div class="sys-plugin-container">
-		<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="769px">
+		<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="800px">
 			<template #header>
 				<div style="color: #fff">
 					<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
 					<span> {{ props.title }} </span>
 				</div>
 			</template>
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<el-form-item label="上级菜单">
-							<el-cascader
-								:options="props.menuData"
-								:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'title' }"
-								placeholder="请选择上级菜单"
-								clearable
-								class="w100"
-								v-model="state.ruleForm.pid"
-							>
-								<template #default="{ node, data }">
-									<span>{{ data.title }}</span>
-									<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
-								</template>
-							</el-cascader>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<el-form-item label="菜单类型" prop="type" :rules="[{ required: true, message: '菜单类型不能为空', trigger: 'blur' }]">
-							<el-radio-group v-model="state.ruleForm.type">
-								<el-radio :label="1">目录</el-radio>
-								<el-radio :label="2">菜单</el-radio>
-								<el-radio :label="3">按钮</el-radio>
-							</el-radio-group>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="菜单名称" prop="title" :rules="[{ required: true, message: '菜单名称不能为空', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.title" placeholder="菜单名称" clearable />
-						</el-form-item>
-					</el-col>
-					<template v-if="state.ruleForm.type === 1 || state.ruleForm.type === 2">
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="路由名称">
-								<el-input v-model="state.ruleForm.name" placeholder="路由名称" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="路由路径">
-								<el-input v-model="state.ruleForm.path" placeholder="路由路径" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="组件路径">
-								<el-input v-model="state.ruleForm.component" placeholder="组件路径" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="菜单图标">
-								<IconSelector v-model="state.ruleForm.icon" placeholder="菜单图标" type="all" />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="重定向">
-								<el-input v-model="state.ruleForm.redirect" placeholder="重定向地址" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="链接地址">
-								<el-input v-model="state.ruleForm.outLink" placeholder="外链/内嵌时链接地址" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="菜单排序">
-								<el-input-number v-model="state.ruleForm.orderNo" placeholder="排序" class="w100" />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="是否隐藏">
-								<el-radio-group v-model="state.ruleForm.isHide">
-									<el-radio :label="true">隐藏</el-radio>
-									<el-radio :label="false">不隐藏</el-radio>
-								</el-radio-group>
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="是否缓存">
-								<el-radio-group v-model="state.ruleForm.isKeepAlive">
-									<el-radio :label="true">缓存</el-radio>
-									<el-radio :label="false">不缓存</el-radio>
-								</el-radio-group>
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="是否固定">
-								<el-radio-group v-model="state.ruleForm.isAffix">
-									<el-radio :label="true">固定</el-radio>
-									<el-radio :label="false">不固定</el-radio>
-								</el-radio-group>
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="是否内嵌">
-								<el-radio-group v-model="state.ruleForm.isIframe">
-									<el-radio :label="true">内嵌</el-radio>
-									<el-radio :label="false">不内嵌</el-radio>
-								</el-radio-group>
-							</el-form-item>
-						</el-col>
-					</template>
-					<template v-if="state.ruleForm.type === 3">
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="权限标识">
-								<el-input v-model="state.ruleForm.permission" placeholder="权限标识" clearable />
-							</el-form-item>
-						</el-col>
-						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-							<el-form-item label="菜单排序">
-								<el-input-number v-model="state.ruleForm.orderNo" placeholder="排序" class="w100" />
-							</el-form-item>
-						</el-col>
-					</template>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="是否启用">
-							<el-radio-group v-model="state.ruleForm.status">
-								<el-radio :label="1">启用</el-radio>
-								<el-radio :label="2">不启用</el-radio>
-							</el-radio-group>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<el-form-item label="备注">
-							<el-input v-model="state.ruleForm.remark" placeholder="请输入备注内容" clearable type="textarea" />
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
+			<el-tabs v-model="state.selectedTabName">
+				<el-tab-pane label="插件信息">
+					<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" style="height: 500px">
+						<el-row :gutter="35">
+							<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+								<el-form-item label="功能名称" prop="name" :rules="[{ required: true, message: '功能名称不能为空', trigger: 'blur' }]">
+									<el-input v-model="state.ruleForm.name" placeholder="功能名称" clearable />
+								</el-form-item>
+							</el-col>
+							<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+								<el-form-item label="程序集名称">
+									<el-input v-model="state.ruleForm.assemblyName" placeholder="程序集名称" clearable />
+								</el-form-item>
+							</el-col>
+							<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+								<el-form-item label="排序">
+									<el-input-number v-model="state.ruleForm.orderNo" placeholder="排序" class="w100" />
+								</el-form-item>
+							</el-col>
+							<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+								<el-form-item label="状态">
+									<el-radio-group v-model="state.ruleForm.status">
+										<el-radio :label="1">启用</el-radio>
+										<el-radio :label="2">禁用</el-radio>
+									</el-radio-group>
+								</el-form-item>
+							</el-col>
+							<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+								<el-form-item label="备注">
+									<el-input v-model="state.ruleForm.remark" placeholder="请输入备注内容" clearable type="textarea" />
+								</el-form-item>
+							</el-col>
+						</el-row>
+					</el-form>
+				</el-tab-pane>
+				<el-tab-pane label="C# 代码">
+					<div ref="monacoEditorRef" style="width: 100%; height: 500px"></div>
+				</el-tab-pane>
+			</el-tabs>
 			<template #footer>
 				<span class="dialog-footer">
 					<el-button @click="cancel">取 消</el-button>
@@ -148,27 +58,63 @@
 
 <script lang="ts" setup name="sysEditPlugin">
 import { reactive, ref } from 'vue';
-import IconSelector from '/@/components/iconSelector/index.vue';
+import { ElMessage } from 'element-plus';
+import * as monaco from 'monaco-editor';
 
 import { getAPI } from '/@/utils/axios-utils';
-import { SysMenuApi } from '/@/api-services/api';
-import { SysMenu, UpdateMenuInput } from '/@/api-services/models';
+import { SysPluginApi } from '/@/api-services/api';
+import { UpdatePluginInput } from '/@/api-services/models';
 
 const props = defineProps({
 	title: String,
-	menuData: Array<SysMenu>,
 });
 const emits = defineEmits(['handleQuery']);
 const ruleFormRef = ref();
+const monacoEditorRef = ref();
 const state = reactive({
 	isShowDialog: false,
-	ruleForm: {} as UpdateMenuInput,
+	ruleForm: {} as UpdatePluginInput,
+	selectedTabName: '0', // 选中的 tab
 });
 
+// 初始化monacoEditor对象
+var monacoEditor: any = null;
+const initMonacoEditor = () => {
+	monacoEditor = monaco.editor.create(monacoEditorRef.value, {
+		theme: 'vs-dark', // 主题 vs vs-dark hc-black
+		value: '', // 默认显示的值
+		language: 'csharp',
+		formatOnPaste: true,
+		wordWrap: 'on', //自动换行,注意大小写
+		wrappingIndent: 'indent',
+		folding: true, // 是否折叠
+		foldingHighlight: true, // 折叠等高线
+		foldingStrategy: 'indentation', // 折叠方式  auto | indentation
+		showFoldingControls: 'always', // 是否一直显示折叠 always | mouSEOver
+		disableLayerHinting: true, // 等宽优化
+		emptySelectionClipboard: false, // 空选择剪切板
+		selectionClipboard: false, // 选择剪切板
+		automaticLayout: true, // 自动布局
+		codeLens: false, // 代码镜头
+		scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
+		colorDecorators: true, // 颜色装饰器
+		accessibilitySupport: 'auto', // 辅助功能支持  "auto" | "off" | "on"
+		lineNumbers: 'on', // 行号 取值: "on" | "off" | "relative" | "interval" | function
+		lineNumbersMinChars: 5, // 行号最小字符   number
+		//enableSplitViewResizing: false,
+		readOnly: false, //是否只读  取值 true | false
+	});
+};
+
 // 打开弹窗
 const openDialog = (row: any) => {
 	state.ruleForm = JSON.parse(JSON.stringify(row));
 	state.isShowDialog = true;
+
+	// 延迟拿值防止取不到
+	setTimeout(() => {
+		if (monacoEditor == null) initMonacoEditor();
+	}, 1);
 };
 
 // 关闭弹窗
@@ -186,10 +132,16 @@ const cancel = () => {
 const submit = () => {
 	ruleFormRef.value.validate(async (valid: boolean) => {
 		if (!valid) return;
+
+		state.ruleForm.csharpCode = monacoEditor.getValue();
+		if (state.ruleForm.csharpCode.length < 100) {
+			ElMessage.warning('请正确编写 C# 代码');
+			return;
+		}
 		if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
-			await getAPI(SysMenuApi).apiSysMenuUpdatePost(state.ruleForm);
+			await getAPI(SysPluginApi).apiSysPluginUpdatePost(state.ruleForm);
 		} else {
-			await getAPI(SysMenuApi).apiSysMenuAddPost(state.ruleForm);
+			await getAPI(SysPluginApi).apiSysPluginAddPost(state.ruleForm);
 		}
 		closeDialog();
 	});

+ 63 - 54
Web/src/views/system/plugin/index.vue

@@ -2,85 +2,81 @@
 	<div class="sys-plugin-container">
 		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
 			<el-form :model="state.queryParams" ref="queryForm" :inline="true">
-				<el-form-item label="菜单名称" prop="title">
-					<el-input placeholder="菜单名称" clearable @keyup.enter="handleQuery" v-model="state.queryParams.title" />
-				</el-form-item>
-				<el-form-item label="类型" prop="type">
-					<el-select v-model="state.queryParams.type" placeholder="类型" clearable>
-						<el-option label="目录" :value="1" />
-						<el-option label="菜单" :value="2" />
-						<el-option label="按钮" :value="3" />
-					</el-select>
+				<el-form-item label="功能名称" prop="name">
+					<el-input placeholder="功能名称" clearable @keyup.enter="handleQuery" v-model="state.queryParams.name" />
 				</el-form-item>
 				<el-form-item>
 					<el-button-group>
-						<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'"> 查询 </el-button>
+						<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysPlugin:page'"> 查询 </el-button>
 						<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
 					</el-button-group>
 				</el-form-item>
 				<el-form-item>
-					<el-button type="primary" icon="ele-Plus" @click="openAddMenu" v-auth="'sysMenu:add'"> 新增 </el-button>
+					<el-button type="primary" icon="ele-Plus" @click="openAddPlugin" v-auth="'sysPlugin:add'"> 新增 </el-button>
 				</el-form-item>
 			</el-form>
 		</el-card>
 
 		<el-card class="full-table" shadow="hover" style="margin-top: 8px">
-			<el-table :data="state.menuData" v-loading="state.loading" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" border>
-				<el-table-column label="菜单名称" show-overflow-tooltip>
-					<template #default="scope">
-						<SvgIcon :name="scope.row.icon" />
-						<span class="ml10">{{ $t(scope.row.title) }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="类型" width="70" align="center" show-overflow-tooltip>
-					<template #default="scope">
-						<el-tag type="warning" v-if="scope.row.type === 1">目录</el-tag>
-						<el-tag v-else-if="scope.row.type === 2">菜单</el-tag>
-						<el-tag type="info" v-else>按钮</el-tag>
-					</template>
-				</el-table-column>
-				<el-table-column prop="path" label="路由路径" show-overflow-tooltip />
-				<el-table-column prop="component" label="组件路径" show-overflow-tooltip />
-				<el-table-column prop="permission" label="权限标识" show-overflow-tooltip />
-				<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
-				<el-table-column label="状态" width="80" align="center" show-overflow-tooltip>
+			<el-table :data="state.pluginData" style="width: 100%" v-loading="state.loading" border>
+				<el-table-column type="index" label="序号" width="55" align="center" fixed />
+				<el-table-column prop="name" label="功能名称" header-align="center" show-overflow-tooltip />
+				<el-table-column prop="assemblyName" label="程序集名称" header-align="center" show-overflow-tooltip />
+				<el-table-column prop="orderNo" label="排序" align="center" show-overflow-tooltip />
+				<el-table-column label="状态" align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
 						<el-tag type="danger" v-else>禁用</el-tag>
 					</template>
 				</el-table-column>
 				<el-table-column prop="createTime" label="修改时间" align="center" show-overflow-tooltip />
+				<el-table-column prop="remark" label="备注" header-align="center" show-overflow-tooltip />
 				<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
-						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditMenu(scope.row)" v-auth="'sysMenu:update'"> 编辑 </el-button>
-						<el-button icon="ele-Delete" size="small" text type="danger" @click="delMenu(scope.row)" v-auth="'sysMenu:delete'"> 删除 </el-button>
+						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditPlugin(scope.row)" v-auth="'sysPrint:update'"> 编辑 </el-button>
+						<el-button icon="ele-Delete" size="small" text type="danger" @click="delPlugin(scope.row)" v-auth="'sysPrint:delete'"> 删除 </el-button>
 					</template>
 				</el-table-column>
 			</el-table>
+			<el-pagination
+				v-model:currentPage="state.tableParams.page"
+				v-model:page-size="state.tableParams.pageSize"
+				:total="state.tableParams.total"
+				:page-sizes="[10, 20, 50, 100]"
+				small
+				background
+				@size-change="handleSizeChange"
+				@current-change="handleCurrentChange"
+				layout="total, sizes, prev, pager, next, jumper"
+			/>
 		</el-card>
 
-		<EditMenu ref="editMenuRef" :title="state.editMenuTitle" :menuData="state.menuData" @handleQuery="handleQuery" />
+		<EditPlugin ref="editPluginRef" :title="state.editPluginTitle" @handleQuery="handleQuery" />
 	</div>
 </template>
 
 <script lang="ts" setup name="sysPlugin">
 import { onMounted, reactive, ref } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
-import EditMenu from '/@/views/system/menu/component/editMenu.vue';
+import EditPlugin from '/@/views/system/plugin/component/editPlugin.vue';
 
 import { getAPI } from '/@/utils/axios-utils';
-import { SysMenuApi } from '/@/api-services/api';
-import { SysMenu } from '/@/api-services/models';
+import { SysPluginApi } from '/@/api-services/api';
+import { SysPlugin } from '/@/api-services/models';
 
-const editMenuRef = ref<InstanceType<typeof EditMenu>>();
+const editPluginRef = ref<InstanceType<typeof EditPlugin>>();
 const state = reactive({
 	loading: false,
-	menuData: [] as Array<SysMenu>,
+	pluginData: [] as Array<SysPlugin>,
 	queryParams: {
-		title: undefined,
-		type: undefined,
+		name: undefined,
 	},
-	editMenuTitle: '',
+	tableParams: {
+		page: 1,
+		pageSize: 10,
+		total: 0 as any,
+	},
+	editPluginTitle: '',
 });
 
 onMounted(async () => {
@@ -90,42 +86,55 @@ onMounted(async () => {
 // 查询操作
 const handleQuery = async () => {
 	state.loading = true;
-	var res = await getAPI(SysMenuApi).apiSysMenuListGet(state.queryParams.title, state.queryParams.type);
-	state.menuData = res.data.result ?? [];
+	let params = Object.assign(state.queryParams, state.tableParams);
+	var res = await getAPI(SysPluginApi).apiSysPluginPagePost(params);
+	state.pluginData = res.data.result?.items ?? [];
+	state.tableParams.total = res.data.result?.total;
 	state.loading = false;
 };
 
 // 重置操作
 const resetQuery = () => {
-	state.queryParams.title = undefined;
-	state.queryParams.type = undefined;
+	state.queryParams.name = undefined;
 	handleQuery();
 };
 
 // 打开新增页面
-const openAddMenu = () => {
-	state.editMenuTitle = '添加菜单';
-	editMenuRef.value?.openDialog({ type: 2 });
+const openAddPlugin = () => {
+	state.editPluginTitle = '添加动态插件';
+	editPluginRef.value?.openDialog({ orderNo: 100, status: 1 });
 };
 
 // 打开编辑页面
-const openEditMenu = (row: any) => {
-	state.editMenuTitle = '编辑菜单';
-	editMenuRef.value?.openDialog(row);
+const openEditPlugin = (row: any) => {
+	state.editPluginTitle = '编辑动态插件';
+	editPluginRef.value?.openDialog(row);
 };
 
 // 删除当前行
-const delMenu = (row: any) => {
-	ElMessageBox.confirm(`确定删除菜单:【${row.title}】?`, '提示', {
+const delPlugin = (row: any) => {
+	ElMessageBox.confirm(`确定删除动态插件:【${row.name}】?`, '提示', {
 		confirmButtonText: '确定',
 		cancelButtonText: '取消',
 		type: 'warning',
 	})
 		.then(async () => {
-			await getAPI(SysMenuApi).apiSysMenuDeletePost({ id: row.id });
+			await getAPI(SysPluginApi).apiSysPluginDeletePost({ id: row.id });
 			handleQuery();
 			ElMessage.success('删除成功');
 		})
 		.catch(() => {});
 };
+
+// 改变页面容量
+const handleSizeChange = (val: number) => {
+	state.tableParams.pageSize = val;
+	handleQuery();
+};
+
+// 改变页码序号
+const handleCurrentChange = (val: number) => {
+	state.tableParams.page = val;
+	handleQuery();
+};
 </script>

+ 9 - 9
Web/src/views/system/print/component/editPrint.vue

@@ -2,7 +2,7 @@
 	<div class="sys-print-container">
 		<div class="printDialog">
 			<el-dialog v-model="state.isShowDialog" :show-close="false" :close-on-click-modal="false" fullscreen>
-				<Designer @onDesigned="onDesigned" style="margin: -20px -12px 0 -20px" />
+				<Designer @onDesigned="onDesigned" :autoConnect="false" theme="bumblebee" style="margin: -20px -12px 0 -20px" />
 				<template #footer>
 					<span class="dialog-footer">
 						<el-button @click="cancel">取 消</el-button>
@@ -57,17 +57,17 @@
 </template>
 
 <script lang="ts" setup name="sysEditPrint">
-import { reactive, ref } from 'vue';
+import { onMounted, reactive, ref } from 'vue';
 import 'sv-print/dist/style.css';
 import { Designer } from '@sv-print/vue3';
+// import { disAutoConnect } from '@sv-print/hiprint';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysPrintApi } from '/@/api-services/api';
-import { SysPrint, UpdatePrintInput } from '/@/api-services/models';
+import { UpdatePrintInput } from '/@/api-services/models';
 
 const props = defineProps({
-	title: String,
-	printData: Array<SysPrint>,
+	title: String
 });
 const emits = defineEmits(['handleQuery']);
 let svPrint = ref();
@@ -78,6 +78,10 @@ const state = reactive({
 	showDialog2: false,
 });
 
+onMounted(async () => {
+	// disAutoConnect();
+});
+
 // 打开弹窗
 const openDialog = (row: any) => {
 	state.ruleForm = JSON.parse(JSON.stringify(row));
@@ -110,10 +114,6 @@ const onDesigned = (e: any) => {
 const loadTemplate = () => {
 	svPrint.value.printTemplate.clear();
 	if (JSON.stringify(state.ruleForm) !== '{}') {
-		// svPrint.value.designerUtils.options.authKey = "123456";
-		svPrint.value.designerUtils.options.autoConnect = false;
-		svPrint.value.designerUtils.options.theme = 'bumblebee';
-		svPrint.value.designerUtils.options.title = state.ruleForm.name;
 		svPrint.value.printTemplate.update(JSON.parse(state.ruleForm.template));
 	}
 };