chore:平台容器框架升级,修复命令行环境丢失的问题
This commit is contained in:
		
							parent
							
								
									3e1a1b4a66
								
							
						
					
					
						commit
						9438489a11
					
				| @ -1,12 +1,12 @@ | |||||||
| <template> |  | ||||||
|   <el-config-provider :locale="zhCn"> |  | ||||||
|     <Suspense> |  | ||||||
|       <router-view></router-view> |  | ||||||
|     </Suspense> |  | ||||||
|   </el-config-provider> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { ElConfigProvider } from 'element-plus'; | import { ElConfigProvider } from 'element-plus'; | ||||||
| import zhCn from 'element-plus/es/locale/lang/zh-cn'; | import zhCn from 'element-plus/es/locale/lang/zh-cn'; | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <ElConfigProvider :locale="zhCn"> | ||||||
|  |     <Suspense> | ||||||
|  |       <router-view /> | ||||||
|  |     </Suspense> | ||||||
|  |   </ElConfigProvider> | ||||||
|  | </template> | ||||||
|  | |||||||
							
								
								
									
										165
									
								
								apps/designer/src/auto-imports.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										165
									
								
								apps/designer/src/auto-imports.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -6,83 +6,98 @@ | |||||||
| // biome-ignore lint: disable
 | // biome-ignore lint: disable
 | ||||||
| export {} | export {} | ||||||
| declare global { | declare global { | ||||||
|   const EffectScope: typeof import('vue')['EffectScope'] |   const EffectScope: (typeof import('vue'))['EffectScope']; | ||||||
|   const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'] |   const acceptHMRUpdate: (typeof import('pinia'))['acceptHMRUpdate']; | ||||||
|   const computed: typeof import('vue')['computed'] |   const computed: (typeof import('vue'))['computed']; | ||||||
|   const createApp: typeof import('vue')['createApp'] |   const createApp: (typeof import('vue'))['createApp']; | ||||||
|   const createPinia: typeof import('pinia')['createPinia'] |   const createPinia: (typeof import('pinia'))['createPinia']; | ||||||
|   const customRef: typeof import('vue')['customRef'] |   const customRef: (typeof import('vue'))['customRef']; | ||||||
|   const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] |   const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent']; | ||||||
|   const defineComponent: typeof import('vue')['defineComponent'] |   const defineComponent: (typeof import('vue'))['defineComponent']; | ||||||
|   const defineStore: typeof import('pinia')['defineStore'] |   const defineStore: (typeof import('pinia'))['defineStore']; | ||||||
|   const effectScope: typeof import('vue')['effectScope'] |   const effectScope: (typeof import('vue'))['effectScope']; | ||||||
|   const getActivePinia: typeof import('pinia')['getActivePinia'] |   const getActivePinia: (typeof import('pinia'))['getActivePinia']; | ||||||
|   const getCurrentInstance: typeof import('vue')['getCurrentInstance'] |   const getCurrentInstance: (typeof import('vue'))['getCurrentInstance']; | ||||||
|   const getCurrentScope: typeof import('vue')['getCurrentScope'] |   const getCurrentScope: (typeof import('vue'))['getCurrentScope']; | ||||||
|   const h: typeof import('vue')['h'] |   const h: (typeof import('vue'))['h']; | ||||||
|   const inject: typeof import('vue')['inject'] |   const inject: (typeof import('vue'))['inject']; | ||||||
|   const isProxy: typeof import('vue')['isProxy'] |   const isProxy: (typeof import('vue'))['isProxy']; | ||||||
|   const isReactive: typeof import('vue')['isReactive'] |   const isReactive: (typeof import('vue'))['isReactive']; | ||||||
|   const isReadonly: typeof import('vue')['isReadonly'] |   const isReadonly: (typeof import('vue'))['isReadonly']; | ||||||
|   const isRef: typeof import('vue')['isRef'] |   const isRef: (typeof import('vue'))['isRef']; | ||||||
|   const mapActions: typeof import('pinia')['mapActions'] |   const mapActions: (typeof import('pinia'))['mapActions']; | ||||||
|   const mapGetters: typeof import('pinia')['mapGetters'] |   const mapGetters: (typeof import('pinia'))['mapGetters']; | ||||||
|   const mapState: typeof import('pinia')['mapState'] |   const mapState: (typeof import('pinia'))['mapState']; | ||||||
|   const mapStores: typeof import('pinia')['mapStores'] |   const mapStores: (typeof import('pinia'))['mapStores']; | ||||||
|   const mapWritableState: typeof import('pinia')['mapWritableState'] |   const mapWritableState: (typeof import('pinia'))['mapWritableState']; | ||||||
|   const markRaw: typeof import('vue')['markRaw'] |   const markRaw: (typeof import('vue'))['markRaw']; | ||||||
|   const nextTick: typeof import('vue')['nextTick'] |   const nextTick: (typeof import('vue'))['nextTick']; | ||||||
|   const onActivated: typeof import('vue')['onActivated'] |   const onActivated: (typeof import('vue'))['onActivated']; | ||||||
|   const onBeforeMount: typeof import('vue')['onBeforeMount'] |   const onBeforeMount: (typeof import('vue'))['onBeforeMount']; | ||||||
|   const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] |   const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave']; | ||||||
|   const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] |   const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate']; | ||||||
|   const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] |   const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount']; | ||||||
|   const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] |   const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate']; | ||||||
|   const onDeactivated: typeof import('vue')['onDeactivated'] |   const onDeactivated: (typeof import('vue'))['onDeactivated']; | ||||||
|   const onErrorCaptured: typeof import('vue')['onErrorCaptured'] |   const onErrorCaptured: (typeof import('vue'))['onErrorCaptured']; | ||||||
|   const onMounted: typeof import('vue')['onMounted'] |   const onMounted: (typeof import('vue'))['onMounted']; | ||||||
|   const onRenderTracked: typeof import('vue')['onRenderTracked'] |   const onRenderTracked: (typeof import('vue'))['onRenderTracked']; | ||||||
|   const onRenderTriggered: typeof import('vue')['onRenderTriggered'] |   const onRenderTriggered: (typeof import('vue'))['onRenderTriggered']; | ||||||
|   const onScopeDispose: typeof import('vue')['onScopeDispose'] |   const onScopeDispose: (typeof import('vue'))['onScopeDispose']; | ||||||
|   const onServerPrefetch: typeof import('vue')['onServerPrefetch'] |   const onServerPrefetch: (typeof import('vue'))['onServerPrefetch']; | ||||||
|   const onUnmounted: typeof import('vue')['onUnmounted'] |   const onUnmounted: (typeof import('vue'))['onUnmounted']; | ||||||
|   const onUpdated: typeof import('vue')['onUpdated'] |   const onUpdated: (typeof import('vue'))['onUpdated']; | ||||||
|   const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] |   const onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup']; | ||||||
|   const provide: typeof import('vue')['provide'] |   const provide: (typeof import('vue'))['provide']; | ||||||
|   const reactive: typeof import('vue')['reactive'] |   const reactive: (typeof import('vue'))['reactive']; | ||||||
|   const readonly: typeof import('vue')['readonly'] |   const readonly: (typeof import('vue'))['readonly']; | ||||||
|   const ref: typeof import('vue')['ref'] |   const ref: (typeof import('vue'))['ref']; | ||||||
|   const resolveComponent: typeof import('vue')['resolveComponent'] |   const resolveComponent: (typeof import('vue'))['resolveComponent']; | ||||||
|   const setActivePinia: typeof import('pinia')['setActivePinia'] |   const setActivePinia: (typeof import('pinia'))['setActivePinia']; | ||||||
|   const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'] |   const setMapStoreSuffix: (typeof import('pinia'))['setMapStoreSuffix']; | ||||||
|   const shallowReactive: typeof import('vue')['shallowReactive'] |   const shallowReactive: (typeof import('vue'))['shallowReactive']; | ||||||
|   const shallowReadonly: typeof import('vue')['shallowReadonly'] |   const shallowReadonly: (typeof import('vue'))['shallowReadonly']; | ||||||
|   const shallowRef: typeof import('vue')['shallowRef'] |   const shallowRef: (typeof import('vue'))['shallowRef']; | ||||||
|   const storeToRefs: typeof import('pinia')['storeToRefs'] |   const storeToRefs: (typeof import('pinia'))['storeToRefs']; | ||||||
|   const toRaw: typeof import('vue')['toRaw'] |   const toRaw: (typeof import('vue'))['toRaw']; | ||||||
|   const toRef: typeof import('vue')['toRef'] |   const toRef: (typeof import('vue'))['toRef']; | ||||||
|   const toRefs: typeof import('vue')['toRefs'] |   const toRefs: (typeof import('vue'))['toRefs']; | ||||||
|   const toValue: typeof import('vue')['toValue'] |   const toValue: (typeof import('vue'))['toValue']; | ||||||
|   const triggerRef: typeof import('vue')['triggerRef'] |   const triggerRef: (typeof import('vue'))['triggerRef']; | ||||||
|   const unref: typeof import('vue')['unref'] |   const unref: (typeof import('vue'))['unref']; | ||||||
|   const useAttrs: typeof import('vue')['useAttrs'] |   const useAttrs: (typeof import('vue'))['useAttrs']; | ||||||
|   const useCssModule: typeof import('vue')['useCssModule'] |   const useCssModule: (typeof import('vue'))['useCssModule']; | ||||||
|   const useCssVars: typeof import('vue')['useCssVars'] |   const useCssVars: (typeof import('vue'))['useCssVars']; | ||||||
|   const useId: typeof import('vue')['useId'] |   const useId: (typeof import('vue'))['useId']; | ||||||
|   const useLink: typeof import('vue-router')['useLink'] |   const useLink: (typeof import('vue-router'))['useLink']; | ||||||
|   const useModel: typeof import('vue')['useModel'] |   const useModel: (typeof import('vue'))['useModel']; | ||||||
|   const useRoute: typeof import('vue-router')['useRoute'] |   const useRoute: (typeof import('vue-router'))['useRoute']; | ||||||
|   const useRouter: typeof import('vue-router')['useRouter'] |   const useRouter: (typeof import('vue-router'))['useRouter']; | ||||||
|   const useSlots: typeof import('vue')['useSlots'] |   const useSlots: (typeof import('vue'))['useSlots']; | ||||||
|   const useTemplateRef: typeof import('vue')['useTemplateRef'] |   const useTemplateRef: (typeof import('vue'))['useTemplateRef']; | ||||||
|   const watch: typeof import('vue')['watch'] |   const watch: (typeof import('vue'))['watch']; | ||||||
|   const watchEffect: typeof import('vue')['watchEffect'] |   const watchEffect: (typeof import('vue'))['watchEffect']; | ||||||
|   const watchPostEffect: typeof import('vue')['watchPostEffect'] |   const watchPostEffect: (typeof import('vue'))['watchPostEffect']; | ||||||
|   const watchSyncEffect: typeof import('vue')['watchSyncEffect'] |   const watchSyncEffect: (typeof import('vue'))['watchSyncEffect']; | ||||||
| } | } | ||||||
| // for type re-export
 | // for type re-export
 | ||||||
