Parcourir la source

feat: 修改框架

DESKTOP-USV654P\pc il y a 8 mois
Parent
commit
ac943ac245

+ 18 - 14
apps/web-baicai/src/components/form/components/input-code/input-code-modal-ignore.vue

@@ -1,7 +1,8 @@
 <script lang="ts" setup>
-import { nextTick, onMounted, ref } from 'vue';
+import { nextTick, reactive, ref } from 'vue';
 
 import { useVbenModal } from '@vben/common-ui';
+import { isString } from '@vben/utils';
 
 import * as monaco from 'monaco-editor';
 import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
@@ -14,11 +15,11 @@ defineOptions({
   name: 'InputCodePreview',
 });
 const emit = defineEmits(['success']);
-// const state = reactive<{
-//   language: string;
-// }>({
-//   language: 'javascript',
-// });
+const state = reactive<{
+  title: string;
+}>({
+  title: '脚本编辑',
+});
 
 // eslint-disable-next-line no-restricted-globals
 self.MonacoEnvironment = {
@@ -94,24 +95,27 @@ const [Modal, { close, setState, getData }] = useVbenModal({
       }
       nextTick(() => {
         const { scriptCode, name, language } = data.baseData;
-        if (scriptCode) {
-          monacoEditor.setValue(scriptCode);
-        }
+        state.title = name;
 
         if (language) {
           monaco.editor.setModelLanguage(monacoEditor.getModel()!, language);
         }
-        setState({ title: `${name}`, loading: false });
+
+        if (scriptCode) {
+          if (isString(scriptCode)) {
+            monacoEditor.setValue(scriptCode);
+          } else {
+            monacoEditor.setValue(JSON.stringify(scriptCode));
+          }
+        }
+        setState({ loading: false });
       });
     }
   },
-  title: ' 脚本编辑',
 });
-
-onMounted(() => {});
 </script>
 <template>
-  <Modal class="h-[800px] w-[1000px]">
+  <Modal class="h-[800px] w-[1000px]" :title="state.title">
     <div ref="monacoEditorRef" class="h-full w-full"></div>
   </Modal>
 </template>

+ 0 - 21
apps/web-baicai/src/router/routes/core.ts

@@ -91,27 +91,6 @@ const coreRoutes: RouteRecordRaw[] = [
       },
     ],
   },
-  {
-    component: BasicLayout,
-    meta: {
-      icon: 'ant-design:user-outlined',
-      title: '个人中心',
-      hideInMenu: true,
-    },
-    name: 'extend',
-    path: '/extend',
-    children: [
-      {
-        meta: {
-          icon: 'fa-solid:user-cog',
-          title: '个人中心',
-        },
-        name: 'personal',
-        path: 'personal',
-        component: () => import('#/views/system/personal/index.vue'),
-      },
-    ],
-  },
 ];
 
 export { coreRoutes, fallbackNotFoundRoute };

+ 30 - 0
apps/web-baicai/src/router/routes/external/form.ts

@@ -0,0 +1,30 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { BasicLayout } from '#/layouts';
+
+const routes: RouteRecordRaw[] = [
+  {
+    component: BasicLayout,
+    meta: {
+      icon: 'material-symbols:dynamic-form',
+      title: '窗体',
+      hideInMenu: true,
+    },
+    name: 'form',
+    path: '/form',
+    children: [
+      {
+        meta: {
+          icon: 'hugeicons:web-design-01',
+          title: '窗体设计',
+          maxNumOfOpenTab: 2,
+        },
+        name: 'formDesign',
+        path: 'design/:id',
+        component: () => import('#/views/form/design/index.vue'),
+      },
+    ],
+  },
+];
+
+export default routes;

+ 29 - 0
apps/web-baicai/src/router/routes/external/personal.ts

@@ -0,0 +1,29 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { BasicLayout } from '#/layouts';
+
+const routes: RouteRecordRaw[] = [
+  {
+    component: BasicLayout,
+    meta: {
+      icon: 'ant-design:user-outlined',
+      title: '个人中心',
+      hideInMenu: true,
+    },
+    name: 'external',
+    path: '/external',
+    children: [
+      {
+        meta: {
+          icon: 'fa-solid:user-cog',
+          title: '个人中心',
+        },
+        name: 'personal',
+        path: 'personal',
+        component: () => import('#/views/system/personal/index.vue'),
+      },
+    ],
+  },
+];
+
+export default routes;

+ 5 - 3
apps/web-baicai/src/router/routes/index.ts

@@ -9,17 +9,19 @@ const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
 });
 
 // 有需要可以自行打开注释,并创建文件夹
-// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
+const externalRouteFiles = import.meta.glob('./external/**/*.ts', {
+  eager: true,
+});
 // const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
 
 /** 动态路由 */
 const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
 
 /** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统(不会显示在菜单中) */
-// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
+const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
 // const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
 const staticRoutes: RouteRecordRaw[] = [];
-const externalRoutes: RouteRecordRaw[] = [];
+// const externalRoutes: RouteRecordRaw[] = [];
 
 /** 路由列表,由基本路由、外部路由和404兜底路由组成
  *  无需走权限验证(会一直显示在菜单中) */

