소스 검색

feat: 新增页面预览方式

奔跑的面条 3 년 전
부모
커밋
3d1ed95bed

+ 1 - 1
index.html

@@ -25,7 +25,7 @@
       </div>
     </div>
     <div class="mobile-terminal">
-      <p>请使用 Web 端进行查看呢 ψ(`∇´)ψ</p>
+      <p>请使用 Web 端进行查看</p>
     </div>
     <script type="module" src="/src/main.ts"></script>
   </body>

+ 1 - 1
package.json

@@ -33,7 +33,7 @@
     "@types/node": "^16.11.26",
     "@typescript-eslint/eslint-plugin": "^5.18.0",
     "@typescript-eslint/parser": "^5.18.0",
-    "@vicons/carbon": "^0.11.0",
+    "@vicons/carbon": "^0.12.0",
     "@vicons/ionicons5": "~0.11.0",
     "@vitejs/plugin-vue": "^1.10.2",
     "@vitejs/plugin-vue-jsx": "^1.3.9",

+ 4 - 4
pnpm-lock.yaml

@@ -7,7 +7,7 @@ specifiers:
   '@types/node': ^16.11.26
   '@typescript-eslint/eslint-plugin': ^5.18.0
   '@typescript-eslint/parser': ^5.18.0
-  '@vicons/carbon': ^0.11.0
+  '@vicons/carbon': ^0.12.0
   '@vicons/ionicons5': ~0.11.0
   '@vitejs/plugin-vue': ^1.10.2
   '@vitejs/plugin-vue-jsx': ^1.3.9
@@ -78,7 +78,7 @@ devDependencies:
   '@types/node': 16.11.26
   '@typescript-eslint/eslint-plugin': 5.18.0_a07dca3bdfc4bfa60f4dda0c1f9e3287
   '@typescript-eslint/parser': 5.18.0_eslint@8.12.0+typescript@4.6.3
-  '@vicons/carbon': 0.11.0
+  '@vicons/carbon': 0.12.0
   '@vicons/ionicons5': 0.11.0
   '@vitejs/plugin-vue': 1.10.2_vite@2.9.5
   '@vitejs/plugin-vue-jsx': 1.3.9
@@ -830,8 +830,8 @@ packages:
       eslint-visitor-keys: 3.3.0
     dev: true
 
-  /@vicons/carbon/0.11.0:
-    resolution: {integrity: sha512-+Wkl8wOP1GR7jS+OKcsJ58NnZr4i+BZhbpLRtgpZQui1zFpYjoWinwvYKLjGKJ/oiR10Q237cBDjGwmMSzXqTg==}
+  /@vicons/carbon/0.12.0:
+    resolution: {integrity: sha512-kCOgr/ZOhZzoiFLJ8pwxMa2TMxrkCUOA22qExPabus35F4+USqzcsxaPoYtqRd9ROOYiHrSqwapak/ywF0D9bg==}
     dev: true
 
   /@vicons/ionicons5/0.11.0:

+ 4 - 4
src/enums/pluginEnum.ts

@@ -1,6 +1,6 @@
 export enum DialogEnum {
-  delete = 'delete',
-  warning = 'warning',
-  error = 'error',
-  success = 'success'
+  DELETE = 'delete',
+  WARNING = 'warning',
+  ERROR = 'error',
+  SUCCESS = 'success'
 }

+ 14 - 4
src/enums/styleEnum.ts

@@ -1,9 +1,19 @@
+// 主题
 export enum ThemeEnum {
-  dark = 'dark',
-  light = 'light'
+  DARK = 'dark',
+  LIGHT = 'light'
 }
 
+// 语言
 export enum LangEnum {
-  zh = 'zh',
-  en = 'en'
+  ZH = 'ZH',
+  EN = 'EN'
 }
+
+// 预览展示
+export enum PreviewScaleEnum {
+  FIT = 'fit',
+  SCROLL_Y = 'scrollY',
+  SCROLL_X = 'scrollX',
+  FULL = 'full'
+}

+ 169 - 16
src/hooks/usePreviewScale.hook.ts

@@ -1,44 +1,99 @@
-import { ref } from 'vue'
 import throttle from 'lodash/throttle'
 
-// * 屏幕缩放适配
-export const usePreviewScale = (
+// 拆出来是为了更好的分离单独复用
+
+// * 屏幕缩放适配(两边留白)
+export const usePreviewFitScale = (
   width: number,
   height: number,
-  scaleDom: HTMLElement | null
+  scaleDom: HTMLElement | null,
+  callback?: (scale: {
+    width: number;
+    height: number;
+  }) => void
 ) => {
-  // * 指向最外层容器(没生效不知道为啥)
-  const appRef = ref()
-
-  // * 屏幕尺寸(px)
+  // * 画布尺寸(px)
   const baseWidth = width
   const baseHeight = height
 
   // * 默认缩放值
   const scale = {
-    width: '1',
-    height: '1',
+    width: 1,
+    height: 1,
   }
 
   // * 需保持的比例
   const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
   const calcRate = () => {
-    // 当前宽高比
+    // 当前屏幕宽高比
     const currentRate = parseFloat(
       (window.innerWidth / window.innerHeight).toFixed(5)
     )
     if (scaleDom) {
       if (currentRate > baseProportion) {
         // 表示更宽
-        scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
-        scale.height = (window.innerHeight / baseHeight).toFixed(5)
+        scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
+        scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
         scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
       } else {
         // 表示更高
-        scale.height = (window.innerWidth / baseProportion / baseHeight).toFixed(5)
-        scale.width = (window.innerWidth / baseWidth).toFixed(5)
+        scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
+        scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
         scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
       }
+      if (callback) callback(scale)
+    }
+  }
+
+  const resize = throttle(() => {
+    calcRate()
+  }, 200)
+
+  // * 改变窗口大小重新绘制
+  const windowResize = () => {
+    window.addEventListener('resize', resize)
+  }
+
+  // * 改变窗口大小重新绘制
+  const unWindowResize = () => {
+    window.removeEventListener('resize', resize)
+  }
+
+  return {
+    calcRate,
+    windowResize,
+    unWindowResize,
+  }
+}
+
+// *  X轴撑满,Y轴滚动条
+export const usePreviewScrollYScale = (
+  width: number,
+  height: number,
+  scaleDom: HTMLElement | null,
+  callback?: (scale: {
+    width: number;
+    height: number;
+  }) => void
+) => {
+  // * 画布尺寸(px)
+  const baseWidth = width
+  const baseHeight = height
+
+  // * 默认缩放值
+  const scale = {
+    width: 1,
+    height: 1,
+  }
+
+  // * 需保持的比例
+  const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
+  const calcRate = () => {
+    if (scaleDom) {
+      scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
+      scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
+      scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
+      if (callback) callback(scale)
     }
   }
 
@@ -57,9 +112,107 @@ export const usePreviewScale = (
   }
 
   return {
-    appRef,
     calcRate,
     windowResize,
     unWindowResize,
   }
 }
+
+// *  Y轴撑满,X轴滚动条
+export const usePreviewScrollXScale = (
+  width: number,
+  height: number,
+  scaleDom: HTMLElement | null,
+  callback?: (scale: {
+    width: number;
+    height: number;
+  }) => void
+) => {
+  // * 画布尺寸(px)
+  const baseWidth = width
+  const baseHeight = height
+
+  // * 默认缩放值
+  const scale = {
+    height: 1,
+    width: 1,
+  }
+
+  // * 需保持的比例
+  const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
+  const calcRate = () => {
+    if (scaleDom) {
+      scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
+      scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
+      scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
+      if (callback) callback(scale)
+    }
+  }
+
+  const resize = throttle(() => {
+    calcRate()
+  }, 200)
+
+  // * 改变窗口大小重新绘制
+  const windowResize = () => {
+    window.addEventListener('resize', resize)
+  }
+
+  // * 改变窗口大小重新绘制
+  const unWindowResize = () => {
+    window.removeEventListener('resize', resize)
+  }
+
+  return {
+    calcRate,
+    windowResize,
+    unWindowResize,
+  }
+}
+
+// * 变形内容,宽高铺满
+export const usePreviewFullScale = (
+  width: number,
+  height: number,
+  scaleDom: HTMLElement | null,
+  callback?: (scale: {
+    width: number;
+    height: number;
+  }) => void
+) => {
+
+  // * 默认缩放值
+  const scale = {
+    width: 1,
+    height: 1,
+  }
+
+  const calcRate = () => {
+    if (scaleDom) {
+      scale.width = parseFloat((window.innerWidth / width).toFixed(5))
+      scale.height = parseFloat((window.innerHeight / height).toFixed(5))
+      scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
+      if (callback) callback(scale)
+    }
+  }
+
+  const resize = throttle(() => {
+    calcRate()
+  }, 200)
+
+  // * 改变窗口大小重新绘制
+  const windowResize = () => {
+    window.addEventListener('resize', resize)
+  }
+
+  // * 改变窗口大小重新绘制
+  const unWindowResize = () => {
+    window.removeEventListener('resize', resize)
+  }
+
+  return {
+    calcRate,
+    windowResize,
+    unWindowResize,
+  }
+}

+ 4 - 4
src/i18n/index.ts

@@ -14,11 +14,11 @@ const langStorage: LangStateType = getLocalStorage(StorageEnum.GO_LANG_STORE)
 export const langList = [
   {
     label: '中文',
-    key: LangEnum.zh
+    key: LangEnum.ZH
   },
   {
     label: 'English',
-    key: LangEnum.en
+    key: LangEnum.EN
   }
 ]
 
@@ -26,8 +26,8 @@ const i18n = createI18n({
   locale: langStorage?.lang || lang,
   fallbackLocale: langStorage?.lang || lang,
   messages: {
-    [LangEnum.zh]: zh,
-    [LangEnum.en]: en
+    [LangEnum.ZH]: zh,
+    [LangEnum.EN]: en
   }
 })
 

+ 10 - 1
src/plugins/icon.ts

@@ -77,6 +77,10 @@ import {
   AlignVerticalBottom as AlignVerticalBottomIcon,
   DocumentAdd as DocumentAddIcon,
   DocumentDownload as DocumentDownloadIcon,
+  Scale as ScaleIcon,
+  FitToScreen as FitToScreenIcon,
+  FitToHeight as FitToHeightIcon,
+  FitToWidth as FitToWidthIcon
 } from '@vicons/carbon'
 
 const ionicons5 = {
@@ -225,7 +229,12 @@ const carbon = {
   // 添加文件
   DocumentAddIcon,
   // 下载文件
-  DocumentDownloadIcon
+  DocumentDownloadIcon,
+  // 预览展示方式
+  ScaleIcon,
+  FitToScreenIcon,
+  FitToHeightIcon,
+  FitToWidthIcon
 }
 
 // https://www.xicons.org/#/ 还有很多

+ 5 - 2
src/settings/designSetting.ts

@@ -1,8 +1,8 @@
-import { LangEnum } from '@/enums/styleEnum'
+import { LangEnum, PreviewScaleEnum } from '@/enums/styleEnum'
 import designColor from './designColor.json'
 
 // 默认语言
-export const lang = LangEnum.zh
+export const lang = LangEnum.ZH
 
 // 水印文字
 export const watermarkText = "GoView 低代码平台"
@@ -45,6 +45,9 @@ export const carouselInterval = 4000
 // 工作台大屏背景图片大小限制(5M)
 export const backgroundImageSize = 5
 
+// 预览展示方式
+export const previewScaleType = PreviewScaleEnum.FIT
+
 // 数据请求间隔
 export const requestInterval = 30
 

+ 4 - 0
src/store/modules/chartEditStore/chartEditStore.d.ts

@@ -1,6 +1,7 @@
 import { CreateComponentType, FilterEnum} from '@/packages/index.d'
 import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
 import { RequestHttpEnum, RequestDataTypeEnum } from '@/enums/httpEnum'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 import type {
   ChartColorsNameType,
   GlobalThemeJsonType,
@@ -46,6 +47,7 @@ export enum EditCanvasConfigEnum {
   BACKGROUND = 'background',
   BACKGROUND_IAMGE = 'backgroundImage',
   SELECT_COLOR = 'selectColor',
+  PREVIEW_SCALE_TYPE = 'previewScaleType',
 }
 
 export interface EditCanvasConfigType {
@@ -72,6 +74,8 @@ export interface EditCanvasConfigType {
   [EditCanvasConfigEnum.CHART_THEME_SETTING]: GlobalThemeJsonType
   // 图表主题颜色
   [EditCanvasConfigEnum.SELECT_COLOR]: boolean
+  // 预览展示方式
+  [EditCanvasConfigEnum.PREVIEW_SCALE_TYPE]: PreviewScaleEnum
 }
 
 // 坐标轴信息

+ 5 - 2
src/store/modules/chartEditStore/chartEditStore.ts

@@ -4,13 +4,14 @@ import { CreateComponentType } from '@/packages/index.d'
 import debounce from 'lodash/debounce'
 import cloneDeep from 'lodash/cloneDeep'
 import { defaultTheme, globalThemeJson } from '@/settings/chartThemes/index'
-import { requestInterval } from '@/settings/designSetting'
+import { requestInterval, previewScaleType } from '@/settings/designSetting'
 // 记录记录
 import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
 // 全局设置
 import { useSettingStore } from '@/store/modules/settingStore/settingStore'
 import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
 import { MenuEnum } from '@/enums/editPageEnum'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 import {
   ChartEditStoreEnum,
   ChartEditStorage,
@@ -89,7 +90,9 @@ export const useChartEditStore = defineStore({
       // chart 主题色
       chartThemeColor: defaultTheme || 'dark',
       // 全局配置
-      chartThemeSetting: globalThemeJson
+      chartThemeSetting: globalThemeJson,
+      // 预览方式
+      previewScaleType: previewScaleType
     },
     // 数据请求处理(需存储给后端)
     requestGlobalConfig: {

+ 0 - 2
src/store/modules/chartLayoutStore/chartLayoutStore.d.ts

@@ -1,5 +1,3 @@
-import { ThemeEnum } from '@/enums/styleEnum'
-
 export enum ChartLayoutStoreEnum {
   LAYERS = 'layers',
   CHARTS = 'charts',

+ 2 - 2
src/store/modules/designStore/designStore.ts

@@ -18,7 +18,7 @@ export const useDesignStore = defineStore({
       // 是否暗黑
       darkTheme,
       // 主题名称
-      themeName: (darkTheme && ThemeEnum.dark) || ThemeEnum.light,
+      themeName: (darkTheme && ThemeEnum.DARK) || ThemeEnum.LIGHT,
       // 颜色色号
       appTheme,
       appThemeDetail,
@@ -38,7 +38,7 @@ export const useDesignStore = defineStore({
     // 切换主题
     changeTheme(): void {
       this.darkTheme = !this.darkTheme
-      this.themeName = this.darkTheme ? ThemeEnum.dark : ThemeEnum.light
+      this.themeName = this.darkTheme ? ThemeEnum.DARK : ThemeEnum.LIGHT
       setLocalStorage(GO_DESIGN_STORE, this.$state)
     },
     // 设置颜色

+ 6 - 6
src/utils/plugin.ts

@@ -82,31 +82,31 @@ export const goDialog = (
 
   const typeObj = {
     // 自定义
-    [DialogEnum.delete]: {
+    [DialogEnum.DELETE]: {
       fn: dialogFn || window['$dialog'].warning,
       message: message || '是否删除此数据?'
     },
     // 原有
-    [DialogEnum.warning]: {
+    [DialogEnum.WARNING]: {
       fn: window['$dialog'].warning,
       message: message || '是否执行此操作?'
     },
-    [DialogEnum.error]: {
+    [DialogEnum.ERROR]: {
       fn: window['$dialog'].error,
       message: message || '是否执行此操作?'
     },
-    [DialogEnum.success]: {
+    [DialogEnum.SUCCESS]: {
       fn: window['$dialog'].success,
       message: message || '是否执行此操作?'
     }
   }
 
-  const dialog: DialogReactive = typeObj[type || DialogEnum.warning]['fn']({
+  const dialog: DialogReactive = typeObj[type || DialogEnum.WARNING]['fn']({
     // 导入其余 NaiveUI 支持参数
     ...params,
     title: title || '提示',
     icon: renderIcon(InformationCircleIcon, { size: dialogIconSize }),
-    content: typeObj[type || DialogEnum.warning]['message'],
+    content: typeObj[type || DialogEnum.WARNING]['message'],
     positiveText: positiveText || '确定',
     negativeText: negativeText || '取消',
     // 是否通过遮罩关闭

+ 67 - 12
src/views/chart/ContentConfigurations/components/CanvasPage/index.vue

@@ -6,6 +6,7 @@
         <n-input-number
           size="small"
           v-model:value="canvasConfig.width"
+          :disabled="editCanvas.lockScale"
           :validator="validator"
           @update:value="changeSizeHandle"
         ></n-input-number>
@@ -14,6 +15,7 @@
         <n-input-number
           size="small"
           v-model:value="canvasConfig.height"
+          :disabled="editCanvas.lockScale"
           :validator="validator"
           @update:value="changeSizeHandle"
         ></n-input-number>
@@ -55,7 +57,7 @@
         ></n-color-picker>
       </n-space>
       <n-space>
-        <n-text>使用颜色</n-text>
+        <n-text>颜色应用</n-text>
         <n-switch
           size="small"
           v-model:value="canvasConfig.selectColor"
@@ -66,10 +68,31 @@
         ></n-switch>
       </n-space>
       <n-space>
-        <n-text>背景</n-text>
+        <n-text>背景控制</n-text>
         <n-button size="small" :disabled="!canvasConfig.backgroundImage" @click="clearImage">清除背景图</n-button>
         <n-button size="small" :disabled="!canvasConfig.background" @click="clearColor">清除颜色</n-button>
       </n-space>
+      <n-space>
+        <n-text>预览方式</n-text>
+        <n-button-group>
+          <n-button 
+            ghost
+            v-for="item in previewTypeList"
+            :key="item.key"
+            :type="canvasConfig.previewScaleType === item.key ? 'primary' : 'tertiary'"
+            size="small"
+            @click="selectPreviewType(item.key)">
+            <n-tooltip :show-arrow="false" trigger="hover">
+              <template #trigger>
+                <n-icon size="18">
+                  <component :is="item.icon"></component>
+                </n-icon>
+              </template>
+              {{ item.desc }}
+            </n-tooltip>
+          </n-button>
+        </n-button-group>
+      </n-space>
     </n-space>
 
     <!-- 滤镜 -->
@@ -108,13 +131,15 @@ import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditSt
 import { StylesSetting } from '@/components/Pages/ChartItemSetting'
 import { UploadCustomRequestOptions } from 'naive-ui'
 import { fileToUrl, loadAsyncComponent } from '@/utils'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 import { icon } from '@/plugins'
 
 const { ColorPaletteIcon } = icon.ionicons5
-const { ZAxisIcon } = icon.carbon
+const { ZAxisIcon, ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
 
 const chartEditStore = useChartEditStore()
 const canvasConfig = chartEditStore.getEditCanvasConfig
+const editCanvas = chartEditStore.getEditCanvas
 
 const uploadFileListRef = ref()
 const switchSelectColorLoading = ref(false)
@@ -153,10 +178,42 @@ const globalTabList = [
   }
 ]
 
-// 规则
+const previewTypeList = [
+  {
+    key: PreviewScaleEnum.FIT,
+    title: '自适应',
+    icon: ScaleIcon,
+    desc: '自适应比例展示,页面会有留白'
+  },
+  {
+    key: PreviewScaleEnum.SCROLL_Y,
+    title: 'Y轴滚动',
+    icon: FitToWidthIcon,
+    desc: 'X轴铺满,Y轴自适应滚动'
+  },
+  {
+    key: PreviewScaleEnum.SCROLL_X,
+    title: 'X轴滚动',
+    icon: FitToHeightIcon,
+    desc: 'Y轴铺满,X轴自适应滚动'
+  },
+  {
+    key: PreviewScaleEnum.FULL,
+    title: '铺满',
+    icon: FitToScreenIcon,
+    desc: '强行拉伸画面,填充所有视图'
+  },
+]
+
+// 画布尺寸规则
 const validator = (x: number) => x > 50
 
-// 前置处理
+// 修改尺寸
+const changeSizeHandle = () => {
+  chartEditStore.computedScale()
+}
+
+// 上传图片前置处理
 //@ts-ignore
 const beforeUploadHandle = async ({ file }) => {
   uploadFileListRef.value = []
@@ -176,12 +233,6 @@ const beforeUploadHandle = async ({ file }) => {
   return true
 }
 
-// 修改尺寸
-const changeSizeHandle = () => {
-  chartEditStore.computedScale
-  chartEditStore.setPageSize
-}
-
 // 清除背景
 const clearImage = () => {
   chartEditStore.setEditCanvasConfig(
@@ -219,7 +270,6 @@ const switchSelectColorHandle = () => {
 // 自定义上传操作
 const customRequest = (options: UploadCustomRequestOptions) => {
   const { file } = options
-
   nextTick(() => {
     if (file.file) {
       const ImageUrl = fileToUrl(file.file)
@@ -236,6 +286,11 @@ const customRequest = (options: UploadCustomRequestOptions) => {
     }
   })
 }
+
+// 选择预览方式
+const selectPreviewType = (key: PreviewScaleEnum) => {
+  chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.PREVIEW_SCALE_TYPE, key)
+}
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/views/chart/ContentEdit/components/EditRange/index.vue

@@ -67,9 +67,9 @@ const rangeModelStyle = computed(() => {
 @include go(edit-range) {
   position: relative;
   transform-origin: left top;
+  background-size: cover;
   @include fetch-border-color('hover-border-color');
   @include fetch-bg-color('background-color2');
-
   @include go(edit-range-model) {
     z-index: -1;
     position: absolute;

+ 0 - 2
src/views/preview/components/PreviewRenderList/index.vue

@@ -34,8 +34,6 @@ const props = defineProps({
   }
 })
 
-console.log(getTranstormStyle(props.localStorageInfo.componentList[0].styles))
-
 // 主题色
 const themeSetting = computed(() => {
   const chartThemeSetting = props.localStorageInfo.editCanvasConfig.chartThemeSetting

+ 72 - 17
src/views/preview/hooks/useScale.hook.ts

@@ -1,31 +1,86 @@
-import { onUnmounted, ref, nextTick, computed } from 'vue'
-import { usePreviewScale } from '@/hooks/index'
+import { ref, nextTick, onMounted, onUnmounted} from 'vue'
+import { usePreviewFitScale, usePreviewScrollYScale, usePreviewScrollXScale, usePreviewFullScale } from '@/hooks/index'
 import type { ChartEditStorageType } from '../index.d'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 
 export const useScale = (localStorageInfo: ChartEditStorageType) => {
-
+  const entityRef = ref()
   const previewRef = ref()
-
-  const width = ref(localStorageInfo?.editCanvasConfig.width)
-  const height = ref(localStorageInfo?.editCanvasConfig.height)
+  const width = ref(localStorageInfo.editCanvasConfig.width)
+  const height = ref(localStorageInfo.editCanvasConfig.height)
 
   // 屏幕适配
-  nextTick(() => {
-    const { calcRate, windowResize, unWindowResize } = usePreviewScale(
-      width.value as number,
-      height.value as number,
-      previewRef.value
-    )
+  onMounted(() => {
+    switch (localStorageInfo.editCanvasConfig.previewScaleType) {
+      case PreviewScaleEnum.FIT: (() => {
+        const { calcRate, windowResize, unWindowResize } = usePreviewFitScale(
+          width.value as number,
+          height.value as number,
+          previewRef.value,
+        )
+        calcRate()
+        windowResize()
+        onUnmounted(() => {
+          unWindowResize()
+        })
+      })()
+        break;
+      case PreviewScaleEnum.SCROLL_Y: (() => {
+        const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale(
+          width.value as number,
+          height.value as number,
+          previewRef.value,
+          (scale) => {
+            const dom = entityRef.value
+            dom.style.width = `${width.value * scale.width}px`
+            dom.style.height = `${height.value * scale.height}px`
+          }
+        )
+        calcRate()
+        windowResize()
+        onUnmounted(() => {
+          unWindowResize()
+        })
+      })()
 
-    calcRate()
-    windowResize()
+        break;
+      case PreviewScaleEnum.SCROLL_X: (() => {
+        const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale(
+          width.value as number,
+          height.value as number,
+          previewRef.value,
+          (scale) => {
+            const dom = entityRef.value
+            dom.style.width = `${width.value * scale.width}px`
+            dom.style.height = `${height.value * scale.height}px`
+          }
+        )
+        calcRate()
+        windowResize()
+        onUnmounted(() => {
+          unWindowResize()
+        })
+      })()
 
-    onUnmounted(() => {
-      unWindowResize()
-    })
+        break;
+      case PreviewScaleEnum.FULL: (() => {
+        const { calcRate, windowResize, unWindowResize } = usePreviewFullScale(
+          width.value as number,
+          height.value as number,
+          previewRef.value,
+        )
+        calcRate()
+        windowResize()
+        onUnmounted(() => {
+          unWindowResize()
+        })
+      })()
+        break;
+    }
   })
 
   return {
+    entityRef,
     previewRef
   }
 }

+ 69 - 17
src/views/preview/index.vue

@@ -1,15 +1,34 @@
 <template>
-  <div class="go-preview">
-    <!-- 缩放层 -->
-    <div ref="previewRef">
-      <!-- 展示层 -->
-      <div :style="previewRefStyle" v-if="show">
-        <!-- 渲染层 -->
-        <preview-render-list
-          :localStorageInfo="localStorageInfo"
-        ></preview-render-list>
+  <div
+    :class="`go-preview ${localStorageInfo.editCanvasConfig.previewScaleType}`"
+  >
+    <template v-if="showEntity">
+      <!-- 实体区域 -->
+      <div ref="entityRef" class="go-preview-entity">
+        <!-- 缩放层 -->
+        <div ref="previewRef" class="go-preview-scale">
+          <!-- 展示层 -->
+          <div :style="previewRefStyle" v-if="show">
+            <!-- 渲染层 -->
+            <preview-render-list
+              :localStorageInfo="localStorageInfo"
+            ></preview-render-list>
+          </div>
+        </div>
       </div>
-    </div>
+    </template>
+    <template v-else>
+      <!-- 缩放层 -->
+      <div ref="previewRef" class="go-preview-scale">
+        <!-- 展示层 -->
+        <div :style="previewRefStyle" v-if="show">
+          <!-- 渲染层 -->
+          <preview-render-list
+            :localStorageInfo="localStorageInfo"
+          ></preview-render-list>
+        </div>
+      </div>
+    </template>
   </div>
 </template>
 
@@ -21,28 +40,61 @@ import { getEditCanvasConfigStyle, getSessionStorageInfo } from './utils'
 import { useComInstall } from './hooks/useComInstall.hook'
 import { useScale } from './hooks/useScale.hook'
 import { useStore } from './hooks/useStore.hook'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 import type { ChartEditStorageType } from './index.d'
 
-const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as ChartEditStorageType
+const localStorageInfo: ChartEditStorageType =
+  getSessionStorageInfo() as ChartEditStorageType
 
 const previewRefStyle = computed(() => {
-  return { ...getEditCanvasConfigStyle(localStorageInfo.editCanvasConfig), ...getFilterStyle(localStorageInfo.editCanvasConfig) }
+  return {
+    ...getEditCanvasConfigStyle(localStorageInfo.editCanvasConfig),
+    ...getFilterStyle(localStorageInfo.editCanvasConfig),
+  }
+})
+
+const showEntity = computed(() => {
+  const type = localStorageInfo.editCanvasConfig.previewScaleType
+  return (
+    type === PreviewScaleEnum.SCROLL_Y || type === PreviewScaleEnum.SCROLL_X
+  )
 })
 
 useStore(localStorageInfo)
-const { previewRef } = useScale(localStorageInfo)
+const { entityRef, previewRef } = useScale(localStorageInfo)
 const { show } = useComInstall(localStorageInfo)
 </script>
 
 <style lang="scss" scoped>
 @include go('preview') {
   position: relative;
-  display: flex;
-  align-items: center;
-  justify-content: center;
   height: 100vh;
   width: 100vw;
-  overflow: hidden;
   @include background-image('background-image');
+  &.fit,
+  &.full {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    overflow: hidden;
+    .go-preview-scale {
+      transform-origin: center center;
+    }
+  }
+  &.scrollY {
+    overflow-x: hidden;
+    .go-preview-scale {
+      transform-origin: left top;
+    }
+  }
+  &.scrollX {
+    overflow-y: hidden;
+    .go-preview-scale {
+      transform-origin: left top;
+    }
+  }
+  .go-preview-entity {
+    overflow: hidden;
+  }
 }
 </style>

+ 1 - 1
src/views/project/items/components/ProjectItemsList/hooks/useData.hook.ts

@@ -40,7 +40,7 @@ export const useDataListInit = () => {
   // 删除
   const deleteHandle = (cardData: object, index: number) => {
     goDialog({
-      type: DialogEnum.delete,
+      type: DialogEnum.DELETE,
       promise: true,
       onPositiveCallback: () =>
         new Promise(res => setTimeout(() => res(1), 1000)),