| declare global { | declare global { | ||||||
|   // @ts-ignore
 |   // @ts-ignore
 | ||||||
|   export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' |   export type { | ||||||
|   import('vue') |     Component, | ||||||
|  |     ComponentPublicInstance, | ||||||
|  |     ComputedRef, | ||||||
|  |     DirectiveBinding, | ||||||
|  |     ExtractDefaultPropTypes, | ||||||
|  |     ExtractPropTypes, | ||||||
|  |     ExtractPublicPropTypes, | ||||||
|  |     InjectionKey, | ||||||
|  |     PropType, | ||||||
|  |     Ref, | ||||||
|  |     MaybeRef, | ||||||
|  |     MaybeRefOrGetter, | ||||||
|  |     VNode, | ||||||
|  |     WritableComputedRef | ||||||
|  |   } from 'vue'; | ||||||
|  |   import('vue'); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								apps/designer/src/env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								apps/designer/src/env.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1,7 +1,8 @@ | |||||||
| /// <reference types="vite/client" />
 | // / <reference types="vite/client" />
 | ||||||
| 
 | 
 | ||||||
| declare module '*.vue' { | declare module '*.vue' { | ||||||
|   import type { DefineComponent } from 'vue'; |   import type { DefineComponent } from 'vue'; | ||||||
|  | 
 | ||||||
|   const component: DefineComponent<{}, {}, any>; |   const component: DefineComponent<{}, {}, any>; | ||||||
|   export default component; |   export default component; | ||||||
| } | } | ||||||
| @ -12,7 +13,7 @@ declare namespace NodeJS { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| declare module global { | declare namespace global { | ||||||
|   interface Window {} |   interface Window {} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,14 +1,14 @@ | |||||||
| import { type BlockSchema } from '@vtj/core'; | import type { BlockSchema } from '@vtj/core'; | ||||||
|  | 
 | ||||||
| import instance from './instance'; | import instance from './instance'; | ||||||
| import { fi } from 'element-plus/es/locale/index.mjs'; |  | ||||||
| 
 | 
 | ||||||
| export type LowCodeFileSchema = { | export type LowCodeFileSchema = { | ||||||
|   project_id: number; |  | ||||||
|   publish: boolean; |  | ||||||
|   active: boolean; |   active: boolean; | ||||||
|   dsl: BlockSchema; |   dsl: BlockSchema; | ||||||
|   file_path?: string; |  | ||||||
|   file_id?: string; |   file_id?: string; | ||||||
|  |   file_path?: string; | ||||||
|  |   project_id: number; | ||||||
|  |   publish: boolean; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function transformFile(file: LowCodeFileSchema): LowCodeFileSchema { | function transformFile(file: LowCodeFileSchema): LowCodeFileSchema { | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
|  | import type { HistorySchema } from '@vtj/core'; | ||||||
|  | 
 | ||||||
| import instance from './instance'; | import instance from './instance'; | ||||||
| import { type HistorySchema } from '@vtj/core'; |  | ||||||
| 
 | 
 | ||||||
| export type LowCodeHistorySchema = { | export type LowCodeHistorySchema = { | ||||||
|   project_id: number; |   dsl?: HistorySchema; | ||||||
|   file_id: string; |   file_id: string; | ||||||
|   history_id: string; |   history_id: string; | ||||||
|   id?: string; |   id?: string; | ||||||
|   dsl?: HistorySchema; |   project_id: number; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function transformHistoryData(data: LowCodeHistorySchema) { | function transformHistoryData(data: LowCodeHistorySchema) { | ||||||
| @ -20,12 +21,12 @@ export type HistoriesResponse = { | |||||||
|   code: number; |   code: number; | ||||||
|   data: { |   data: { | ||||||
|     list: Array<{ |     list: Array<{ | ||||||
|       id: number; |       created_at: string; | ||||||
|       project_id: number; |       dsl: Record<string, any>; | ||||||
|       file_id: string; |       file_id: string; | ||||||
|       history_id: string; |       history_id: string; | ||||||
|       dsl: Record<string, any>; |       id: number; | ||||||
|       created_at: string; |       project_id: number; | ||||||
|       updated_at: string; |       updated_at: string; | ||||||
|     }>; |     }>; | ||||||
|     total: number; |     total: number; | ||||||
| @ -34,10 +35,10 @@ export type HistoriesResponse = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type GetHistoriesParams = { | export type GetHistoriesParams = { | ||||||
|   project_id: number; |  | ||||||
|   file_id: string; |   file_id: string; | ||||||
|   page?: number; |   page?: number; | ||||||
|   per_page?: number; |   per_page?: number; | ||||||
|  |   project_id: number; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const getHistories = async (params: GetHistoriesParams) => { | export const getHistories = async (params: GetHistoriesParams) => { | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| export * from './api'; | export * from './api'; | ||||||
|  | export * from './application'; | ||||||
| export * from './block'; | export * from './block'; | ||||||
| export * from './file'; | export * from './file'; | ||||||
|  | export * from './history'; | ||||||
| export * from './materials'; | export * from './materials'; | ||||||
| export * from './project'; | export * from './project'; | ||||||
| export * from './application'; |  | ||||||
| export * from './history'; |  | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { type MaterialDescription } from '@vtj/core'; | import type { MaterialDescription } from '@vtj/core'; | ||||||
| 
 | 
 | ||||||
| import instance from './instance'; | import instance from './instance'; | ||||||
| 
 | 
 | ||||||
| @ -52,13 +52,13 @@ export const getMaterials = async (id: number): Promise<MaterialResponse> => { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| type MaterialData = { | type MaterialData = { | ||||||
|   project_id: number; |   created_at?: string; | ||||||
|   value: Record<string, MaterialDescription>; |  | ||||||
|   // 从原interface合并的字段
 |   // 从原interface合并的字段
 | ||||||
|   id?: number; |   id?: number; | ||||||
|   name?: string; |   name?: string; | ||||||
|   created_at?: string; |   project_id: number; | ||||||
|   updated_at?: string; |   updated_at?: string; | ||||||
|  |   value: Record<string, MaterialDescription>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function transformMaterialData(data: MaterialData) { | function transformMaterialData(data: MaterialData) { | ||||||
|  | |||||||
| @ -1,11 +1,13 @@ | |||||||
| import { createApp } from 'vue'; | import { createApp } from 'vue'; | ||||||
|  | 
 | ||||||
| import { createPersistedState } from 'pinia-plugin-persistedstate'; | import { createPersistedState } from 'pinia-plugin-persistedstate'; | ||||||
| 
 | 
 | ||||||
| import router from './router'; |  | ||||||
| import App from './App.vue'; | import App from './App.vue'; | ||||||
| import './style/index.scss'; | import router from './router'; | ||||||
| import { pinia } from './store'; | import { pinia } from './store'; | ||||||
| 
 | 
 | ||||||
|  | import './style/index.scss'; | ||||||
|  | 
 | ||||||
| // 添加持久化插件
 | // 添加持久化插件
 | ||||||
| pinia.use( | pinia.use( | ||||||
|   createPersistedState({ |   createPersistedState({ | ||||||
|  | |||||||
| @ -1,55 +1,105 @@ | |||||||
| // @ts-nocheck
 | import type { | ||||||
| import { |   BlockFile, | ||||||
|   type ProjectSchema, |   BlockSchema, | ||||||
|   type BlockSchema, |   ExtensionConfig, | ||||||
|   type HistorySchema, |   HistoryItem, | ||||||
|   type HistoryItem, |   HistorySchema, | ||||||
|   type MaterialDescription, |   MaterialDescription, | ||||||
|   type ExtensionConfig, |   NodeFromPlugin, | ||||||
|   type PageFile, |   PageFile, | ||||||
|   type BlockFile, |   ProjectSchema | ||||||
|   type NodeFromPlugin, |  | ||||||
|   ProjectModel, |  | ||||||
|   HistoryModel |  | ||||||
| } from '@vtj/core'; | } from '@vtj/core'; | ||||||
| import { mapToObject, Storage } from '@vtj/utils'; | 
 | ||||||
| import { BaseService } from '@vtj/renderer'; |  | ||||||
| import { isEmpty } from 'licia-es'; |  | ||||||
| import { | import { | ||||||
|   getProject, |  | ||||||
|   updateProject, |  | ||||||
|   createFile, |   createFile, | ||||||
|   updateFile as updateLowCodeFile, |  | ||||||
|   getFile as getLowCodeFile, |  | ||||||
|   deleteFile as deleteLowCodeFile, |  | ||||||
|   getHistory as getLowCodeHistory, |  | ||||||
|   deleteHistory as deleteLowCodeHistory, |  | ||||||
|   createHistory as createLowCodeHistory, |   createHistory as createLowCodeHistory, | ||||||
|  |   deleteFile as deleteLowCodeFile, | ||||||
|  |   deleteHistory as deleteLowCodeHistory, | ||||||
|  |   getFile as getLowCodeFile, | ||||||
|   getHistories as getLowCodeHistories, |   getHistories as getLowCodeHistories, | ||||||
|   publishFile as publishLowCodeFile, |   getHistory as getLowCodeHistory, | ||||||
|   publishAllFile as publishLowCodeAllFile, |  | ||||||
|   getMaterials as getLowCodeMaterials, |   getMaterials as getLowCodeMaterials, | ||||||
|  |   getProject, | ||||||
|   postMaterials as postLowCodeMaterials, |   postMaterials as postLowCodeMaterials, | ||||||
|  |   publishAllFile as publishLowCodeAllFile, | ||||||
|  |   publishFile as publishLowCodeFile, | ||||||
|  |   updateFile as updateLowCodeFile, | ||||||
|   updateMaterials as updateLowCodeMaterials, |   updateMaterials as updateLowCodeMaterials, | ||||||
|   deleteMaterials as deleteLowCodeMaterials |   updateProject | ||||||
| } from '@/io'; | } from '@/io'; | ||||||
|  | // @ts-nocheck
 | ||||||
|  | import { HistoryModel, ProjectModel } from '@vtj/core'; | ||||||
|  | import { BaseService } from '@vtj/renderer'; | ||||||
|  | import { mapToObject, Storage } from '@vtj/utils'; | ||||||
|  | import { isEmpty } from 'licia-es'; | ||||||
|  | 
 | ||||||
| const storage = new Storage({ | const storage = new Storage({ | ||||||
|   type: 'local', |   type: 'local', | ||||||
|   expired: 0 |   expired: 0 | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const stringifyFields = [ | const stringifyFields = new Set([ | ||||||
|   'config', |  | ||||||
|   'pages', |  | ||||||
|   'dependencies', |  | ||||||
|   'blocks', |  | ||||||
|   'apis', |   'apis', | ||||||
|   'meta' |   'blocks', | ||||||
| ]; |   'config', | ||||||
|  |   'dependencies', | ||||||
|  |   'meta', | ||||||
|  |   'pages' | ||||||
|  | ]); | ||||||
| 
 | 
 | ||||||
| let initProject: ProjectSchema; | let initProject: ProjectSchema; | ||||||
| 
 | 
 | ||||||
| export class LowCodeService extends BaseService { | export class LowCodeService extends BaseService { | ||||||
|  |   public api = (type: string, data: any): Promise<any> => { | ||||||
|  |     // console.log('api', type, data);
 | ||||||
|  |     return Promise.resolve(true); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   public getExtension(): Promise<ExtensionConfig | undefined> { | ||||||
|  |     const extension = storage.get('extension'); | ||||||
|  |     console.log('ExtensionConfig', extension); | ||||||
|  |     return Promise.resolve(extension as ExtensionConfig | undefined); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async getFile(id: string): Promise<BlockSchema> { | ||||||
|  |     return getLowCodeFile(id).then((lowCodeFile) => { | ||||||
|  |       return lowCodeFile.dsl | ||||||
|  |         ? Promise.resolve(lowCodeFile.dsl as BlockSchema) | ||||||
|  |         : Promise.reject(null); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async getHistory(fileId: string): Promise<HistorySchema> { | ||||||
|  |     const histories = await getLowCodeHistories({ | ||||||
|  |       project_id: initProject.id, | ||||||
|  |       file_id: fileId, | ||||||
|  |       per_page: 50 | ||||||
|  |     }); | ||||||
|  |     const formatDsl = { | ||||||
|  |       id: histories.list[0].file_id, | ||||||
|  |       items: histories.list.map((item) => { | ||||||
|  |         return { | ||||||
|  |           ...item, | ||||||
|  |           id: item.history_id, | ||||||
|  |           label: item.created_at | ||||||
|  |         }; | ||||||
|  |       }) | ||||||
|  |     }; | ||||||
|  |     const history = new HistoryModel(formatDsl); | ||||||
|  |     return history.toDsl(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async getHistoryItem(fId: string, id: string): Promise<HistoryItem> { | ||||||
|  |     const history = await getLowCodeHistory(id); | ||||||
|  |     return history; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public getPluginMaterial( | ||||||
|  |     from: NodeFromPlugin | ||||||
|  |   ): Promise<MaterialDescription | null> { | ||||||
|  |     return Promise.resolve(null); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   public async init(project: ProjectSchema): Promise<ProjectSchema> { |   public async init(project: ProjectSchema): Promise<ProjectSchema> { | ||||||
|     console.log('init', project); |     console.log('init', project); | ||||||
|     initProject = project; |     initProject = project; | ||||||
| @ -64,34 +114,85 @@ export class LowCodeService extends BaseService { | |||||||
|     const model = new ProjectModel(remoteProject); |     const model = new ProjectModel(remoteProject); | ||||||
|     console.log('model', model || { id: initProject.id }); |     console.log('model', model || { id: initProject.id }); | ||||||
|     const dsl = model.toDsl(); |     const dsl = model.toDsl(); | ||||||
|     return Promise.resolve(dsl); |     return dsl; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public getExtension(): Promise<ExtensionConfig | undefined> { |   public publish(project: ProjectSchema): Promise<boolean> { | ||||||
|     const extension = storage.get('extension'); |     return publishLowCodeAllFile(Number(project.id)).then((res) => { | ||||||
|     console.log('ExtensionConfig', extension); |       return true; | ||||||
|     return Promise.resolve(extension as ExtensionConfig | undefined); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public async saveProject(project: ProjectSchema): Promise<boolean> { |   public publishFile( | ||||||
|     const newProject = { |     project: ProjectSchema, | ||||||
|       ...project, |     file: BlockFile | PageFile | ||||||
|       ...Object.fromEntries( |   ): Promise<boolean> { | ||||||
|         Object.entries(project) |     return publishLowCodeFile(file.id).then((res) => { | ||||||
|           .filter(([key]) => stringifyFields.includes(key)) |       return true; | ||||||
|           .map(([key, value]) => [key, JSON.stringify(value)]) |     }); | ||||||
|       ) |   } | ||||||
|     }; | 
 | ||||||
|     // 剔除引擎自行添加的 id,避免接口更新冲突报错
 |   public async removeFile(id: string): Promise<boolean> { | ||||||
|     Reflect.deleteProperty(newProject, 'id'); |     return deleteLowCodeFile(id).then(() => true); | ||||||
|     await updateProject(initProject.id, newProject); |   } | ||||||
|  | 
 | ||||||
|  |   // TODO: 做成数据库存储后没啥用,保留就行
 | ||||||
|  |   public removeHistory(id: string): Promise<boolean> { | ||||||
|  |     // console.log('removeHistory', id);
 | ||||||
|     return Promise.resolve(true); |     return Promise.resolve(true); | ||||||
|   } |   } | ||||||
|  |   public async removeHistoryItem(fId: string, ids: string[]): Promise<boolean> { | ||||||
|  |     await Promise.all(ids.map((id) => deleteLowCodeHistory(id))); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   public getPluginMaterial( |   public async saveFile(file: BlockSchema): Promise<boolean> { | ||||||
|     from: NodeFromPlugin |     console.log('saveFile', file); | ||||||
|   ): Promise<MaterialDescription | null> { |     if (file.id) { | ||||||
|     return Promise.resolve(null); |       const existFile = await getLowCodeFile(file.id); | ||||||
|  |       return existFile.file_id | ||||||
|  |         ? updateLowCodeFile(file.id, { | ||||||
|  |             ...existFile, | ||||||
|  |             dsl: file | ||||||
|  |           }) | ||||||
|  |             .then(() => { | ||||||
|  |               return true; | ||||||
|  |             }) | ||||||
|  |             .catch((error) => { | ||||||
|  |               throw error; | ||||||
|  |             }) | ||||||
|  |         : createFile({ | ||||||
|  |             project_id: initProject.id, | ||||||
|  |             publish: false, | ||||||
|  |             active: true, | ||||||
|  |             dsl: file, | ||||||
|  |             file_id: file.id | ||||||
|  |           }) | ||||||
|  |             .then(() => { | ||||||
|  |               return true; | ||||||
|  |             }) | ||||||
|  |             .catch((error) => { | ||||||
|  |               throw error; | ||||||
|  |             }); | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async saveHistory(history: HistorySchema): Promise<boolean> { | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async saveHistoryItem( | ||||||
|  |     fileId: string, | ||||||
|  |     historyItem: HistoryItem | ||||||
|  |   ): Promise<boolean> { | ||||||
|  |     await createLowCodeHistory({ | ||||||
|  |       project_id: initProject.id, | ||||||
|  |       file_id: fileId, | ||||||
|  |       history_id: historyItem.id, | ||||||
|  |       dsl: historyItem.dsl as HistorySchema | ||||||
|  |     }); | ||||||
|  |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // TODO: 物料存储只有在发布为其他端 (比如 uinapp) 时才有用,当前版本时不需要的,暂且保留
 |   // TODO: 物料存储只有在发布为其他端 (比如 uinapp) 时才有用,当前版本时不需要的,暂且保留
 | ||||||
| @ -120,130 +221,25 @@ export class LowCodeService extends BaseService { | |||||||
| 
 | 
 | ||||||
|     // @ts-ignore
 |     // @ts-ignore
 | ||||||
|     // await deleteLowCodeMaterials(project.id);
 |     // await deleteLowCodeMaterials(project.id);
 | ||||||
|     return Promise.resolve(true); |     return true; | ||||||
|   } |   } | ||||||
| 
 |   public async saveProject(project: ProjectSchema): Promise<boolean> { | ||||||
|   public async saveFile(file: BlockSchema): Promise<boolean> { |     const newProject = { | ||||||
|     console.log('saveFile', file); |       ...project, | ||||||
|     if (file.id) { |       ...Object.fromEntries( | ||||||
|       const existFile = await getLowCodeFile(file.id); |         Object.entries(project) | ||||||
|       if (existFile.file_id) { |           .filter(([key]) => stringifyFields.has(key)) | ||||||
|         return updateLowCodeFile(file.id, { |           .map(([key, value]) => [key, JSON.stringify(value)]) | ||||||
|           ...existFile, |       ) | ||||||
|           dsl: file |     }; | ||||||
|         }) |     // 剔除引擎自行添加的 id,避免接口更新冲突报错
 | ||||||
|           .then(() => { |     Reflect.deleteProperty(newProject, 'id'); | ||||||
|             return Promise.resolve(true); |     await updateProject(initProject.id, newProject); | ||||||
|           }) |     return true; | ||||||
|           .catch((err) => { |  | ||||||
|             return Promise.reject(err); |  | ||||||
|           }); |  | ||||||
|       } else { |  | ||||||
|         return createFile({ |  | ||||||
|           project_id: initProject.id, |  | ||||||
|           publish: false, |  | ||||||
|           active: true, |  | ||||||
|           dsl: file, |  | ||||||
|           file_id: file.id |  | ||||||
|         }) |  | ||||||
|           .then(() => { |  | ||||||
|             return Promise.resolve(true); |  | ||||||
|           }) |  | ||||||
|           .catch((err) => { |  | ||||||
|             return Promise.reject(err); |  | ||||||
|           }); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     return Promise.resolve(false); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public async getFile(id: string): Promise<BlockSchema> { |  | ||||||
|     return getLowCodeFile(id).then((lowCodeFile) => { |  | ||||||
|       if (lowCodeFile.dsl) { |  | ||||||
|         return Promise.resolve(lowCodeFile.dsl as BlockSchema); |  | ||||||
|       } else { |  | ||||||
|         return Promise.reject(null); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async removeFile(id: string): Promise<boolean> { |  | ||||||
|     return deleteLowCodeFile(id).then(() => Promise.resolve(true)); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async saveHistory(history: HistorySchema): Promise<boolean> { |  | ||||||
|     return Promise.resolve(true); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public api = (type: string, data: any): Promise<any> => { |  | ||||||
|     // console.log('api', type, data);
 |  | ||||||
|     return Promise.resolve(true); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   protected uploader = (file: File, projectId: string): Promise<any> => { |   protected uploader = (file: File, projectId: string): Promise<any> => { | ||||||
|     // console.log('uploader', file, projectId);
 |     // console.log('uploader', file, projectId);
 | ||||||
|     return Promise.resolve(true); |     return Promise.resolve(true); | ||||||
|   }; |   }; | ||||||
|   // TODO: 做成数据库存储后没啥用,保留就行
 |  | ||||||
|   public removeHistory(id: string): Promise<boolean> { |  | ||||||
|     // console.log('removeHistory', id);
 |  | ||||||
|     return Promise.resolve(true); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async getHistory(fileId: string): Promise<HistorySchema> { |  | ||||||
|     const histories = await getLowCodeHistories({ |  | ||||||
|       project_id: initProject.id, |  | ||||||
|       file_id: fileId, |  | ||||||
|       per_page: 50 |  | ||||||
|     }); |  | ||||||
|     const formatDsl = { |  | ||||||
|       id: histories.list[0].file_id, |  | ||||||
|       items: histories.list.map((item) => { |  | ||||||
|         return { |  | ||||||
|           ...item, |  | ||||||
|           id: item.history_id, |  | ||||||
|           label: item.created_at |  | ||||||
|         }; |  | ||||||
|       }) |  | ||||||
|     }; |  | ||||||
|     const history = new HistoryModel(formatDsl); |  | ||||||
|     return Promise.resolve(history.toDsl()); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async getHistoryItem(fId: string, id: string): Promise<HistoryItem> { |  | ||||||
|     const history = await getLowCodeHistory(id); |  | ||||||
|     return Promise.resolve(history); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async saveHistoryItem( |  | ||||||
|     fileId: string, |  | ||||||
|     historyItem: HistoryItem |  | ||||||
|   ): Promise<boolean> { |  | ||||||
|     await createLowCodeHistory({ |  | ||||||
|       project_id: initProject.id, |  | ||||||
|       file_id: fileId, |  | ||||||
|       history_id: historyItem.id, |  | ||||||
|       dsl: historyItem.dsl as HistorySchema |  | ||||||
|     }); |  | ||||||
|     return Promise.resolve(true); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public async removeHistoryItem(fId: string, ids: string[]): Promise<boolean> { |  | ||||||
|     await Promise.all(ids.map((id) => deleteLowCodeHistory(id))); |  | ||||||
|     return Promise.resolve(true); |  | ||||||
|   } |  | ||||||
|   public publish(project: ProjectSchema): Promise<boolean> { |  | ||||||
|     return publishLowCodeAllFile(Number(project.id)).then((res) => { |  | ||||||
|       return Promise.resolve(true); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public publishFile( |  | ||||||
|     project: ProjectSchema, |  | ||||||
|     file: PageFile | BlockFile |  | ||||||
|   ): Promise<boolean> { |  | ||||||
|     return publishLowCodeFile(file.id).then((res) => { |  | ||||||
|       return Promise.resolve(true); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { ref, computed } from 'vue'; | import { computed, ref } from 'vue'; | ||||||
| import axios from 'axios'; | 
 | ||||||
| import { createPinia, defineStore } from 'pinia'; | import { createPinia, defineStore } from 'pinia'; | ||||||
| 
 | 
 | ||||||
| // 创建 pinia 实例
 | // 创建 pinia 实例
 | ||||||
| @ -38,7 +38,7 @@ export const useUserStore = defineStore('user', () => { | |||||||
| 
 | 
 | ||||||
| // 应用配置 store
 | // 应用配置 store
 | ||||||
| export const useAppStore = defineStore('app', () => { | export const useAppStore = defineStore('app', () => { | ||||||
|   const theme = ref<'light' | 'dark'>('light'); |   const theme = ref<'dark' | 'light'>('light'); | ||||||
|   const sidebarCollapsed = ref(false); |   const sidebarCollapsed = ref(false); | ||||||
| 
 | 
 | ||||||
|   // 持久化配置
 |   // 持久化配置
 | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| @use '@vtj/web/src/index.scss'; | @use '@vtj/web/src/index'; | ||||||
| 
 | 
 | ||||||
| html, | html, | ||||||
| body, | body, | ||||||
| #app { | #app { | ||||||
|  |   height: 100%; | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   margin: 0; |   margin: 0; | ||||||
|   font-size: 14px; |  | ||||||
|   height: 100%; |  | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
|  |   font-size: 14px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #vtjLink { | #vtjLink { | ||||||
|  | |||||||
| @ -1,14 +1,16 @@ | |||||||
| import * as Vue from 'vue'; |  | ||||||
| import * as core from '@vtj/core'; |  | ||||||
| import * as VtjUtils from '@vtj/utils'; |  | ||||||
| import * as VtjUI from '@vtj/ui'; |  | ||||||
| import * as designer from '@vtj/designer'; |  | ||||||
| import * as renderer from '@vtj/renderer'; |  | ||||||
| import * as VtjIcons from '@vtj/icons'; |  | ||||||
| import * as ElementPlus from 'element-plus'; |  | ||||||
| import type { ExtensionConfig } from '@vtj/core'; | import type { ExtensionConfig } from '@vtj/core'; | ||||||
| import type { EngineOptions } from '@vtj/designer'; | import type { EngineOptions } from '@vtj/designer'; | ||||||
| 
 | 
 | ||||||
|  | import * as Vue from 'vue'; | ||||||
|  | 
 | ||||||
|  | import * as core from '@vtj/core'; | ||||||
|  | import * as designer from '@vtj/designer'; | ||||||
|  | import * as VtjIcons from '@vtj/icons'; | ||||||
|  | import * as renderer from '@vtj/renderer'; | ||||||
|  | import * as VtjUI from '@vtj/ui'; | ||||||
|  | import * as VtjUtils from '@vtj/utils'; | ||||||
|  | import * as ElementPlus from 'element-plus'; | ||||||
|  | 
 | ||||||
| export type ExtensionOptions = ExtensionConfig; | export type ExtensionOptions = ExtensionConfig; | ||||||
| export type ExtensionFactory = ( | export type ExtensionFactory = ( | ||||||
|   config: ExtensionConfig |   config: ExtensionConfig | ||||||
| @ -20,11 +22,11 @@ export interface ExtensionOutput { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class Extension { | export class Extension { | ||||||
|   private urls: string[] = []; |   private __adapters__: Record<string, any> = {}; | ||||||
|  |   private __BASE_PATH__: string = '/'; | ||||||
|   private library: string = ''; |   private library: string = ''; | ||||||
|   private params: any[] = []; |   private params: any[] = []; | ||||||
|   private __BASE_PATH__: string = '/'; |   private urls: string[] = []; | ||||||
|   private __adapters__: Record<string, any> = {}; |  | ||||||
|   constructor(private options: ExtensionOptions) { |   constructor(private options: ExtensionOptions) { | ||||||
|     const __VTJ_PRO__ = { |     const __VTJ_PRO__ = { | ||||||
|       ...core, |       ...core, | ||||||
| @ -62,15 +64,14 @@ export class Extension { | |||||||
|         .filter((n) => renderer.isJSUrl(n)) |         .filter((n) => renderer.isJSUrl(n)) | ||||||
|         .map((n) => `${base}${n}`); |         .map((n) => `${base}${n}`); | ||||||
|       renderer.loadCssUrl(css); |       renderer.loadCssUrl(css); | ||||||
|       if (scripts.length) { |       if (scripts.length > 0) { | ||||||
|         const output = await renderer |         const output = await renderer | ||||||
|           .loadScriptUrl(scripts, this.library) |           .loadScriptUrl(scripts, this.library) | ||||||
|           .catch(() => null); |           .catch(() => null); | ||||||
|         if (output && typeof output === 'function') { |         options = | ||||||
|           options = output.call(output, this.options, this.params); |           output && typeof output === 'function' | ||||||
|         } else { |             ? output.call(output, this.options, this.params) | ||||||
|           options = output || {}; |             : output || {}; | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return { |     return { | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import 'element-plus/theme-chalk/index.css'; | |||||||
| import '@vtj/ui/dist/style.css'; | import '@vtj/ui/dist/style.css'; | ||||||
| import '@vtj/icons/dist/style.css'; | import '@vtj/icons/dist/style.css'; | ||||||
| 
 | 
 | ||||||
|  | export * from './extension'; | ||||||
| export * from '@vtj/core'; | export * from '@vtj/core'; | ||||||
| export * from '@vtj/designer'; | export * from '@vtj/designer'; | ||||||
| export * from '@vtj/renderer'; | export * from '@vtj/renderer'; | ||||||
| export * from './extension'; |  | ||||||
|  | |||||||
| @ -1,10 +1,11 @@ | |||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { ref } from 'vue'; | import { ref } from 'vue'; | ||||||
| import Postmate from 'postmate'; | 
 | ||||||
| import { Engine, widgetManager } from '@vtj/pro'; |  | ||||||
| import { request, jsonp } from '@vtj/utils'; |  | ||||||
| import { useUserStore } from '@/store'; |  | ||||||
| import { LowCodeService } from '@/service'; | import { LowCodeService } from '@/service'; | ||||||
|  | import { useUserStore } from '@/store'; | ||||||
|  | import { Engine, widgetManager } from '@vtj/pro'; | ||||||
|  | import { jsonp, request } from '@vtj/utils'; | ||||||
|  | import Postmate from 'postmate'; | ||||||
| 
 | 
 | ||||||
| const container = ref(); | const container = ref(); | ||||||
| const service = new LowCodeService(); | const service = new LowCodeService(); | ||||||
| @ -68,7 +69,7 @@ onMounted(async () => { | |||||||
| 
 | 
 | ||||||
| <style scoped> | <style scoped> | ||||||
| .designer-container { | .designer-container { | ||||||
|   height: 100%; |  | ||||||
|   width: 100%; |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
|  | <script lang="ts" setup> | ||||||
|  | import { XContainer } from '@vtj/web'; | ||||||
|  | import { ElEmpty } from 'element-plus'; | ||||||
|  | </script> | ||||||
| <template> | <template> | ||||||
|   <XContainer class="not-found" fit justify="center"> |   <XContainer class="not-found" fit justify="center"> | ||||||
|     <ElEmpty description="找不到页面【404】"></ElEmpty> |     <ElEmpty description="找不到页面【404】" /> | ||||||
|   </XContainer> |   </XContainer> | ||||||
| </template> | </template> | ||||||
| <script lang="ts" setup> |  | ||||||
|   import { XContainer } from '@vtj/web'; |  | ||||||
|   import { ElEmpty } from 'element-plus'; |  | ||||||
| </script> |  | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped></style> | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| <template> |  | ||||||
|   <XContainer class="unauthorized" fit justify="center"> |  | ||||||
|     <ElEmpty description="无权限访问该页面"></ElEmpty> |  | ||||||
|   </XContainer> |  | ||||||
| </template> |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { XContainer } from '@vtj/ui'; | import { XContainer } from '@vtj/ui'; | ||||||
| import { ElEmpty } from 'element-plus'; | import { ElEmpty } from 'element-plus'; | ||||||
| </script> | </script> | ||||||
|  | <template> | ||||||
|  |   <XContainer class="unauthorized" fit justify="center"> | ||||||
|  |     <ElEmpty description="无权限访问该页面" /> | ||||||
|  |   </XContainer> | ||||||
|  | </template> | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped></style> | ||||||
|  | |||||||
| @ -1,9 +1,8 @@ | |||||||
| import { defineConfig, loadEnv } from 'vite'; |  | ||||||
| import { createViteConfig } from '@vtj/cli'; | import { createViteConfig } from '@vtj/cli'; | ||||||
| import { createDevTools } from '@vtj/local'; | import { createDevTools } from '@vtj/local'; | ||||||
| import mkcert from 'vite-plugin-mkcert'; |  | ||||||
| import AutoImport from 'unplugin-auto-import/vite'; | import AutoImport from 'unplugin-auto-import/vite'; | ||||||
| import path from 'path'; | import { defineConfig, loadEnv } from 'vite'; | ||||||
|  | import mkcert from 'vite-plugin-mkcert'; | ||||||
| 
 | 
 | ||||||
| const config = createViteConfig({ | const config = createViteConfig({ | ||||||
|   // proxy,
 |   // proxy,
 | ||||||
|  | |||||||
| @ -64,7 +64,6 @@ onMounted(() => { | |||||||
| .responsive-iframe { | .responsive-iframe { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   height: 100%; |   height: 100%; | ||||||
| 
 |  | ||||||
|   border: none; |   border: none; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								apps/renderer/env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								apps/renderer/env.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1,8 +1,8 @@ | |||||||
| /// <reference types="vite/client" />
 | // / <reference types="vite/client" />
 | ||||||
| 
 | 
 | ||||||
| interface ImportMeta { | interface ImportMeta { | ||||||
|   readonly env: { |   readonly env: { | ||||||
|     NODE_ENV: "development" | "production"; |     NODE_ENV: 'development' | 'production'; | ||||||
|     VITE_API_BASE?: string; |     VITE_API_BASE?: string; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,24 +1,24 @@ | |||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { computed, watch, ref, getCurrentInstance } from 'vue' | import { computed, watch, ref, getCurrentInstance } from 'vue'; | ||||||
| import { ElLoading } from 'element-plus' | import { ElLoading } from 'element-plus'; | ||||||
| import Postmate from 'postmate' | import Postmate from 'postmate'; | ||||||
| import { createProvider } from '@vtj/web' | import { createProvider } from '@vtj/web'; | ||||||
| import { useQuery } from '@tanstack/vue-query' | import { useQuery } from '@tanstack/vue-query'; | ||||||
| import { LowCodeService } from './service' | import { LowCodeService } from './service'; | ||||||
| import { getFile } from './io' | import { getFile } from './io'; | ||||||
| import { request, jsonp } from '@vtj/utils' | import { request, jsonp } from '@vtj/utils'; | ||||||
| // import * as VtjUI from '@vtj/ui' | // import * as VtjUI from '@vtj/ui' | ||||||
| 
 | 
 | ||||||
| // 响应式状态 | // 响应式状态 | ||||||
| const renderer = ref() | const renderer = ref(); | ||||||
| const lowCodeService = new LowCodeService() | const lowCodeService = new LowCodeService(); | ||||||
| 
 | 
 | ||||||
| // Postmate 握手协议 | // Postmate 握手协议 | ||||||
| const postmate = new Postmate.Model({ | const postmate = new Postmate.Model({ | ||||||
|   sayHi: (data: any) => { |   sayHi: (data: any) => { | ||||||
|     console.log('sayHi',data) |     console.log('sayHi', data); | ||||||
|   } |   }, | ||||||
| }) | }); | ||||||
| 
 | 
 | ||||||
| // 数据模型 | // 数据模型 | ||||||
| const model = { | const model = { | ||||||
| @ -27,54 +27,54 @@ const model = { | |||||||
|   projectId: -1, |   projectId: -1, | ||||||
|   fileId: '', |   fileId: '', | ||||||
|   url: '', |   url: '', | ||||||
|   accessToken: '' |   accessToken: '', | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| // 数据查询 | // 数据查询 | ||||||
| const { data: file, isFetching } = useQuery({ | const { data: file, isFetching } = useQuery({ | ||||||
|   queryKey: ['getFile'], |   queryKey: ['getFile'], | ||||||
|   queryFn: async () => { |   queryFn: async () => { | ||||||
|     await postmate.then((parent) => { |     await postmate.then((parent) => { | ||||||
|       parent.emit('some-event', 'y-code-renderer is ready') |       parent.emit('some-event', 'y-code-renderer is ready'); | ||||||
|       Object.assign(model, parent.model) |       Object.assign(model, parent.model); | ||||||
|       localStorage.setItem('y-code-access-token', model.accessToken || '') |       localStorage.setItem('y-code-access-token', model.accessToken || ''); | ||||||
|     }) |     }); | ||||||
| 
 | 
 | ||||||
|     return getFile(model.fileId).then(() => { |     return getFile(model.fileId).then(() => { | ||||||
|       request.useRequest((req) => { |       request.useRequest((req) => { | ||||||
|         req.headers.set('Authorization', `Bearer ${model.accessToken}`) |         req.headers.set('Authorization', `Bearer ${model.accessToken}`); | ||||||
|         return req |         return req; | ||||||
|       }) |       }); | ||||||
|       const { provider, onReady } = createProvider({ |       const { provider, onReady } = createProvider({ | ||||||
|         nodeEnv: import.meta.env.NODE_ENV, |         nodeEnv: import.meta.env.NODE_ENV, | ||||||
|         service: lowCodeService, |         service: lowCodeService, | ||||||
|         project: { id: model.projectId }, |         project: { id: model.projectId }, | ||||||
|         adapter: { |         adapter: { | ||||||
|           request, |           request, | ||||||
|           jsonp |           jsonp, | ||||||
|         } |         }, | ||||||
|       }) |       }); | ||||||
|       onReady(async () => { |       onReady(async () => { | ||||||
|         const instance = getCurrentInstance() |         const instance = getCurrentInstance(); | ||||||
|         instance?.appContext.app.use(provider) |         instance?.appContext.app.use(provider); | ||||||
|         renderer.value = await provider.getRenderComponent(model.fileId) |         renderer.value = await provider.getRenderComponent(model.fileId); | ||||||
|       }) |       }); | ||||||
|     }) |     }); | ||||||
|   } |   }, | ||||||
| }) | }); | ||||||
| 
 | 
 | ||||||
| // 加载状态监控 | // 加载状态监控 | ||||||
| watch(isFetching, (newVal) => { | watch(isFetching, (newVal) => { | ||||||
|   if (newVal) { |   if (newVal) { | ||||||
|     ElLoading.service({ text: '低代码文件加载中...' }) |     ElLoading.service({ text: '低代码文件加载中...' }); | ||||||
|   } else { |   } else { | ||||||
|     ElLoading.service().close() |     ElLoading.service().close(); | ||||||
|   } |   } | ||||||
| }) | }); | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <div style="padding: 20px;"> |   <div style="padding: 20px"> | ||||||
|     <component :is="renderer" v-if="renderer" /> |     <component :is="renderer" v-if="renderer" /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| export * from "./env"; | export * from './env'; | ||||||
|  | |||||||
| @ -1,13 +1,14 @@ | |||||||
| import { BlockSchema } from "@vtj/core"; | import { BlockSchema } from '@vtj/core'; | ||||||
| import instance from "./instance"; | 
 | ||||||
|  | import instance from './instance'; | ||||||
| 
 | 
 | ||||||
| export type LowCodeFileSchema = { | export type LowCodeFileSchema = { | ||||||
|   project_id: number; |  | ||||||
|   publish: boolean; |  | ||||||
|   active: boolean; |   active: boolean; | ||||||
|   dsl: BlockSchema; |   dsl: BlockSchema; | ||||||
|   file_path?: string; |  | ||||||
|   file_id?: string; |   file_id?: string; | ||||||
|  |   file_path?: string; | ||||||
|  |   project_id: number; | ||||||
|  |   publish: boolean; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const getFile = async (id: string): Promise<LowCodeFileSchema> => { | export const getFile = async (id: string): Promise<LowCodeFileSchema> => { | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| export * from "./file"; | export * from './file'; | ||||||
| export * from "./project"; | export * from './project'; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import axios from "axios"; | import axios from 'axios'; | ||||||
| 
 | 
 | ||||||
| // 创建独立实例
 | // 创建独立实例
 | ||||||
| const instance = axios.create({ | const instance = axios.create({ | ||||||
| @ -13,7 +13,7 @@ instance.interceptors.request.use( | |||||||
|   }, |   }, | ||||||
|   (error) => { |   (error) => { | ||||||
|     return Promise.reject(error); |     return Promise.reject(error); | ||||||
|   } |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| instance.interceptors.response.use( | instance.interceptors.response.use( | ||||||
| @ -22,7 +22,7 @@ instance.interceptors.response.use( | |||||||
|   }, |   }, | ||||||
|   (error) => { |   (error) => { | ||||||
|     return Promise.reject(error); |     return Promise.reject(error); | ||||||
|   } |   }, | ||||||
| ); | ); | ||||||
| // 导出实例
 | // 导出实例
 | ||||||
| export default instance; | export default instance; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import instance from "./instance"; | import instance from './instance'; | ||||||
| 
 | 
 | ||||||
| export const getProject = async (id: string) => { | export const getProject = async (id: string) => { | ||||||
|   const response = await instance.get(`/api/v1/projects/${id}`); |   const response = await instance.get(`/api/v1/projects/${id}`); | ||||||
|  | |||||||
| @ -1,18 +1,29 @@ | |||||||
| import { type ProjectSchema, type BlockSchema, ProjectModel } from "@vtj/core"; | import type { BlockSchema, ProjectSchema } from '@vtj/core'; | ||||||
| import { BaseService } from "@vtj/renderer"; | 
 | ||||||
| import { getProject, getFile as getLowCodeFile } from "@/io"; | import { getFile as getLowCodeFile, getProject } from '@/io'; | ||||||
|  | import { ProjectModel } from '@vtj/core'; | ||||||
|  | import { BaseService } from '@vtj/renderer'; | ||||||
| 
 | 
 | ||||||
| let initProject: ProjectModel = {}; | let initProject: ProjectModel = {}; | ||||||
| 
 | 
 | ||||||
| export class LowCodeService extends BaseService { | export class LowCodeService extends BaseService { | ||||||
|  |   public async getFile(id: string): Promise<BlockSchema> { | ||||||
|  |     console.log('service getFile', id); | ||||||
|  |     return getLowCodeFile(id).then((lowCodeFile) => { | ||||||
|  |       return lowCodeFile.dsl | ||||||
|  |         ? Promise.resolve(lowCodeFile.dsl as BlockSchema) | ||||||
|  |         : Promise.reject(null); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   public async init(project: ProjectSchema) { |   public async init(project: ProjectSchema) { | ||||||
|     console.log("init", project); |     console.log('init', project); | ||||||
|     initProject = project; |     initProject = project; | ||||||
|     const remoteProject = await getProject(project.id); |     const remoteProject = await getProject(project.id); | ||||||
|     console.log("remoteProject", remoteProject); |     console.log('remoteProject', remoteProject); | ||||||
|     const model = new ProjectModel(remoteProject); |     const model = new ProjectModel(remoteProject); | ||||||
|     const dsl = model.toDsl(); |     const dsl = model.toDsl(); | ||||||
|     return Promise.resolve(dsl); |     return dsl; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public saveProject(project: ProjectSchema): Promise<boolean> { |   public saveProject(project: ProjectSchema): Promise<boolean> { | ||||||
| @ -21,7 +32,7 @@ export class LowCodeService extends BaseService { | |||||||
|       ...Object.fromEntries( |       ...Object.fromEntries( | ||||||
|         Object.entries(project) |         Object.entries(project) | ||||||
|           .filter(([key]) => stringifyFields.includes(key)) |           .filter(([key]) => stringifyFields.includes(key)) | ||||||
|           .map(([key, value]) => [key, JSON.stringify(value)]) |           .map(([key, value]) => [key, JSON.stringify(value)]), | ||||||
|       ), |       ), | ||||||
|     }; |     }; | ||||||
|     updateProject(initProject.id, newProject); |     updateProject(initProject.id, newProject); | ||||||
| @ -29,15 +40,4 @@ export class LowCodeService extends BaseService { | |||||||
|     // storage.save(`project_${model.id}`, model.toDsl());
 |     // storage.save(`project_${model.id}`, model.toDsl());
 | ||||||
|     return Promise.resolve(true); |     return Promise.resolve(true); | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   public async getFile(id: string): Promise<BlockSchema> { |  | ||||||
|     console.log("service getFile", id); |  | ||||||
|     return getLowCodeFile(id).then((lowCodeFile) => { |  | ||||||
|       if (lowCodeFile.dsl) { |  | ||||||
|         return Promise.resolve(lowCodeFile.dsl as BlockSchema); |  | ||||||
|       } else { |  | ||||||
|         return Promise.reject(null); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,15 +1,15 @@ | |||||||
| module.exports = { | module.exports = { | ||||||
|   branches: ["main", "master"], |   branches: ['main', 'master'], | ||||||
|   plugins: [ |   plugins: [ | ||||||
|     "@semantic-release/commit-analyzer", |     '@semantic-release/commit-analyzer', | ||||||
|     "@semantic-release/release-notes-generator", |     '@semantic-release/release-notes-generator', | ||||||
|     "@semantic-release/changelog", |     '@semantic-release/changelog', | ||||||
|     // "@semantic-release/npm",
 |     // "@semantic-release/npm",
 | ||||||
|     [ |     [ | ||||||
|       "@semantic-release/git", |       '@semantic-release/git', | ||||||
|       { |       { | ||||||
|         assets: ["CHANGELOG.md", "package.json"], |         assets: ['CHANGELOG.md', 'package.json'], | ||||||
|         message: "chore(release): ${nextRelease.version} [skip ci]", |         message: 'chore(release): ${nextRelease.version} [skip ci]', | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|     // "@semantic-release/github",
 |     // "@semantic-release/github",
 | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								apps/y-code-v1/components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								apps/y-code-v1/components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -7,39 +7,39 @@ export {} | |||||||
| 
 | 
 | ||||||
| declare module 'vue' { | declare module 'vue' { | ||||||
|   export interface GlobalComponents { |   export interface GlobalComponents { | ||||||
|     ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb'] |     ABreadcrumb: (typeof import('ant-design-vue/es'))['Breadcrumb']; | ||||||
|     ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem'] |     ABreadcrumbItem: (typeof import('ant-design-vue/es'))['BreadcrumbItem']; | ||||||
|     AButton: typeof import('ant-design-vue/es')['Button'] |     AButton: (typeof import('ant-design-vue/es'))['Button']; | ||||||
|     ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] |     ACheckbox: (typeof import('ant-design-vue/es'))['Checkbox']; | ||||||
|     ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup'] |     ACheckboxGroup: (typeof import('ant-design-vue/es'))['CheckboxGroup']; | ||||||
|     ACol: typeof import('ant-design-vue/es')['Col'] |     ACol: (typeof import('ant-design-vue/es'))['Col']; | ||||||
|     AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider'] |     AConfigProvider: (typeof import('ant-design-vue/es'))['ConfigProvider']; | ||||||
|     ADropdown: typeof import('ant-design-vue/es')['Dropdown'] |     ADropdown: (typeof import('ant-design-vue/es'))['Dropdown']; | ||||||
|     AFloatButton: typeof import('ant-design-vue/es')['FloatButton'] |     AFloatButton: (typeof import('ant-design-vue/es'))['FloatButton']; | ||||||
|     AForm: typeof import('ant-design-vue/es')['Form'] |     AForm: (typeof import('ant-design-vue/es'))['Form']; | ||||||
|     AFormItem: typeof import('ant-design-vue/es')['FormItem'] |     AFormItem: (typeof import('ant-design-vue/es'))['FormItem']; | ||||||
|     AImage: typeof import('ant-design-vue/es')['Image'] |     AImage: (typeof import('ant-design-vue/es'))['Image']; | ||||||
|     AInput: typeof import('ant-design-vue/es')['Input'] |     AInput: (typeof import('ant-design-vue/es'))['Input']; | ||||||
|     AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] |     AInputNumber: (typeof import('ant-design-vue/es'))['InputNumber']; | ||||||
|     AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] |     AInputPassword: (typeof import('ant-design-vue/es'))['InputPassword']; | ||||||
|     AMenu: typeof import('ant-design-vue/es')['Menu'] |     AMenu: (typeof import('ant-design-vue/es'))['Menu']; | ||||||
|     AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] |     AMenuItem: (typeof import('ant-design-vue/es'))['MenuItem']; | ||||||
|     AModal: typeof import('ant-design-vue/es')['Modal'] |     AModal: (typeof import('ant-design-vue/es'))['Modal']; | ||||||
|     APagination: typeof import('ant-design-vue/es')['Pagination'] |     APagination: (typeof import('ant-design-vue/es'))['Pagination']; | ||||||
|     APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] |     APopconfirm: (typeof import('ant-design-vue/es'))['Popconfirm']; | ||||||
|     ARadio: typeof import('ant-design-vue/es')['Radio'] |     ARadio: (typeof import('ant-design-vue/es'))['Radio']; | ||||||
|     ARadioButton: typeof import('ant-design-vue/es')['RadioButton'] |     ARadioButton: (typeof import('ant-design-vue/es'))['RadioButton']; | ||||||
|     ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] |     ARadioGroup: (typeof import('ant-design-vue/es'))['RadioGroup']; | ||||||
|     ARangePicker: typeof import('ant-design-vue/es')['RangePicker'] |     ARangePicker: (typeof import('ant-design-vue/es'))['RangePicker']; | ||||||
|     ARow: typeof import('ant-design-vue/es')['Row'] |     ARow: (typeof import('ant-design-vue/es'))['Row']; | ||||||
|     ASelect: typeof import('ant-design-vue/es')['Select'] |     ASelect: (typeof import('ant-design-vue/es'))['Select']; | ||||||
|     ASpace: typeof import('ant-design-vue/es')['Space'] |     ASpace: (typeof import('ant-design-vue/es'))['Space']; | ||||||
|     ASpin: typeof import('ant-design-vue/es')['Spin'] |     ASpin: (typeof import('ant-design-vue/es'))['Spin']; | ||||||
|     ASwitch: typeof import('ant-design-vue/es')['Switch'] |     ASwitch: (typeof import('ant-design-vue/es'))['Switch']; | ||||||
|     ATable: typeof import('ant-design-vue/es')['Table'] |     ATable: (typeof import('ant-design-vue/es'))['Table']; | ||||||
|     RouterLink: typeof import('vue-router')['RouterLink'] |     RouterLink: (typeof import('vue-router'))['RouterLink']; | ||||||
|     RouterView: typeof import('vue-router')['RouterView'] |     RouterView: (typeof import('vue-router'))['RouterView']; | ||||||
|     YChart: typeof import('./src/components/common/y-chart.vue')['default'] |     YChart: (typeof import('./src/components/common/y-chart.vue'))['default']; | ||||||
|     YTable: typeof import('./src/components/common/y-table.vue')['default'] |     YTable: (typeof import('./src/components/common/y-table.vue'))['default']; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								apps/y-code-v1/env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								apps/y-code-v1/env.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | |||||||
| /// <reference types="vite/client" />
 | // / <reference types="vite/client" />
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| <!DOCTYPE html> | <!doctype html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
|   <head> |   <head> | ||||||
|     <meta charset="UTF-8" /> |     <meta charset="UTF-8" /> | ||||||
|  | |||||||
| @ -1,23 +1,28 @@ | |||||||
| <script setup> | <script setup> | ||||||
|  | import { | ||||||
|  |   ConfigProvider, | ||||||
|  |   legacyLogicalPropertiesTransformer, | ||||||
|  |   StyleProvider, | ||||||
|  |   theme, | ||||||
|  | } from 'ant-design-vue'; | ||||||
| import zhCN from 'ant-design-vue/es/locale/zh_CN'; | import zhCN from 'ant-design-vue/es/locale/zh_CN'; | ||||||
| import { legacyLogicalPropertiesTransformer, StyleProvider, ConfigProvider, theme  } from 'ant-design-vue'; |  | ||||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||||
|  | 
 | ||||||
| import 'dayjs/locale/zh-cn'; | import 'dayjs/locale/zh-cn'; | ||||||
| 
 | 
 | ||||||
| const { compactAlgorithm } = theme; | const { compactAlgorithm } = theme; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| dayjs.locale('zh-cn'); | dayjs.locale('zh-cn'); | ||||||
| 
 | 
 | ||||||
| ConfigProvider.config({ | ConfigProvider.config({ | ||||||
|   prefixCls: 'ycode-ant', |   prefixCls: 'ycode-ant', | ||||||
| }) | }); | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <a-config-provider |   <a-config-provider | ||||||
|     :theme="{ |     :theme="{ | ||||||
|       algorithm: [ compactAlgorithm], |       algorithm: [compactAlgorithm], | ||||||
|     }" |     }" | ||||||
|     :locale="zhCN" |     :locale="zhCN" | ||||||
|     :transformers="[legacyLogicalPropertiesTransformer]" |     :transformers="[legacyLogicalPropertiesTransformer]" | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { get } from "@/utils/request"; | import { get } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| export interface UserInfoType { | export interface UserInfoType { | ||||||
|   alias: string; |   alias: string; | ||||||
| @ -17,18 +17,18 @@ export interface UserInfoType { | |||||||
| 
 | 
 | ||||||
| interface DropListItem { | interface DropListItem { | ||||||
|   label: string; |   label: string; | ||||||
|   value: string | number; |   value: number | string; | ||||||
|   mark: string; |   mark: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const getUserInfo = () => | export const getUserInfo = () => | ||||||
|   get<UserInfoType>({ |   get<UserInfoType>({ | ||||||
|     url: "/api/home/grade", |     url: '/api/home/grade', | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| export const logout = () => get({ url: "/api/common/logout" }); | export const logout = () => get({ url: '/api/common/logout' }); | ||||||
| 
 | 
 | ||||||
| export const getProjectDrop = () => | export const getProjectDrop = () => | ||||||
|   get<DropListItem[]>({ |   get<DropListItem[]>({ | ||||||
|     url: "/api/v1/project/get-project-drop", |     url: '/api/v1/project/get-project-drop', | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { post } from "@/utils/request"; | import { post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| interface PreviewItemParams { | interface PreviewItemParams { | ||||||
|   previewId: string | number; |   previewId: number | string; | ||||||
|   filter?: string | []; |   filter?: [] | string; | ||||||
|   page?: number; |   page?: number; | ||||||
|   perPage?: number; |   perPage?: number; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,3 +1,78 @@ | |||||||
|  | <script setup> | ||||||
|  | import { computed, ref } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import Column from '@/plugins/antv-g2plot/column.vue'; | ||||||
|  | import Line from '@/plugins/antv-g2plot/line.vue'; | ||||||
|  | import { cloneDeep } from 'lodash-es'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   title: { | ||||||
|  |     type: String, | ||||||
|  |     default: '', | ||||||
|  |   }, | ||||||
|  |   chartCfg: { | ||||||
|  |     type: Object, | ||||||
|  |     default: () => ({}), | ||||||
|  |   }, | ||||||
|  |   filterConfig: { | ||||||
|  |     type: Array, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | const emit = defineEmits(['toFilt']); | ||||||
|  | 
 | ||||||
|  | const chartType = ref('line'); | ||||||
|  | const dateType = ref('day'); | ||||||
|  | const filterData = ref({}); | ||||||
|  | 
 | ||||||
|  | const rangePicker = computed(() => { | ||||||
|  |   switch (dateType.value) { | ||||||
|  |     case 'month': { | ||||||
|  |       return 'month'; | ||||||
|  |     } | ||||||
|  |     case 'week': { | ||||||
|  |       return 'week'; | ||||||
|  |     } | ||||||
|  |     default: { | ||||||
|  |       return 'date'; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const currentChart = computed(() => { | ||||||
|  |   return props.chartCfg[chartType.value]; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const toFilt = () => { | ||||||
|  |   const cloneFilter = cloneDeep(props.filterConfig); | ||||||
|  |   const filter = cloneFilter | ||||||
|  |     .filter((item) => { | ||||||
|  |       return ( | ||||||
|  |         filterData.value[item.name] !== undefined && | ||||||
|  |         filterData.value[item.name] !== null | ||||||
|  |       ); | ||||||
|  |     }) | ||||||
|  |     .map((item) => { | ||||||
|  |       return item.type === 'time' | ||||||
|  |         ? { | ||||||
|  |             name: item.name, | ||||||
|  |             type: item.type, | ||||||
|  |             start_time: filterData.value[item.name][0].format('YYYY-MM-DD'), | ||||||
|  |             end_time: filterData.value[item.name][1].format('YYYY-MM-DD'), | ||||||
|  |             date_type: dateType.value, | ||||||
|  |           } | ||||||
|  |         : { | ||||||
|  |             name: item.name, | ||||||
|  |             type: item.type, | ||||||
|  |             value: filterData.value[item.name], | ||||||
|  |           }; | ||||||
|  |     }); | ||||||
|  |   emit('toFilt', { | ||||||
|  |     filter, | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|   <div class="chart-show-box"> |   <div class="chart-show-box"> | ||||||
|     <div class="chart-name"> |     <div class="chart-name"> | ||||||
| @ -38,72 +113,6 @@ | |||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> |  | ||||||
| import { computed, ref } from "vue"; |  | ||||||
| import Line from "@/plugins/antv-g2plot/line.vue"; |  | ||||||
| import Column from "@/plugins/antv-g2plot/column.vue"; |  | ||||||
| import { cloneDeep } from "lodash-es"; |  | ||||||
| 
 |  | ||||||
| const props = defineProps({ |  | ||||||
|   title: { |  | ||||||
|     type: String, |  | ||||||
|     default: "", |  | ||||||
|   }, |  | ||||||
|   chartCfg: { |  | ||||||
|     type: Object, |  | ||||||
|     default: () => ({}), |  | ||||||
|   }, |  | ||||||
|   filterConfig: { |  | ||||||
|     type: Array, |  | ||||||
|     default: () => [], |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| const emit = defineEmits(["toFilt"]); |  | ||||||
| 
 |  | ||||||
| const chartType = ref("line"); |  | ||||||
| const dateType = ref("day"); |  | ||||||
| const filterData = ref({}); |  | ||||||
| 
 |  | ||||||
| const rangePicker = computed(() => { |  | ||||||
|   switch(dateType.value) { |  | ||||||
|     case 'week': |  | ||||||
|       return 'week'; |  | ||||||
|     case 'month': |  | ||||||
|       return 'month'; |  | ||||||
|     default: |  | ||||||
|       return 'date'; |  | ||||||
|   } |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const currentChart = computed(() => { |  | ||||||
|   return props.chartCfg[chartType.value]; |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| const toFilt = () => { |  | ||||||
|   const cloneFilter = cloneDeep(props.filterConfig); |  | ||||||
|   const filter = cloneFilter |  | ||||||
|     .filter((item) => { |  | ||||||
|       return filterData.value[item.name] !== undefined && filterData.value[item.name] !== null; |  | ||||||
|     }) |  | ||||||
|     .map((item) => { |  | ||||||
|       return item.type === 'time' ? { |  | ||||||
|         name: item.name, |  | ||||||
|         type: item.type, |  | ||||||
|         start_time: filterData.value[item.name][0].format('YYYY-MM-DD'), |  | ||||||
|         end_time: filterData.value[item.name][1].format('YYYY-MM-DD'), |  | ||||||
|         date_type: dateType.value, |  | ||||||
|       } : { |  | ||||||
|         name: item.name, |  | ||||||
|         type: item.type, |  | ||||||
|         value: filterData.value[item.name], |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|   emit('toFilt', { |  | ||||||
|     filter, |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| .chart-wrap { | .chart-wrap { | ||||||
|   padding: 20px; |   padding: 20px; | ||||||
|  | |||||||
| @ -1,3 +1,139 @@ | |||||||
|  | <script setup> | ||||||
|  | import { reactive, ref, watch } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { CloudDownloadOutlined } from '@ant-design/icons-vue'; | ||||||
|  | import { useDebounceFn } from '@vueuse/core'; | ||||||
|  | import { cloneDeep } from 'lodash-es'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   previewId: { | ||||||
|  |     type: Number, | ||||||
|  |     default: null, | ||||||
|  |   }, | ||||||
|  |   filterConfig: { | ||||||
|  |     type: Array, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|  |   columnConfig: { | ||||||
|  |     type: Array, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|  |   dataList: { | ||||||
|  |     type: Array, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|  |   total: { | ||||||
|  |     type: Number, | ||||||
|  |     default: 0, | ||||||
|  |   }, | ||||||
|  |   title: { | ||||||
|  |     type: String, | ||||||
|  |     default: '', | ||||||
|  |   }, | ||||||
|  |   isExport: { | ||||||
|  |     type: Number, | ||||||
|  |     default: 0, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const emit = defineEmits(['toFilt']); | ||||||
|  | 
 | ||||||
|  | const YCODE_BASEURL = import.meta.env.VITE_YCODE_BASEURL; | ||||||
|  | 
 | ||||||
|  | const filterData = ref({}); | ||||||
|  | 
 | ||||||
|  | const pageState = reactive({ | ||||||
|  |   page: 1, | ||||||
|  |   perPage: 20, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | watch( | ||||||
|  |   () => props.filterConfig, | ||||||
|  |   (newVal) => { | ||||||
|  |     newVal.forEach((item) => { | ||||||
|  |       // 给数值区间类型赋初始值,防止报错 | ||||||
|  |       if (item.type === 'number_range' && !filterData.value[item.name]) { | ||||||
|  |         filterData.value[item.name] = { | ||||||
|  |           min: undefined, | ||||||
|  |           max: undefined, | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  |   { immediate: true }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const filterOption = (input, option) => { | ||||||
|  |   return option.label.toLowerCase().includes(input.toLowerCase()); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const getFilter = () => { | ||||||
|  |   const cloneFilter = cloneDeep(props.filterConfig); | ||||||
|  |   const filter = cloneFilter | ||||||
|  |     .filter((item) => { | ||||||
|  |       return ( | ||||||
|  |         filterData.value[item.name] !== undefined && | ||||||
|  |         filterData.value[item.name] !== null | ||||||
|  |       ); | ||||||
|  |     }) | ||||||
|  |     .map((item) => { | ||||||
|  |       if (item.type === 'time' && filterData.value[item.name]) { | ||||||
|  |         // 日期类型的参数 | ||||||
|  |         return { | ||||||
|  |           name: item.name, | ||||||
|  |           type: item.type, | ||||||
|  |           start_time: filterData.value[item.name][0].format('YYYY-MM-DD'), | ||||||
|  |           end_time: filterData.value[item.name][1].format('YYYY-MM-DD'), | ||||||
|  |         }; | ||||||
|  |       } else if (item.type === 'date_time' && filterData.value[item.name]) { | ||||||
|  |         // 带时分的日期类型参数 | ||||||
|  |         return { | ||||||
|  |           name: item.name, | ||||||
|  |           type: item.type, | ||||||
|  |           start_time: `${filterData.value[item.name][0].format('YYYY-MM-DD HH:mm')}:00`, | ||||||
|  |           end_time: `${filterData.value[item.name][1].format('YYYY-MM-DD HH:mm')}:59`, | ||||||
|  |         }; | ||||||
|  |       } else if (item.type === 'number_range') { | ||||||
|  |         // 数值区间 | ||||||
|  |         return { | ||||||
|  |           name: item.name, | ||||||
|  |           type: item.type, | ||||||
|  |           min: filterData.value[item.name].min | ||||||
|  |             ? String(filterData.value[item.name].min) | ||||||
|  |             : '', | ||||||
|  |           max: filterData.value[item.name].max | ||||||
|  |             ? String(filterData.value[item.name].max) | ||||||
|  |             : '', | ||||||
|  |         }; | ||||||
|  |       } else { | ||||||
|  |         return { | ||||||
|  |           name: item.name, | ||||||
|  |           type: item.type, | ||||||
|  |           value: filterData.value[item.name], | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   return filter; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const getData = () => { | ||||||
|  |   emit('toFilt', { | ||||||
|  |     filter: getFilter(), | ||||||
|  |     page: pageState.page, | ||||||
|  |     perPage: pageState.perPage, | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const toFilt = useDebounceFn(() => { | ||||||
|  |   pageState.page = 1; | ||||||
|  |   getData(); | ||||||
|  | }, 500); | ||||||
|  | 
 | ||||||
|  | const pageChange = () => { | ||||||
|  |   getData(); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|   <div class="y-table-container"> |   <div class="y-table-container"> | ||||||
|     <div class="y-table-name"> |     <div class="y-table-name"> | ||||||
| @ -21,7 +157,7 @@ | |||||||
|           :filter-option="filterOption" |           :filter-option="filterOption" | ||||||
|           v-model:value="filterData[item.name]" |           v-model:value="filterData[item.name]" | ||||||
|           @change="toFilt" |           @change="toFilt" | ||||||
|         ></a-select> |         /> | ||||||
|         <!-- 输入框 --> |         <!-- 输入框 --> | ||||||
|         <a-input |         <a-input | ||||||
|           v-else-if="item.type === 'text'" |           v-else-if="item.type === 'text'" | ||||||
| @ -71,8 +207,7 @@ | |||||||
|         <a |         <a | ||||||
|           :href="`${YCODE_BASEURL}/api/v1/preview/export?preview_id=${previewId}&filter=${JSON.stringify(getFilter())}`" |           :href="`${YCODE_BASEURL}/api/v1/preview/export?preview_id=${previewId}&filter=${JSON.stringify(getFilter())}`" | ||||||
|           target="_blank" |           target="_blank" | ||||||
|           ><a-button type="primary"><CloudDownloadOutlined />导出</a-button></a |           ><a-button type="primary"><CloudDownloadOutlined />导出</a-button></a> | ||||||
|         > |  | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="y-table-content"> |     <div class="y-table-content"> | ||||||
| @ -94,8 +229,7 @@ | |||||||
|             v-else-if="column.show_type === 'link'" |             v-else-if="column.show_type === 'link'" | ||||||
|             target="_blank" |             target="_blank" | ||||||
|             :href="record[column.dataIndex]" |             :href="record[column.dataIndex]" | ||||||
|             >{{ record[column.dataIndex] }}</a |             >{{ record[column.dataIndex] }}</a> | ||||||
|           > |  | ||||||
|           <div |           <div | ||||||
|             v-else-if="column.show_type === 'richText'" |             v-else-if="column.show_type === 'richText'" | ||||||
|             v-html="record[column.dataIndex]" |             v-html="record[column.dataIndex]" | ||||||
| @ -111,136 +245,13 @@ | |||||||
|         :show-size-changer="false" |         :show-size-changer="false" | ||||||
|         size="small" |         size="small" | ||||||
|         class="pagination-box" |         class="pagination-box" | ||||||
|         :show-total="total => `共 ${total} 条`" |         :show-total="(total) => `共 ${total} 条`" | ||||||
|         @change="pageChange" |         @change="pageChange" | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> |  | ||||||
| import { reactive, ref, watch } from "vue"; |  | ||||||
| import { useDebounceFn } from "@vueuse/core"; |  | ||||||
| import { cloneDeep } from "lodash-es"; |  | ||||||
| import { CloudDownloadOutlined } from "@ant-design/icons-vue"; |  | ||||||
| 
 |  | ||||||
| const YCODE_BASEURL = import.meta.env.VITE_YCODE_BASEURL |  | ||||||
| 
 |  | ||||||
| const props = defineProps({ |  | ||||||
|   previewId: { |  | ||||||
|     type: Number, |  | ||||||
|     default: null, |  | ||||||
|   }, |  | ||||||
|   filterConfig: { |  | ||||||
|     type: Array, |  | ||||||
|     default: () => [], |  | ||||||
|   }, |  | ||||||
|   columnConfig: { |  | ||||||
|     type: Array, |  | ||||||
|     default: () => [], |  | ||||||
|   }, |  | ||||||
|   dataList: { |  | ||||||
|     type: Array, |  | ||||||
|     default: () => [], |  | ||||||
|   }, |  | ||||||
|   total: { |  | ||||||
|     type: Number, |  | ||||||
|     default: 0, |  | ||||||
|   }, |  | ||||||
|   title: { |  | ||||||
|     type: String, |  | ||||||
|     default: "", |  | ||||||
|   }, |  | ||||||
|   isExport: { |  | ||||||
|     type: Number, |  | ||||||
|     default: 0, |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| const emit = defineEmits(["toFilt"]); |  | ||||||
| 
 |  | ||||||
| const filterData = ref({}); |  | ||||||
| 
 |  | ||||||
| const pageState = reactive({ |  | ||||||
|   page: 1, |  | ||||||
|   perPage: 20, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| watch(() => props.filterConfig, (newVal) => { |  | ||||||
|   newVal.forEach((item) => { |  | ||||||
|     // 给数值区间类型赋初始值,防止报错 |  | ||||||
|     if (item.type === 'number_range' && !filterData.value[item.name]) { |  | ||||||
|       filterData.value[item.name] = { |  | ||||||
|         min: undefined, |  | ||||||
|         max: undefined, |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }, { immediate: true }); |  | ||||||
| 
 |  | ||||||
| const filterOption = (input, option) => { |  | ||||||
|   return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const getFilter = () => { |  | ||||||
|   const cloneFilter = cloneDeep(props.filterConfig); |  | ||||||
|   const filter = cloneFilter |  | ||||||
|     .filter((item) => { |  | ||||||
|       return filterData.value[item.name] !== undefined && filterData.value[item.name] !== null; |  | ||||||
|     }) |  | ||||||
|     .map((item) => { |  | ||||||
|       if (item.type === 'time' && filterData.value[item.name]) { |  | ||||||
|         // 日期类型的参数 |  | ||||||
|         return { |  | ||||||
|           name: item.name, |  | ||||||
|           type: item.type, |  | ||||||
|           start_time: filterData.value[item.name][0].format('YYYY-MM-DD'), |  | ||||||
|           end_time: filterData.value[item.name][1].format('YYYY-MM-DD'), |  | ||||||
|         }; |  | ||||||
|       } else if (item.type === 'date_time' && filterData.value[item.name]) { |  | ||||||
|         // 带时分的日期类型参数 |  | ||||||
|         return { |  | ||||||
|           name: item.name, |  | ||||||
|           type: item.type, |  | ||||||
|           start_time: filterData.value[item.name][0].format('YYYY-MM-DD HH:mm') + ':00', |  | ||||||
|           end_time: filterData.value[item.name][1].format('YYYY-MM-DD HH:mm') + ':59', |  | ||||||
|         }; |  | ||||||
|       } else if (item.type === 'number_range') { |  | ||||||
|         // 数值区间 |  | ||||||
|         return { |  | ||||||
|           name: item.name, |  | ||||||
|           type: item.type, |  | ||||||
|           min: filterData.value[item.name].min ? String(filterData.value[item.name].min) : '', |  | ||||||
|           max: filterData.value[item.name].max ? String(filterData.value[item.name].max) : '', |  | ||||||
|         }; |  | ||||||
|       } else { |  | ||||||
|         return { |  | ||||||
|           name: item.name, |  | ||||||
|           type: item.type, |  | ||||||
|           value: filterData.value[item.name], |  | ||||||
|         }; |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   return filter |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const getData = () => { |  | ||||||
|   emit("toFilt", { |  | ||||||
|     filter: getFilter(), |  | ||||||
|     page: pageState.page, |  | ||||||
|     perPage: pageState.perPage, |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const toFilt = useDebounceFn(() => { |  | ||||||
|   pageState.page = 1 |  | ||||||
|   getData(); |  | ||||||
| }, 500); |  | ||||||
| 
 |  | ||||||
| const pageChange = () => { |  | ||||||
|   getData(); |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| .y-table-name { | .y-table-name { | ||||||
|   margin-bottom: 10px; |   margin-bottom: 10px; | ||||||
|  | |||||||
| @ -1,13 +1,14 @@ | |||||||
| // @primary-bg-color: #f8f8f8; | // @primary-bg-color: #f8f8f8; | ||||||
| @import "../src/assets/styles/variable.less"; | @import '../src/assets/styles/variable.less'; | ||||||
| 
 | 
 | ||||||
| html, | html, | ||||||
| body { | body { | ||||||
|   background-color: @primary-bg-color; |   height: 100%; | ||||||
|   padding: 0; |   padding: 0; | ||||||
|   margin: 0; |   margin: 0; | ||||||
|   height: 100%; |   background-color: @primary-bg-color; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| #app { | #app { | ||||||
|   height: 100%; |   height: 100%; | ||||||
| } | } | ||||||
| @ -24,23 +25,25 @@ body { | |||||||
| 
 | 
 | ||||||
| /* 滚动条滑块 */ | /* 滚动条滑块 */ | ||||||
| ::-webkit-scrollbar-thumb { | ::-webkit-scrollbar-thumb { | ||||||
|   background-color: rgba(0, 0, 0, 0.15); |   background-color: rgb(0 0 0 / 15%); | ||||||
|   border-radius: 15px; |   border-radius: 15px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* 滚动条滑块悬停 */ | /* 滚动条滑块悬停 */ | ||||||
| ::-webkit-scrollbar-thumb:hover { | ::-webkit-scrollbar-thumb:hover { | ||||||
|   background-color: rgba(0, 0, 0, 0.25); |   background-color: rgb(0 0 0 / 25%); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .normal-container { | .normal-container { | ||||||
|   padding: 16px 24px; |   padding: 16px 24px; | ||||||
|   border-radius: 6px; |  | ||||||
|   background-color: #fff; |   background-color: #fff; | ||||||
|  |   border-radius: 6px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .mt-8 { | .mt-8 { | ||||||
|   margin-top: 8px; |   margin-top: 8px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .mt-16 { | .mt-16 { | ||||||
|   margin-top: 16px; |   margin-top: 16px; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,18 +1,23 @@ | |||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { computed, onMounted, ref } from "vue"; | import { computed, onMounted, ref } from 'vue'; | ||||||
| import Header from "./components/Header.vue"; | 
 | ||||||
| import Sider from "./components/Sider.vue"; |  | ||||||
| import { | import { | ||||||
|  |   FullscreenExitOutlined, | ||||||
|   MenuFoldOutlined, |   MenuFoldOutlined, | ||||||
|   MenuUnfoldOutlined, |   MenuUnfoldOutlined, | ||||||
|   FullscreenExitOutlined, | } from '@ant-design/icons-vue'; | ||||||
| } from "@ant-design/icons-vue"; | import { useEventListener } from '@vueuse/core'; | ||||||
| import { useEventListener } from "@vueuse/core"; | import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'; | ||||||
| import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper' | 
 | ||||||
|  | import Header from './components/Header.vue'; | ||||||
|  | import Sider from './components/Sider.vue'; | ||||||
| 
 | 
 | ||||||
| const __POWERED_BY_QIANKUN__ = computed(() => { | const __POWERED_BY_QIANKUN__ = computed(() => { | ||||||
|   return qiankunWindow.__POWERED_BY_QIANKUN__ || window?.proxy?.__POWERED_BY_QIANKUN__ |   return ( | ||||||
| }) |     qiankunWindow.__POWERED_BY_QIANKUN__ || | ||||||
|  |     window?.proxy?.__POWERED_BY_QIANKUN__ | ||||||
|  |   ); | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| // const userInfoStore = useUserInfoStore(); | // const userInfoStore = useUserInfoStore(); | ||||||
| const isCollapsed = ref(false); | const isCollapsed = ref(false); | ||||||
| @ -23,7 +28,7 @@ onMounted(() => { | |||||||
|   // userInfoStore.fetchUserInfo(); |   // userInfoStore.fetchUserInfo(); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| useEventListener(window, "fullscreenchange", () => { | useEventListener(window, 'fullscreenchange', () => { | ||||||
|   isFullscreen.value = !!document.fullscreenElement; |   isFullscreen.value = !!document.fullscreenElement; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -43,7 +48,7 @@ const handleExitFullscreen = () => { | |||||||
|       class="left-aside" |       class="left-aside" | ||||||
|       :class="{ 'left-aside-collapsed': isCollapsed }" |       :class="{ 'left-aside-collapsed': isCollapsed }" | ||||||
|     > |     > | ||||||
|       <Sider :inlineCollapsed="isCollapsed" /> |       <Sider :inline-collapsed="isCollapsed" /> | ||||||
|       <div class="collapsed-icon"> |       <div class="collapsed-icon"> | ||||||
|         <component |         <component | ||||||
|           :is="isCollapsed ? MenuUnfoldOutlined : MenuFoldOutlined" |           :is="isCollapsed ? MenuUnfoldOutlined : MenuFoldOutlined" | ||||||
| @ -60,7 +65,7 @@ const handleExitFullscreen = () => { | |||||||
|       ref="container" |       ref="container" | ||||||
|     > |     > | ||||||
|       <header class="header"> |       <header class="header"> | ||||||
|         <Header @requestFullscreen="handleFullscreen" /> |         <Header @request-fullscreen="handleFullscreen" /> | ||||||
|       </header> |       </header> | ||||||
|       <div class="i-container"> |       <div class="i-container"> | ||||||
|         <router-view /> |         <router-view /> | ||||||
| @ -127,8 +132,8 @@ const handleExitFullscreen = () => { | |||||||
|     height: 100%; |     height: 100%; | ||||||
|   } |   } | ||||||
|   :deep( |   :deep( | ||||||
|       :where(.css-dev-only-do-not-override-1hsjdkk).ant-menu-inline-collapsed |     :where(.css-dev-only-do-not-override-1hsjdkk).ant-menu-inline-collapsed | ||||||
|     ), |   ), | ||||||
|   .left-aside-collapsed { |   .left-aside-collapsed { | ||||||
|     width: @aside-width-collapsed; |     width: @aside-width-collapsed; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,37 +1,40 @@ | |||||||
| import { createApp } from "vue"; | import { createApp } from 'vue'; | ||||||
| import { createPinia } from "pinia"; | import VueGridLayout from 'vue-grid-layout'; // 引入layout
 | ||||||
| import App from "./App.vue"; | 
 | ||||||
| import { createProjectRouter } from "./router"; | import { createPinia } from 'pinia'; | ||||||
| import "./global.less"; |  | ||||||
| import VueGridLayout from "vue-grid-layout"; // 引入layout
 |  | ||||||
| import { | import { | ||||||
|   renderWithQiankun, |  | ||||||
|   qiankunWindow, |   qiankunWindow, | ||||||
| } from "vite-plugin-qiankun/dist/helper"; |   renderWithQiankun, | ||||||
|  | } from 'vite-plugin-qiankun/dist/helper'; | ||||||
|  | 
 | ||||||
|  | import App from './App.vue'; | ||||||
|  | import { createProjectRouter } from './router'; | ||||||
|  | 
 | ||||||
|  | import './global.less'; | ||||||
| 
 | 
 | ||||||
| let app; | let app; | ||||||
| function render(props: Object = {}) { | function render(props: object = {}) { | ||||||
|   app = createApp(App); |   app = createApp(App); | ||||||
|   setStyleSheet(props.styles); |   setStyleSheet(props.styles); | ||||||
|   const router = createProjectRouter(props.base); |   const router = createProjectRouter(props.base); | ||||||
|   app.use(router); |   app.use(router); | ||||||
|   app.use(VueGridLayout); |   app.use(VueGridLayout); | ||||||
|   app.use(createPinia()); |   app.use(createPinia()); | ||||||
|   app.mount("#y-code-app"); |   app.mount('#y-code-app'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function setStyleSheet(styles: Object = {}) { | function setStyleSheet(styles: object = {}) { | ||||||
|   const styleEle = document.createElement("style"); |   const styleEle = document.createElement('style'); | ||||||
|   styleEle.type = "text/css"; |   styleEle.type = 'text/css'; | ||||||
|   styleEle.innerHTML = ` |   styleEle.innerHTML = ` | ||||||
|   :root { |   :root { | ||||||
|     --primary-color: ${styles.primaryColor || "#1677ff"}; |     --primary-color: ${styles.primaryColor || '#1677ff'}; | ||||||
|     --primary-light-color: ${styles.primaryLightColor || "#4096ff"}; |     --primary-light-color: ${styles.primaryLightColor || '#4096ff'}; | ||||||
|     --table-head-bg-color: ${styles.tableHeadBgColor || "#fafafa"}; |     --table-head-bg-color: ${styles.tableHeadBgColor || '#fafafa'}; | ||||||
|     --table-head-font-color: ${styles.tableHeadFontColor || "#191919"}; |     --table-head-font-color: ${styles.tableHeadFontColor || '#191919'}; | ||||||
|   } |   } | ||||||
|   `;
 |   `;
 | ||||||
|   document.head.appendChild(styleEle); |   document.head.append(styleEle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const __POWERED_BY_QIANKUN__ = | const __POWERED_BY_QIANKUN__ = | ||||||
| @ -41,16 +44,16 @@ const __POWERED_BY_QIANKUN__ = | |||||||
| if (__POWERED_BY_QIANKUN__) { | if (__POWERED_BY_QIANKUN__) { | ||||||
|   renderWithQiankun({ |   renderWithQiankun({ | ||||||
|     bootstrap() { |     bootstrap() { | ||||||
|       console.log("bootstrap"); |       console.log('bootstrap'); | ||||||
|       return Promise.resolve(); |       return Promise.resolve(); | ||||||
|     }, |     }, | ||||||
|     mount(props) { |     mount(props) { | ||||||
|       console.log("mount"); |       console.log('mount'); | ||||||
|       render(props); |       render(props); | ||||||
|       return Promise.resolve(); |       return Promise.resolve(); | ||||||
|     }, |     }, | ||||||
|     unmount() { |     unmount() { | ||||||
|       console.log("unmount"); |       console.log('unmount'); | ||||||
|       if (app) { |       if (app) { | ||||||
|         app.unmount(); |         app.unmount(); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -1,16 +1,13 @@ | |||||||
| <template> |  | ||||||
|   <div :class="className" :style="style" ref="container"></div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script setup> | <script setup> | ||||||
| import { Column } from "@antv/g2plot"; | import { Column } from '@antv/g2plot'; | ||||||
|  | 
 | ||||||
| // hooks | // hooks | ||||||
| import useChart from "./useChart"; | import useChart from './useChart'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   className: { |   className: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: "", |     default: '', | ||||||
|   }, |   }, | ||||||
|   style: { |   style: { | ||||||
|     type: Object, |     type: Object, | ||||||
| @ -24,3 +21,7 @@ const props = defineProps({ | |||||||
| 
 | 
 | ||||||
| const { container } = useChart(Column, props); | const { container } = useChart(Column, props); | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div :class="className" :style="style" ref="container"></div> | ||||||
|  | </template> | ||||||
|  | |||||||
| @ -1,17 +1,13 @@ | |||||||
| <template> |  | ||||||
|   <div :class="className" :style="style" ref="container"></div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script setup> | <script setup> | ||||||
|  | import { Line } from '@antv/g2plot'; | ||||||
| 
 | 
 | ||||||
| import { Line } from "@antv/g2plot"; |  | ||||||
| // hooks | // hooks | ||||||
| import useChart from "./useChart"; | import useChart from './useChart'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   className: { |   className: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: "", |     default: '', | ||||||
|   }, |   }, | ||||||
|   style: { |   style: { | ||||||
|     type: Object, |     type: Object, | ||||||
| @ -25,3 +21,7 @@ const props = defineProps({ | |||||||
| 
 | 
 | ||||||
| const { container } = useChart(Line, props); | const { container } = useChart(Line, props); | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div :class="className" :style="style" ref="container"></div> | ||||||
|  | </template> | ||||||
|  | |||||||
| @ -1,16 +1,13 @@ | |||||||
| <template> |  | ||||||
|   <div :class="className" :style="style" ref="container"></div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script setup> | <script setup> | ||||||
| import { Pie } from "@antv/g2plot"; | import { Pie } from '@antv/g2plot'; | ||||||
|  | 
 | ||||||
| // hooks | // hooks | ||||||
| import useChart from "./useChart"; | import useChart from './useChart'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   className: { |   className: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: "", |     default: '', | ||||||
|   }, |   }, | ||||||
|   style: { |   style: { | ||||||
|     type: Object, |     type: Object, | ||||||
| @ -24,3 +21,7 @@ const props = defineProps({ | |||||||
| 
 | 
 | ||||||
| const { container } = useChart(Pie, props); | const { container } = useChart(Pie, props); | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div :class="className" :style="style" ref="container"></div> | ||||||
|  | </template> | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| import { onBeforeUnmount, onMounted, ref, watch } from "vue"; | import { onBeforeUnmount, onMounted, ref, watch } from 'vue'; | ||||||
| import { cloneDeep } from "lodash-es"; | 
 | ||||||
|  | import { cloneDeep } from 'lodash-es'; | ||||||
| 
 | 
 | ||||||
| export default function useChart(ChartClass, props) { | export default function useChart(ChartClass, props) { | ||||||
|   const chart = ref(null); // 表格实例
 |   const chart = ref(null); // 表格实例
 | ||||||
| @ -35,12 +36,12 @@ export default function useChart(ChartClass, props) { | |||||||
|         onEvent(chartInstance, event); |         onEvent(chartInstance, event); | ||||||
|       } |       } | ||||||
|     }; |     }; | ||||||
|     chartInstance.on("*", handler); |     chartInstance.on('*', handler); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   onBeforeUnmount(() => { |   onBeforeUnmount(() => { | ||||||
|     chart.value.destroy(); |     chart.value.destroy(); | ||||||
|     chart.value.off("*", handler); |     chart.value.off('*', handler); | ||||||
|     chart.value = undefined; |     chart.value = undefined; | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -54,32 +55,32 @@ export default function useChart(ChartClass, props) { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       deep: true, |       deep: true, | ||||||
|     } |     }, | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   const toDataURL = (type = "image/png", encoderOptions) => { |   const toDataURL = (type = 'image/png', encoderOptions) => { | ||||||
|     return chart.value?.chart.canvas.cfg.el.toDataURL(type, encoderOptions); |     return chart.value?.chart.canvas.cfg.el.toDataURL(type, encoderOptions); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const downloadImage = ( |   const downloadImage = ( | ||||||
|     name = "download", |     name = 'download', | ||||||
|     type = "image/png", |     type = 'image/png', | ||||||
|     encoderOptions |     encoderOptions, | ||||||
|   ) => { |   ) => { | ||||||
|     let imageName = name; |     let imageName = name; | ||||||
|     if (name.indexOf(".") === -1) { |     if (!name.includes('.')) { | ||||||
|       imageName = `${name}.${type.split("/")[1]}`; |       imageName = `${name}.${type.split('/')[1]}`; | ||||||
|     } |     } | ||||||
|     const base64 = chart.value?.chart.canvas.cfg.el.toDataURL( |     const base64 = chart.value?.chart.canvas.cfg.el.toDataURL( | ||||||
|       type, |       type, | ||||||
|       encoderOptions |       encoderOptions, | ||||||
|     ); |     ); | ||||||
|     let a = document.createElement("a"); |     let a = document.createElement('a'); | ||||||
|     a.href = base64; |     a.href = base64; | ||||||
|     a.download = imageName; |     a.download = imageName; | ||||||
|     document.body.appendChild(a); |     document.body.append(a); | ||||||
|     a.click(); |     a.click(); | ||||||
|     document.body.removeChild(a); |     a.remove(); | ||||||
|     a = null; |     a = null; | ||||||
|     return imageName; |     return imageName; | ||||||
|   }; |   }; | ||||||
|  | |||||||
| @ -1,16 +1,20 @@ | |||||||
| import { createRouter, createWebHistory, type Router } from "vue-router"; | import type { Router } from 'vue-router'; | ||||||
| import { titleGuard } from "./guards"; |  | ||||||
| import routeList from "./routes"; |  | ||||||
| import { qiankunWindow } from "vite-plugin-qiankun/dist/helper"; |  | ||||||
| 
 | 
 | ||||||
| let router: Router | null = null; | import { createRouter, createWebHistory } from 'vue-router'; | ||||||
| export const createProjectRouter = (base = "") => { | 
 | ||||||
|  | import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'; | ||||||
|  | 
 | ||||||
|  | import { titleGuard } from './guards'; | ||||||
|  | import routeList from './routes'; | ||||||
|  | 
 | ||||||
|  | let router: null | Router = null; | ||||||
|  | export const createProjectRouter = (base = '') => { | ||||||
|   const __POWERED_BY_QIANKUN__ = |   const __POWERED_BY_QIANKUN__ = | ||||||
|     qiankunWindow?.__POWERED_BY_QIANKUN__ || |     qiankunWindow?.__POWERED_BY_QIANKUN__ || | ||||||
|     window.proxy?.__POWERED_BY_QIANKUN__; |     window.proxy?.__POWERED_BY_QIANKUN__; | ||||||
|   router = createRouter({ |   router = createRouter({ | ||||||
|     history: createWebHistory( |     history: createWebHistory( | ||||||
|       base || (__POWERED_BY_QIANKUN__ ? "/y-code-app/" : "") |       base || (__POWERED_BY_QIANKUN__ ? '/y-code-app/' : ''), | ||||||
|     ), |     ), | ||||||
|     routes: routeList, |     routes: routeList, | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -1,11 +1,13 @@ | |||||||
| import Layout from "@/layout/index.vue"; | import type { RendererElement, RendererNode, VNode } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { h } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import Layout from '@/layout/index.vue'; | ||||||
| import { | import { | ||||||
|   HomeOutlined, |  | ||||||
|   BarChartOutlined, |  | ||||||
|   AppstoreOutlined, |   AppstoreOutlined, | ||||||
| } from "@ant-design/icons-vue"; |   BarChartOutlined, | ||||||
| import { h } from "vue"; |   HomeOutlined, | ||||||
| import type { VNode, RendererNode, RendererElement } from "vue"; | } from '@ant-design/icons-vue'; | ||||||
| 
 | 
 | ||||||
| export interface RouteType { | export interface RouteType { | ||||||
|   path: string; |   path: string; | ||||||
| @ -26,85 +28,85 @@ export interface RouteType { | |||||||
| 
 | 
 | ||||||
| const routeList: RouteType[] = [ | const routeList: RouteType[] = [ | ||||||
|   { |   { | ||||||
|     path: "/", |     path: '/', | ||||||
|     name: "layout", |     name: 'layout', | ||||||
|     component: Layout, |     component: Layout, | ||||||
|     meta: { title: "首页" }, |     meta: { title: '首页' }, | ||||||
|     children: [ |     children: [ | ||||||
|       { |       { | ||||||
|         path: "", |         path: '', | ||||||
|         name: "-", |         name: '-', | ||||||
|         meta: {}, |         meta: {}, | ||||||
|         children: [], |         children: [], | ||||||
|         redirect: "/config-manage/project-cfg", |         redirect: '/config-manage/project-cfg', | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         path: "/config-manage", |         path: '/config-manage', | ||||||
|         name: "config-manage", |         name: 'config-manage', | ||||||
|         isMenu: true, |         isMenu: true, | ||||||
|         meta: { title: "配置管理" }, |         meta: { title: '配置管理' }, | ||||||
|         icon: () => h(HomeOutlined), |         icon: () => h(HomeOutlined), | ||||||
|         children: [ |         children: [ | ||||||
|           { |           { | ||||||
|             path: "project-cfg", |             path: 'project-cfg', | ||||||
|             name: "project-cfg", |             name: 'project-cfg', | ||||||
|             component: () => |             component: () => | ||||||
|               import("@/views/config-manage/project-cfg/index.vue"), |               import('@/views/config-manage/project-cfg/index.vue'), | ||||||
|             meta: { title: "项目配置" }, |             meta: { title: '项目配置' }, | ||||||
|             isMenu: true, |             isMenu: true, | ||||||
|             children: [], |             children: [], | ||||||
|           }, |           }, | ||||||
|           { |           { | ||||||
|             path: "module-cfg", |             path: 'module-cfg', | ||||||
|             name: "module-cfg", |             name: 'module-cfg', | ||||||
|             component: () => |             component: () => | ||||||
|               import("@/views/config-manage/module-cfg/index.vue"), |               import('@/views/config-manage/module-cfg/index.vue'), | ||||||
|             meta: { title: "数据来源配置" }, |             meta: { title: '数据来源配置' }, | ||||||
|             isMenu: true, |             isMenu: true, | ||||||
|             children: [], |             children: [], | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         path: "/view-all-manage", |         path: '/view-all-manage', | ||||||
|         name: "view-all-manage", |         name: 'view-all-manage', | ||||||
|         isMenu: true, |         isMenu: true, | ||||||
|         meta: { title: "视图管理" }, |         meta: { title: '视图管理' }, | ||||||
|         icon: () => h(BarChartOutlined), |         icon: () => h(BarChartOutlined), | ||||||
|         children: [ |         children: [ | ||||||
|           { |           { | ||||||
|             path: "view-list", |             path: 'view-list', | ||||||
|             name: "view-list", |             name: 'view-list', | ||||||
|             component: () => |             component: () => | ||||||
|               import("@/views/view-all-manage/view-list/index.vue"), |               import('@/views/view-all-manage/view-list/index.vue'), | ||||||
|             meta: { title: "视图列表" }, |             meta: { title: '视图列表' }, | ||||||
|             isMenu: true, |             isMenu: true, | ||||||
|             children: [], |             children: [], | ||||||
|           }, |           }, | ||||||
|           { |           { | ||||||
|             path: "create-view", |             path: 'create-view', | ||||||
|             name: "create-view", |             name: 'create-view', | ||||||
|             component: () => |             component: () => | ||||||
|               import("@/views/view-all-manage/create-view/index.vue"), |               import('@/views/view-all-manage/create-view/index.vue'), | ||||||
|             meta: { title: "创建视图" }, |             meta: { title: '创建视图' }, | ||||||
|             isMenu: true, |             isMenu: true, | ||||||
|             children: [], |             children: [], | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         path: "/page-show-info", |         path: '/page-show-info', | ||||||
|         name: "page-show-info", |         name: 'page-show-info', | ||||||
|         isMenu: true, |         isMenu: true, | ||||||
|         meta: { title: "视图预览" }, |         meta: { title: '视图预览' }, | ||||||
|         icon: () => h(AppstoreOutlined), |         icon: () => h(AppstoreOutlined), | ||||||
|         children: [ |         children: [ | ||||||
|           { |           { | ||||||
|             path: "page-info", |             path: 'page-info', | ||||||
|             name: "page-info", |             name: 'page-info', | ||||||
|             component: () => |             component: () => | ||||||
|               import("@/views/page-show-info/page-info/index.vue"), |               import('@/views/page-show-info/page-info/index.vue'), | ||||||
|             meta: { title: "项目报表" }, |             meta: { title: '项目报表' }, | ||||||
|             isMenu: true, |             isMenu: true, | ||||||
|             children: [], |             children: [], | ||||||
|           }, |           }, | ||||||
|  | |||||||
| @ -1,8 +1,10 @@ | |||||||
| import { readonly, ref } from 'vue'; |  | ||||||
| import { defineStore } from 'pinia'; |  | ||||||
| import { getUserInfo } from '@/api/common'; |  | ||||||
| import type { UserInfoType } from '@/api/common'; | import type { UserInfoType } from '@/api/common'; | ||||||
| 
 | 
 | ||||||
|  | import { readonly, ref } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { getUserInfo } from '@/api/common'; | ||||||
|  | import { defineStore } from 'pinia'; | ||||||
|  | 
 | ||||||
| export const useUserInfoStore = defineStore('userInfoStore', () => { | export const useUserInfoStore = defineStore('userInfoStore', () => { | ||||||
|   const userInfo = ref<UserInfoType>(); |   const userInfo = ref<UserInfoType>(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,26 +1,27 @@ | |||||||
| import axios, { AxiosError } from 'axios'; |  | ||||||
| import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; | import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; | ||||||
|  | 
 | ||||||
| import { message } from 'ant-design-vue'; | import { message } from 'ant-design-vue'; | ||||||
|  | import axios, { AxiosError } from 'axios'; | ||||||
| 
 | 
 | ||||||
| export interface ResopnseType<T> { | export interface ResopnseType<T> { | ||||||
|   reason: string |   reason: string; | ||||||
|   message: string |   message: string; | ||||||
|   data: T |   data: T; | ||||||
|   ts: string |   ts: string; | ||||||
| } | } | ||||||
| // export const YCODE_BASEURL: string = import.meta.env.VITE_YCODE_BASEURL;
 | // export const YCODE_BASEURL: string = import.meta.env.VITE_YCODE_BASEURL;
 | ||||||
| 
 | 
 | ||||||
| // https://custom-chart-pre-api.shiyue.com
 | // https://custom-chart-pre-api.shiyue.com
 | ||||||
| 
 | 
 | ||||||
| export const YCODE_BASEURL: string = 'https://custom-chart-pre-api.shiyue.com' | export const YCODE_BASEURL: string = 'https://custom-chart-pre-api.shiyue.com'; | ||||||
| 
 | 
 | ||||||
| const requestType  = { | const requestType = { | ||||||
|   base: YCODE_BASEURL, |   base: YCODE_BASEURL, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const baseAxios: AxiosInstance = axios.create({ | const baseAxios: AxiosInstance = axios.create({ | ||||||
|   baseURL: '', |   baseURL: '', | ||||||
|   timeout: 100000, |   timeout: 100_000, | ||||||
|   withCredentials: true, |   withCredentials: true, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -28,26 +29,30 @@ const errorHandle = (error: AxiosError) => { | |||||||
|   if (error.response) { |   if (error.response) { | ||||||
|     const status = error.response?.status; |     const status = error.response?.status; | ||||||
|     switch (status) { |     switch (status) { | ||||||
|       case 401: |       case 401: { | ||||||
|         message.warning('请先登录'); |         message.warning('请先登录'); | ||||||
|         window.location.href = `${YCODE_BASEURL}/login?redirect=${encodeURIComponent(window.location.href)}`; |         window.location.href = `${YCODE_BASEURL}/login?redirect=${encodeURIComponent(window.location.href)}`; | ||||||
|         break; |         break; | ||||||
|       case 403: |       } | ||||||
|  |       case 403: { | ||||||
|         message.warning('权限不足'); |         message.warning('权限不足'); | ||||||
|         break; |         break; | ||||||
|       case 500: |       } | ||||||
|  |       case 500: { | ||||||
|         message.warning('服务器出错了……  (>_<)'); |         message.warning('服务器出错了……  (>_<)'); | ||||||
|         break; |         break; | ||||||
|       default: |       } | ||||||
|  |       default: { | ||||||
|         message.warning('服务器出错了……  (>_<)'); |         message.warning('服务器出错了……  (>_<)'); | ||||||
|         break; |         break; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     return Promise.reject(error); |     return Promise.reject(error); | ||||||
|   } |   } | ||||||
|   message.error(error.message); |   message.error(error.message); | ||||||
|   return Promise.reject(error); |   return Promise.reject(error); | ||||||
| }; | }; | ||||||
| //响应拦截器
 | // 响应拦截器
 | ||||||
| baseAxios.interceptors.response.use((response: AxiosResponse) => { | baseAxios.interceptors.response.use((response: AxiosResponse) => { | ||||||
|   const { data, status } = response; |   const { data, status } = response; | ||||||
| 
 | 
 | ||||||
| @ -64,7 +69,9 @@ baseAxios.interceptors.response.use((response: AxiosResponse) => { | |||||||
|   } |   } | ||||||
| }, errorHandle); | }, errorHandle); | ||||||
| 
 | 
 | ||||||
| type RequestConfig =  Omit<AxiosRequestConfig, 'baseURL'> & { baseURL?: keyof typeof requestType } | type RequestConfig = Omit<AxiosRequestConfig, 'baseURL'> & { | ||||||
|  |   baseURL?: keyof typeof requestType; | ||||||
|  | }; | ||||||
| const request = <T = any>(config: RequestConfig) => { | const request = <T = any>(config: RequestConfig) => { | ||||||
|   const host = requestType[config.baseURL || 'base']; |   const host = requestType[config.baseURL || 'base']; | ||||||
|   return new Promise<T>((resolve, reject) => { |   return new Promise<T>((resolve, reject) => { | ||||||
| @ -73,8 +80,8 @@ const request = <T = any>(config: RequestConfig) => { | |||||||
|       .then((res: T) => { |       .then((res: T) => { | ||||||
|         resolve(res); |         resolve(res); | ||||||
|       }) |       }) | ||||||
|       .catch((err: unknown) => { |       .catch((error: unknown) => { | ||||||
|         reject(err); |         reject(error); | ||||||
|       }); |       }); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -101,6 +108,7 @@ const put = <T = any>(config?: RequestConfig) => | |||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| const del = <T = any>(config?: { url: string }) => request<ResopnseType<T>>({ ...config, method: 'DELETE' }); | const del = <T = any>(config?: { url: string }) => | ||||||
|  |   request<ResopnseType<T>>({ ...config, method: 'DELETE' }); | ||||||
| 
 | 
 | ||||||
| export { get, post, del, put, request }; | export { del, get, post, put, request }; | ||||||
|  | |||||||
| @ -1,3 +1,121 @@ | |||||||
|  | <script setup> | ||||||
|  | import { ref, watch } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { getDbTableSelect } from '@/views/config-manage/module-cfg/service'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   open: { | ||||||
|  |     type: Boolean, | ||||||
|  |     default: false, | ||||||
|  |   }, | ||||||
|  |   type: { | ||||||
|  |     type: String, | ||||||
|  |     default: 'add', | ||||||
|  |   }, | ||||||
|  |   data: { | ||||||
|  |     type: Object, | ||||||
|  |     default: () => ({}), | ||||||
|  |   }, | ||||||
|  |   projectSelect: { | ||||||
|  |     type: Array, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const emit = defineEmits(['ok']); | ||||||
|  | const formRules = ref({ | ||||||
|  |   modular_name: [ | ||||||
|  |     { required: true, message: '请输入数据来源', trigger: 'submit' }, | ||||||
|  |   ], | ||||||
|  |   original_type: [{ required: true, message: '请选择', trigger: 'submit' }], | ||||||
|  |   original_sql: [{ required: true, message: '请输入', trigger: 'submit' }], | ||||||
|  |   table: [{ required: true, message: '请选择', trigger: 'submit' }], | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const tableTypes = ref([]); | ||||||
|  | const formRef = ref(); | ||||||
|  | const formData = ref({ | ||||||
|  |   project_id: undefined, | ||||||
|  |   modular_name: undefined, | ||||||
|  |   is_show: 0, | ||||||
|  |   original_type: 1, // 1 - 自定义,2 - 指定表 | ||||||
|  |   original_sql: undefined, | ||||||
|  |   table: undefined, | ||||||
|  |   is_other_database: 0, | ||||||
|  |   drive_type: 1, | ||||||
|  |   database_address: undefined, | ||||||
|  |   database_port: undefined, | ||||||
|  |   database_name: undefined, | ||||||
|  |   database_username: undefined, | ||||||
|  |   database_password: undefined, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | watch( | ||||||
|  |   () => props.data, | ||||||
|  |   (newVal) => { | ||||||
|  |     if (props.type === 'add') { | ||||||
|  |       resetFormData(); | ||||||
|  |     } else { | ||||||
|  |       formData.value = { | ||||||
|  |         modular_id: newVal.modular_id, | ||||||
|  |         project_id: newVal.project_id, | ||||||
|  |         modular_name: newVal.modular_name, | ||||||
|  |         is_show: newVal.is_show, | ||||||
|  |         original_type: newVal.original_type, | ||||||
|  |         original_sql: newVal.original_sql, | ||||||
|  |         table: newVal.table, | ||||||
|  |         drive_type: newVal.drive_type, | ||||||
|  |         is_other_database: newVal.is_other_database, | ||||||
|  |         database_address: newVal.database_address, | ||||||
|  |         database_port: newVal.database_port, | ||||||
|  |         database_name: newVal.database_name, | ||||||
|  |         database_username: newVal.database_username, | ||||||
|  |         database_password: newVal.database_password, | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const toGetDbTable = () => { | ||||||
|  |   getDbTableSelect({ projectId: formData.value.project_id }).then((res) => { | ||||||
|  |     tableTypes.value = res.data; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const isOtherChange = (val) => { | ||||||
|  |   formData.value.drive_type = val ? 1 : undefined; | ||||||
|  |   formData.value.database_address = undefined; | ||||||
|  |   formData.value.database_port = undefined; | ||||||
|  |   formData.value.database_name = undefined; | ||||||
|  |   formData.value.database_username = undefined; | ||||||
|  |   formData.value.database_password = undefined; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const resetFormData = () => { | ||||||
|  |   formData.value = { | ||||||
|  |     project_id: undefined, | ||||||
|  |     modular_name: undefined, | ||||||
|  |     is_show: 0, | ||||||
|  |     original_type: 1, // 1 - 自定义,2 - 指定表 | ||||||
|  |     original_sql: undefined, | ||||||
|  |     table: undefined, | ||||||
|  |     is_other_database: 0, | ||||||
|  |     drive_type: undefined, | ||||||
|  |     database_address: undefined, | ||||||
|  |     database_port: undefined, | ||||||
|  |     database_name: undefined, | ||||||
|  |     database_username: undefined, | ||||||
|  |     database_password: undefined, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleOk = () => { | ||||||
|  |   formRef.value.validate().then(() => { | ||||||
|  |     emit('ok', formData.value); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|   <a-modal :open="open" @ok="handleOk"> |   <a-modal :open="open" @ok="handleOk"> | ||||||
|     <a-form |     <a-form | ||||||
| @ -24,8 +142,8 @@ | |||||||
|       <a-form-item label="展示状态" name="is_show"> |       <a-form-item label="展示状态" name="is_show"> | ||||||
|         <a-switch |         <a-switch | ||||||
|           v-model:checked="formData.is_show" |           v-model:checked="formData.is_show" | ||||||
|           :checkedValue="1" |           :checked-value="1" | ||||||
|           :unCheckedValue="0" |           :un-checked-value="0" | ||||||
|         /> |         /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item label="数据源类型" name="original_type"> |       <a-form-item label="数据源类型" name="original_type"> | ||||||
| @ -58,8 +176,8 @@ | |||||||
|       <a-form-item label="数据库特殊配置" name="is_other_database"> |       <a-form-item label="数据库特殊配置" name="is_other_database"> | ||||||
|         <a-switch |         <a-switch | ||||||
|           v-model:checked="formData.is_other_database" |           v-model:checked="formData.is_other_database" | ||||||
|           :checkedValue="1" |           :checked-value="1" | ||||||
|           :unCheckedValue="0" |           :un-checked-value="0" | ||||||
|           @change="isOtherChange" |           @change="isOtherChange" | ||||||
|         /> |         /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
| @ -104,124 +222,6 @@ | |||||||
|           </a-space> |           </a-space> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </template> |       </template> | ||||||
|        |  | ||||||
|     </a-form> |     </a-form> | ||||||
|   </a-modal> |   </a-modal> | ||||||
| </template> | </template> | ||||||
| 
 |  | ||||||
| <script setup> |  | ||||||
| import { ref, watch } from "vue"; |  | ||||||
| import { getDbTableSelect } from "@/views/config-manage/module-cfg/service"; |  | ||||||
| 
 |  | ||||||
| const props = defineProps({ |  | ||||||
|   open: { |  | ||||||
|     type: Boolean, |  | ||||||
|     default: false, |  | ||||||
|   }, |  | ||||||
|   type: { |  | ||||||
|     type: String, |  | ||||||
|     default: "add", |  | ||||||
|   }, |  | ||||||
|   data: { |  | ||||||
|     type: Object, |  | ||||||
|     default: () => ({}), |  | ||||||
|   }, |  | ||||||
|   projectSelect: { |  | ||||||
|     type: Array, |  | ||||||
|     default: () => [], |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const emit = defineEmits(["ok"]); |  | ||||||
| const formRules = ref({ |  | ||||||
|   modular_name: [ |  | ||||||
|     { required: true, message: "请输入数据来源", trigger: "submit" }, |  | ||||||
|   ], |  | ||||||
|   original_type: [{ required: true, message: "请选择", trigger: "submit" }], |  | ||||||
|   original_sql: [{ required: true, message: "请输入", trigger: "submit" }], |  | ||||||
|   table: [{ required: true, message: "请选择", trigger: "submit" }], |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const tableTypes = ref([]); |  | ||||||
| const formRef = ref(); |  | ||||||
| const formData = ref({ |  | ||||||
|   project_id: undefined, |  | ||||||
|   modular_name: undefined, |  | ||||||
|   is_show: 0, |  | ||||||
|   original_type: 1, // 1 - 自定义,2 - 指定表 |  | ||||||
|   original_sql: undefined, |  | ||||||
|   table: undefined, |  | ||||||
|   is_other_database: 0, |  | ||||||
|   drive_type: 1, |  | ||||||
|   database_address: undefined, |  | ||||||
|   database_port: undefined, |  | ||||||
|   database_name: undefined, |  | ||||||
|   database_username: undefined, |  | ||||||
|   database_password: undefined, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| watch( |  | ||||||
|   () => props.data, |  | ||||||
|   (newVal) => { |  | ||||||
|     if (props.type === "add") { |  | ||||||
|       resetFormData(); |  | ||||||
|     } else { |  | ||||||
|       formData.value = { |  | ||||||
|         modular_id: newVal.modular_id, |  | ||||||
|         project_id: newVal.project_id, |  | ||||||
|         modular_name: newVal.modular_name, |  | ||||||
|         is_show: newVal.is_show, |  | ||||||
|         original_type: newVal.original_type, |  | ||||||
|         original_sql: newVal.original_sql, |  | ||||||
|         table: newVal.table, |  | ||||||
|         drive_type: newVal.drive_type, |  | ||||||
|         is_other_database: newVal.is_other_database, |  | ||||||
|         database_address: newVal.database_address, |  | ||||||
|         database_port: newVal.database_port, |  | ||||||
|         database_name: newVal.database_name, |  | ||||||
|         database_username: newVal.database_username, |  | ||||||
|         database_password: newVal.database_password, |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| const toGetDbTable = () => { |  | ||||||
|   getDbTableSelect({ projectId: formData.value.project_id }).then((res) => { |  | ||||||
|     tableTypes.value = res.data; |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const isOtherChange = (val) => { |  | ||||||
|   formData.value.drive_type = val ? 1 : undefined |  | ||||||
|   formData.value.database_address = undefined |  | ||||||
|   formData.value.database_port = undefined |  | ||||||
|   formData.value.database_name = undefined |  | ||||||
|   formData.value.database_username = undefined |  | ||||||
|   formData.value.database_password = undefined |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const resetFormData = () => { |  | ||||||
|   formData.value = { |  | ||||||
|     project_id: undefined, |  | ||||||
|     modular_name: undefined, |  | ||||||
|     is_show: 0, |  | ||||||
|     original_type: 1, // 1 - 自定义,2 - 指定表 |  | ||||||
|     original_sql: undefined, |  | ||||||
|     table: undefined, |  | ||||||
|     is_other_database: 0, |  | ||||||
|     drive_type: undefined, |  | ||||||
|     database_address: undefined, |  | ||||||
|     database_port: undefined, |  | ||||||
|     database_name: undefined, |  | ||||||
|     database_username: undefined, |  | ||||||
|     database_password: undefined, |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const handleOk = () => { |  | ||||||
|   formRef.value.validate().then(() => { |  | ||||||
|     emit("ok", formData.value); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
|  | |||||||
| @ -1,3 +1,223 @@ | |||||||
|  | <script setup> | ||||||
|  | import { onMounted, reactive, ref, watch } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { | ||||||
|  |   originalTypes, | ||||||
|  |   showTypeOpts, | ||||||
|  |   viewCfgCols, | ||||||
|  | } from '@/views/config-manage/module-cfg/config'; | ||||||
|  | import { | ||||||
|  |   deleteField, | ||||||
|  |   getFieldList, | ||||||
|  |   getFieldNumSelect, | ||||||
|  |   getFieldTypeSelect, | ||||||
|  |   saveField, | ||||||
|  |   // getFieldDetail, | ||||||
|  | } from '@/views/config-manage/module-cfg/service'; | ||||||
|  | import { message } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   open: { | ||||||
|  |     type: Boolean, | ||||||
|  |     default: false, | ||||||
|  |   }, | ||||||
|  |   modularId: { | ||||||
|  |     type: Number, | ||||||
|  |     default: 0, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | const listLoading = ref(false); | ||||||
|  | const fieldName = ref(''); | ||||||
|  | const dataList = ref([]); | ||||||
|  | const fieldTypeSel = ref([]); | ||||||
|  | const fieldNumTypeSel = ref([]); | ||||||
|  | const specialVisible = ref(false); | ||||||
|  | const specialModalId = ref(); | ||||||
|  | const pageState = reactive({ | ||||||
|  |   page: 1, | ||||||
|  |   perPage: 20, | ||||||
|  |   total: 0, | ||||||
|  | }); | ||||||
|  | const editableData = reactive({}); | ||||||
|  | const specialModalData = reactive({ | ||||||
|  |   drive_type: undefined, | ||||||
|  |   database_address: undefined, | ||||||
|  |   database_port: undefined, | ||||||
|  |   database_name: undefined, | ||||||
|  |   database_username: undefined, | ||||||
|  |   database_password: undefined, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | watch( | ||||||
|  |   () => props.open, | ||||||
|  |   (newVal) => { | ||||||
|  |     if (newVal) { | ||||||
|  |       toGetList(); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  |   toGetFieldTypes(); | ||||||
|  |   toGetFieldNumSelect(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // 字段搜索类型下拉 | ||||||
|  | const toGetFieldTypes = () => { | ||||||
|  |   getFieldTypeSelect().then((res) => { | ||||||
|  |     fieldTypeSel.value = res.data; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 字段类型下拉 | ||||||
|  | const toGetFieldNumSelect = () => { | ||||||
|  |   getFieldNumSelect().then((res) => { | ||||||
|  |     fieldNumTypeSel.value = res.data; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 字段列表 | ||||||
|  | const toGetList = () => { | ||||||
|  |   listLoading.value = true; | ||||||
|  |   getFieldList({ | ||||||
|  |     fieldName: fieldName.value, | ||||||
|  |     modularId: props.modularId, | ||||||
|  |     page: pageState.page, | ||||||
|  |     perPage: pageState.perPage, | ||||||
|  |   }).then((res) => { | ||||||
|  |     dataList.value = res.data.list; | ||||||
|  |     pageState.total = res.data.total; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const pageChange = () => { | ||||||
|  |   toGetList(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const search = () => { | ||||||
|  |   pageState.page = 1; | ||||||
|  |   toGetList(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const addField = () => { | ||||||
|  |   const item = { | ||||||
|  |     field_id: `${Date.now()}`, | ||||||
|  |     field_title: undefined, | ||||||
|  |     field_name: undefined, | ||||||
|  |     field_numerical_type_id: undefined, | ||||||
|  |     is_search: 0, | ||||||
|  |     field_type_id: undefined, | ||||||
|  |     belong_to_table: undefined, | ||||||
|  |     is_other_database: 0, | ||||||
|  |     original_type: undefined, | ||||||
|  |     original_sql: undefined, | ||||||
|  |     sort: 0, | ||||||
|  |     drive_type: undefined, | ||||||
|  |     database_address: undefined, | ||||||
|  |     database_port: undefined, | ||||||
|  |     database_name: undefined, | ||||||
|  |     database_username: undefined, | ||||||
|  |     database_password: undefined, | ||||||
|  |   }; | ||||||
|  |   dataList.value.unshift(item); | ||||||
|  |   editableData[item.field_id] = { | ||||||
|  |     ...item, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleEdit = (record) => { | ||||||
|  |   editableData[record.field_id] = { | ||||||
|  |     ...record, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleDelete = (record) => { | ||||||
|  |   deleteField({ | ||||||
|  |     field_id: record.field_id, | ||||||
|  |   }).then(() => { | ||||||
|  |     message.success('删除成功'); | ||||||
|  |     toGetList(); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleCancel = (record) => { | ||||||
|  |   if (typeof record.field_id === 'string') { | ||||||
|  |     dataList.value.shift(); | ||||||
|  |   } else { | ||||||
|  |     delete editableData[record.field_id]; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const openSpecialModal = (record) => { | ||||||
|  |   specialVisible.value = true; | ||||||
|  |   specialModalId.value = record.field_id; | ||||||
|  |   if (!specialModalData[record.field_id]) { | ||||||
|  |     specialModalData[record.field_id] = { | ||||||
|  |       drive_type: undefined, | ||||||
|  |       database_address: undefined, | ||||||
|  |       database_port: undefined, | ||||||
|  |       database_name: undefined, | ||||||
|  |       database_username: undefined, | ||||||
|  |       database_password: undefined, | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleSave = (record) => { | ||||||
|  |   const params = { | ||||||
|  |     is_search: record.is_search, | ||||||
|  |     field_type_id: record.field_type_id, | ||||||
|  |     modular_id: props.modularId, | ||||||
|  |     original_type: record.original_type, | ||||||
|  |     original_sql: record.original_sql, | ||||||
|  |     is_other_database: record.is_other_database, | ||||||
|  |   }; | ||||||
|  |   // 如果数据库特配弹框有数据 | ||||||
|  |   if (specialModalData[record.field_id]) { | ||||||
|  |     params.drive_type = specialModalData[record.field_id].drive_type; | ||||||
|  |     params.database_address = | ||||||
|  |       specialModalData[record.field_id].database_address; | ||||||
|  |     params.database_port = specialModalData[record.field_id].database_port; | ||||||
|  |     params.database_name = specialModalData[record.field_id].database_name; | ||||||
|  |     params.database_username = | ||||||
|  |       specialModalData[record.field_id].database_username; | ||||||
|  |     params.database_password = | ||||||
|  |       specialModalData[record.field_id].database_password; | ||||||
|  |   } | ||||||
|  |   // 检验必填参数 | ||||||
|  |   const validateFields = [ | ||||||
|  |     { field: 'field_title', msg: '请填写字段标题' }, | ||||||
|  |     { field: 'field_name', msg: '请填写字段名称' }, | ||||||
|  |     { field: 'field_numerical_type_id', msg: '请选择字段类型' }, | ||||||
|  |     { field: 'belong_to_table', msg: '请填写关联表' }, | ||||||
|  |     { field: 'show_type', msg: '请选择展示类型' }, | ||||||
|  |   ]; | ||||||
|  |   for (const curr of validateFields) { | ||||||
|  |     if (record[curr.field]) { | ||||||
|  |       params[curr.field] = record[curr.field]; | ||||||
|  |     } else { | ||||||
|  |       message.error(curr.msg); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   if (record.is_search && !record.field_type_id) { | ||||||
|  |     message.error('请选择搜索类型'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 如果是编辑操作 | ||||||
|  |   if (typeof record.field_id === 'number') { | ||||||
|  |     params.field_id = record.field_id; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   saveField(params).then(() => { | ||||||
|  |     delete editableData[record.field_id]; | ||||||
|  |     message.success('保存成功'); | ||||||
|  |     toGetList(); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|   <a-modal :open="open" title="字段管理" style="top: 30px" :footer="null"> |   <a-modal :open="open" title="字段管理" style="top: 30px" :footer="null"> | ||||||
|     <div class="field-manager"> |     <div class="field-manager"> | ||||||
| @ -49,8 +269,7 @@ | |||||||
|               placeholder="请选择" |               placeholder="请选择" | ||||||
|               allow-clear |               allow-clear | ||||||
|               style="width: 120px" |               style="width: 120px" | ||||||
|             > |             /> | ||||||
|             </a-select> |  | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.field_numerical_name }} |               {{ record.field_numerical_name }} | ||||||
|             </template> |             </template> | ||||||
| @ -63,8 +282,7 @@ | |||||||
|               placeholder="请选择" |               placeholder="请选择" | ||||||
|               allow-clear |               allow-clear | ||||||
|               style="width: 120px" |               style="width: 120px" | ||||||
|             > |             /> | ||||||
|             </a-select> |  | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.show_type }} |               {{ record.show_type }} | ||||||
|             </template> |             </template> | ||||||
| @ -77,8 +295,7 @@ | |||||||
|               placeholder="请选择" |               placeholder="请选择" | ||||||
|               allow-clear |               allow-clear | ||||||
|               style="width: 120px" |               style="width: 120px" | ||||||
|             > |             /> | ||||||
|             </a-select> |  | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.field_type_name }} |               {{ record.field_type_name }} | ||||||
|             </template> |             </template> | ||||||
| @ -87,29 +304,30 @@ | |||||||
|             <a-switch |             <a-switch | ||||||
|               v-if="editableData[record.field_id]" |               v-if="editableData[record.field_id]" | ||||||
|               v-model:checked="record.is_search" |               v-model:checked="record.is_search" | ||||||
|               :checkedValue="1" |               :checked-value="1" | ||||||
|               :unCheckedValue="0" |               :un-checked-value="0" | ||||||
|             /> |             /> | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.is_search ? "是" : "否" }} |               {{ record.is_search ? '是' : '否' }} | ||||||
|             </template> |             </template> | ||||||
|           </template> |           </template> | ||||||
|           <template v-if="column.dataIndex === 'is_other_database'"> |           <template v-if="column.dataIndex === 'is_other_database'"> | ||||||
|             <template v-if="editableData[record.field_id]"> |             <template v-if="editableData[record.field_id]"> | ||||||
|               <a-switch |               <a-switch | ||||||
|                 v-model:checked="record.is_other_database" |                 v-model:checked="record.is_other_database" | ||||||
|                 :checkedValue="1" |                 :checked-value="1" | ||||||
|                 :unCheckedValue="0" |                 :un-checked-value="0" | ||||||
|               /> |               /> | ||||||
|               <a-button |               <a-button | ||||||
|                 v-if="record.is_other_database" |                 v-if="record.is_other_database" | ||||||
|                 type="link" |                 type="link" | ||||||
|                 @click="openSpecialModal(record)" |                 @click="openSpecialModal(record)" | ||||||
|                 >请填写</a-button |  | ||||||
|               > |               > | ||||||
|  |                 请填写 | ||||||
|  |               </a-button> | ||||||
|             </template> |             </template> | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.is_other_database ? "是" : "否" }} |               {{ record.is_other_database ? '是' : '否' }} | ||||||
|             </template> |             </template> | ||||||
|           </template> |           </template> | ||||||
|           <template v-if="column.dataIndex === 'original_type'"> |           <template v-if="column.dataIndex === 'original_type'"> | ||||||
| @ -119,20 +337,19 @@ | |||||||
|               v-model:value="record.original_type" |               v-model:value="record.original_type" | ||||||
|               :options="originalTypes" |               :options="originalTypes" | ||||||
|               allow-clear |               allow-clear | ||||||
|             > |             /> | ||||||
|             </a-select> |  | ||||||
|             <template v-else> |             <template v-else> | ||||||
|               {{ record.original_type_name }} |               {{ record.original_type_name }} | ||||||
|             </template> |             </template> | ||||||
|           </template> |           </template> | ||||||
|           <template v-if="column.dataIndex === 'action'"> |           <template v-if="column.dataIndex === 'action'"> | ||||||
|             <a-space v-if="editableData[record.field_id]"> |             <a-space v-if="editableData[record.field_id]"> | ||||||
|               <a-button type="primary" size="small" @click="handleSave(record)" |               <a-button type="primary" size="small" @click="handleSave(record)"> | ||||||
|                 >保存</a-button |                 保存 | ||||||
|               > |               </a-button> | ||||||
|               <a-button size="small" @click="handleCancel(record)" |               <a-button size="small" @click="handleCancel(record)"> | ||||||
|                 >取消</a-button |                 取消 | ||||||
|               > |               </a-button> | ||||||
|             </a-space> |             </a-space> | ||||||
|             <div v-else> |             <div v-else> | ||||||
|               <a-button type="link" @click="handleEdit(record)">修改</a-button> |               <a-button type="link" @click="handleEdit(record)">修改</a-button> | ||||||
| @ -159,7 +376,7 @@ | |||||||
|       :open="specialVisible" |       :open="specialVisible" | ||||||
|       :width="640" |       :width="640" | ||||||
|       title="数据库特配" |       title="数据库特配" | ||||||
|       :bodyStyle="{ marginTop: '30px' }" |       :body-style="{ marginTop: '30px' }" | ||||||
|       @ok="specialVisible = false" |       @ok="specialVisible = false" | ||||||
|       @cancel="specialVisible = false" |       @cancel="specialVisible = false" | ||||||
|     > |     > | ||||||
| @ -213,219 +430,6 @@ | |||||||
|   </a-modal> |   </a-modal> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> |  | ||||||
| import { onMounted, reactive, ref, watch } from "vue"; |  | ||||||
| import { viewCfgCols, originalTypes, showTypeOpts } from "@/views/config-manage/module-cfg/config"; |  | ||||||
| import { |  | ||||||
|   getFieldTypeSelect, |  | ||||||
|   getFieldNumSelect, |  | ||||||
|   getFieldList, |  | ||||||
|   deleteField, |  | ||||||
|   saveField, |  | ||||||
|   // getFieldDetail, |  | ||||||
| } from "@/views/config-manage/module-cfg/service"; |  | ||||||
| import { message } from "ant-design-vue"; |  | ||||||
| 
 |  | ||||||
| const props = defineProps({ |  | ||||||
|   open: { |  | ||||||
|     type: Boolean, |  | ||||||
|     default: false, |  | ||||||
|   }, |  | ||||||
|   modularId: { |  | ||||||
|     type: Number, |  | ||||||
|     default: 0, |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| const listLoading = ref(false); |  | ||||||
| const fieldName = ref(""); |  | ||||||
| const dataList = ref([]); |  | ||||||
| const fieldTypeSel = ref([]); |  | ||||||
| const fieldNumTypeSel = ref([]); |  | ||||||
| const specialVisible = ref(false); |  | ||||||
| const specialModalId = ref(); |  | ||||||
| const pageState = reactive({ |  | ||||||
|   page: 1, |  | ||||||
|   perPage: 20, |  | ||||||
|   total: 0, |  | ||||||
| }); |  | ||||||
| const editableData = reactive({}); |  | ||||||
| const specialModalData = reactive({ |  | ||||||
|   drive_type: undefined, |  | ||||||
|   database_address: undefined, |  | ||||||
|   database_port: undefined, |  | ||||||
|   database_name: undefined, |  | ||||||
|   database_username: undefined, |  | ||||||
|   database_password: undefined, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| watch( |  | ||||||
|   () => props.open, |  | ||||||
|   (newVal) => { |  | ||||||
|     if (newVal) { |  | ||||||
|       toGetList(); |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| onMounted(() => { |  | ||||||
|   toGetFieldTypes(); |  | ||||||
|   toGetFieldNumSelect(); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| // 字段搜索类型下拉 |  | ||||||
| const toGetFieldTypes = () => { |  | ||||||
|   getFieldTypeSelect().then((res) => { |  | ||||||
|     fieldTypeSel.value = res.data; |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // 字段类型下拉 |  | ||||||
| const toGetFieldNumSelect = () => { |  | ||||||
|   getFieldNumSelect().then((res) => { |  | ||||||
|     fieldNumTypeSel.value = res.data; |  | ||||||
|   }) |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // 字段列表 |  | ||||||
| const toGetList = () => { |  | ||||||
|   listLoading.value = true; |  | ||||||
|   getFieldList({ |  | ||||||
|     fieldName: fieldName.value, |  | ||||||
|     modularId: props.modularId, |  | ||||||
|     page: pageState.page, |  | ||||||
|     perPage: pageState.perPage, |  | ||||||
|   }).then((res) => { |  | ||||||
|     dataList.value = res.data.list; |  | ||||||
|     pageState.total = res.data.total; |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const pageChange = () => { |  | ||||||
|   toGetList(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const search = () => { |  | ||||||
|   pageState.page = 1; |  | ||||||
|   toGetList(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const addField = () => { |  | ||||||
|   const item = { |  | ||||||
|     field_id: new Date().getTime() + "", |  | ||||||
|     field_title: undefined, |  | ||||||
|     field_name: undefined, |  | ||||||
|     field_numerical_type_id: undefined, |  | ||||||
|     is_search: 0, |  | ||||||
|     field_type_id: undefined, |  | ||||||
|     belong_to_table: undefined, |  | ||||||
|     is_other_database: 0, |  | ||||||
|     original_type: undefined, |  | ||||||
|     original_sql: undefined, |  | ||||||
|     sort: 0, |  | ||||||
|     drive_type: undefined, |  | ||||||
|     database_address: undefined, |  | ||||||
|     database_port: undefined, |  | ||||||
|     database_name: undefined, |  | ||||||
|     database_username: undefined, |  | ||||||
|     database_password: undefined, |  | ||||||
|   }; |  | ||||||
|   dataList.value.unshift(item); |  | ||||||
|   editableData[item.field_id] = { |  | ||||||
|     ...item, |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const handleEdit = (record) => { |  | ||||||
|   editableData[record.field_id] = { |  | ||||||
|     ...record, |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const handleDelete = (record) => { |  | ||||||
|   deleteField({ |  | ||||||
|     field_id: record.field_id, |  | ||||||
|   }).then(() => { |  | ||||||
|     message.success('删除成功') |  | ||||||
|     toGetList(); |  | ||||||
|   }) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const handleCancel = (record) => { |  | ||||||
|   if (typeof record.field_id === "string") { |  | ||||||
|     dataList.value.shift(); |  | ||||||
|   } else { |  | ||||||
|     delete editableData[record.field_id]; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const openSpecialModal = (record) => { |  | ||||||
|   specialVisible.value = true |  | ||||||
|   specialModalId.value = record.field_id |  | ||||||
|   if (!specialModalData[record.field_id]) { |  | ||||||
|     specialModalData[record.field_id] = { |  | ||||||
|       drive_type: undefined, |  | ||||||
|       database_address: undefined, |  | ||||||
|       database_port: undefined, |  | ||||||
|       database_name: undefined, |  | ||||||
|       database_username: undefined, |  | ||||||
|       database_password: undefined, |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const handleSave = (record) => { |  | ||||||
|   const params = { |  | ||||||
|     is_search: record.is_search, |  | ||||||
|     field_type_id: record.field_type_id, |  | ||||||
|     modular_id: props.modularId, |  | ||||||
|     original_type: record.original_type, |  | ||||||
|     original_sql: record.original_sql, |  | ||||||
|     is_other_database: record.is_other_database, |  | ||||||
|   }; |  | ||||||
|   // 如果数据库特配弹框有数据 |  | ||||||
|   if (specialModalData[record.field_id]) { |  | ||||||
|     params.drive_type = specialModalData[record.field_id].drive_type |  | ||||||
|     params.database_address = specialModalData[record.field_id].database_address |  | ||||||
|     params.database_port = specialModalData[record.field_id].database_port |  | ||||||
|     params.database_name = specialModalData[record.field_id].database_name |  | ||||||
|     params.database_username = specialModalData[record.field_id].database_username |  | ||||||
|     params.database_password = specialModalData[record.field_id].database_password |  | ||||||
|   } |  | ||||||
|   // 检验必填参数 |  | ||||||
|   const validateFields = [ |  | ||||||
|     { field: 'field_title', msg: "请填写字段标题" }, |  | ||||||
|     { field: 'field_name', msg: "请填写字段名称" }, |  | ||||||
|     { field: 'field_numerical_type_id', msg: "请选择字段类型" }, |  | ||||||
|     { field: 'belong_to_table', msg: "请填写关联表" }, |  | ||||||
|     { field: 'show_type', msg: "请选择展示类型" }, |  | ||||||
|   ] |  | ||||||
|   for(let i = 0; i < validateFields.length; i++) { |  | ||||||
|     const curr = validateFields[i]; |  | ||||||
|     if (!record[curr.field]) { |  | ||||||
|       message.error(curr.msg); |  | ||||||
|       return; |  | ||||||
|     } else { |  | ||||||
|       params[curr.field] = record[curr.field]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (record.is_search && !record.field_type_id) { |  | ||||||
|     message.error("请选择搜索类型"); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // 如果是编辑操作 |  | ||||||
|   if (typeof record.field_id === "number") { |  | ||||||
|     params.field_id = record.field_id; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   saveField(params).then(() => { |  | ||||||
|     delete editableData[record.field_id]; |  | ||||||
|     message.success("保存成功"); |  | ||||||
|     toGetList(); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| .header-box { | .header-box { | ||||||
|   margin-bottom: 10px; |   margin-bottom: 10px; | ||||||
|  | |||||||
| @ -1,41 +1,41 @@ | |||||||
| export const moduleCfgCols = [ | export const moduleCfgCols = [ | ||||||
|   { dataIndex: "modular_id", title: "编号", align: "center" }, |   { dataIndex: 'modular_id', title: '编号', align: 'center' }, | ||||||
|   { dataIndex: "modular_name", title: "数据来源名称", align: "center" }, |   { dataIndex: 'modular_name', title: '数据来源名称', align: 'center' }, | ||||||
|   { dataIndex: "project_name", title: "项目名称", align: "center" }, |   { dataIndex: 'project_name', title: '项目名称', align: 'center' }, | ||||||
|   { dataIndex: "is_show", title: "展示状态", align: "center" }, |   { dataIndex: 'is_show', title: '展示状态', align: 'center' }, | ||||||
|   { dataIndex: "original_type_handle", title: "数据源类型", align: "center" }, |   { dataIndex: 'original_type_handle', title: '数据源类型', align: 'center' }, | ||||||
|   // { dataIndex: 'sort', title: '排序', align: 'center'},
 |   // { dataIndex: 'sort', title: '排序', align: 'center'},
 | ||||||
|   { dataIndex: "action", title: "操作", align: "center" }, |   { dataIndex: 'action', title: '操作', align: 'center' }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| export const viewCfgCols = [ | export const viewCfgCols = [ | ||||||
|   { dataIndex: "field_name", title: "字段名称", align: "center" }, |   { dataIndex: 'field_name', title: '字段名称', align: 'center' }, | ||||||
|   { dataIndex: "field_title", title: "字段标题", align: "center" }, |   { dataIndex: 'field_title', title: '字段标题', align: 'center' }, | ||||||
|   { |   { | ||||||
|     dataIndex: "field_numerical_name", |     dataIndex: 'field_numerical_name', | ||||||
|     title: "字段类型", |     title: '字段类型', | ||||||
|     align: "center", |     align: 'center', | ||||||
|     width: 120, |     width: 120, | ||||||
|   }, |   }, | ||||||
|   { dataIndex: "show_type", title: "展示类型", align: "center", width: 120 }, |   { dataIndex: 'show_type', title: '展示类型', align: 'center', width: 120 }, | ||||||
|   { dataIndex: "field_type_name", title: "搜索类型", align: "center" }, |   { dataIndex: 'field_type_name', title: '搜索类型', align: 'center' }, | ||||||
|   { dataIndex: "is_search", title: "是否可搜索", align: "center" }, |   { dataIndex: 'is_search', title: '是否可搜索', align: 'center' }, | ||||||
|   { dataIndex: "sort", title: "排序", align: "center" }, |   { dataIndex: 'sort', title: '排序', align: 'center' }, | ||||||
|   { dataIndex: "belong_to_table", title: "所属表名称", align: "center" }, |   { dataIndex: 'belong_to_table', title: '所属表名称', align: 'center' }, | ||||||
|   { dataIndex: "is_other_database", title: "数据库特配", align: "center" }, |   { dataIndex: 'is_other_database', title: '数据库特配', align: 'center' }, | ||||||
|   { dataIndex: "original_type", title: "数据源类型", align: "center" }, |   { dataIndex: 'original_type', title: '数据源类型', align: 'center' }, | ||||||
|   { dataIndex: "original_sql", title: "数据源", align: "center", width: 400 }, |   { dataIndex: 'original_sql', title: '数据源', align: 'center', width: 400 }, | ||||||
|   { dataIndex: "action", title: "操作", align: "center", width: 120 }, |   { dataIndex: 'action', title: '操作', align: 'center', width: 120 }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| export const originalTypes = [ | export const originalTypes = [ | ||||||
|   { label: "sql", value: 1 }, |   { label: 'sql', value: 1 }, | ||||||
|   { label: "json", value: 2 }, |   { label: 'json', value: 2 }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| export const showTypeOpts = [ | export const showTypeOpts = [ | ||||||
|   { label: "文本", value: "text" }, |   { label: '文本', value: 'text' }, | ||||||
|   { label: "图片", value: "img" }, |   { label: '图片', value: 'img' }, | ||||||
|   { label: "链接", value: "link" }, |   { label: '链接', value: 'link' }, | ||||||
|   { label: "富文本", value: "richText" }, |   { label: '富文本', value: 'richText' }, | ||||||
| ]; | ]; | ||||||
|  | |||||||
| @ -1,123 +1,36 @@ | |||||||
| <template> |  | ||||||
|   <div class="normal-container module-cfg-box"> |  | ||||||
|     <div class="header-box"> |  | ||||||
|       <a-space> |  | ||||||
|         <a-input |  | ||||||
|           v-model:value="modularName" |  | ||||||
|           placeholder="请输入数据来源名称" |  | ||||||
|           allow-clear |  | ||||||
|           style="width: 200px" |  | ||||||
|           @change="search" |  | ||||||
|         /> |  | ||||||
|         <a-select |  | ||||||
|           placeholder="请选项目" |  | ||||||
|           v-model:value="projectId" |  | ||||||
|           :options="projectSel" |  | ||||||
|           allow-clear |  | ||||||
|           style="width: 200px" |  | ||||||
|           @change="search" |  | ||||||
|         ></a-select> |  | ||||||
|         <a-button type="primary" @click="openCreateModal">新建</a-button> |  | ||||||
|       </a-space> |  | ||||||
|     </div> |  | ||||||
|     <div class="content-box"> |  | ||||||
|       <a-table |  | ||||||
|         :columns="moduleCfgCols" |  | ||||||
|         :data-source="dataList" |  | ||||||
|         :pagination="false" |  | ||||||
|         size="small" |  | ||||||
|         bordered |  | ||||||
|       > |  | ||||||
|         <template #bodyCell="{ column, record }"> |  | ||||||
|           <template v-if="column.dataIndex === 'is_show'"> |  | ||||||
|             <a-switch |  | ||||||
|               :checked="record.is_show" |  | ||||||
|               :checkedValue="1" |  | ||||||
|               :unCheckedValue="0" |  | ||||||
|               @change="toChangeStatus(record.modular_id, $event)" |  | ||||||
|             /> |  | ||||||
|           </template> |  | ||||||
|           <template v-if="column.dataIndex === 'action'"> |  | ||||||
|             <a-space> |  | ||||||
|               <a-button type="link" size="small" @click="openFieldModal(record)" |  | ||||||
|                 >字段管理</a-button |  | ||||||
|               > |  | ||||||
|               <a-button |  | ||||||
|                 type="link" |  | ||||||
|                 size="small" |  | ||||||
|                 @click="toGetModularDetail(record.modular_id)" |  | ||||||
|                 >编辑</a-button |  | ||||||
|               > |  | ||||||
|               <a-popconfirm |  | ||||||
|                 title="确定删除吗?" |  | ||||||
|                 @confirm="toDelete(record.modular_id)" |  | ||||||
|               > |  | ||||||
|                 <a-button type="link" size="small">删除</a-button> |  | ||||||
|               </a-popconfirm> |  | ||||||
|             </a-space> |  | ||||||
|           </template> |  | ||||||
|         </template> |  | ||||||
|       </a-table> |  | ||||||
|       <a-pagination |  | ||||||
|         v-model:current="pageState.page" |  | ||||||
|         :total="pageState.total" |  | ||||||
|         :page-size="pageState.perPage" |  | ||||||
|         :hide-on-single-page="false" |  | ||||||
|         size="small" |  | ||||||
|         class="pagination-box" |  | ||||||
|         @change="toGetModularList" |  | ||||||
|       /> |  | ||||||
|     </div> |  | ||||||
|     <CreateModal |  | ||||||
|       :width="700" |  | ||||||
|       :open="modalState.visible" |  | ||||||
|       :title="modalState.title" |  | ||||||
|       :type="modalState.type" |  | ||||||
|       :data="modalState.data" |  | ||||||
|       :projectSelect="projectSel" |  | ||||||
|       @cancel="modalState.visible = false" |  | ||||||
|       @ok="toSave" |  | ||||||
|     /> |  | ||||||
|     <FieldModal |  | ||||||
|       title="字段管理" |  | ||||||
|       width="90%" |  | ||||||
|       :open="fieldModalState.visible" |  | ||||||
|       :modularId="fieldModalState.modularId" |  | ||||||
|       @cancel="fieldModalState.visible = false" |  | ||||||
|     /> |  | ||||||
|   </div> |  | ||||||
| </template> |  | ||||||
| <script setup> | <script setup> | ||||||
| import { ref, reactive, onMounted } from "vue"; | import { onMounted, reactive, ref } from 'vue'; | ||||||
| import { message } from "ant-design-vue"; | 
 | ||||||
| import { moduleCfgCols } from "./config"; | import { message } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | import CreateModal from './components/create-modal.vue'; | ||||||
|  | import FieldModal from './components/field-modal.vue'; | ||||||
|  | import { moduleCfgCols } from './config'; | ||||||
| import { | import { | ||||||
|   getModularList, |  | ||||||
|   deleteModular, |   deleteModular, | ||||||
|   getModularDetail, |   getModularDetail, | ||||||
|  |   getModularList, | ||||||
|   getProjectSelect, |   getProjectSelect, | ||||||
|   saveModular, |   saveModular, | ||||||
|   updateStatus, |   updateStatus, | ||||||
| } from "./service"; | } from './service'; | ||||||
| import CreateModal from "./components/create-modal.vue"; |  | ||||||
| import FieldModal from "./components/field-modal.vue"; |  | ||||||
| 
 | 
 | ||||||
| const dataList = ref([]); | const dataList = ref([]); | ||||||
| const listLoading = ref(false); | const listLoading = ref(false); | ||||||
| const saveLoading = ref(false); | const saveLoading = ref(false); | ||||||
| const detailLoading = ref(false); | const detailLoading = ref(false); | ||||||
| const modularName = ref(""); | const modularName = ref(''); | ||||||
| const projectId = ref(); | const projectId = ref(); | ||||||
| const projectSel = ref([]); | const projectSel = ref([]); | ||||||
| const modalState = reactive({ | const modalState = reactive({ | ||||||
|   title: "", |   title: '', | ||||||
|   visible: false, |   visible: false, | ||||||
|   type: "", // add - 新建,edit - 编辑 |   type: '', // add - 新建,edit - 编辑 | ||||||
|   data: {}, |   data: {}, | ||||||
| }); | }); | ||||||
| const fieldModalState = reactive({ | const fieldModalState = reactive({ | ||||||
|   visible: false, |   visible: false, | ||||||
|   title: "", |   title: '', | ||||||
|   modularId: undefined, |   modularId: undefined, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -156,8 +69,8 @@ const toGetModularList = () => { | |||||||
| const toGetModularDetail = (modularId) => { | const toGetModularDetail = (modularId) => { | ||||||
|   detailLoading.value = true; |   detailLoading.value = true; | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "编辑"; |   modalState.title = '编辑'; | ||||||
|   modalState.type = "edit"; |   modalState.type = 'edit'; | ||||||
|   getModularDetail({ modularId }) |   getModularDetail({ modularId }) | ||||||
|     .then((res) => { |     .then((res) => { | ||||||
|       modalState.data = res.data; |       modalState.data = res.data; | ||||||
| @ -172,7 +85,7 @@ const toSave = (data) => { | |||||||
|   saveLoading.value = true; |   saveLoading.value = true; | ||||||
|   saveModular(data) |   saveModular(data) | ||||||
|     .then(() => { |     .then(() => { | ||||||
|       message.success("保存成功"); |       message.success('保存成功'); | ||||||
|       modalState.visible = false; |       modalState.visible = false; | ||||||
|       toGetModularList(); |       toGetModularList(); | ||||||
|     }) |     }) | ||||||
| @ -184,7 +97,7 @@ const toSave = (data) => { | |||||||
| // 删除 | // 删除 | ||||||
| const toDelete = (id) => { | const toDelete = (id) => { | ||||||
|   deleteModular({ modular_id: id }).then(() => { |   deleteModular({ modular_id: id }).then(() => { | ||||||
|     message.success("删除成功"); |     message.success('删除成功'); | ||||||
|     search(); |     search(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -194,7 +107,7 @@ const toChangeStatus = (id, status) => { | |||||||
|     modular_id: id, |     modular_id: id, | ||||||
|     status, |     status, | ||||||
|   }).then(() => { |   }).then(() => { | ||||||
|     message.success("修改成功"); |     message.success('修改成功'); | ||||||
|     search(); |     search(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -202,8 +115,8 @@ const toChangeStatus = (id, status) => { | |||||||
| // 点击新建 | // 点击新建 | ||||||
| const openCreateModal = () => { | const openCreateModal = () => { | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "新建"; |   modalState.title = '新建'; | ||||||
|   modalState.type = "add"; |   modalState.type = 'add'; | ||||||
|   modalState.data = {}; |   modalState.data = {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -217,6 +130,100 @@ const openFieldModal = (record) => { | |||||||
|   fieldModalState.modularId = record.modular_id; |   fieldModalState.modularId = record.modular_id; | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|  | <template> | ||||||
|  |   <div class="normal-container module-cfg-box"> | ||||||
|  |     <div class="header-box"> | ||||||
|  |       <a-space> | ||||||
|  |         <a-input | ||||||
|  |           v-model:value="modularName" | ||||||
|  |           placeholder="请输入数据来源名称" | ||||||
|  |           allow-clear | ||||||
|  |           style="width: 200px" | ||||||
|  |           @change="search" | ||||||
|  |         /> | ||||||
|  |         <a-select | ||||||
|  |           placeholder="请选项目" | ||||||
|  |           v-model:value="projectId" | ||||||
|  |           :options="projectSel" | ||||||
|  |           allow-clear | ||||||
|  |           style="width: 200px" | ||||||
|  |           @change="search" | ||||||
|  |         /> | ||||||
|  |         <a-button type="primary" @click="openCreateModal">新建</a-button> | ||||||
|  |       </a-space> | ||||||
|  |     </div> | ||||||
|  |     <div class="content-box"> | ||||||
|  |       <a-table | ||||||
|  |         :columns="moduleCfgCols" | ||||||
|  |         :data-source="dataList" | ||||||
|  |         :pagination="false" | ||||||
|  |         size="small" | ||||||
|  |         bordered | ||||||
|  |       > | ||||||
|  |         <template #bodyCell="{ column, record }"> | ||||||
|  |           <template v-if="column.dataIndex === 'is_show'"> | ||||||
|  |             <a-switch | ||||||
|  |               :checked="record.is_show" | ||||||
|  |               :checked-value="1" | ||||||
|  |               :un-checked-value="0" | ||||||
|  |               @change="toChangeStatus(record.modular_id, $event)" | ||||||
|  |             /> | ||||||
|  |           </template> | ||||||
|  |           <template v-if="column.dataIndex === 'action'"> | ||||||
|  |             <a-space> | ||||||
|  |               <a-button | ||||||
|  |                 type="link" | ||||||
|  |                 size="small" | ||||||
|  |                 @click="openFieldModal(record)" | ||||||
|  |               > | ||||||
|  |                 字段管理 | ||||||
|  |               </a-button> | ||||||
|  |               <a-button | ||||||
|  |                 type="link" | ||||||
|  |                 size="small" | ||||||
|  |                 @click="toGetModularDetail(record.modular_id)" | ||||||
|  |               > | ||||||
|  |                 编辑 | ||||||
|  |               </a-button> | ||||||
|  |               <a-popconfirm | ||||||
|  |                 title="确定删除吗?" | ||||||
|  |                 @confirm="toDelete(record.modular_id)" | ||||||
|  |               > | ||||||
|  |                 <a-button type="link" size="small">删除</a-button> | ||||||
|  |               </a-popconfirm> | ||||||
|  |             </a-space> | ||||||
|  |           </template> | ||||||
|  |         </template> | ||||||
|  |       </a-table> | ||||||
|  |       <a-pagination | ||||||
|  |         v-model:current="pageState.page" | ||||||
|  |         :total="pageState.total" | ||||||
|  |         :page-size="pageState.perPage" | ||||||
|  |         :hide-on-single-page="false" | ||||||
|  |         size="small" | ||||||
|  |         class="pagination-box" | ||||||
|  |         @change="toGetModularList" | ||||||
|  |       /> | ||||||
|  |     </div> | ||||||
|  |     <CreateModal | ||||||
|  |       :width="700" | ||||||
|  |       :open="modalState.visible" | ||||||
|  |       :title="modalState.title" | ||||||
|  |       :type="modalState.type" | ||||||
|  |       :data="modalState.data" | ||||||
|  |       :project-select="projectSel" | ||||||
|  |       @cancel="modalState.visible = false" | ||||||
|  |       @ok="toSave" | ||||||
|  |     /> | ||||||
|  |     <FieldModal | ||||||
|  |       title="字段管理" | ||||||
|  |       width="90%" | ||||||
|  |       :open="fieldModalState.visible" | ||||||
|  |       :modular-id="fieldModalState.modularId" | ||||||
|  |       @cancel="fieldModalState.visible = false" | ||||||
|  |     /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
| 
 | 
 | ||||||
| <style lang="less"> | <style lang="less"> | ||||||
| .header-box { | .header-box { | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| // 获取数据表配置列表
 | // 获取数据表配置列表
 | ||||||
| export function getModularList({ page, perPage, modularName, projectId }) { | export function getModularList({ page, perPage, modularName, projectId }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/modular/list", |     url: '/api/v1/modular/list', | ||||||
|     params: { |     params: { | ||||||
|       page, |       page, | ||||||
|       per_page: perPage, |       per_page: perPage, | ||||||
| @ -16,7 +16,7 @@ export function getModularList({ page, perPage, modularName, projectId }) { | |||||||
| // 获取数据表配置详情
 | // 获取数据表配置详情
 | ||||||
| export function getModularDetail({ modularId }) { | export function getModularDetail({ modularId }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/modular/info", |     url: '/api/v1/modular/info', | ||||||
|     params: { |     params: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|     }, |     }, | ||||||
| @ -26,7 +26,7 @@ export function getModularDetail({ modularId }) { | |||||||
| // 保存数据库配置
 | // 保存数据库配置
 | ||||||
| export function saveModular(data) { | export function saveModular(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/modular/save", |     url: '/api/v1/modular/save', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -34,7 +34,7 @@ export function saveModular(data) { | |||||||
| // 删除数据库配置
 | // 删除数据库配置
 | ||||||
| export function deleteModular(data) { | export function deleteModular(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/modular/del", |     url: '/api/v1/modular/del', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -42,7 +42,7 @@ export function deleteModular(data) { | |||||||
| // 修改数据表状态
 | // 修改数据表状态
 | ||||||
| export function updateStatus(data) { | export function updateStatus(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/modular/change-status", |     url: '/api/v1/modular/change-status', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -75,13 +75,13 @@ export function getFieldTypeSelect() { | |||||||
| export function getFieldNumSelect() { | export function getFieldNumSelect() { | ||||||
|   return get({ |   return get({ | ||||||
|     url: `/api/v1/field/get-field-numerical-type-drop`, |     url: `/api/v1/field/get-field-numerical-type-drop`, | ||||||
|   }) |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 获取字段列表
 | // 获取字段列表
 | ||||||
| export function getFieldList({ modularId, fieldName, page, perPage }) { | export function getFieldList({ modularId, fieldName, page, perPage }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/list", |     url: '/api/v1/field/list', | ||||||
|     params: { |     params: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|       field_name: fieldName, |       field_name: fieldName, | ||||||
| @ -94,7 +94,7 @@ export function getFieldList({ modularId, fieldName, page, perPage }) { | |||||||
| // 获取字段详情
 | // 获取字段详情
 | ||||||
| export function getFieldDetail({ fieldId }) { | export function getFieldDetail({ fieldId }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/info", |     url: '/api/v1/field/info', | ||||||
|     params: { |     params: { | ||||||
|       field_id: fieldId, |       field_id: fieldId, | ||||||
|     }, |     }, | ||||||
| @ -104,7 +104,7 @@ export function getFieldDetail({ fieldId }) { | |||||||
| // 保存字段
 | // 保存字段
 | ||||||
| export function saveField(data) { | export function saveField(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/field/save", |     url: '/api/v1/field/save', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -112,7 +112,7 @@ export function saveField(data) { | |||||||
| // 删除字段
 | // 删除字段
 | ||||||
| export function deleteField(data) { | export function deleteField(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/field/del", |     url: '/api/v1/field/del', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,3 +1,117 @@ | |||||||
|  | <script setup> | ||||||
|  | import { ref, watch } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { checkDbConnect } from '@/views/config-manage/project-cfg/service'; | ||||||
|  | import { message } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   open: { | ||||||
|  |     type: Boolean, | ||||||
|  |     default: false, | ||||||
|  |   }, | ||||||
|  |   type: { | ||||||
|  |     type: String, | ||||||
|  |     default: 'add', | ||||||
|  |   }, | ||||||
|  |   data: { | ||||||
|  |     type: Object, | ||||||
|  |     default: () => ({}), | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const emit = defineEmits(['ok']); | ||||||
|  | const formRules = { | ||||||
|  |   project_name: [ | ||||||
|  |     { required: true, message: '请输入项目名称', trigger: 'submit' }, | ||||||
|  |   ], | ||||||
|  |   mark: [{ required: true, message: '请输入项目标识', trigger: 'submit' }], | ||||||
|  |   database_address: [ | ||||||
|  |     { required: true, message: '请输入数据库地址', trigger: 'submit' }, | ||||||
|  |   ], | ||||||
|  |   database_port: [ | ||||||
|  |     { required: true, message: '请输入数据库端口', trigger: 'submit' }, | ||||||
|  |   ], | ||||||
|  |   database_name: [ | ||||||
|  |     { required: true, message: '请输入数据库名称', trigger: 'submit' }, | ||||||
|  |   ], | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const formRef = ref(); | ||||||
|  | const formData = ref({ | ||||||
|  |   project_name: undefined, | ||||||
|  |   mark: undefined, | ||||||
|  |   is_show: 0, | ||||||
|  |   database_address: undefined, | ||||||
|  |   database_port: undefined, | ||||||
|  |   database_name: undefined, | ||||||
|  |   database_username: undefined, | ||||||
|  |   database_password: undefined, | ||||||
|  |   drive_type: 1, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | watch( | ||||||
|  |   () => props.data, | ||||||
|  |   (newVal) => { | ||||||
|  |     if (props.type === 'add') { | ||||||
|  |       resetFormData(); | ||||||
|  |     } else { | ||||||
|  |       formData.value = newVal; | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | // 检查数据库连接 | ||||||
|  | const toCheckDbConnect = () => { | ||||||
|  |   if (validateConnect()) { | ||||||
|  |     checkDbConnect({ | ||||||
|  |       database_name: formData.value.database_name, | ||||||
|  |       database_port: formData.value.database_port, | ||||||
|  |       database_address: formData.value.database_address, | ||||||
|  |       database_username: formData.value.database_username, | ||||||
|  |       database_password: formData.value.database_password, | ||||||
|  |       drive_type: formData.value.drive_type, | ||||||
|  |     }).then((res) => { | ||||||
|  |       message.success(res.message); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const validateConnect = () => { | ||||||
|  |   const fields = { | ||||||
|  |     database_name: '请输入数据库名称', | ||||||
|  |     database_port: '请输入数据库端口', | ||||||
|  |     database_address: '请输入数据库地址', | ||||||
|  |   }; | ||||||
|  |   for (const key in fields) { | ||||||
|  |     if (!formData.value[key]) { | ||||||
|  |       message.error(fields[key]); | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return true; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const resetFormData = () => { | ||||||
|  |   formData.value = { | ||||||
|  |     project_name: undefined, | ||||||
|  |     mark: undefined, | ||||||
|  |     is_show: 0, | ||||||
|  |     database_address: undefined, | ||||||
|  |     database_port: undefined, | ||||||
|  |     database_name: undefined, | ||||||
|  |     database_username: undefined, | ||||||
|  |     database_password: undefined, | ||||||
|  |     drive_type: 1, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleOk = () => { | ||||||
|  |   formRef.value.validate().then(() => { | ||||||
|  |     emit('ok', formData.value); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
| <template> | <template> | ||||||
|   <a-modal :open="open" @ok="handleOk"> |   <a-modal :open="open" @ok="handleOk"> | ||||||
|     <a-form |     <a-form | ||||||
| @ -14,13 +128,16 @@ | |||||||
|         /> |         /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item label="项目标识" name="mark"> |       <a-form-item label="项目标识" name="mark"> | ||||||
|         <a-input placeholder="请输入项目标识,例如:oa" v-model:value="formData.mark" /> |         <a-input | ||||||
|  |           placeholder="请输入项目标识,例如:oa" | ||||||
|  |           v-model:value="formData.mark" | ||||||
|  |         /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item label="展示状态" name="is_show"> |       <a-form-item label="展示状态" name="is_show"> | ||||||
|         <a-switch |         <a-switch | ||||||
|           v-model:checked="formData.is_show" |           v-model:checked="formData.is_show" | ||||||
|           :checkedValue="1" |           :checked-value="1" | ||||||
|           :unCheckedValue="0" |           :un-checked-value="0" | ||||||
|         /> |         /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item label="数据库地址" name="database_address"> |       <a-form-item label="数据库地址" name="database_address"> | ||||||
| @ -54,9 +171,9 @@ | |||||||
|             placeholder="请输入数据库密码" |             placeholder="请输入数据库密码" | ||||||
|             v-model:value="formData.database_password" |             v-model:value="formData.database_password" | ||||||
|           /> |           /> | ||||||
|           <a-button type="primary" @click="toCheckDbConnect" |           <a-button type="primary" @click="toCheckDbConnect"> | ||||||
|             >检测数据库连接</a-button |             检测数据库连接 | ||||||
|           > |           </a-button> | ||||||
|         </a-space> |         </a-space> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item label="数据库驱动" name="drive_type"> |       <a-form-item label="数据库驱动" name="drive_type"> | ||||||
| @ -68,116 +185,3 @@ | |||||||
|     </a-form> |     </a-form> | ||||||
|   </a-modal> |   </a-modal> | ||||||
| </template> | </template> | ||||||
| 
 |  | ||||||
| <script setup> |  | ||||||
| import { ref, watch } from "vue"; |  | ||||||
| import { checkDbConnect } from "@/views/config-manage/project-cfg/service"; |  | ||||||
| import { message } from "ant-design-vue"; |  | ||||||
| 
 |  | ||||||
| const props = defineProps({ |  | ||||||
|   open: { |  | ||||||
|     type: Boolean, |  | ||||||
|     default: false, |  | ||||||
|   }, |  | ||||||
|   type: { |  | ||||||
|     type: String, |  | ||||||
|     default: "add", |  | ||||||
|   }, |  | ||||||
|   data: { |  | ||||||
|     type: Object, |  | ||||||
|     default: () => ({}), |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const emit = defineEmits(["ok"]); |  | ||||||
| const formRules = { |  | ||||||
|   project_name: [ |  | ||||||
|     { required: true, message: "请输入项目名称", trigger: "submit" }, |  | ||||||
|   ], |  | ||||||
|   mark: [{ required: true, message: "请输入项目标识", trigger: "submit" }], |  | ||||||
|   database_address: [ |  | ||||||
|     { required: true, message: "请输入数据库地址", trigger: "submit" }, |  | ||||||
|   ], |  | ||||||
|   database_port: [ |  | ||||||
|     { required: true, message: "请输入数据库端口", trigger: "submit" }, |  | ||||||
|   ], |  | ||||||
|   database_name: [ |  | ||||||
|     { required: true, message: "请输入数据库名称", trigger: "submit" }, |  | ||||||
|   ], |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const formRef = ref(); |  | ||||||
| const formData = ref({ |  | ||||||
|   project_name: undefined, |  | ||||||
|   mark: undefined, |  | ||||||
|   is_show: 0, |  | ||||||
|   database_address: undefined, |  | ||||||
|   database_port: undefined, |  | ||||||
|   database_name: undefined, |  | ||||||
|   database_username: undefined, |  | ||||||
|   database_password: undefined, |  | ||||||
|   drive_type: 1, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| watch( |  | ||||||
|   () => props.data, |  | ||||||
|   (newVal) => { |  | ||||||
|     if (props.type === "add") { |  | ||||||
|       resetFormData(); |  | ||||||
|     } else { |  | ||||||
|       formData.value = newVal; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| // 检查数据库连接 |  | ||||||
| const toCheckDbConnect = () => { |  | ||||||
|   if (validateConnect()) { |  | ||||||
|     checkDbConnect({ |  | ||||||
|       database_name: formData.value.database_name, |  | ||||||
|       database_port: formData.value.database_port, |  | ||||||
|       database_address: formData.value.database_address, |  | ||||||
|       database_username: formData.value.database_username, |  | ||||||
|       database_password: formData.value.database_password, |  | ||||||
|       drive_type: formData.value.drive_type, |  | ||||||
|     }).then((res) => { |  | ||||||
|       message.success(res.message); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const validateConnect = () => { |  | ||||||
|   const fields = { |  | ||||||
|     database_name: "请输入数据库名称", |  | ||||||
|     database_port: "请输入数据库端口", |  | ||||||
|     database_address: "请输入数据库地址", |  | ||||||
|   }; |  | ||||||
|   for (const key in fields) { |  | ||||||
|     if (!formData.value[key]) { |  | ||||||
|       message.error(fields[key]); |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return true; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const resetFormData = () => { |  | ||||||
|   formData.value = { |  | ||||||
|     project_name: undefined, |  | ||||||
|     mark: undefined, |  | ||||||
|     is_show: 0, |  | ||||||
|     database_address: undefined, |  | ||||||
|     database_port: undefined, |  | ||||||
|     database_name: undefined, |  | ||||||
|     database_username: undefined, |  | ||||||
|     database_password: undefined, |  | ||||||
|     drive_type: 1, |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const handleOk = () => { |  | ||||||
|   formRef.value.validate().then(() => { |  | ||||||
|     emit("ok", formData.value); |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| export const projectCfgCols = [ | export const projectCfgCols = [ | ||||||
|   { dataIndex: 'project_id', title: '编号', align: 'center'}, |   { dataIndex: 'project_id', title: '编号', align: 'center' }, | ||||||
|   { dataIndex: 'project_name', title: '项目名称', align: 'center'}, |   { dataIndex: 'project_name', title: '项目名称', align: 'center' }, | ||||||
|   { dataIndex: 'mark', title: '项目标识', align: 'center'}, |   { dataIndex: 'mark', title: '项目标识', align: 'center' }, | ||||||
|   { dataIndex: 'database_name', title: '数据库名', align: 'center'}, |   { dataIndex: 'database_name', title: '数据库名', align: 'center' }, | ||||||
|   { dataIndex: 'is_show', title: '展示状态', align: 'center'}, |   { dataIndex: 'is_show', title: '展示状态', align: 'center' }, | ||||||
|   // { dataIndex: 'sort', title: '排序', align: 'center'},
 |   // { dataIndex: 'sort', title: '排序', align: 'center'},
 | ||||||
|   { dataIndex: 'action', title: '操作', align: 'center'}, |   { dataIndex: 'action', title: '操作', align: 'center' }, | ||||||
| ]; | ]; | ||||||
|  | |||||||
| @ -1,99 +1,28 @@ | |||||||
| <template> |  | ||||||
|   <div class="normal-container project-cfg-box"> |  | ||||||
|     <div class="header-box"> |  | ||||||
|       <a-space> |  | ||||||
|         <a-input |  | ||||||
|           v-model:value="projectName" |  | ||||||
|           placeholder="请输入项目名称" |  | ||||||
|           allow-clear |  | ||||||
|           style="width: 200px" |  | ||||||
|           @change="search" |  | ||||||
|         /> |  | ||||||
|         <a-button type="primary" @click="openCreateModal">新建</a-button> |  | ||||||
|       </a-space> |  | ||||||
|     </div> |  | ||||||
|     <div class="content-box"> |  | ||||||
|       <a-table |  | ||||||
|         :columns="projectCfgCols" |  | ||||||
|         :data-source="dataList" |  | ||||||
|         :pagination="false" |  | ||||||
|         size="small" |  | ||||||
|         bordered |  | ||||||
|       > |  | ||||||
|         <template #bodyCell="{ column, record }"> |  | ||||||
|           <template v-if="column.dataIndex === 'is_show'"> |  | ||||||
|             <a-switch |  | ||||||
|               v-model:checked="record.is_show" |  | ||||||
|               :checkedValue="1" |  | ||||||
|               :unCheckedValue="0" |  | ||||||
|               @change="toChangeStatus(record.project_id, $event)" |  | ||||||
|             /> |  | ||||||
|           </template> |  | ||||||
|           <template v-if="column.dataIndex === 'action'"> |  | ||||||
|             <a-space> |  | ||||||
|               <a-button |  | ||||||
|                 type="link" |  | ||||||
|                 size="small" |  | ||||||
|                 @click="toGetDetail(record.project_id)" |  | ||||||
|               > |  | ||||||
|                 编辑 |  | ||||||
|               </a-button> |  | ||||||
|               <a-popconfirm |  | ||||||
|                 title="确定删除?" |  | ||||||
|                 @confirm="toDelete(record.project_id)" |  | ||||||
|               > |  | ||||||
|                 <a-button type="link" size="small">删除</a-button> |  | ||||||
|               </a-popconfirm> |  | ||||||
|             </a-space> |  | ||||||
|           </template> |  | ||||||
|         </template> |  | ||||||
|       </a-table> |  | ||||||
|       <a-pagination |  | ||||||
|         v-model:current="pageState.page" |  | ||||||
|         :total="pageState.total" |  | ||||||
|         :page-size="pageState.perPage" |  | ||||||
|         :hide-on-single-page="false" |  | ||||||
|         size="small" |  | ||||||
|         class="pagination-box" |  | ||||||
|         @change="toGetProjectList" |  | ||||||
|       /> |  | ||||||
|     </div> |  | ||||||
|     <CreateModal |  | ||||||
|       :width="700" |  | ||||||
|       :open="modalState.visible" |  | ||||||
|       :title="modalState.title" |  | ||||||
|       :type="modalState.type" |  | ||||||
|       :data="modalState.data" |  | ||||||
|       :confirmLoading="saveLoading" |  | ||||||
|       @cancel="modalState.visible = false" |  | ||||||
|       @ok="toSave" |  | ||||||
|     /> |  | ||||||
|   </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script setup> | <script setup> | ||||||
| import { onMounted, ref, reactive } from "vue"; | import { onMounted, reactive, ref } from 'vue'; | ||||||
| import { message } from "ant-design-vue"; | 
 | ||||||
| import { projectCfgCols } from "./config"; | import { message } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | import CreateModal from './components/create-modal.vue'; | ||||||
|  | import { projectCfgCols } from './config'; | ||||||
| import { | import { | ||||||
|   getProjectList, |  | ||||||
|   saveProject, |  | ||||||
|   deleteProject, |   deleteProject, | ||||||
|   getProjectDetail, |   getProjectDetail, | ||||||
|  |   getProjectList, | ||||||
|  |   saveProject, | ||||||
|   updateStatus, |   updateStatus, | ||||||
| } from "./service"; | } from './service'; | ||||||
| import CreateModal from "./components/create-modal.vue"; |  | ||||||
| 
 | 
 | ||||||
| const dataList = ref([]); | const dataList = ref([]); | ||||||
| const listLoading = ref(false); | const listLoading = ref(false); | ||||||
| const saveLoading = ref(false); | const saveLoading = ref(false); | ||||||
| const detailLoading = ref(false); | const detailLoading = ref(false); | ||||||
| const projectName = ref(""); | const projectName = ref(''); | ||||||
| 
 | 
 | ||||||
| const modalState = reactive({ | const modalState = reactive({ | ||||||
|   title: undefined, |   title: undefined, | ||||||
|   visible: false, |   visible: false, | ||||||
|   type: "", // add - 新建,edit - 编辑 |   type: '', // add - 新建,edit - 编辑 | ||||||
|   data: { |   data: { | ||||||
|     project_name: undefined, |     project_name: undefined, | ||||||
|     is_show: 0, |     is_show: 0, | ||||||
| @ -137,7 +66,7 @@ const toSave = (data) => { | |||||||
|   saveLoading.value = true; |   saveLoading.value = true; | ||||||
|   saveProject(data) |   saveProject(data) | ||||||
|     .then(() => { |     .then(() => { | ||||||
|       message.success("保存成功"); |       message.success('保存成功'); | ||||||
|       modalState.visible = false; |       modalState.visible = false; | ||||||
|       toGetProjectList(); |       toGetProjectList(); | ||||||
|     }) |     }) | ||||||
| @ -150,8 +79,8 @@ const toSave = (data) => { | |||||||
| const toGetDetail = (projectId) => { | const toGetDetail = (projectId) => { | ||||||
|   detailLoading.value = true; |   detailLoading.value = true; | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "编辑"; |   modalState.title = '编辑'; | ||||||
|   modalState.type = "edit"; |   modalState.type = 'edit'; | ||||||
|   getProjectDetail({ projectId }).then((res) => { |   getProjectDetail({ projectId }).then((res) => { | ||||||
|     modalState.data = res.data; |     modalState.data = res.data; | ||||||
|   }); |   }); | ||||||
| @ -160,14 +89,14 @@ const toGetDetail = (projectId) => { | |||||||
| // 删除 | // 删除 | ||||||
| const toDelete = (id) => { | const toDelete = (id) => { | ||||||
|   deleteProject({ projectId: id }).then(() => { |   deleteProject({ projectId: id }).then(() => { | ||||||
|     message.success("删除成功"); |     message.success('删除成功'); | ||||||
|     search(); |     search(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const toChangeStatus = (id, status) => { | const toChangeStatus = (id, status) => { | ||||||
|   updateStatus({ project_id: id, status }).then(() => { |   updateStatus({ project_id: id, status }).then(() => { | ||||||
|     message.success("修改成功"); |     message.success('修改成功'); | ||||||
|     search(); |     search(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -180,12 +109,85 @@ const search = () => { | |||||||
| // 点击新建 | // 点击新建 | ||||||
| const openCreateModal = () => { | const openCreateModal = () => { | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "新建"; |   modalState.title = '新建'; | ||||||
|   modalState.type = "add"; |   modalState.type = 'add'; | ||||||
|   modalState.data = {}; |   modalState.data = {}; | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | <template> | ||||||
|  |   <div class="normal-container project-cfg-box"> | ||||||
|  |     <div class="header-box"> | ||||||
|  |       <a-space> | ||||||
|  |         <a-input | ||||||
|  |           v-model:value="projectName" | ||||||
|  |           placeholder="请输入项目名称" | ||||||
|  |           allow-clear | ||||||
|  |           style="width: 200px" | ||||||
|  |           @change="search" | ||||||
|  |         /> | ||||||
|  |         <a-button type="primary" @click="openCreateModal">新建</a-button> | ||||||
|  |       </a-space> | ||||||
|  |     </div> | ||||||
|  |     <div class="content-box"> | ||||||
|  |       <a-table | ||||||
|  |         :columns="projectCfgCols" | ||||||
|  |         :data-source="dataList" | ||||||
|  |         :pagination="false" | ||||||
|  |         size="small" | ||||||
|  |         bordered | ||||||
|  |       > | ||||||
|  |         <template #bodyCell="{ column, record }"> | ||||||
|  |           <template v-if="column.dataIndex === 'is_show'"> | ||||||
|  |             <a-switch | ||||||
|  |               v-model:checked="record.is_show" | ||||||
|  |               :checked-value="1" | ||||||
|  |               :un-checked-value="0" | ||||||
|  |               @change="toChangeStatus(record.project_id, $event)" | ||||||
|  |             /> | ||||||
|  |           </template> | ||||||
|  |           <template v-if="column.dataIndex === 'action'"> | ||||||
|  |             <a-space> | ||||||
|  |               <a-button | ||||||
|  |                 type="link" | ||||||
|  |                 size="small" | ||||||
|  |                 @click="toGetDetail(record.project_id)" | ||||||
|  |               > | ||||||
|  |                 编辑 | ||||||
|  |               </a-button> | ||||||
|  |               <a-popconfirm | ||||||
|  |                 title="确定删除?" | ||||||
|  |                 @confirm="toDelete(record.project_id)" | ||||||
|  |               > | ||||||
|  |                 <a-button type="link" size="small">删除</a-button> | ||||||
|  |               </a-popconfirm> | ||||||
|  |             </a-space> | ||||||
|  |           </template> | ||||||
|  |         </template> | ||||||
|  |       </a-table> | ||||||
|  |       <a-pagination | ||||||
|  |         v-model:current="pageState.page" | ||||||
|  |         :total="pageState.total" | ||||||
|  |         :page-size="pageState.perPage" | ||||||
|  |         :hide-on-single-page="false" | ||||||
|  |         size="small" | ||||||
|  |         class="pagination-box" | ||||||
|  |         @change="toGetProjectList" | ||||||
|  |       /> | ||||||
|  |     </div> | ||||||
|  |     <CreateModal | ||||||
|  |       :width="700" | ||||||
|  |       :open="modalState.visible" | ||||||
|  |       :title="modalState.title" | ||||||
|  |       :type="modalState.type" | ||||||
|  |       :data="modalState.data" | ||||||
|  |       :confirm-loading="saveLoading" | ||||||
|  |       @cancel="modalState.visible = false" | ||||||
|  |       @ok="toSave" | ||||||
|  |     /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
| <style lang="less" scope> | <style lang="less" scope> | ||||||
| .header-box { | .header-box { | ||||||
|   margin-bottom: 10px; |   margin-bottom: 10px; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| // 获取项目列表
 | // 获取项目列表
 | ||||||
| export function getProjectList({ page, perPage, projectName }) { | export function getProjectList({ page, perPage, projectName }) { | ||||||
|  | |||||||
| @ -46,12 +46,12 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { ref, watch } from "vue"; | import { ref, watch } from 'vue'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   type: { |   type: { | ||||||
|     type: String, |     type: String, | ||||||
|     default: "add", |     default: 'add', | ||||||
|   }, |   }, | ||||||
|   data: { |   data: { | ||||||
|     type: Object, |     type: Object, | ||||||
| @ -59,22 +59,22 @@ const props = defineProps({ | |||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(["ok"]); | const emit = defineEmits(['ok']); | ||||||
| const formRules = { | const formRules = { | ||||||
|   field_title: [ |   field_title: [ | ||||||
|     { required: true, message: "请输入字段标题", trigger: "submit" }, |     { required: true, message: '请输入字段标题', trigger: 'submit' }, | ||||||
|   ], |   ], | ||||||
|   field_name: [ |   field_name: [ | ||||||
|     { required: true, message: "请输入字段名称", trigger: "submit" }, |     { required: true, message: '请输入字段名称', trigger: 'submit' }, | ||||||
|   ], |   ], | ||||||
|   field_type_id: [ |   field_type_id: [ | ||||||
|     { required: true, message: "请选择字段类型", trigger: "submit" }, |     { required: true, message: '请选择字段类型', trigger: 'submit' }, | ||||||
|   ], |   ], | ||||||
|   belong_to_table: [ |   belong_to_table: [ | ||||||
|     { required: true, message: "请输入所属表", trigger: "submit" }, |     { required: true, message: '请输入所属表', trigger: 'submit' }, | ||||||
|   ], |   ], | ||||||
|   original_sql: [ |   original_sql: [ | ||||||
|     { required: true, message: "请输入sql数据源", trigger: "submit" }, |     { required: true, message: '请输入sql数据源', trigger: 'submit' }, | ||||||
|   ], |   ], | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -92,19 +92,19 @@ const formData = ref({ | |||||||
| watch( | watch( | ||||||
|   () => props.type, |   () => props.type, | ||||||
|   (newVal) => { |   (newVal) => { | ||||||
|     if (newVal === "add") { |     if (newVal === 'add') { | ||||||
|       resetFormData(); |       resetFormData(); | ||||||
|     } else { |     } else { | ||||||
|       formData.value = props.data; |       formData.value = props.data; | ||||||
|     } |     } | ||||||
|   } |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| const resetFormData = () => {}; | const resetFormData = () => {}; | ||||||
| 
 | 
 | ||||||
| const handleOk = () => { | const handleOk = () => { | ||||||
|   formRef.value.validate().then(() => { |   formRef.value.validate().then(() => { | ||||||
|     emit("ok", formData.value); |     emit('ok', formData.value); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| export const viewCfgCols = [ | export const viewCfgCols = [ | ||||||
|   { dataIndex: 'field_name', title: '字段名称', align: 'center'}, |   { dataIndex: 'field_name', title: '字段名称', align: 'center' }, | ||||||
|   { dataIndex: 'field_title', title: '字段标题', align: 'center'}, |   { dataIndex: 'field_title', title: '字段标题', align: 'center' }, | ||||||
|   { dataIndex: 'field_type_name', title: '字段类型', align: 'center'}, |   { dataIndex: 'field_type_name', title: '字段类型', align: 'center' }, | ||||||
|   { dataIndex: 'is_search', title: '是否可搜索', align: 'center'}, |   { dataIndex: 'is_search', title: '是否可搜索', align: 'center' }, | ||||||
|   { dataIndex: 'sort', title: '排序', align: 'center'}, |   { dataIndex: 'sort', title: '排序', align: 'center' }, | ||||||
|   { dataIndex: 'belong_to_table', title: '所属表名称', align: 'center'}, |   { dataIndex: 'belong_to_table', title: '所属表名称', align: 'center' }, | ||||||
|   { dataIndex: 'original_sql', title: 'sql数据源', align: 'center'}, |   { dataIndex: 'original_sql', title: 'sql数据源', align: 'center' }, | ||||||
|   { dataIndex: 'action', title: '操作', align: 'center'}, |   { dataIndex: 'action', title: '操作', align: 'center' }, | ||||||
| ]; | ]; | ||||||
|  | |||||||
| @ -69,26 +69,26 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { onMounted, ref, reactive } from "vue"; | import { onMounted, ref, reactive } from 'vue'; | ||||||
| import { viewCfgCols } from "./config"; | import { viewCfgCols } from './config'; | ||||||
| import { | import { | ||||||
|   getFieldList, |   getFieldList, | ||||||
|   deleteField, |   deleteField, | ||||||
|   saveField, |   saveField, | ||||||
|   getFieldDetail, |   getFieldDetail, | ||||||
| } from "./service"; | } from './service'; | ||||||
| import CreateModal from "./components/create-modal.vue"; | import CreateModal from './components/create-modal.vue'; | ||||||
| import { message } from "ant-design-vue"; | import { message } from 'ant-design-vue'; | ||||||
| 
 | 
 | ||||||
| const listLoading = ref(false); | const listLoading = ref(false); | ||||||
| const saveLoading = ref(false); | const saveLoading = ref(false); | ||||||
| const dataList = ref([]); | const dataList = ref([]); | ||||||
| const fieldName = ref(""); | const fieldName = ref(''); | ||||||
| const modularId = ref(""); | const modularId = ref(''); | ||||||
| const modalState = reactive({ | const modalState = reactive({ | ||||||
|   title: undefined, |   title: undefined, | ||||||
|   visible: false, |   visible: false, | ||||||
|   type: "", // add - 新建,edit - 编辑 |   type: '', // add - 新建,edit - 编辑 | ||||||
|   data: {}, |   data: {}, | ||||||
| }); | }); | ||||||
| const pageState = reactive({ | const pageState = reactive({ | ||||||
| @ -123,7 +123,7 @@ const toSave = (data) => { | |||||||
|   saveLoading.value = true; |   saveLoading.value = true; | ||||||
|   saveField(data) |   saveField(data) | ||||||
|     .then(() => { |     .then(() => { | ||||||
|       message.success("保存成功"); |       message.success('保存成功'); | ||||||
|     }) |     }) | ||||||
|     .finally(() => { |     .finally(() => { | ||||||
|       saveLoading.value = false; |       saveLoading.value = false; | ||||||
| @ -133,8 +133,8 @@ const toSave = (data) => { | |||||||
| // 获取详情 | // 获取详情 | ||||||
| const toGetDetail = (fieldId) => { | const toGetDetail = (fieldId) => { | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "编辑"; |   modalState.title = '编辑'; | ||||||
|   modalState.type = "edit"; |   modalState.type = 'edit'; | ||||||
|   getFieldDetail({ fieldId }).then((res) => { |   getFieldDetail({ fieldId }).then((res) => { | ||||||
|     modalState.data = res.data; |     modalState.data = res.data; | ||||||
|   }); |   }); | ||||||
| @ -143,7 +143,7 @@ const toGetDetail = (fieldId) => { | |||||||
| // 删除 | // 删除 | ||||||
| const toDelete = (fieldId) => { | const toDelete = (fieldId) => { | ||||||
|   deleteField({ field_id: fieldId }).then(() => { |   deleteField({ field_id: fieldId }).then(() => { | ||||||
|     message.success("删除成功"); |     message.success('删除成功'); | ||||||
|     search(); |     search(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -151,8 +151,8 @@ const toDelete = (fieldId) => { | |||||||
| // 点击新建 | // 点击新建 | ||||||
| const openCreateModal = () => { | const openCreateModal = () => { | ||||||
|   modalState.visible = true; |   modalState.visible = true; | ||||||
|   modalState.title = "新建"; |   modalState.title = '新建'; | ||||||
|   modalState.type = "add"; |   modalState.type = 'add'; | ||||||
|   modalState.data = {}; |   modalState.data = {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| // 获取列表
 | // 获取列表
 | ||||||
| export function getFieldList({ modularId, fieldName, page, perPage }) { | export function getFieldList({ modularId, fieldName, page, perPage }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/list", |     url: '/api/v1/field/list', | ||||||
|     params: { |     params: { | ||||||
|       modularId, |       modularId, | ||||||
|       fieldName, |       fieldName, | ||||||
| @ -16,7 +16,7 @@ export function getFieldList({ modularId, fieldName, page, perPage }) { | |||||||
| // 获取详情
 | // 获取详情
 | ||||||
| export function getFieldDetail({ fieldId }) { | export function getFieldDetail({ fieldId }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/info", |     url: '/api/v1/field/info', | ||||||
|     params: { |     params: { | ||||||
|       fieldId, |       fieldId, | ||||||
|     }, |     }, | ||||||
| @ -26,7 +26,7 @@ export function getFieldDetail({ fieldId }) { | |||||||
| // 保存字段
 | // 保存字段
 | ||||||
| export function saveField(data) { | export function saveField(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/field/save", |     url: '/api/v1/field/save', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -34,7 +34,7 @@ export function saveField(data) { | |||||||
| // 删除字段
 | // 删除字段
 | ||||||
| export function deleteField(data) { | export function deleteField(data) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/field/del", |     url: '/api/v1/field/del', | ||||||
|     data, |     data, | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ | |||||||
|                     :title="item.data.preview_name" |                     :title="item.data.preview_name" | ||||||
|                     :is-export="item.data.is_export" |                     :is-export="item.data.is_export" | ||||||
|                     @toFilt=" |                     @toFilt=" | ||||||
|                       (params?:object) => { |                       (params?: object) => { | ||||||
|                         handleSingle(ids[index], params); |                         handleSingle(ids[index], params); | ||||||
|                       } |                       } | ||||||
|                     " |                     " | ||||||
| @ -58,8 +58,8 @@ | |||||||
|                     :title="item.data.preview_name" |                     :title="item.data.preview_name" | ||||||
|                     :filter-config="item.data.filter" |                     :filter-config="item.data.filter" | ||||||
|                     @toFilt=" |                     @toFilt=" | ||||||
|                     (params?:object) => { |                       (params?: object) => { | ||||||
|                       handleSingle(ids[index], params); |                         handleSingle(ids[index], params); | ||||||
|                       } |                       } | ||||||
|                     " |                     " | ||||||
|                   ></y-chart> |                   ></y-chart> | ||||||
| @ -87,8 +87,8 @@ | |||||||
|                       :title="item.data.preview_name" |                       :title="item.data.preview_name" | ||||||
|                       :is-export="item.data.is_export" |                       :is-export="item.data.is_export" | ||||||
|                       @toFilt=" |                       @toFilt=" | ||||||
|                         (params?:object) => { |                         (params?: object) => { | ||||||
|                           handleSingle(ids[index], params,); |                           handleSingle(ids[index], params); | ||||||
|                         } |                         } | ||||||
|                       " |                       " | ||||||
|                     ></y-table> |                     ></y-table> | ||||||
| @ -98,7 +98,7 @@ | |||||||
|                       :title="item.data.preview_name" |                       :title="item.data.preview_name" | ||||||
|                       :filter-config="item.data.filter" |                       :filter-config="item.data.filter" | ||||||
|                       @toFilt=" |                       @toFilt=" | ||||||
|                         (params?:object) => { |                         (params?: object) => { | ||||||
|                           handleSingle(ids[index], params); |                           handleSingle(ids[index], params); | ||||||
|                         } |                         } | ||||||
|                       " |                       " | ||||||
| @ -114,17 +114,17 @@ | |||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { ref, shallowRef, computed, onMounted, watch } from "vue"; | import { ref, shallowRef, computed, onMounted, watch } from 'vue'; | ||||||
| import { useRoute, useRouter } from "vue-router"; | import { useRoute, useRouter } from 'vue-router'; | ||||||
| import { BarsOutlined } from "@ant-design/icons-vue"; | import { BarsOutlined } from '@ant-design/icons-vue'; | ||||||
| // utils | // utils | ||||||
| import PLimit from "p-limit"; | import PLimit from 'p-limit'; | ||||||
| // api | // api | ||||||
| import { searchInfo } from "@/api/preview/index"; | import { searchInfo } from '@/api/preview/index'; | ||||||
| import { getProjectDrop } from "@/api/common"; | import { getProjectDrop } from '@/api/common'; | ||||||
| import { getPageInfo } from "./service"; | import { getPageInfo } from './service'; | ||||||
| import type { SelectProps } from "ant-design-vue"; | import type { SelectProps } from 'ant-design-vue'; | ||||||
| import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper' | import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'; | ||||||
| 
 | 
 | ||||||
| interface ItemDetail { | interface ItemDetail { | ||||||
|   id: number | string; |   id: number | string; | ||||||
| @ -143,13 +143,13 @@ interface Option extends SelectProps { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const VIEW_TYPE = { | const VIEW_TYPE = { | ||||||
|   TABLE: "table", |   TABLE: 'table', | ||||||
|   CHART: "chart", |   CHART: 'chart', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SEARCH_TYPE = { | const SEARCH_TYPE = { | ||||||
|   SEARCH: "search", |   SEARCH: 'search', | ||||||
|   INIT: "init", |   INIT: 'init', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // hooks | // hooks | ||||||
| @ -162,8 +162,11 @@ const projectOptions = shallowRef<Option[]>(); | |||||||
| const isDraggable = false; | const isDraggable = false; | ||||||
| 
 | 
 | ||||||
| const isInQiankun = computed(() => { | const isInQiankun = computed(() => { | ||||||
|   return qiankunWindow?.__POWERED_BY_QIANKUN__ || window?.proxy?.__POWERED_BY_QIANKUN__ |   return ( | ||||||
| }) |     qiankunWindow?.__POWERED_BY_QIANKUN__ || | ||||||
|  |     window?.proxy?.__POWERED_BY_QIANKUN__ | ||||||
|  |   ); | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| const layoutList = computed(() => { | const layoutList = computed(() => { | ||||||
|   return ids.value.map((item, index) => { |   return ids.value.map((item, index) => { | ||||||
| @ -186,9 +189,12 @@ const ids = ref<Item[]>([]); | |||||||
| 
 | 
 | ||||||
| const pLimit = PLimit(2); | const pLimit = PLimit(2); | ||||||
| 
 | 
 | ||||||
| watch(() => route.query.viewId, () => { | watch( | ||||||
|   getPageInfoData() |   () => route.query.viewId, | ||||||
| }) |   () => { | ||||||
|  |     getPageInfoData(); | ||||||
|  |   }, | ||||||
|  | ); | ||||||
| 
 | 
 | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   getProjectList(); |   getProjectList(); | ||||||
| @ -254,19 +260,21 @@ const getSinglePreview = (data: { | |||||||
| 
 | 
 | ||||||
| // 获取页面信息所有的id | // 获取页面信息所有的id | ||||||
| const getPageInfoData = () => { | const getPageInfoData = () => { | ||||||
|   getPageInfo({ mark:projectTag.value, page_id: pageId.value ?? "-1" }) |   getPageInfo({ mark: projectTag.value, page_id: pageId.value ?? '-1' }) | ||||||
|     .then((res) => { |     .then((res) => { | ||||||
|       if (res.code === 200) { |       if (res.code === 200) { | ||||||
|         if (route.query.viewId) { |         if (route.query.viewId) { | ||||||
|           ids.value = res.data?.filter((item: any) => { |           ids.value = res.data | ||||||
|             return item.preview_id === Number(route.query.viewId); |             ?.filter((item: any) => { | ||||||
|           }).map((item: any) => { |               return item.preview_id === Number(route.query.viewId); | ||||||
|             return { |             }) | ||||||
|               id: item.preview_id, |             .map((item: any) => { | ||||||
|               data: item, |               return { | ||||||
|               loading: false, |                 id: item.preview_id, | ||||||
|             } |                 data: item, | ||||||
|           }) |                 loading: false, | ||||||
|  |               }; | ||||||
|  |             }); | ||||||
|         } else { |         } else { | ||||||
|           ids.value = res.data?.map((item: any) => { |           ids.value = res.data?.map((item: any) => { | ||||||
|             return { |             return { | ||||||
| @ -295,14 +303,13 @@ const fetchFn = (delay: number, info: ItemDetail) => { | |||||||
| const getAllCardsData = async () => { | const getAllCardsData = async () => { | ||||||
|   let listDB = []; |   let listDB = []; | ||||||
|   for (let i in ids.value) { |   for (let i in ids.value) { | ||||||
|     listDB.push(pLimit(() => fetchFn(i === "0" ? 200 : 1000, ids.value[i]))); |     listDB.push(pLimit(() => fetchFn(i === '0' ? 200 : 1000, ids.value[i]))); | ||||||
|   } |   } | ||||||
|   await Promise.all(listDB); |   await Promise.all(listDB); | ||||||
|   //此处的listDB就是最后整合的数据 |   //此处的listDB就是最后整合的数据 | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| 
 |  | ||||||
| .view-box { | .view-box { | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   width: 100%; |   width: 100%; | ||||||
| @ -312,7 +319,9 @@ const getAllCardsData = async () => { | |||||||
|   border-radius: 4px; |   border-radius: 4px; | ||||||
|   transition: all 0.3s; |   transition: all 0.3s; | ||||||
|   &:hover { |   &:hover { | ||||||
|     box-shadow: 0 0 20px 0 #0a103205, 0 14px 40px 0 #0a103208, |     box-shadow: | ||||||
|  |       0 0 20px 0 #0a103205, | ||||||
|  |       0 14px 40px 0 #0a103208, | ||||||
|       0 20px 60px 0 #0a10320d; |       0 20px 60px 0 #0a10320d; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| interface PageInfoParams { | interface PageInfoParams { | ||||||
|   mark: string; |   mark: string; | ||||||
|   page_id: number | string; |   page_id: number | string; | ||||||
| } | } | ||||||
| export const getPageInfo = (data: PageInfoParams) => | export const getPageInfo = (data: PageInfoParams) => | ||||||
|   get({ |   get({ | ||||||
|     url: "/api/v1/preview/get-preview-info", |     url: '/api/v1/preview/get-preview-info', | ||||||
|     params: data, |     params: data, | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -1,8 +1,9 @@ | |||||||
| @import "@/assets/styles/variable.less"; | @import '@/assets/styles/variable.less'; | ||||||
| 
 | 
 | ||||||
| // 设置按钮 | // 设置按钮 | ||||||
| :deep(.ycode-ant-btn-primary) { | :deep(.ycode-ant-btn-primary) { | ||||||
|   background-color: @primary-color !important; |   background-color: @primary-color !important; | ||||||
|  | 
 | ||||||
|   &:hover { |   &:hover { | ||||||
|     background-color: @primary-light-color !important; |     background-color: @primary-light-color !important; | ||||||
|   } |   } | ||||||
| @ -10,10 +11,10 @@ | |||||||
| 
 | 
 | ||||||
| // 设置输入框 | // 设置输入框 | ||||||
| :deep( | :deep( | ||||||
|     .ycode-ant-input-affix-wrapper:not( |   .ycode-ant-input-affix-wrapper:not( | ||||||
|         .ycode-ant-input-affix-wrapper-disabled |       .ycode-ant-input-affix-wrapper-disabled | ||||||
|       ):hover |     ):hover | ||||||
|   ) { | ) { | ||||||
|   border-color: @primary-light-color !important; |   border-color: @primary-light-color !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -34,6 +35,7 @@ | |||||||
|   &-focused { |   &-focused { | ||||||
|     border-color: @primary-light-color !important; |     border-color: @primary-light-color !important; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   &-active-bar { |   &-active-bar { | ||||||
|     background-color: @primary-light-color !important; |     background-color: @primary-light-color !important; | ||||||
|   } |   } | ||||||
| @ -41,18 +43,20 @@ | |||||||
| 
 | 
 | ||||||
| // 设置表格 | // 设置表格 | ||||||
| :deep(.ycode-ant-table-thead > tr > th) { | :deep(.ycode-ant-table-thead > tr > th) { | ||||||
|   background-color: @table-head-bg-color !important; |  | ||||||
|   color: @table-head-font-color !important; |   color: @table-head-font-color !important; | ||||||
|  |   background-color: @table-head-bg-color !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 设置分页器 | // 设置分页器 | ||||||
| :deep(.ycode-ant-pagination-item) { | :deep(.ycode-ant-pagination-item) { | ||||||
|   &-active { |   &-active { | ||||||
|     border-color: @primary-color !important; |     border-color: @primary-color !important; | ||||||
|  | 
 | ||||||
|     a { |     a { | ||||||
|       color: @primary-color !important; |       color: @primary-color !important; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   &-link-icon { |   &-link-icon { | ||||||
|     color: @primary-color !important; |     color: @primary-color !important; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -62,7 +62,11 @@ | |||||||
|           <a-button |           <a-button | ||||||
|             class="preview-btn" |             class="preview-btn" | ||||||
|             :loading="previewLoading" |             :loading="previewLoading" | ||||||
|             @click="() => {toPreview({})}" |             @click=" | ||||||
|  |               () => { | ||||||
|  |                 toPreview({}); | ||||||
|  |               } | ||||||
|  |             " | ||||||
|             >预览</a-button |             >预览</a-button | ||||||
|           > |           > | ||||||
|           <a-button type="primary" @click="addViewName">点击保存</a-button> |           <a-button type="primary" @click="addViewName">点击保存</a-button> | ||||||
| @ -113,7 +117,10 @@ | |||||||
|               /> |               /> | ||||||
|               <!-- 数值区间 --> |               <!-- 数值区间 --> | ||||||
|               <div |               <div | ||||||
|                 v-else-if="item.type === 'number_range' && previewData.filterData[item.name]" |                 v-else-if=" | ||||||
|  |                   item.type === 'number_range' && | ||||||
|  |                   previewData.filterData[item.name] | ||||||
|  |                 " | ||||||
|                 class="number_range_box" |                 class="number_range_box" | ||||||
|               > |               > | ||||||
|                 <a-input-number |                 <a-input-number | ||||||
| @ -170,7 +177,11 @@ | |||||||
|               :hide-on-single-page="false" |               :hide-on-single-page="false" | ||||||
|               size="small" |               size="small" | ||||||
|               class="pagination-box" |               class="pagination-box" | ||||||
|               @change="() => { toPreview({}) }" |               @change=" | ||||||
|  |                 () => { | ||||||
|  |                   toPreview({}); | ||||||
|  |                 } | ||||||
|  |               " | ||||||
|             /> |             /> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
| @ -178,7 +189,11 @@ | |||||||
|           v-else-if="previewData.type === 'chart'" |           v-else-if="previewData.type === 'chart'" | ||||||
|           :chart-cfg="previewData.chartCfg" |           :chart-cfg="previewData.chartCfg" | ||||||
|           :filter-config="previewData.filter" |           :filter-config="previewData.filter" | ||||||
|           @toFilt="() => {toPreview({})}" |           @toFilt=" | ||||||
|  |             () => { | ||||||
|  |               toPreview({}); | ||||||
|  |             } | ||||||
|  |           " | ||||||
|         ></y-chart> |         ></y-chart> | ||||||
|         <div class="preview-area" v-else> |         <div class="preview-area" v-else> | ||||||
|           <div><BarChartOutlined /></div> |           <div><BarChartOutlined /></div> | ||||||
| @ -203,21 +218,21 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { onMounted, reactive, ref } from "vue"; | import { onMounted, reactive, ref } from 'vue'; | ||||||
| import { | import { | ||||||
|   getProModularField, |   getProModularField, | ||||||
|   preview, |   preview, | ||||||
|   saveView, |   saveView, | ||||||
|   getShowTypeSelect, |   getShowTypeSelect, | ||||||
|   getFieldOpts, |   getFieldOpts, | ||||||
| } from "./service"; | } from './service'; | ||||||
| import { message } from "ant-design-vue"; | import { message } from 'ant-design-vue'; | ||||||
| import { BarChartOutlined } from "@ant-design/icons-vue"; | import { BarChartOutlined } from '@ant-design/icons-vue'; | ||||||
| import yChart from "@/components/common/y-chart.vue"; | import yChart from '@/components/common/y-chart.vue'; | ||||||
| import { cloneDeep } from "lodash-es"; | import { cloneDeep } from 'lodash-es'; | ||||||
| 
 | 
 | ||||||
| const projectSel = ref([]); // 项目下拉 | const projectSel = ref([]); // 项目下拉 | ||||||
| const modularSel = ref([])  // 数据来源下拉 | const modularSel = ref([]); // 数据来源下拉 | ||||||
| const showTypeSel = ref([]); // 展示类型下拉 | const showTypeSel = ref([]); // 展示类型下拉 | ||||||
| const fieldList = ref([]); // 字段列表 | const fieldList = ref([]); // 字段列表 | ||||||
| const xDataList = ref([]); // x轴数据列表 | const xDataList = ref([]); // x轴数据列表 | ||||||
| @ -235,7 +250,7 @@ const nameVisible = ref(false); | |||||||
| const previewName = ref(); | const previewName = ref(); | ||||||
| 
 | 
 | ||||||
| const previewData = reactive({ | const previewData = reactive({ | ||||||
|   type: "", |   type: '', | ||||||
|   filterConfig: [], // 筛选条件 |   filterConfig: [], // 筛选条件 | ||||||
|   columnConfig: [], // 表格表头 |   columnConfig: [], // 表格表头 | ||||||
|   dataList: [], // 表格数据 |   dataList: [], // 表格数据 | ||||||
| @ -308,23 +323,23 @@ const tranformList = (list) => { | |||||||
|       value: item.field_id, |       value: item.field_id, | ||||||
|     }; |     }; | ||||||
|   }); |   }); | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| // 重置配置数据 | // 重置配置数据 | ||||||
| const resetSelectData = () => { | const resetSelectData = () => { | ||||||
|   showTypeId.value = undefined |   showTypeId.value = undefined; | ||||||
|   isExport.value = 0 |   isExport.value = 0; | ||||||
|   fieldList.value = []; |   fieldList.value = []; | ||||||
|   fieldIds.value = []; |   fieldIds.value = []; | ||||||
|   xDataList.value = []; |   xDataList.value = []; | ||||||
|   yDataList.value = []; |   yDataList.value = []; | ||||||
|   xDataId.value = undefined; |   xDataId.value = undefined; | ||||||
|   yDataId.value = []; |   yDataId.value = []; | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| // 重置预览数据 | // 重置预览数据 | ||||||
| const resetPreviewData = () => { | const resetPreviewData = () => { | ||||||
|   previewData.type = ""; |   previewData.type = ''; | ||||||
|   previewData.filterConfig = []; |   previewData.filterConfig = []; | ||||||
|   previewData.columnConfig = []; |   previewData.columnConfig = []; | ||||||
|   previewData.dataList = []; |   previewData.dataList = []; | ||||||
| @ -336,14 +351,17 @@ const resetPreviewData = () => { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // 请求预览数据 | // 请求预览数据 | ||||||
| const toPreview = ({filter}) => { | const toPreview = ({ filter }) => { | ||||||
|   previewLoading.value = true; |   previewLoading.value = true; | ||||||
|   let filterData |   let filterData; | ||||||
|   if (!filter) { |   if (!filter) { | ||||||
|     const cloneFilter = cloneDeep(previewData.filterConfig) |     const cloneFilter = cloneDeep(previewData.filterConfig); | ||||||
|     filterData = cloneFilter |     filterData = cloneFilter | ||||||
|       .filter((item) => { |       .filter((item) => { | ||||||
|         return previewData.filterData[item.name] !== undefined && previewData.filterData[item.name] !== null; |         return ( | ||||||
|  |           previewData.filterData[item.name] !== undefined && | ||||||
|  |           previewData.filterData[item.name] !== null | ||||||
|  |         ); | ||||||
|       }) |       }) | ||||||
|       .map((item) => { |       .map((item) => { | ||||||
|         if (item.type === 'time' && previewData.filterData[item.name]) { |         if (item.type === 'time' && previewData.filterData[item.name]) { | ||||||
| @ -351,24 +369,36 @@ const toPreview = ({filter}) => { | |||||||
|           return { |           return { | ||||||
|             name: item.name, |             name: item.name, | ||||||
|             type: item.type, |             type: item.type, | ||||||
|             start_time: previewData.filterData[item.name][0].format('YYYY-MM-DD'), |             start_time: | ||||||
|  |               previewData.filterData[item.name][0].format('YYYY-MM-DD'), | ||||||
|             end_time: previewData.filterData[item.name][1].format('YYYY-MM-DD'), |             end_time: previewData.filterData[item.name][1].format('YYYY-MM-DD'), | ||||||
|           }; |           }; | ||||||
|         } else if (item.type === 'date_time' && previewData.filterData[item.name]) { |         } else if ( | ||||||
|  |           item.type === 'date_time' && | ||||||
|  |           previewData.filterData[item.name] | ||||||
|  |         ) { | ||||||
|           // 带时分的日期类型参数 |           // 带时分的日期类型参数 | ||||||
|           return { |           return { | ||||||
|             name: item.name, |             name: item.name, | ||||||
|             type: item.type, |             type: item.type, | ||||||
|             start_time: previewData.filterData[item.name][0].format('YYYY-MM-DD HH:mm') + ':00', |             start_time: | ||||||
|             end_time: previewData.filterData[item.name][1].format('YYYY-MM-DD HH:mm') + ':59', |               previewData.filterData[item.name][0].format('YYYY-MM-DD HH:mm') + | ||||||
|  |               ':00', | ||||||
|  |             end_time: | ||||||
|  |               previewData.filterData[item.name][1].format('YYYY-MM-DD HH:mm') + | ||||||
|  |               ':59', | ||||||
|           }; |           }; | ||||||
|         } else if (item.type === 'number_range') { |         } else if (item.type === 'number_range') { | ||||||
|           // 数值区间 |           // 数值区间 | ||||||
|           return { |           return { | ||||||
|             name: item.name, |             name: item.name, | ||||||
|             type: item.type, |             type: item.type, | ||||||
|             min: previewData.filterData[item.name].min ? String(previewData.filterData[item.name].min) : '', |             min: previewData.filterData[item.name].min | ||||||
|             max: previewData.filterData[item.name].max ? String(previewData.filterData[item.name].max) : '', |               ? String(previewData.filterData[item.name].min) | ||||||
|  |               : '', | ||||||
|  |             max: previewData.filterData[item.name].max | ||||||
|  |               ? String(previewData.filterData[item.name].max) | ||||||
|  |               : '', | ||||||
|           }; |           }; | ||||||
|         } else { |         } else { | ||||||
|           return { |           return { | ||||||
| @ -395,17 +425,22 @@ const toPreview = ({filter}) => { | |||||||
|   }) |   }) | ||||||
|     .then((res) => { |     .then((res) => { | ||||||
|       previewData.type = res.data.type; |       previewData.type = res.data.type; | ||||||
|       if (res.data.type === "table") { |       if (res.data.type === 'table') { | ||||||
|         previewData.filterConfig = res.data.filter; |         previewData.filterConfig = res.data.filter; | ||||||
|         previewData.filterConfig.forEach((item) => { |         previewData.filterConfig.forEach((item) => { | ||||||
|           if (item.type === 'number_range' && !previewData.filterData[item.name]) { |           if ( | ||||||
|  |             item.type === 'number_range' && | ||||||
|  |             !previewData.filterData[item.name] | ||||||
|  |           ) { | ||||||
|             previewData.filterData[item.name] = { |             previewData.filterData[item.name] = { | ||||||
|               ...item, |               ...item, | ||||||
|               min: undefined, |               min: undefined, | ||||||
|               max: undefined, |               max: undefined, | ||||||
|             }; |             }; | ||||||
|           } else { |           } else { | ||||||
|             previewData.filterData[item.name] = previewData.filterData[item.name] |             previewData.filterData[item.name] = previewData.filterData[ | ||||||
|  |               item.name | ||||||
|  |             ] | ||||||
|               ? previewData.filterData[item.name] |               ? previewData.filterData[item.name] | ||||||
|               : undefined; |               : undefined; | ||||||
|           } |           } | ||||||
| @ -413,7 +448,7 @@ const toPreview = ({filter}) => { | |||||||
|         previewData.columnConfig = res.data.header; |         previewData.columnConfig = res.data.header; | ||||||
|         previewData.dataList = res.data.data; |         previewData.dataList = res.data.data; | ||||||
|         previewData.total = res.data.count; |         previewData.total = res.data.count; | ||||||
|         previewData.isExport = res.data.is_export |         previewData.isExport = res.data.is_export; | ||||||
|       } else { |       } else { | ||||||
|         previewData.chartCfg = res.data.config; |         previewData.chartCfg = res.data.config; | ||||||
|         previewData.filter = res.data.filter; |         previewData.filter = res.data.filter; | ||||||
| @ -431,7 +466,7 @@ const addViewName = () => { | |||||||
| 
 | 
 | ||||||
| const toSaveView = () => { | const toSaveView = () => { | ||||||
|   if (!previewName.value) { |   if (!previewName.value) { | ||||||
|     message.error("请输入名称"); |     message.error('请输入名称'); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   saveView({ |   saveView({ | ||||||
| @ -443,7 +478,7 @@ const toSaveView = () => { | |||||||
|     yDataId: yDataId.value?.toString(), |     yDataId: yDataId.value?.toString(), | ||||||
|     isExport: isExport.value, |     isExport: isExport.value, | ||||||
|   }).then(() => { |   }).then(() => { | ||||||
|     message.success("保存成功,可前往视图列表查看"); |     message.success('保存成功,可前往视图列表查看'); | ||||||
|     nameVisible.value = false; |     nameVisible.value = false; | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| // 项目-表-字段下拉
 | // 项目-表-字段下拉
 | ||||||
| export function getProModularField() { | export function getProModularField() { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/get-project-modular-field-drop", |     url: '/api/v1/field/get-project-modular-field-drop', | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -17,7 +17,7 @@ export function getShowTypeSelect() { | |||||||
| // 字段列表
 | // 字段列表
 | ||||||
| export function getFieldOpts({ modularId, showTypeId }) { | export function getFieldOpts({ modularId, showTypeId }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/preview/get-preview-field", |     url: '/api/v1/preview/get-preview-field', | ||||||
|     params: { |     params: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|       show_type_id: showTypeId, |       show_type_id: showTypeId, | ||||||
| @ -26,9 +26,19 @@ export function getFieldOpts({ modularId, showTypeId }) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 预览
 | // 预览
 | ||||||
| export function preview({ modularId, fieldIds, page, perPage, filter, showTypeId, xDataId, yDataId, isExport }) { | export function preview({ | ||||||
|  |   modularId, | ||||||
|  |   fieldIds, | ||||||
|  |   page, | ||||||
|  |   perPage, | ||||||
|  |   filter, | ||||||
|  |   showTypeId, | ||||||
|  |   xDataId, | ||||||
|  |   yDataId, | ||||||
|  |   isExport, | ||||||
|  | }) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "api/v1/preview/view", |     url: 'api/v1/preview/view', | ||||||
|     data: { |     data: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|       field_ids: fieldIds, |       field_ids: fieldIds, | ||||||
| @ -44,9 +54,16 @@ export function preview({ modularId, fieldIds, page, perPage, filter, showTypeId | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 点击保存
 | // 点击保存
 | ||||||
| export function saveView({ modularId, fieldIds, previewName, showTypeId, xDataId, yDataId }) { | export function saveView({ | ||||||
|  |   modularId, | ||||||
|  |   fieldIds, | ||||||
|  |   previewName, | ||||||
|  |   showTypeId, | ||||||
|  |   xDataId, | ||||||
|  |   yDataId, | ||||||
|  | }) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "api/v1/preview/save", |     url: 'api/v1/preview/save', | ||||||
|     data: { |     data: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|       field_ids: fieldIds, |       field_ids: fieldIds, | ||||||
|  | |||||||
| @ -83,7 +83,8 @@ | |||||||
|           @toFilt=" |           @toFilt=" | ||||||
|             (params) => { |             (params) => { | ||||||
|               toGetViewInfo(params); |               toGetViewInfo(params); | ||||||
|             }" |             } | ||||||
|  |           " | ||||||
|         /> |         /> | ||||||
|         <y-chart |         <y-chart | ||||||
|           v-else-if="selectViewInfo.type === 'chart'" |           v-else-if="selectViewInfo.type === 'chart'" | ||||||
| @ -102,12 +103,12 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { onMounted, ref, reactive } from "vue"; | import { onMounted, ref, reactive } from 'vue'; | ||||||
| import { getProModular, getViewList, getViewInfo, deleteView } from "./service"; | import { getProModular, getViewList, getViewInfo, deleteView } from './service'; | ||||||
| import { viewListCols } from "./config"; | import { viewListCols } from './config'; | ||||||
| import yTable from "@/components/common/y-table.vue"; | import yTable from '@/components/common/y-table.vue'; | ||||||
| import { message } from "ant-design-vue"; | import { message } from 'ant-design-vue'; | ||||||
| import { BarChartOutlined } from "@ant-design/icons-vue"; | import { BarChartOutlined } from '@ant-design/icons-vue'; | ||||||
| 
 | 
 | ||||||
| const projectSel = ref([]); | const projectSel = ref([]); | ||||||
| const modularSel = ref([]); | const modularSel = ref([]); | ||||||
| @ -116,13 +117,13 @@ const modularId = ref(); | |||||||
| const dataList = ref([]); | const dataList = ref([]); | ||||||
| const selectedRowId = ref(); | const selectedRowId = ref(); | ||||||
| const selectViewInfo = ref({ | const selectViewInfo = ref({ | ||||||
|   type: "", |   type: '', | ||||||
|   filter: [], |   filter: [], | ||||||
|   config: { |   config: { | ||||||
|     line: { |     line: { | ||||||
|       data: [] |       data: [], | ||||||
|     } |     }, | ||||||
|   } |   }, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const pageState = reactive({ | const pageState = reactive({ | ||||||
| @ -140,7 +141,7 @@ const toGetProModular = () => { | |||||||
|     projectSel.value = res.data; |     projectSel.value = res.data; | ||||||
|     if (res.data.length) { |     if (res.data.length) { | ||||||
|       projectId.value = res.data[0].value; |       projectId.value = res.data[0].value; | ||||||
|       onProjectChange(projectId.value) |       onProjectChange(projectId.value); | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| @ -177,7 +178,7 @@ const onModularChange = () => { | |||||||
| 
 | 
 | ||||||
| const toDelete = (previewId) => { | const toDelete = (previewId) => { | ||||||
|   deleteView({ previewId }).then(() => { |   deleteView({ previewId }).then(() => { | ||||||
|     message.success("删除成功"); |     message.success('删除成功'); | ||||||
|     toGetList(); |     toGetList(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
| import { get, post } from "@/utils/request"; | import { get, post } from '@/utils/request'; | ||||||
| 
 | 
 | ||||||
| // 联动下拉
 | // 联动下拉
 | ||||||
| export function getProModular() { | export function getProModular() { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/field/get-project-modular-drop", |     url: '/api/v1/field/get-project-modular-drop', | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 视图列表
 | // 视图列表
 | ||||||
| export function getViewList({ modularId, page = 1, perPage = 20 }) { | export function getViewList({ modularId, page = 1, perPage = 20 }) { | ||||||
|   return get({ |   return get({ | ||||||
|     url: "/api/v1/preview/list", |     url: '/api/v1/preview/list', | ||||||
|     params: { |     params: { | ||||||
|       modular_id: modularId, |       modular_id: modularId, | ||||||
|       page, |       page, | ||||||
| @ -27,7 +27,7 @@ export function getViewInfo({ | |||||||
|   filter = [], |   filter = [], | ||||||
| }) { | }) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/preview/info", |     url: '/api/v1/preview/info', | ||||||
|     data: { |     data: { | ||||||
|       preview_id: previewId, |       preview_id: previewId, | ||||||
|       page, |       page, | ||||||
| @ -40,7 +40,7 @@ export function getViewInfo({ | |||||||
| // 删除视图
 | // 删除视图
 | ||||||
| export function deleteView({ previewId }) { | export function deleteView({ previewId }) { | ||||||
|   return post({ |   return post({ | ||||||
|     url: "/api/v1/preview/del", |     url: '/api/v1/preview/del', | ||||||
|     data: { |     data: { | ||||||
|       preview_id: previewId, |       preview_id: previewId, | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { defineConfig } from "@farmfe/core"; | import { defineConfig } from '@farmfe/core'; | ||||||
| 
 | 
 | ||||||
| export default defineConfig({ | export default defineConfig({ | ||||||
|   compilation: { |   compilation: { | ||||||
|     input: { |     input: { | ||||||
|       index: "./src/index.ts", |       index: './src/index.ts', | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { onLCP, onINP, onCLS } from "web-vitals"; | import { onCLS, onINP, onLCP } from 'web-vitals'; | ||||||
| // import { initializeApp } from "firebase/app";
 | // import { initializeApp } from "firebase/app";
 | ||||||
| // import { getAnalytics } from "firebase/analytics";
 | // import { getAnalytics } from "firebase/analytics";
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 wangxuefeng
						wangxuefeng