diff --git a/package.json b/package.json
index 2ac4a5fc..9f11668d 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
     "vue": "^3.2.16",
     "vue-i18n": "^9.2.0-beta.23",
     "vue-router": "4.0.12",
-    "vue3-lazyload": "^0.2.5-beta"
+    "vue3-lazyload": "^0.2.5-beta",
+    "vue3-sketch-ruler": "^1.3.3"
   },
   "devDependencies": {
     "@types/node": "^16.11.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 176c9291..006de1b7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -41,6 +41,7 @@ specifiers:
   vue-router: 4.0.12
   vue-tsc: ^0.28.7
   vue3-lazyload: ^0.2.5-beta
+  vue3-sketch-ruler: ^1.3.3
 
 dependencies:
   animate.css: r2.cnpmjs.org/animate.css/4.1.1
@@ -53,6 +54,7 @@ dependencies:
   vue-i18n: rg.cnpmjs.org/vue-i18n/9.2.0-beta.23_vue@3.2.24
   vue-router: rg.cnpmjs.org/vue-router/4.0.12_vue@3.2.24
   vue3-lazyload: registry.npmjs.org/vue3-lazyload/0.2.5-beta_e9ad48123e44f1efa3c90c8e8375ea6d
+  vue3-sketch-ruler: registry.npmjs.org/vue3-sketch-ruler/1.3.3_vue@3.2.24
 
 devDependencies:
   '@types/node': rg.cnpmjs.org/@types/node/16.11.12
@@ -2356,6 +2358,25 @@ packages:
       vue: rg.cnpmjs.org/vue/3.2.24
     dev: false
 
+  registry.npmjs.org/vue3-sketch-ruler/1.3.3_vue@3.2.24:
+    resolution: {integrity: sha512-k7wK34fWq0v4PiEklF0KAxS37UJS2nm8mMaE8g4Bqv9ZbBY7MxqrkM1wIj9VHmjN/MyQeodFWdg6lJv/ZESKlw==, registry: https://skimdb.npmjs.com/registry/, tarball: https://registry.npmjs.org/vue3-sketch-ruler/-/vue3-sketch-ruler-1.3.3.tgz}
+    id: registry.npmjs.org/vue3-sketch-ruler/1.3.3
+    name: vue3-sketch-ruler
+    version: 1.3.3
+    hasBin: true
+    requiresBuild: true
+    peerDependencies:
+      '@vue/composition-api': ^1.1.0
+      vue: ^2.6.0 || ^3.2.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+      vue:
+        optional: true
+    dependencies:
+      vue: rg.cnpmjs.org/vue/3.2.24
+    dev: false
+
   registry.npmjs.org/vueuc/0.4.26_vue@3.2.24:
     resolution: {integrity: sha512-IK6TV4468k7Hpj1SXXPYelT/aYqmfa/SYTLFospwJ/uMebRExS1fh5tx6ZT3fSA0OkmCOHmmi2OGke+eSseAgw==, registry: https://skimdb.npmjs.com/registry/, tarball: https://registry.npmjs.org/vueuc/-/vueuc-0.4.26.tgz}
     id: registry.npmjs.org/vueuc/0.4.26
diff --git a/src/main.ts b/src/main.ts
index 7dc599e8..df253ad1 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -6,7 +6,11 @@ import { setupStore } from '@/store'
 import { setupNaive, setupDirectives, setupCustomComponents } from '@/plugins'
 import { AppProvider } from '@/components/AppProvider/index'
 import { setHtmlTheme } from '@/utils'
+
+// 引入动画
 import 'animate.css/animate.min.css'
+// 引入标尺
+import 'vue3-sketch-ruler/lib/style.css'
 
 async function appInit() {
   const appProvider = createApp(AppProvider)
diff --git a/src/plugins/customComponents.ts b/src/plugins/customComponents.ts
index 547c859e..484e113f 100644
--- a/src/plugins/customComponents.ts
+++ b/src/plugins/customComponents.ts
@@ -1,6 +1,7 @@
 import type { App } from 'vue'
 import { GoSkeleton } from '@/components/GoSkeleton'
 import { LoadingComponent } from '@/components/LoadingComponent'
+import { SketchRule } from 'vue3-sketch-ruler'
 
 /**
  * 全局注册自定义组件
@@ -9,4 +10,5 @@ import { LoadingComponent } from '@/components/LoadingComponent'
 export function setupCustomComponents(app: App) {
   app.component('GoSkeleton', GoSkeleton)
   app.component('LoadingComponent', LoadingComponent)
+  app.component('SketchRule', SketchRule)
 }
diff --git a/src/views/chart/ContentEdit/components/EditRule/index.ts b/src/views/chart/ContentEdit/components/EditRule/index.ts
new file mode 100644
index 00000000..426c4cec
--- /dev/null
+++ b/src/views/chart/ContentEdit/components/EditRule/index.ts
@@ -0,0 +1,3 @@
+import EditRule from './index.vue'
+
+export { EditRule }
diff --git a/src/views/chart/ContentEdit/components/EditRule/index.vue b/src/views/chart/ContentEdit/components/EditRule/index.vue
new file mode 100644
index 00000000..ed6984d3
--- /dev/null
+++ b/src/views/chart/ContentEdit/components/EditRule/index.vue
@@ -0,0 +1,68 @@
+<template>
+  <sketch-rule
+    :thick="thick"
+    :scale="scale"
+    :width="width"
+    :height="height"
+    :startX="startX"
+    :startY="startY"
+    :lines="lines"
+  ></sketch-rule>
+</template>
+
+<script setup lang="ts">
+import { ref, toRefs } from 'vue'
+import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
+import { useDesignStore } from '@/store/modules/designStore/designStore'
+
+const chartEditStore = useChartEditStore()
+const designStore = useDesignStore()
+const themeColor = ref(designStore.getAppTheme)
+
+const { width, height } = toRefs(chartEditStore.getEditCanvasConfig)
+
+// 初始化标尺的缩放
+const scale = 2
+// x轴标尺开始的坐标数值
+const startX = 0
+// y轴标尺开始的坐标数值
+const startY = 0
+// 标尺的厚度
+const thick = 20
+// 初始化水平标尺上的参考线
+const lines = {
+  h: [],
+  v: []
+}
+</script>
+
+<style>
+/* 横线 */
+#mb-ruler .v-container .lines .line {
+  border-top: 1px dashed v-bind('themeColor') !important;
+}
+#mb-ruler .v-container .indicator {
+  border-bottom: 1px dashed v-bind('themeColor') !important;
+}
+/* 竖线 */
+#mb-ruler .h-container .lines .line {
+  border-left: 1px dashed v-bind('themeColor') !important;
+}
+#mb-ruler .h-container .indicator {
+  border-left: 1px dashed v-bind('themeColor') !important;
+}
+/* 坐标数值背景颜色 */
+#mb-ruler .indicator .value {
+  background-color: rgba(0, 0, 0, 0);
+}
+/* 删除按钮 */
+#mb-ruler .line .del {
+  padding: 0;
+  color: v-bind('themeColor');
+  font-size: 26px;
+  font-weight: bolder;
+}
+#mb-ruler .corner{
+  border-width: 0!important;
+}
+</style>
diff --git a/src/views/chart/ContentEdit/hooks/useStyle.hook.ts b/src/views/chart/ContentEdit/hooks/useStyle.hook.ts
index 22f96ce7..14507f73 100644
--- a/src/views/chart/ContentEdit/hooks/useStyle.hook.ts
+++ b/src/views/chart/ContentEdit/hooks/useStyle.hook.ts
@@ -3,6 +3,7 @@ import { PickCreateComponentType } from '@/packages/index.d'
 type AttrType = PickCreateComponentType<'attr'>
 
 export const useComponentStyle = (attr: AttrType, index: number) => {
+  if(!attr) return {}
   const componentStyle = {
     zIndex: index + 1,
     left: `${attr.x}px`,
@@ -12,6 +13,7 @@ export const useComponentStyle = (attr: AttrType, index: number) => {
 }
 
 export const useSizeStyle = (attr: AttrType, scale?: number) => {
+  if(!attr) return {}
   return {
     width: `${scale ? scale * attr.w : attr.w}px`,
     height: `${scale ? scale * attr.h : attr.h}px`
diff --git a/src/views/chart/ContentEdit/index.vue b/src/views/chart/ContentEdit/index.vue
index 0a2931f0..4942891f 100644
--- a/src/views/chart/ContentEdit/index.vue
+++ b/src/views/chart/ContentEdit/index.vue
@@ -9,9 +9,10 @@
     @drop="handleDrag"
     @dragover="handleDragOver"
   >
+    <edit-rule></edit-rule>
     <div id="go-chart-edit-content">
       <!-- 展示 -->
-      <edit-range ref="editRangeRef">
+      <edit-range>
         <!-- 图表 -->
         <edit-shape-box
           v-for="(item, index) in chartEditStore.getComponentList"
@@ -44,11 +45,12 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted, computed } from 'vue'
+import { onMounted, computed } from 'vue'
 import { ContentBox } from '../contentBox/index'
 import { EditRange } from './components/EditRange'
 import { EditBottom } from './components/EditBottom'
-import { EditShapeBox } from './components/EditShapeBox/index'
+import { EditShapeBox } from './components/EditShapeBox'
+import { EditRule } from './components/EditRule'
 
 import { useLayout } from './hooks/useLayout.hook'
 import { useAddKeyboard } from '../hooks/useKeyboard.hook'
@@ -65,7 +67,6 @@ const { handleContextMenu } = useContextMenu()
 useLayout()
 
 // 点击事件
-const editRangeRef = ref<HTMLElement | null>(null)
 const { mouseenterHandle, mouseleaveHandle, mousedownHandle } = useMouseHandle()
 
 // 主题色
@@ -95,7 +96,7 @@ onMounted(() => {
   @include background-image('background-point');
   @extend .go-point-bg;
   @include goId(chart-edit-content) {
-    margin: 20px;
+    padding: 25px;
     border: 1px solid rgba(0, 0, 0, 0);
     @extend .go-transition;
     &.content-resize {