+ 4 - 14
apps/web-baicai/src/views/form/design/components/form/index.vue

@@ -29,8 +29,8 @@ const handleDragStart = (e: any) => {
 };
 </script>
 <template>
-  <div class="form-edit">
-    <div class="form-edit-container">
+  <div class="form-edit h-full p-4">
+    <div class="form-edit-container h-hull">
       <div v-if="formConfig.schemas.length === 0" class="form-edit-empty">
         表单未添加组件
       </div>
@@ -39,8 +39,9 @@ const handleDragStart = (e: any) => {
         :label-col="{
           style: { width: `${formConfig.config?.commonConfig?.labelWidth}px` },
         }"
+        class="h-full"
       >
-        <div class="form-edit-list">
+        <div class="form-edit-list h-full">
           <Draggable
             class="grid items-start"
             group="form-draggable"
@@ -70,22 +71,11 @@ const handleDragStart = (e: any) => {
 
 <style scoped lang="less">
 .form-edit {
-  width: 100%;
-  height: 100%;
-  box-sizing: border-box;
-  border-bottom-left-radius: 26px;
-  border-bottom-right-radius: 26px;
-
   &-container {
-    width: 100%;
-    height: 100%;
     box-sizing: border-box;
   }
 
   &-list {
-    height: 100%;
-    min-height: calc(100vh - 228px);
-
     & .ghost {
       background: #f56c6c;
       border: 2px solid #f56c6c;

+ 1 - 1
apps/web-baicai/src/views/form/design/components/control-config.vue → apps/web-baicai/src/views/form/design/components/setting/form/index.vue

@@ -3,7 +3,7 @@ import { watch } from 'vue';
 
 import { useVbenForm } from '@vben/common-ui';
 
-import { useFormDesignState } from '../hooks/useFormDesignState';
+import { useFormDesignState } from '../../../hooks/useFormDesignState';
 
 const { formConfig } = useFormDesignState();
 

+ 17 - 0
apps/web-baicai/src/views/form/design/components/setting/index.vue

@@ -0,0 +1,17 @@
+<script lang="ts" setup>
+import { Tabs } from 'ant-design-vue';
+
+import FormConfig from './form/index.vue';
+import WidgetConfig from './widget/index.vue';
+</script>
+
+<template>
+  <Tabs :centered="true">
+    <Tabs.TabPane key="1" tab="组件属性">
+      <FormConfig />
+    </Tabs.TabPane>
+    <Tabs.TabPane key="2" tab="表单属性">
+      <WidgetConfig />
+    </Tabs.TabPane>
+  </Tabs>
+</template>

+ 1 - 1
apps/web-baicai/src/views/form/design/components/form-config.vue → apps/web-baicai/src/views/form/design/components/setting/widget/index.vue

@@ -5,7 +5,7 @@ import { onMounted, reactive } from 'vue';
 
 import { useVbenForm } from '@vben/common-ui';
 
-import { useFormDesignState } from '../hooks/useFormDesignState';
+import { useFormDesignState } from '../../../hooks/useFormDesignState';
 
 const { formConfig } = useFormDesignState();
 

+ 69 - 0
apps/web-baicai/src/views/form/design/components/tools/index.vue

@@ -0,0 +1,69 @@
+<script setup lang="ts">
+import type { IVFormComponent } from '../../types';
+
+import { useVbenModal } from '@vben/common-ui';
+
+import InputCode from '#/components/form/components/input-code/input-code-modal-ignore.vue';
+import { Icon } from '#/components/icon';
+
+import { useFormDesignState } from '../../hooks/useFormDesignState';
+
+const [InputCodeModal, inputCodeApi] = useVbenModal({
+  connectedComponent: InputCode,
+});
+
+const { formConfig, formDesignMethods } = useFormDesignState();
+
+const handleClear = () => {
+  formConfig.value.schemas = [];
+  formDesignMethods.setSelectSchema({ component: '' } as IVFormComponent);
+};
+
+const handleSuccess = (scriptCode: any) => {
+  // eslint-disable-next-line no-console
+  console.log('scriptCode', scriptCode);
+};
+
+const handleImport = () => {
+  inputCodeApi
+    .setData({
+      baseData: {
+        scriptCode: {
+          config: {
+            wrapperClass: 'grid-cols-1',
+            showDefaultActions: false,
+            commonConfig: {
+              labelWidth: 100,
+            },
+          },
+          schemas: [],
+        },
+        name: '导入JSON',
+        language: 'json',
+      },
+    })
+    .open();
+};
+</script>
+<template>
+  <div class="flex items-center justify-between border-b px-4">
+    <InputCodeModal :close-on-click-modal="false" @success="handleSuccess" />
+    <h3 class="text-lg">设计区域</h3>
+    <div class="flex flex-wrap gap-3">
+      <Icon
+        icon="carbon:tag-import"
+        size="24"
+        class="cursor-pointer"
+        @click="handleImport"
+      />
+      <Icon icon="carbon:tag-export" size="24" class="cursor-pointer" />
+      <Icon
+        icon="carbon:clean"
+        size="24"
+        class="cursor-pointer"
+        @click="handleClear"
+      />
+      <Icon icon="carbon:view-filled" size="24" class="cursor-pointer" />
+    </div>
+  </div>
+</template>

+ 26 - 22
apps/web-baicai/src/views/form/design/index.vue

@@ -3,19 +3,26 @@ import type { Ref } from 'vue';
 
 import type { IFormConfig, IFormDesignMethods, IVFormComponent } from './types';
 
-import { onMounted, provide, ref } from 'vue';
+import { computed, onMounted, provide, ref } from 'vue';
+import { useRoute } from 'vue-router';
 
-import { Card, Tabs } from 'ant-design-vue';
+import { BcPage, VbenScrollbar } from '@vben/common-ui';
 
-import ControlConfig from './components/control-config.vue';
-import FormConfig from './components/form-config.vue';
 import FormEdit from './components/form/index.vue';
+import FormSetting from './components/setting/index.vue';
+import Tools from './components/tools/index.vue';
 import Widget from './components/widget/index.vue';
 
 defineOptions({
   name: 'FormDesign',
 });
 
+const route = useRoute();
+
+const keyValue = computed(() => {
+  return route.params?.id ?? -1;
+});
+
 const formConfig = ref<IFormConfig>({
   config: {
     wrapperClass: 'grid-cols-1',
@@ -38,27 +45,24 @@ provide<IFormDesignMethods>('formDesignMethods', {
   setSelectSchema,
 });
 
-onMounted(async () => {});
+onMounted(async () => {
+  // eslint-disable-next-line no-console
+  console.log('keyValue', keyValue.value);
+});
 </script>
 <template>
-  <div class="flex h-full w-full">
-    <div class="w-[300px]">
+  <BcPage auto-content-height :default-layout="[20, 60, 20]">
+    <template #left>
       <Widget />
-    </div>
-    <div class="h-full flex-1 pl-2 pr-2">
-      <Card title="设计区域" class="h-full w-full">
+    </template>
+    <template #right>
+      <FormSetting />
+    </template>
+    <div class="relative h-full">
+      <Tools class="h-[46px]" />
+      <VbenScrollbar class="h-[calc(100%-46px)]">
         <FormEdit />
-      </Card>
-    </div>
-    <div class="w-[300px]">
-      <Tabs>
-        <Tabs.TabPane key="1" tab="组件属性">
-          <ControlConfig />
-        </Tabs.TabPane>
-        <Tabs.TabPane key="2" tab="表单属性">
-          <FormConfig v-model:config="formConfig.config" />
-        </Tabs.TabPane>
-      </Tabs>
+      </VbenScrollbar>
     </div>
-  </div>
+  </BcPage>
 </template>

+ 10 - 18
apps/web-baicai/src/views/system/design/table/index.vue

@@ -1,19 +1,22 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
+import { useRouter } from 'vue-router';
+
 import { Page, useVbenModal } from '@vben/common-ui';
 
 import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { TableApi } from '#/api';
-import FormDesign from '#/views/form/design/form-modal.vue';
 import FormMenuEdit from '#/views/system/menu/components/editMenu.vue';
 
 import FormEdit from './components/edit.vue';
 import FormPreview from './components/preview.vue';
 import { useColumns, useSearchSchema } from './data.config';
 
+const router = useRouter();
+
 const [FormEditModal, formEditApi] = useVbenModal({
   connectedComponent: FormEdit,
 });
@@ -26,10 +29,6 @@ const [FormPreviewModal, formPreviewApi] = useVbenModal({
   connectedComponent: FormPreview,
 });
 
-const [FormDesignModal, formDesignApi] = useVbenModal({
-  connectedComponent: FormDesign,
-});
-
 const handleDelete = async (id: number) => {
   await TableApi.deleteDetail(id);
   message.success('数据删除成功');
@@ -70,17 +69,6 @@ const handleCreateMenu = (record: any) => {
     .open();
 };
 
-const handleDesign = (id: number) => {
-  formDesignApi
-    .setData({
-      isUpdate: false,
-      baseData: {
-        id,
-      },
-    })
-    .open();
-};
-
 const handleActionClick = async ({
   code,
   row,
@@ -91,7 +79,12 @@ const handleActionClick = async ({
       break;
     }
     case 'design': {
-      handleDesign(row.id);
+      router.push({
+        name: 'formDesign',
+        params: {
+          id: row.id,
+        },
+      });
       break;
     }
     case 'edit': {
@@ -137,7 +130,6 @@ const [Grid, { reload }] = useVbenVxeGrid(
     <FormEditModal :close-on-click-modal="false" @success="handelSuccess" />
     <FormMenuEditModal :close-on-click-modal="false" @success="handelSuccess" />
     <FormPreviewModal :close-on-click-modal="false" />
-    <FormDesignModal :close-on-click-modal="false" />
     <Grid>
       <template #toolbar-tools>
         <Button