Browse Source

feat:实现i18n

Grnetsky 7 months ago
parent
commit
c24110fa1e
40 changed files with 4796 additions and 3415 deletions
  1. 2 1
      package.json
  2. 9 8
      src/http.ts
  3. 20 0
      src/i18n/index.ts
  4. 1374 0
      src/i18n/lang/en.ts
  5. 2 0
      src/i18n/lang/index.ts
  6. 1375 0
      src/i18n/lang/zh_CHT.ts
  7. 2 0
      src/main.ts
  8. 29 28
      src/services/common.ts
  9. 141 140
      src/services/defaults.ts
  10. 122 121
      src/services/echarts.ts
  11. 9 8
      src/services/enterprise.ts
  12. 5 4
      src/services/excel.ts
  13. 3 1
      src/services/file.ts
  14. 3 1
      src/services/updateC.ts
  15. 6 5
      src/services/utils.ts
  16. 152 282
      src/views/components/Actions.vue
  17. 71 85
      src/views/components/AnimateFrames.vue
  18. 7 7
      src/views/components/ChargeCloudPublish.vue
  19. 45 64
      src/views/components/Conditions.vue
  20. 29 28
      src/views/components/ContextMenu.vue
  21. 15 15
      src/views/components/Custom.vue
  22. 109 141
      src/views/components/Data.vue
  23. 34 33
      src/views/components/Dataset.vue
  24. 16 40
      src/views/components/ElementTree.vue
  25. 86 207
      src/views/components/FileProps.vue
  26. 25 58
      src/views/components/FitProps.vue
  27. 57 106
      src/views/components/GlobalStates.vue
  28. 18 18
      src/views/components/Graphics.vue
  29. 113 109
      src/views/components/Header.vue
  30. 34 54
      src/views/components/Network.vue
  31. 11 13
      src/views/components/Pay.vue
  32. 94 211
      src/views/components/PenAnimates.vue
  33. 160 261
      src/views/components/PenDatas.vue
  34. 36 43
      src/views/components/PenEvents.vue
  35. 179 571
      src/views/components/PenProps.vue
  36. 51 69
      src/views/components/PenStatus.vue
  37. 129 330
      src/views/components/PensProps.vue
  38. 33 55
      src/views/components/Structure.vue
  39. 172 278
      src/views/components/View.vue
  40. 18 20
      src/views/components/common/ShareModal.vue

+ 2 - 1
package.json

@@ -33,7 +33,8 @@
     "tdesign-icons-vue-next": "^0.2.2",
     "tdesign-vue-next": "^1.7.0",
     "vue": "^3.3.4",
-    "vue-router": "^4.2.0"
+    "vue-router": "^4.2.0",
+    "vue-i18n": "^10.0.4"
   },
   "devDependencies": {
     "@types/file-saver": "^2.0.5",

+ 9 - 8
src/http.ts

@@ -2,7 +2,8 @@ import { MessagePlugin } from 'tdesign-vue-next';
 import axios from 'axios';
 import { getCookie } from '@/services/cookie';
 import router from './router';
-
+import i18n from './i18n';
+const $t = i18n.global.t;
 // axios 配置
 axios.defaults.timeout = 60000;
 axios.defaults.withCredentials = false;
@@ -40,7 +41,7 @@ axios.interceptors.response.use(
     if (error && error.response) {
       if (
         error.response.config.url === '/api/account/profile' ||
-        error.response.data.error === '此为付费数据,请购买后访问'
+        error.response.data.error === $t('此为付费数据,请购买后访问')
       ) {
         return;
       }
@@ -61,26 +62,26 @@ axios.interceptors.response.use(
             break;
           }
           sessionStorage.setItem('cb', encodeURIComponent(location.href));
-          MessagePlugin.error('请先登录!');
+          MessagePlugin.error($t('请先登录!'));
           // router.replace({ path: '/login' });
           break;
         case 403:
-          MessagePlugin.error('请求错误,不合法的请求!');
+          MessagePlugin.error($t('请求错误,不合法的请求!'));
 
           break;
         case 404:
           if (error.response.config.url.indexOf('/data/') !== 0) {
-            MessagePlugin.error('访问数据不存在,请检查后重试!');
+            MessagePlugin.error($t('访问数据不存在,请检查后重试!'));
           }
           break;
         case 500:
-          MessagePlugin.error('请求服务错误,请稍后重试!');
+          MessagePlugin.error($t('请求服务错误,请稍后重试!'));
           break;
         case 504:
-          MessagePlugin.error('网络超时,请检测你的网络!');
+          MessagePlugin.error($t('网络超时,请检测你的网络!'));
           break;
         default:
-          MessagePlugin.error('未知网络错误!');
+          MessagePlugin.error($t('未知网络错误!'));
           break;
       }
     }

+ 20 - 0
src/i18n/index.ts

@@ -0,0 +1,20 @@
+import {createI18n} from 'vue-i18n';
+import {en,zh_CHT} from './lang';
+const i18n = createI18n({
+    legacy: false,
+    locale: localStorage.getItem('i18n') || navigator.language,    
+    silentTranslationWarn: true,
+    missingWarn: false,
+    silentFallbackWarn: true,
+    fallbackWarn: false,  
+    fallbackLocale: 'zh',
+    globalInjection: true,  
+    messages: {
+        en,zh_CHT
+    },
+    missing(locale,key){
+        return key;
+    }
+});
+
+export default i18n;

+ 1374 - 0
src/i18n/lang/en.ts

@@ -0,0 +1,1374 @@
+const a = {
+  "          动作": "movement",
+  "单位ms,默认不延迟执行": "The unit is ms. By default, execution is not delayed",
+  "延迟": "Put off",
+  "动作类型": "Action type",
+  "请选择": "Please select",
+  "链接地址": "Link address",
+  "打开方式": "Open mode",
+  "新页面": "New page",
+  "当前页面": "Current page",
+  "视图": "view",
+  "对象类型": "Object type",
+  "图元": "pixel",
+  "组": "group",
+  "播放对象": "Play object",
+  "默认自己": "Acquiesce oneself",
+  "动画名称": "Animation name",
+  "缺省第一个动画": "The default is the first animation",
+  "更改对象": "Change object",
+  "属性数据": "Attribute data",
+  "属性名": "Attribute name",
+  "属性值": "Attribute value",
+  "自定义": "Custom",
+  "值": "value",
+  "暂无数据": "No data available",
+  "窗口标题": "Window title",
+  "弹框标题": "Pop-up title",
+  "画面": "Graphics",
+  "窗口画面URL": "Window URL",
+  "弹框位置": "Pop-up position",
+  "弹框大小": "Pop-up size",
+  "宽": "wide",
+  "高": "high",
+  "消息名称": "Message name",
+  "名称": "name",
+  "消息参数": "Message parameter",
+  "参数": "argument",
+  "数据": "data",
+  "数据对象": "Data object",
+  "添加数据": "Add data",
+  "回调": "callback",
+  "可获取": "available",
+  "和": "and",
+  "参考": "Refer to",
+  "发送指令": "Send instruction",
+  "函数名称": "Function name",
+  "函数参数": "Function parameter",
+  "场景对象": "Scene object",
+  "必填": "required",
+  "消息名": "Message name",
+  "消息数据": "Message data",
+  "消息对象": "Message object",
+  "添加消息数据": "Add message data",
+  "添加动作": "Add action",
+  "在当前帧后面添加动画帧": "Adds an animation frame after the current frame",
+  "添加属性": "Add attribute",
+  "确认删除该动画帧吗": "Are you sure to delete this animation frame",
+  "时长": "duration",
+  "毫秒": "ms",
+  "添加帧": "Add frame",
+  "还没有动画帧": "No animation frames yet",
+  "添加动画帧": "Add animation frame",
+  "快速发布": "Quick release",
+  "提升工作效率": "Improve work efficiency",
+  "减少运维工作": "Reduce operation and maintenance work",
+  "降低成本": "Reduce cost",
+  "专注业务": "Focus on business",
+  "创新无负担": "Innovation without burden",
+  "原价": "Original price",
+  "提交订单": "Submit an order",
+  "乐吾乐收银台": "Logol checkout counter",
+  "支付完成": "Payment completion",
+  "分享公开": "Share publicly",
+  "不分享": "Not share",
+  "复制链接": "Copy link",
+  "分享到": "Share to",
+  "扫一扫": "sweep",
+  "微信扫一扫": "Scan wechat",
+  "分享私有图纸请确保小程序登录的账号与": "Share private drawings please make sure that the small program login account with",
+  "端一致": "End consistency",
+  "或者将私有图纸设置为分享公开": "Or set private drawings to share public",
+  "才可以正常扫码预览": "Can scan code preview normally",
+  "触发条件": "Trigger condition",
+  "满足全部条件": "Meet all conditions",
+  "满足任意条件": "Satisfy any condition",
+  "          条件": "Conditions",
+  "条件类型": "Condition type",
+  "关系条件": "Relation condition",
+  "高级条件": "Advanced condition",
+  "关系运算": "Relational operation",
+  "运算对象": "operand",
+  "固定值": "Fixed value",
+  "对象属性值": "Object attribute value",
+  "对象": "object",
+  "属性": "Stats",
+  "添加触发条件": "Add trigger condition",
+  "添加手柄": "Add handle",
+  "删除手柄": "Delete handle",
+  "切换手柄": "Switch handle",
+  "一键更新我的组件": "Update my components with one click",
+  "追加状态": "Append state",
+  "进入": "enter",
+  "可视化编辑": "Visual editing",
+  "进入大屏可视化编辑": "Enter large screen visual editing",
+  "替换方案": "Alternative scheme",
+  "置顶": "Pinned",
+  "置底": "bottom",
+  "上一个图层": "Previous layer",
+  "下一个图层": "Next layer",
+  "组合": "assembly",
+  "组合为状态": "Combination as state",
+  "确认取消组合?(将丢失组合图元的数据)": "Confirm to cancel the combination? (Will lose the combined element data)",
+  "取消组合": "unassemble",
+  "解锁": "Unlock",
+  "锁定": "lock",
+  "删除": "delete",
+  "变成节点": "Become a node",
+  "变成连线": "Become wired",
+  "撤销": "cancel",
+  "重做": "redo",
+  "剪切": "shear",
+  "复制": "copy",
+  "粘贴": "affix",
+  "        选中单元格(第": "Select the cell (No",
+  "{ cell.row }}行,第": "{cell.row}} row, no",
+  "        第": "The first",
+  "背景颜色": "Background color",
+  "文字颜色": "Text color",
+  "文字大小": "Text size",
+  "文本对齐": "Text alignment",
+  "居左": "left",
+  "水平居中": "Horizontal centering",
+  "居右": "right",
+  "水平偏移": "Horizontal migration",
+  "是否绘制": "Draw or not",
+  "关闭": "Off",
+  "运行": "operation",
+  "group === '属性'": "group === 'attribute'",
+  "导入属性列表": "Import property list",
+  "新建属性": "New attribute",
+  "我的属性列表": "My attribute list",
+  "请先登录": "Please log in first",
+  "在线接口": "Online interface",
+  "地址:": "Address:",
+  "请输入地址": "Please enter the address",
+  "从": "from",
+  "导入": "To lead into",
+  "下载": "Download",
+  "示例": "Give an example",
+  "导出属性列表": "Derived attribute list",
+  "下载为": "Download as",
+  "保存为我的属性列表": "Save as my properties list",
+  "确认清空属性列表吗?": "Are you sure to clear the property list?",
+  "清空列表": "Clear list",
+  "可批量导入数据图元到画布": "Data primitives can be imported to the canvas in batches",
+  "批量导入到画布": "Batch import to canvas",
+  "开启全局数据模拟": "Enable global data simulation",
+  "开启": "On",
+  "搜索我的属性列表": "Search my property list",
+  "开启单个模拟": "Open a single simulation",
+  "确认删除吗?": "Do you want to delete it?",
+  "类型": "type",
+  "值范围": "Value range",
+  "group === '数据源'": "group === 'Data source'",
+  "添加数据源": "Add data source",
+  "搜索我的数据源": "Search my data sources",
+  "显示名称": "Display name",
+  "通信方式": "Communication mode",
+  "地址": "address",
+  "group === '解析'": "group === 'parse'",
+  "参考文档": "Reference document",
+  "解析自定义格式数据": "Parse custom format data",
+  "属性简短描述": "Attribute short description",
+  "字符串": "Character string",
+  "可用做数据模拟": "Can be used for data simulation",
+  "值范围说明": "Value range declaration",
+  "直接填写": "Direct entry",
+  "例如": "Such as",
+  "随机值": "Random value",
+  "范围数字": "Range digit",
+  "最小值": "Minimum value",
+  "最大值": "Maximum value",
+  "或": "or",
+  "随机字符串": "Random string",
+  "长度": "Length",
+  "同时保存到我的数据源": "Also save to my data source",
+  "确定": "OK",
+  "数据监听": "Data monitoring",
+  "变量列表": "Variable list",
+  "数据方式": "Data mode",
+  "请求": "request",
+  "视图结构": "View structure",
+  "可编辑": "Can be edited",
+  "禁止编辑": "Forbid editing",
+  "禁止编辑和移动": "Forbid editing and moving",
+  "禁止所有事件": "Disable all events",
+  "分组": "group",
+  "新建分组": "New group",
+  "确认删除该分组吗?": "Are you sure to delete the group?",
+  "画布": "Canvas",
+  "文件名": "filename",
+  "分类": "sort",
+  "画布尺寸": "Canvas size",
+  "背景图片": "Background picture",
+  "主题": "theme",
+  "暗黑": "Dark",
+  "预览设置": "Preview Settings",
+  "缩放方式": "Scale mode",
+  "宽高中较小的铺满": "A wide high school is covered with a smaller one",
+  "自动铺满": "self-filling",
+  "高度等比例缩放": "The height is scaled equally",
+  "宽度铺满": "Width spread",
+  "宽度等比例缩放": "The width is scaled equally",
+  "高度铺满": "Full height",
+  "显示滚动条": "Display scroll bar",
+  "禁止移动": "Do not move",
+  "禁止缩放": "Zoom disable",
+  "进阶设置": "Advanced setting",
+  "图标": "icon",
+  "Font class方式URL": "Font class Indicates the URL of the mode",
+  "添加": "append",
+  "初始化动作": "Initialization action",
+  "辅助设置": "Auxiliary setting",
+  "此功能仅对直线和折线有效": "This feature is only available for straight and broken lines",
+  "连线相交弯曲": "Line intersection bend",
+  "行为": "behavior",
+  "布局容器": "Layout container",
+  "默认0": "Default 0",
+  "靠左": "Keep left",
+  "靠右": "Keep right",
+  "靠上": "Lean against",
+  "靠下": "Lean down",
+  "展示图元": "Display element",
+  "图元列表": "Primitive list",
+  "操作": "Controls",
+  "确认移除吗": "Confirm removal?",
+  "从布局容器中移除此图元": "Removes this element from the layout container",
+  "确认删除该行为吗?": "Are you sure to delete the behavior?",
+  "                条件": "Conditions",
+  "添加条件": "Add condition",
+  "执行动作": "Execution action",
+  "添加行为": "Additive behavior",
+  "系统资源": "System resource",
+  "我的资源": "My resources",
+  "结构": "structure",
+  "搜索": "search",
+  "展开/折叠": "Unfold/fold",
+  "加载中...": "Loading...",
+  "              activedGroup === '图片' ||": "activedGroup === 'Picture' ||",
+  "                (activedGroup === '方案' || activedGroup === '模板' || activedGroup === '组件'))": "(activedGroup === 'scheme' || activedGroup === 'template' || activedGroup === 'component ')",
+  "新建文件夹": "New folder",
+  "item.canEdited && activedGroup === '图片'": "item.canEdited &&activedGroup === = 'Picture'",
+  "new": "new",
+  "['组件', '方案', '模板'].includes(activedGroup)": "[' component ', 'scheme ',' template '].includes(activedGroup)",
+  "确认删除该文件夹吗": "Are you sure to delete this folder",
+  "移动到": "Move to",
+  "方案": "option",
+  "模板": "template",
+  "['方案', '模板'].includes(activedGroup)": "[' scheme ', 'template '].includes(activedGroup)",
+  "subMenu in moveGroups[activedGroup==='方案'?'模板':'方案']": "subMenu in moveGroups[activedGroup===' Scheme '?' template ':' scheme ']",
+  "图片": "picture",
+  "编辑": "EDITOR",
+  "检测到该图纸正在被编辑,": "Detects that the drawing is being edited,",
+  "画布将被清空,": "The canvas will be emptied,",
+  "{current?$t('检测到该图纸正在被编辑,'):''}}确定删除该数据吗?": "{current? $t(' Detected that the drawing is being edited, '):''}} Are you sure to delete this data?",
+  "管理": "manage",
+  "文件": "document",
+  "新建文件": "New file",
+  "打开文件": "Open file",
+  "导入文件": "Import file",
+  "保存": "save",
+  "另存为": "Save as",
+  "仅保存": "Save only",
+  "导出为": "Be exported as",
+  "下载离线部署包": "Download the offline deployment package",
+  "组件包": "Component package",
+  "明亮主题": "Bright theme",
+  "暗黑主题": "Dark theme",
+  "全选": "select all",
+  "工具": "tool",
+  "窗口大小": "Window size",
+  "放大": "Blow up",
+  "缩小": "minification",
+  "鹰眼地图": "Hawkeye map",
+  "放大镜": "Magnifying glass",
+  "自动锚点": "Automatic anchor point",
+  "显示锚点": "Display anchor",
+  "删除锚点": "Delete anchor",
+  "帮助": "assist",
+  "账户中心": "Account center",
+  "大屏可视化": "Large screen visualization",
+  "可视化": "visualization",
+  "我的大屏": "My big screen",
+  "我的团队": "My team",
+  "账号信息": "Account information",
+  "安全设置": "Security Settings",
+  "退出": "quit",
+  "登录": "Log in",
+  "提示": "Tips",
+  "保存后新建": "Save new",
+  "不保存直接新建": "Create without saving",
+  "当前画布数据未保存": "The current canvas data is not saved",
+  "是否保存后新建": "Whether to save and create a new one",
+  "数据获取": "Data acquisition",
+  "数据发送": "Data transmission",
+  "我的数据发送": "My data is sent",
+  "              名称: ": "Name:",
+  "地址: ": "Address:",
+  "http": "http",
+  "必须是wss协议": "It must be the wss protocol",
+  "必须是ws协议": "It must be a ws protocol",
+  "请输入": "Please enter",
+  "请求方式": "Request mode",
+  "请求间隔": "Request interval",
+  "默认1000 ms": "Default 1000 ms",
+  "请求头": "Request header",
+  "支持设置动态参数": "Supports setting dynamic parameters",
+  "请求体": "Request body",
+  "自动生成": "Automatic generation",
+  "用户名": "username",
+  "密码": "cipher",
+  "保存到我的数据发送": "Save my data to send",
+  "订单编号:": "Order Number:",
+  "订单类型:": "Order type:",
+  "应付金额": "Amount payable",
+  "余额支付": "Balance payment",
+  "当前余额": "Current balance",
+  "扫码支付": "scan to pay",
+  "注意": "Look out",
+  "不支持退款": "Refund is not supported",
+  "确认支付": "Confirm payment",
+  "确认删除该动画吗": "Are you sure to delete the animation",
+  "动画类型": "Animation type",
+  "水流": "stream",
+  "水珠": "Drop of water",
+  "圆点": "dot",
+  "箭头": "arrow",
+  "水滴": "Water drop",
+  "运动速度": "Velocity of motion",
+  "动画颜色": "Animation color",
+  "发光效果": "Luminous effect",
+  "发光颜色": "Luminous color",
+  "发光模糊": "Luminous blur",
+  "默认6": "Default 6",
+  "轨迹宽度": "Track width",
+  "轨迹间隔": "Track interval",
+  "默认100": "Default 100",
+  "反向流动": "Reverse flow",
+  "播放次数": "Number of plays",
+  "无限": "Unlimited",
+  "缺省无限循环播放": "By default, the playback is infinite",
+  "自动播放": "autoplay",
+  "下个动画类型": "Next animation type",
+  "当前动画结束后自动播放下一个对象的动画": "The animation of the next object will play automatically after the current animation ends",
+  "下个动画": "Next animation",
+  "无": "There is no",
+  "动画": "ANIMATIONS",
+  "结束状态": "End state",
+  "初始状态": "Initial state",
+  "当前状态": "Current state",
+  "线性播放": "Linear playback",
+  "仅支持数字属性匀速线性播放": "Only digital attribute uniform linear playback is supported",
+  "是": "is",
+  "否": "no",
+  "添加动画": "Add animation",
+  "还没有动画": "No animation yet",
+  "数据源": "Data source",
+  "API接口": "API interface",
+  "CSV文件": "CSV file",
+  "从Excel导入": "Import from Excel",
+  "                当前选中单元格  (第": "The currently selected cell (No",
+  "                当前选中行  (第": "The currently selected row (no",
+  "快捷绑定": "Shortcut binding",
+  "关联设备": "Associated device",
+  "设备ID": "Device ID",
+  "数据名": "Data name",
+  "绑定": "bind",
+  "整数": "integer",
+  "浮点数": "Floating point number",
+  "添加动态数据": "Add dynamic data",
+  "还没有动态数据": "No dynamic data yet",
+  "ctrl+shift+点击,可选中子图元": "ctrl+shift+ click to select subprimitives",
+  "子图元": "subpixel",
+  "简短描述": "Short description",
+  "关键字": "keyword",
+  "动态数据设置": "Dynamic data setting",
+  "绑定变量": "Bound variable",
+  "当前绑定": "Current binding",
+  "本地调试": "Local debugging",
+  "模拟值": "Simulated value",
+  "模拟值说明": "Analog value declaration",
+  "数据状态": "Data state",
+  "确认删除该状态吗?": "Are you sure to delete this state?",
+  "满足条件": "Satisfy the condition",
+  "所有": "own",
+  "任意": "At will",
+  "                  条件": "Conditions",
+  "比较条件": "Comparison condition",
+  "添加状态": "Add state",
+  "数据编辑": "Data editing",
+  "请输入(临时请求,不会保存)": "Please enter (temporary request, not saved)",
+  "确认删除该交互事件吗?": "Are you sure to delete the interaction event?",
+  "添加交互事件": "Add interactive event",
+  "还没有交互事件": "No interaction events yet",
+  "外观": "appearance",
+  "请输入或选择分组": "Please enter or select a group",
+  "默认5": "Default 5",
+  "画布层": "Canvas layer",
+  "上层图片层": "Upper picture layer",
+  "主画布层": "Main canvas layer",
+  "下层图片层": "Lower picture layer",
+  "模板层": "Template layer",
+  "大屏对齐": "Large screen alignment",
+  "旋转": "rotate",
+  "固定比例": "Fixed proportion",
+  "不固定比例": "Variable proportion",
+  "圆角": "Fillet corner",
+  "透明度": "transparency",
+  "状态": "status",
+  "                    状态": "status",
+  "点击上传": "Click to upload",
+  "拖拽图片到此区域": "Drag the image to this area",
+  "图片地址": "Picture address",
+  "前景颜色": "Foreground color",
+  "悬停颜色": "Hover color",
+  "选中颜色": "Select color",
+  "线条": "line",
+  "线条样式": "Line style",
+  "线条宽度": "Line width",
+  "平滑度": "smoothness",
+  "线条渐变": "Line gradient",
+  "起点箭头": "Starting arrow",
+  "终点箭头": "End arrow",
+  "默认": "acquiesce",
+  "圆形": "roundness",
+  "方形": "quadrate",
+  "末端样式": "End style",
+  "斜角": "Bevel Angle",
+  "连接样式": "Connection style",
+  "背景": "backdrop",
+  "纯色": "Solid color",
+  "线性渐变": "Linear gradient",
+  "径向渐变": "Radial gradient",
+  "渐变半径": "Gradient radius",
+  "选中": "Select",
+  "阴影": "shadow",
+  "文字阴影": "Text shadow",
+  "X偏移": "x-shift",
+  "Y偏移": "y-shift",
+  "模糊": "Blur",
+  "模糊大小": "Blur size",
+  "文字": "Text",
+  "字体名": "fontname",
+  "字体大小": "Font size",
+  "顶部对齐": "Top alignment",
+  "垂直居中": "Vertical centering",
+  "底部对齐": "Bottom align",
+  "悬停": "hover",
+  "前景": "foreground",
+  "换行": "Line feed",
+  "省略号": "apostrophe",
+  "行高": "Row height",
+  "显示时保留小数位数": "Display with decimal places reserved",
+  "小数": "Fractional part",
+  "垂直偏移": "Vertical migration",
+  "只读": "Read only",
+  "隐藏文字": "Hidden text",
+  "自动调整": "Automatic adjustment",
+  "文本内容": "Text content",
+  "自适应": "self-adaptation",
+  "转动图": "Rotation diagram",
+  "选择": "Select",
+  "选择图标": "Select icon",
+  "进度": "schedule",
+  "垂直进度": "Vertical progress",
+  "反向进度": "Reverse progress",
+  "进度渐变": "Progress gradient",
+  "水平翻转": "Horizontal flip",
+  "垂直翻转": "Vertical flip",
+  "锚点半径": "Anchor radius",
+  "禁止": "prohibit",
+  "禁用": "forbidden",
+  "禁用背景": "Forbidden background",
+  "禁用颜色": "Forbidden color",
+  "禁用文字颜色": "Disable text color",
+  "禁止旋转": "Disable rotation",
+  "禁用锚点": "Forbidden anchor point",
+  "鼠标提示": "Mouse prompt",
+  "函数": "function",
+  "支持": "support",
+  "格式": "format",
+  "交互": "interaction",
+  "选中了": "checked",
+  "对齐": "aligning",
+  "区域对齐": "Zone alignment",
+  "以最后选中图元对齐": "Align with last selected primitives",
+  "居中": "Mediate between two parties",
+  "状态场景名": "Status scene name",
+  "还没有状态场景": "No status scene yet",
+  "添加状态场景": "Add status scene",
+  "状态名": "Status name",
+  "对象属性": "Object attribute",
+  "group === '图层'": "group === 'Layer'",
+  "上一层": "Upper floor",
+  "下一层": "Next floor",
+  "折叠": "fold",
+  "展开": "unfold",
+  "dom": "dom",
+  "DOM元素": "DOM element",
+  "": "",
+  "group === '分组'": "group === 'Group'",
+  "新建": "new",
+  "保存为方案": "Save as scheme",
+  "保存为模板": "Save as template",
+  "保存为我的组件": "Save as my component",
+  "格式化(双击可连续使用)": "Formatting (Double click for continuous use)",
+  "清除格式": "Clear format",
+  "直线": "Straight line",
+  "铅笔": "Pencil",
+  "钢笔(双击可连续使用)": "Pen (Double click for continuous use)",
+  "视图大小": "View size",
+  "100%视图": "100% view",
+  "允许缩放": "Zoom enabled",
+  "自适应设置": "Adaptive setting",
+  "浏览模式": "Browsing mode",
+  "编辑模式": "Edit mode",
+  "运行(预览)": "Run (preview)",
+  "分享": "Share",
+  "当前项目为本地编辑模式": "The current project is in local edit mode",
+  "请保存为大屏项目后访问": "Please save as a large screen project and access later",
+  "仅支持手机访问大屏项目": "Only mobile phones can access large-screen projects",
+  "云发布": "Cloud publishing",
+  "数据管理": "Data management",
+  "搜索我的数据获取": "Search my data to get",
+  "添加数据获取": "Add data fetch",
+  "返回": "Back",
+  "新建变量": "New variable",
+  "导入变量": "Import variable",
+  "选择变量": "Selection variable",
+  "我的变量列表": "My variable list",
+  "选择变量列表": "Select variable list",
+  "点击图标或回车获取数据": "Click the icon or enter to get the data",
+  "同时保存到我的数据获取": "Also save to my data get",
+  "同时保存为我的变量列表": "Also save as my variable list",
+  "另存为新变量列表": "Save as new variable list",
+  "开启模拟数据": "Open analog data",
+  "保存为我的变量列表": "Save as my variable list",
+  "完成": "complete",
+  "项目名称": "Project name",
+  "发布状态": "Release status",
+  "已过期": "expired",
+  "正在运行": "Be running",
+  "                有效期至:": "Valid until:",
+  "需要开通高级会员": "A premium membership is required",
+  "未发布": "unpublish",
+  "乐吾乐域名": "Lewule domain name",
+  "子域名": "subdomain",
+  "随机生成": "Random generation",
+  "访问域名": "Access domain name",
+  "支持自定义域名": "Supports user-defined domain names",
+  "点击访问": "Click to visit",
+  "手机访问": "Mobile access",
+  "仅支持": "Only support",
+  "小时免费试用": "Hourly free trial",
+  "到期后需要续费使用": "It needs to be renewed after expiration",
+  "自定义域名": "Customize the domain name",
+  "在域名服务商的": "At the domain name service provider",
+  "控制台设置好对应的": "The console is set up accordingly",
+  "值为乐吾乐域名": "Value for the Loh Loh domain name",
+  "更多帮助": "More help",
+  "发布": "publish",
+  "取消发布": "unpublish",
+  "云发布续费": "Cloud publishing renewal fee",
+  "变量简短描述": "Variable short description",
+  "变量名": "Variable name",
+  "方案列表": "Scheme list",
+  "复制链接成功!": "Copy link successful!",
+  "请先保存!": "Please save first!",
+  "分享成功!": "Share success!",
+  "取消分享成功": "Unshare success",
+  "获取二维码失败!": "Failed to get QR code!",
+  "获取微信小程序码失败!": "Get wechat small program code failed!",
+  "打开链接": "Open the link",
+  "打开视图": "Open view",
+  "播放动画": "Play animation",
+  "暂停动画": "Pause animation",
+  "停止动画": "Stop animation",
+  "更改属性": "Change attribute",
+  "打开弹框": "popup",
+  "发送消息": "Send a message",
+  "发送数据": "Send data",
+  "播放视频": "Play video",
+  "暂停视频": "Pause video",
+  "停止视频": "Stop video",
+  "自定义函数": "Custom function",
+  "全局函数": "Global function",
+  "向场景发送消息": "Send a message to the scene",
+  "向父窗口发送消息": "Sends a message to the parent window",
+  "显示": "reveal",
+  "颜色": "colour",
+  "进度颜色": "Progress color",
+  "单选选中值": "Select a value",
+  "网页地址": "Web address",
+  "缩放": "Zoom",
+  "缩放比例": "Zoom ratio",
+  "X位移": "X displacement",
+  "Y位移": "y-shift",
+  "背景类型": "Background type",
+  "0 - 1之间": "Between 0 and 1",
+  "背景渐变半径": "Background gradient radius",
+  "线条渐变颜色": "Line gradient color",
+  "显示阴影": "Display shadow",
+  "新宋体": "New Song typeface",
+  "微软雅黑": "Microsoft black",
+  "黑体": "Black body",
+  "楷体": "Regular script",
+  "文字背景": "Text background",
+  "文字倾斜": "Text slant",
+  "正常": "normal",
+  "倾斜": "tilt",
+  "文字加粗": "Text bolding",
+  "加粗": "overbold",
+  "阴影颜色": "Shadow color",
+  "阴影模糊半径": "Shadow blur radius",
+  "正数": "Positive number",
+  "阴影X偏移": "Shadow X shift",
+  "阴影Y偏移": "Shadow Y shift",
+  "包含": "contain",
+  "不包含": "exclude",
+  "选中单元格": "Check cell",
+  "第": "The first",
+  "行": "line",
+  "列": "column",
+  "样式": "pattern",
+  "行样式": "Line style",
+  "列样式": "Column style",
+  "数据不满足json格式": "The data does not meet the json format",
+  "编辑数据": "Edit data",
+  "显示名称不能为空!": "The display name cannot be empty!",
+  "显示名称重复!": "Display name duplication!",
+  "属性名不能为空!": "The property name cannot be empty!",
+  "属性名重复!": "Attribute name duplicate!",
+  "请填写名称": "Please fill in the name",
+  "请填写数据ID": "Please fill in the data ID",
+  "设备": "equipment",
+  "属性列表不能为空!": "The property list cannot be empty!",
+  "未命名": "untitled",
+  "名称不能为空": "The name cannot be empty",
+  "属性列表不能为空": "The property list cannot be empty",
+  "编辑数据源": "Edit data source",
+  "URL地址不能为空!": "The URL cannot be empty!",
+  "名称不能为空!": "The name cannot be empty!",
+  "请先选择数据": "Please select the data first",
+  "变量名不能为空!": "Variable names cannot be empty!",
+  "变量名重复!": "The variable name is repeated!",
+  "导入Excel": "Import Excel",
+  "下载Excel示例": "Download Excel Example",
+  "已经存在相同分组!": "The same group already exists!",
+  "/大屏/图片/默认": "/ Large screen/Picture/Default",
+  "智慧物联": "Intelligent Internet of Things",
+  "电力能源": "Electric energy",
+  "智慧水务": "Smart water",
+  "智慧工厂": "Smart factory",
+  "智慧校园": "Smart campus",
+  "智慧园区": "Smart park",
+  "智慧交通": "Intelligent transportation",
+  "智慧城市": "Smart city",
+  "智慧农业": "Smart agriculture",
+  "电信机房": "Telecommunication room",
+  "航空航天": "aerospace",
+  "智能家居": "Smart home",
+  "明亮": "lightness",
+  "大屏": "large-screen",
+  "网页": "WEB",
+  "平板Mini": "Flat Mini",
+  "华为P8": "Huawei P8",
+  "华为P40": "Huawei P40",
+  "手机1": "Phone 1",
+  "手机2": "Phone 2",
+  "请先登录!": "Please log in first!",
+  "请填写以.css结尾的font-class引用方式的URL地址": "Please enter the URL with a font class reference ending in.css",
+  "行为${i + 1}": "Behavior ${i + 1}",
+  "确定删除该数据吗?": "Are you sure to delete this data?",
+  "删除后不可恢复!": "It is not recoverable after deletion!",
+  "语言": "Language",
+  "新建项目": "New project",
+  "简体中文": "Simplified Chinese",
+  "繁体中文": "Traditional Chinese",
+  "可二次编辑但转换存在损失,若作为图片使用,请使用右侧属性面板的上传图片功能": "It can be edited twice, but there is a loss in conversion. If you use it as an image, please use the upload image function on the right property panel",
+  "打开文件只支持 json,svg,zip 格式": "Open files only support json, svg, zip format",
+  "svg转换成功,请点击画布决定放置位置": "svg conversion is successful. Click on canvas to decide where to place it",
+  "需要开通会员~": "Need to open membership ~",
+  "正在读取...": "Reading...",
+  "正在上传文件...": "Uploading files...",
+  "导入成功!": "Import success!",
+  "需要开通普通会员~": "Need to open ordinary member ~",
+  "画布没有画笔!": "The canvas has no brushes!",
+  "正在下载打包中,可能需要几分钟,请耐心等待...": "Is downloading package, may take a few minutes, please wait...",
+  "下载成功,请在浏览器下载列表中查看": "Download successfully, please view in the browser download list",
+  "无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制": "Cannot download, width is not legal, canvas may not have a brush/canvas size exceeds browser maximum limit",
+  "请先加载乐吾乐官网下的canvas2svg.js": "Please first load canvas2svg.js under the official website of Lewule",
+  "正在下载中,可能需要几分钟,请耐心等待...": "Downloading, may take a few minutes, please be patient...",
+  "支付成功": "Payment success",
+  "保存成功!": "Save successfully!",
+  "动画名不能为空!": "Animation name cannot be empty!",
+  "已存在同名动画!": "An animation of the same name already exists!",
+  "闪烁": "flicker",
+  "逆向旋转": "Reverse rotation",
+  "上下跳动": "Jump up and down",
+  "左右跳动": "Skip side to side",
+  "颜色变化": "Color change",
+  "背景变化": "Background change",
+  "文字变化": "Literal variation",
+  "乐吾乐": "Le Wule",
+  "状态变化": "State change",
+  "翻转": "flip",
+  "当前选中单元格": "The cell is currently selected",
+  "当前选中行": "Currently selected line",
+  "查看状态": "View status",
+  "自定义状态": "Custom state",
+  "移除": "Remove",
+  "数据名或属性名不能为空!": "The data name or attribute name cannot be empty!",
+  "已经存在相同属性数据!": "The same property data already exists!",
+  "编辑动态数据": "Edit dynamic data",
+  "请输入数组格式数据": "Please enter data in array format",
+  "请输入严格的JSON格式数据": "Please enter data in strict JSON format",
+  "状态场景${pen.triggers.length + 1}": "Status Scenario ${pen.triggers.length + 1}",
+  "状态1": "Status 1",
+  "状态2": "Status 2",
+  "条件告警": "Conditional alarm",
+  "条件动画": "Conditional animation",
+  "状态切换": "State switch",
+  "满足条件,切换到状态1": "If the condition is met, switch to state 1",
+  "默认显示状态": "Default display status",
+  "满足条件,触发告警": "If the conditions are met, the alarm is triggered",
+  "恢复默认": "Restore default",
+  "满足条件,触发动画执行": "If the conditions are met, animation execution is triggered",
+  "恢复默认状态": "Restore to default",
+  "状态场景${props.pen.triggers.length + 1}": "State scene ${props. Pen. Triggers. Length + 1}",
+  "第${cell.value.row}行,第${cell.value.col}列": "Row ${cell.value.row}, column ${cell.value.col}",
+  "第${cell.value.row}行": "Line ${cell.value.row}",
+  "数据格式必需是二维数组": "The data format must be a two-dimensional array",
+  "请输入API地址": "Please enter the API address",
+  "导入成功": "Import successfully",
+  "数据格式必需是数组类型": "The data format must be an array type",
+  "状态场景": "State scene",
+  "单击": "Click",
+  "双击": "double-click",
+  "输入完成": "Input complete",
+  "输入": "input",
+  "鼠标右键": "Right mouse button",
+  "鼠标移入": "Mouse in",
+  "鼠标移出": "Mouse out",
+  "获得焦点": "Gain focus",
+  "失去焦点": "Lose focus",
+  "鼠标按下": "Mouse down",
+  "鼠标抬起": "Mouse up",
+  "监听全局消息": "Listen to global messages",
+  "选择完成": "Selection complete",
+  "左对齐": "Justification left",
+  "垂直居中对齐": "Center vertically",
+  "右对齐": "Justify right",
+  "水平居中对齐": "Center align horizontally",
+  "id 不能为空": "The id cannot be empty",
+  "id 修改失败,请检查 id 是否重复": "Failed to change the id. Please check whether the id is the same",
+  "上传的图片不能大于5M": "The uploaded image cannot be larger than 5M",
+  "水平等距": "Horizontal equidistance",
+  "垂直等距": "Vertical equidistance",
+  "相同大小": "Of the same size",
+  "确认删除这条状态场景吗?": "Are you sure to delete this status scene?",
+  "编辑状态": "Edit status",
+  "图层": "layer",
+  "底层图片层": "Bottom picture layer",
+  "模版层": "Template layer",
+  "请先选中图元": "Please select the primitive first",
+  "值1,值2,": "Value 1, value 2,",
+  "解析的svg图元不允许编辑!": "Parsed svg primitives do not allow editing!",
+  "曲线": "curve",
+  "线段": "Line segment",
+  "脑图曲线": "encephalogram",
+  "变量列表不能为空": "The variable list cannot be empty",
+  "保存新增成功!": "Save new successfully!",
+  "保存更新成功!": "Save the update successfully!",
+  "变量列表不能为空!": "The variable list cannot be empty!",
+  "组件不允许分享!": "Components are not allowed to share!",
+  "请填写子域名": "Please fill in the subdomain",
+  "已经存在相同子域名": "The same subdomain name already exists",
+  "请选择将要发布的方案": "Please select the solution to be published",
+  "dom层级(z-index)": "dom hierarchy (z-index)",
+  "默认4": "Default 4",
+  "可操作x": "Operable x",
+  "范围0-1": "It ranges from 0 to 1",
+  "可操作y": "Operable y",
+  "可操作宽度": "Operable width",
+  "可操作高度": "Operational height",
+  "背景模糊": "Background blur",
+  "毛玻璃颜色": "Frosted glass color",
+  "基本形状": "Basic shape",
+  "正方形": "square",
+  "矩形": "rectangle",
+  "圆": "round",
+  "三角形": "triangle",
+  "菱形": "rhomboid",
+  "五边形": "pentagon",
+  "六边形": "hexagon",
+  "五角星": "Five-pointed star",
+  "左箭头": "Left arrow",
+  "右箭头": "Right arrow",
+  "双向箭头": "Bidirectional arrow",
+  "云": "cloud",
+  "消息框": "Message box",
+  "立方体": "cube",
+  "<= 1 即宽度的比例": "<= 1 is the ratio of width",
+  "前背景色": "Front background color",
+  "顶背景色": "Top background color",
+  "右背景色": "Right background color",
+  "人": "people",
+  "脑图": "Brain map",
+  "子主题": "subtopic",
+  "流程图": "Flow chart",
+  "开始/结束": "Start/end",
+  "流程": "flow",
+  "判定": "determine",
+  "斜率": "slope",
+  "准备": "Equipping Items",
+  "子流程": "subprocess",
+  "数据库": "Archive",
+  "文档": "document",
+  "内部存储": "Internal storage",
+  "外部存储": "External storage",
+  "队列": "queue",
+  "手动输入": "Manual input",
+  "展示": "show",
+  "并行模式": "Parallel mode",
+  "注释": "annotation",
+  "活动图": "Activity graph",
+  "开始": "initiate",
+  "结束": "finish",
+  "活动": "Events",
+  "决策/合并": "Decision/Merger",
+  "垂直泳道": "Vertical lane",
+  "水平泳道": "Horizontal lane",
+  "垂直分岔/汇合": "Vertical bifurcation/confluence",
+  "水平分岔/汇合": "Horizontal bifurcation/confluence",
+  "时序图和类图": "Sequence diagram and class diagram",
+  "生命线": "lifeline",
+  "激活": "Activate",
+  "简单类": "Simple class",
+  "类": "class",
+  "故障树": "Fault tree",
+  "与门": "And gate",
+  "基本事件": "Basic event",
+  "未展开事件": "Undeveloped event",
+  "优先AND门": "Priority AND gate",
+  "禁止门": "Exclusion gate",
+  "事件": "incident",
+  "开关事件": "Switching event",
+  "条件事件": "Conditional event",
+  "转移符号": "Branch symbol",
+  "或门": "Disjunction gate",
+  "异或门": "Exclusive-or gate",
+  "表决门": "Vote gate",
+  "基础": "Basics",
+  "文本": "text",
+  "乐吾乐le5le - 大屏可视化": "le5le - Large screen visualization",
+  "文本自动大小": "Automatic text sizing",
+  "数字": "figure",
+  "进度条": "Progress bar",
+  "/png/电信机房/防火墙.gif": "/png/ Telecommunication Room/firewall.gif",
+  "头像": "avatar",
+  "图片圆角半径": "Picture rounded radius",
+  "徽标": "logo",
+  "标签": "tag",
+  "音视频": "Av (audio and video)",
+  "视频": "video",
+  "视频地址": "Video address",
+  "FLV视频流": "FLV video stream",
+  "媒体数据源": "Media data source",
+  "具体配置参考:https://github.com/bilibili/flv.js/blob/master/docs/api.md": "Specific configuration reference: https://github.com/bilibili/flv.js/blob/master/docs/api.md",
+  "配置": "disposition",
+  "音频": "Audio frequency",
+  "音频地址": "Audio address",
+  "摄像头": "camera",
+  "Webrtc(低延迟,仅支持H264格式)": "Webrtc(Low latency, H264 format only)",
+  "MSE(支持H265格式,需最新chrome)": "MSE(Support H265 format, latest chrome required)",
+  "流服务": "Stream service",
+  "时间": "time",
+  "当前时间": "Current time",
+  "显示格式": "Display format",
+  "补0": "Complement by 0",
+  "倒计时": "Countdown:",
+  "截止时间": "Cut-off time",
+  "水平时间轴": "Horizontal timeline",
+  "事件一": "Event one",
+  "事件二": "Event two",
+  "事件三": "Event three",
+  "事件四": "Event IV",
+  "时间轴": "timeline",
+  "标签分布": "Label distribution",
+  "同侧": "ipsilateral",
+  "交叉": "intersect",
+  "标签对齐": "Label alignment",
+  "顶部": "upper",
+  "底部": "bottom",
+  "垂直时间轴": "Vertical timeline",
+  "日历(日期)": "Calendar (date)",
+  "8月": "August",
+  "日历(日期时间)": "Calendar (Date and time)",
+  "面板": "Panel",
+  "列表": "list",
+  "列表标题": "List heading",
+  "列表内容的描述性文字": "Descriptive text for the contents of the list",
+  "标题大小": "Title size",
+  "标题颜色": "Title color",
+  "表格": "tabulation",
+  "列宽": "Column width",
+  "行头": "outfit",
+  "列头": "Line header",
+  "边框": "border",
+  "垂直线": "Vertical line",
+  "水平线": "Horizontal line",
+  "最大展示数": "Maximum display number",
+  "列配置": "Column configuration",
+  "斑马纹表格": "Zebra print form",
+  "一级告警": "Primary alarm",
+  "二级告警": "Level two alarm",
+  "三级告警": "Level three alarm",
+  "设备 ID": "Device ID",
+  "设备名称": "Device name",
+  "数据协议": "Data protocol",
+  "级别": "rank",
+  "湿度传感器": "Humidity sensor",
+  "物联网设备": "Internet of things devices",
+  "物联网设备/智能家居/智慧城市": "Iot devices/Smart home/Smart City",
+  "显示斑马纹": "Zebra print",
+  "斑马纹颜色": "Zebra color",
+  "外边框": "border",
+  "有无表头": "With or without table head",
+  "{一级告警,二级告警,三级告警}": "{Level 1 Alarm, Level 2 alarm, Level 3 alarm}",
+  "触发器1": "Flip-flop 1",
+  "触发器2": "Flip-flop 2",
+  "触发器3": "Flip-flop 3",
+  "滚动表格": "Scroll table",
+  "处理中": "In process",
+  "已完成": "completed",
+  "待处理": "To be processed",
+  "序号": "Serial number",
+  "事件内容": "Event content",
+  "处理状态": "Processing state",
+  "是否轮播": "Carousel or not",
+  "表格分页": "Table paging",
+  "场景": "Map",
+  "图纸id": "Drawing id",
+  "冷源群控系统": "Cold source group control system",
+  "中央空调模拟演示台系统": "Central air conditioning simulation demonstration station system",
+  "换热站远程监控系统": "Heat exchange station remote monitoring system",
+  "变电站主接线图": "Substation main wiring diagram",
+  "制冷站": "Refrigeration station",
+  "废水处理": "Wastewater treatment",
+  "数据中心": "Data center",
+  "破碎筛分监控": "Crushing and screening monitoring",
+  "光伏系统": "Photovoltaic system",
+  "点击查看": "Click to view",
+  "分页配置": "Paging configuration",
+  "最大展示数量": "Maximum display quantity",
+  "多功能表格": "Multifunction form",
+  "选项一": "Option one",
+  "选项二": "Option two",
+  "选项三": "Option three",
+  "树": "The tree",
+  "展开全部节点": "Expand all nodes",
+  "提醒": "warn",
+  "业务指标": "Service indicator",
+  "全局消息": "Global message",
+  "用于表示普通操作信息提示": "Indicates common operation information prompts",
+  "文本颜色": "Text color",
+  "通知": "notification",
+  "通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;": "The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice; The specific contents of the notice;",
+  "标题名称": "Title name",
+  "标题": "title",
+  "标题加粗": "Bold title",
+  "对话框": "Dialog box",
+  "轮播": "carousel",
+  "水平轮播": "Horizontal rotation",
+  "轮播第一次数据": "The first data of the rotation",
+  "轮播第二次数据": "The second data of the rotation",
+  "轮播第三次数据": "Data of the third round casting",
+  "轮播时间": "Rotation time",
+  "垂直轮播": "Vertical wheel seeding",
+  "轮播图": "Carousel map",
+  "轮播页面": "Carousel page",
+  "导航": "Navigation",
+  "链接": "link",
+  "乐吾乐2D编辑器": "Logol 2D editor",
+  "锚点": "Anchor point",
+  "定位图元": "Location element",
+  "回到顶部": "Back to the top",
+  "面包屑": "crumbs",
+  "页面1": "Page 1",
+  "页面2": "Page 2",
+  "页面3": "Page 3",
+  "间距": "interval",
+  "下拉菜单": "Drop-down menu",
+  "个人中心": "Individual center",
+  "测试测试": "Test test",
+  "安全运行": "Safe operation",
+  "智慧能源": "Smart energy",
+  "数据分析": "Data analysis",
+  "运维管理": "Operation and maintenance management",
+  "字体颜色": "Font color",
+  "图标大小": "Icon size",
+  "图标位置": "Icon position",
+  "图标右间距": "Icon right spacing",
+  "选项宽度": "Option width",
+  "选项背景图": "Option background",
+  "选项高度": "Option height",
+  "hover背景色": "hover background",
+  "hover字体颜色": "hover font color",
+  "选中背景色": "Select background color",
+  "选中字体颜色": "Select font color",
+  "下拉内容背景色": "Drop down the content background color",
+  "是否渲染二级菜单": "Whether to render the secondary menu",
+  "关联Iframe": "The Iframe is associated",
+  "导航菜单": "Navigation menu",
+  "实时监测": "Real-time monitoring",
+  "站点看板": "Site signage",
+  "三级标题": "Three-level heading",
+  "监控画面": "Surveillance screen",
+  "设备监控": "Equipment monitoring",
+  "控制中心": "Control center",
+  "告警管理": "Alarm management",
+  "分页": "paging",
+  "数据总条数": "Total number of data items",
+  "每页数据量": "Amount of data per page",
+  "分页大小控制器": "Page size controller",
+  "最多显示页码数按钮数": "Display a maximum of page number buttons",
+  "步骤条": "Step bar",
+  "已完成的步骤": "Completed steps",
+  "这里是提示文字": "Here is the prompt text",
+  "出错的步骤": "Error step",
+  "进行中的步骤": "Steps in progress",
+  "未完成的步骤": "Unfinished steps",
+  "各个状态颜色": "Color by state",
+  "方向": "direction",
+  "水平": "level",
+  "垂直": "perpendicularity",
+  "快速选项卡": "Quick TAB",
+  "场景一": "Scenario one",
+  "场景二": "Scenario two",
+  "场景三": "Scenario three",
+  "场景四": "Scenario four",
+  "间隔": "interval",
+  "按钮宽度": "Button width",
+  "按钮高度": "Button height",
+  "选中背景": "Select background",
+  "选中边框": "Check border",
+  "选中文字": "Selected text",
+  "选中背景图片": "Select background image",
+  "(未选中)背景": "(Unchecked) Background",
+  "(未选中)边框": "(Unchecked) Border",
+  "(未选中)文字": "(unchecked) text",
+  "(未选中)背景图片": "(Unchecked) Background image",
+  "显示拖拽范围": "Shows the drag range",
+  "基本选项卡": "Basic TAB",
+  "卡片选项卡": "Card TAB",
+  "全部(15)": "All (15)",
+  "正常运行(7)": "Normal operation (7)",
+  "故障告警(0)": "Fault Alarm (0)",
+  "通讯异常(8)": "Abnormal Communication (8)",
+  "多选选项卡": "Multiple selection TAB",
+  "按钮": "Button",
+  "按下颜色": "Press color",
+  "按下背景": "Press background",
+  "状态按钮": "Status button",
+  "文本输入框": "Text entry field",
+  "输入文本": "Input text",
+  "数字输入框": "Digital input box",
+  "输入数字": "Input digit",
+  "单选框": "Radio box",
+  "选项示例二": "Option example 2",
+  "排列方向": "Arrangement direction",
+  "横向": "Landscape orientation",
+  "纵向": "portrait",
+  "模式": "mode",
+  "通用模式": "Universal mode",
+  "按钮模式": "Button mode",
+  "多选框": "checkbox",
+  "下拉选择器": "Drop down selector",
+  "选项1": "Option 1",
+  "选项2": "Option 2",
+  "选项3": "Option 3",
+  "下拉列表": "Drop-down list",
+  "下拉背景": "Pull-down background",
+  "下拉颜色": "Pull-down color",
+  "下拉悬停背景": "Drop down to hover background",
+  "下拉悬停颜色": "Drop down to hover colors",
+  "密码输入框": "Password entry field",
+  "时间选择器": "Time selector",
+  "日期选择器": "Date selector",
+  "颜色选择器": "Color selector",
+  "开关": "Switch",
+  "开颜色": "Open color",
+  "关颜色": "Color off",
+  "开描边颜色": "Open stroke color",
+  "关描边颜色": "Turn off stroke color",
+  "是否禁用": "Whether to disable",
+  "开(禁)颜色": "On (off) color",
+  "关(禁)颜色": "Off (forbidden) color",
+  "滑块": "Sliding block",
+  "工控": "Industrial control",
+  "圆柱水位": "Cylindrical water level",
+  "水位": "Water level",
+  "水位颜色": "Water level color",
+  "球形水位": "Spherical water level",
+  ">最大颜色": "> Maximum color",
+  "<最小颜色": "< Minimum color",
+  "刻度显示": "Scale display",
+  "宽幅,推荐值0-10": "The value ranges from 0 to 10",
+  "默认2": "Default 2",
+  "高幅,推荐值1-10": "High width, recommended value 1-10",
+  "液边距": "Liquid edge distance",
+  "水箱": "cistern",
+  "指示灯": "Pilot lamp",
+  "动画1": "Animations 1",
+  "显示状态": "Display status",
+  "开": "open",
+  "关": "close",
+  "圆形按钮": "Round button",
+  "开时颜色": "Open color",
+  "关时颜色": "Off color",
+  "开时阴影颜色": "Open shading color",
+  "关时阴影颜色": "Turn off the shadow color",
+  "船型开关": "Hull switch",
+  "转换开关": "Transfer switch",
+  "闸刀": "Switch knife",
+  "拨动开关": "Toggle switch",
+  "空气开关": "Air switch",
+  "水柱温度计": "Water column thermometer",
+  "当前值": "Current value",
+  "扁平温度计": "Flat thermometer",
+  "电池": "battery",
+  "默认1": "Default 1",
+  "分段数": "Number of segments",
+  "间隔占比": "Interval ratio",
+  "航天航空": "aerospace",
+  "布局": "layout",
+  "帧": "frame",
+  "请先登录,否则无法保存!": "Please log in first, otherwise you can't save!",
+  "请开通vip,即将跳转到开通页面...": "Please open vip, will soon jump to the opening page...",
+  "状态情况": "State situation",
+  "产品介绍": "Product introduction",
+  "快速上手": "Get started quickly",
+  "使用手册": "User manual",
+  "快捷键": "Shortcut key",
+  "企业服务与支持": "Corporate Services and support",
+  "关于我们": "About us",
+  "画布为空,无法保存!": "Canvas is empty and cannot be saved!",
+  "无法下载,宽度不合法,可能没有选中画笔/选中画笔大小超出浏览器最大限制": "Cannot download, width is not legal, brush may not be selected/brush size is out of browser maximum limit",
+  "成功保存为组件!": "Successfully saved as component!",
+  "系统可能不会保存您所做的更改,是否继续?": "The system may not save your changes. Do you want to continue?",
+  "未登录,系统可能不会保存您的文件,是否继续?": "Not logged in, the system may not save your file, do you want to continue?",
+  "当前文件未保存,是否继续?(开通vip可享受自动保存服务)": "The current file is not saved. Do you want to continue? (Open vip can enjoy automatic saving service)",
+  "布尔": "Boole",
+  "数组": "array",
+  "场景状态": "Scene state",
+  "折线图": "Line chart",
+  "基础折线图-hover": "Base line chart -hover",
+  "系列1": "Series 1",
+  "1月": "Jan.",
+  "2月": "February",
+  "3月": "March",
+  "4月": "April",
+  "5月": "May",
+  "6月": "June",
+  "单位": "unit",
+  "echarts配置": "echarts configuration",
+  "基础折线图": "Basic line chart",
+  "多折线图": "Multiline chart",
+  "折线一的1月": "January of line one",
+  "折线二的1月": "January of the second line",
+  "折线一的2月": "Broken line one's February",
+  "折线二的2月": "Line two's February",
+  "折线一的3月": "March of line one",
+  "折线二的3月": "March of line two",
+  "折线一的4月": "April of line one",
+  "折线二的4月": "In April of line two",
+  "折线一的5月": "May of line one",
+  "折线二的5月": "May of line two",
+  "折线一的6月": "June of line one",
+  "折线二的6月": "Line two in June",
+  "折线趋势图": "Broken line trend chart",
+  "数据点": "Data point",
+  "基础曲线图": "Base chart",
+  "多曲线图": "multigraph",
+  "曲线趋势图": "Curve trend chart",
+  "渐变单曲线图1": "Gradient track chart 1",
+  "单位:kwh ": "Unit: kwh",
+  "渐变单曲线图2": "Gradient track chart 2",
+  "单位:A ": "Unit: A",
+  "渐变单曲线图3": "Gradient track chart 3",
+  "单位:V": "Unit: V",
+  "阶梯折线图": "Step line chart",
+  "面积图": "Area chart",
+  "基础面积图": "Foundation area plan",
+  "堆叠面积图": "Stack area diagram",
+  "柱状图": "Bar chart",
+  "基础柱状图": "Foundation bar chart",
+  "分组柱状图": "Group bar charts",
+  "分组一的1月": "Group one of January",
+  "分组二的1月": "Group two of January",
+  "分组一的2月": "Group one of February",
+  "分组二的2月": "Group two of February",
+  "分组一的3月": "Group one of March",
+  "分组二的3月": "Group two of March",
+  "分组一的4月": "Group one of April",
+  "分组二的4月": "Group two of April",
+  "分组一的5月": "Group one of May",
+  "分组二的5月": "Group two of May",
+  "分组一的6月": "Group one in June",
+  "分组二的6月": "Group two of June",
+  "堆叠柱状图": "Stacked bar chart",
+  "渐变柱状图": "Gradient bar chart",
+  "单位:万kwh": "Unit: 10,000 kwh",
+  "条形图": "Bar chart",
+  "基础条形图": "Base bar chart",
+  "分组条形图": "Group bar charts",
+  "堆叠条形图": "Stack bar charts",
+  "正负条形图": "Plus and minus bar chart",
+  "分组三的1月": "Group three of January",
+  "分组三的2月": "Group three of February",
+  "分组三的3月": "Group three of March",
+  "分组三的4月": "Group three of April",
+  "分组三的5月": "Group three of May",
+  "分组三的6月": "Group three of June",
+  "饼环图": "Pie chart",
+  "饼图": "Pie chart",
+  "物联网平台": "Internet of Things platform",
+  "图形库": "Graphic library",
+  "环图": "Ring graph",
+  "圆角环图": "Rounded ring diagram",
+  "散点图": "Scatter diagram",
+  "点1.X": "Point 1.X",
+  "点1.Y": "Point 1.Y",
+  "点2.X": "Point 2.X",
+  "点2.Y": "Point 2.Y",
+  "点3.X": "Point 3.X",
+  "点3.Y": "Point 3.Y",
+  "涟漪散点图": "Ripple scatter diagram",
+  "雷达图": "Radar map",
+  "销售": "sell",
+  "开发": "exploit",
+  "营销": "MARKETING",
+  "预算": "budget",
+  "消费": "consumption",
+  "预算.销售": "Budget. Sales",
+  "预算.管理": "Budgeting. Management",
+  "预算.数据": "Budget. Data",
+  "预算.支持": "Budget. Support",
+  "预算.开发": "Budget. Development",
+  "预算.营销": "Budgeting. Marketing",
+  "圆形雷达图": "Circular radar map",
+  "关系图": "Relational graph",
+  "力引导布局": "Force-guided layout",
+  "知识图谱": "Knowledge graph",
+  "操作系统": "Operating system",
+  "浏览器": "Browser",
+  "实现": "realize",
+  "属于": "Belong to",
+  "关联": "relevance",
+  "桑葚图": "Mulberry map",
+  "桑基图": "Sanchitou",
+  "自定义桑基图": "Custom Sankey diagram",
+  "华中": "Central China",
+  "华南": "South China",
+  "华东": "East China",
+  "华北": "North China",
+  "西北": "northwest",
+  "西南": "southwest",
+  "北京": "Peking",
+  "上海": "Shanghai",
+  "武汉": "Wuhan (capital of Hubei Province)",
+  "济南": "Jinan (in Shandong Province)",
+  "东莞": "Dongguan (a city in Guangdong Province)",
+  "珠海": "Zhuhai",
+  "青岛": "Qingdao",
+  "无锡": "Wuxi",
+  "厦门": "Xiamen (in Fujian Province)",
+  "成都": "Chengdu",
+  "杭州": "Hangzhou",
+  "金华": "Jinhua",
+  "南京": "Nanjing",
+  "西安": "Xi 'an",
+  "中山": "A surname",
+  "天津": "Tianjin",
+  "苏州": "Suzhou",
+  "威海": "Weihai",
+  "银川": "Yinchuan",
+  "贵阳": "Guiyang",
+  "佛山": "Foshan",
+  "东营": "Dongying",
+  "舟山": "Zhoushan",
+  "郑州": "Zhengzhou",
+  "烟台": "Yantai",
+  "嘉兴": "Jiaxing",
+  "三亚": "Sanya",
+  "宁波": "Ningbo",
+  "潍坊": "Weifang",
+  "合肥": "Hefei (Capital of Anhui Province)",
+  "湖州": "Huzhou",
+  "枣庄": "Zaozhuang",
+  "太原": "Taiyuan",
+  "海口": "Haikou",
+  "长沙": "Changsha",
+  "淄博": "Zibo",
+  "聊城": "Liaocheng",
+  "常州": "Changzhou",
+  "济宁": "Jining",
+  "南宁": "Nanning",
+  "梅州": "Meizhou",
+  "遵义": "Zunyi",
+  "南昌": "Nanchang",
+  "宿迁": "Suqian",
+  "福州": "Fuzhou (capital of Fujian Province)",
+  "桂林": "Guilin",
+  "广州": "Guangzhou",
+  "深圳": "Shenzhen",
+  "惠州": "Huizhou",
+  "拉萨": "Lhasa",
+  "武汉->华中": "Wuhan -> Central China",
+  "仪表盘": "Instrument panel",
+  "基础仪表盘": "Base instrument panel",
+  "圆盘仪表盘": "Disk instrument panel",
+  "最外部进度条": "Outermost progress bar",
+  "指针上的圆": "The circle on the pointer",
+  "外层透明圆": "Outer transparent circle",
+  "内圆": "Inner circle",
+  "进度仪表盘": "Progress dashboard",
+  "最外部环": "Outermost ring",
+  "蓝色科技1": "Blue Technology 1",
+  "蓝色科技2": "Blue Technology 2",
+  "蓝色科技3": "Blue Technology 3",
+  "刻度线": "Scale mark",
+  "地图": "map",
+  "中国地图": "Map of China",
+  "涟漪散点": "Ripple scatter",
+  "散点": "splattering",
+  "湖北地图": "Map of Hubei",
+  "涟漪": "ripple",
+  "襄阳": "Xiangyang",
+  "宜昌": "Yichang",
+  "荆州": "Jingzhou",
+  "统计:{b}": "Statistics: {b}",
+  "地图·流量": "Map · Traffic",
+  "乐吾乐Charts": "Logole Charts",
+  "调色盘色值列表": "Palette color value list",
+  "横坐标轴数据": "Horizontal axis data",
+  "纵坐标数据": "Ordinate data",
+  "平滑线": "Smooth line",
+  "半径范围": "Radius range",
+  "起始角": "Angle of origin",
+  "结束角": "End Angle",
+  "时钟": "clock",
+  "3d-饼图": "3d- Pie chart",
+  "导入的excel文件不可为空!": "The imported excel file cannot be empty!",
+  "导入成功!": "Import success!",
+  "导出成功!": "Export success!",
+  "正在更新...": "Updating...",
+  "此为付费数据,请购买后访问": "This is paid data, please access after purchase",
+  "请求错误,不合法的请求!": "Request error, illegal request!",
+  "访问数据不存在,请检查后重试!": "Access data does not exist, please check and try again!",
+  "请求服务错误,请稍后重试!": "Service request error, please try again later!",
+  "网络超时,请检测你的网络!": "Network timeout, please check your network!",
+  "未知网络错误!": "Unknown network error!"
+};export default a

+ 2 - 0
src/i18n/lang/index.ts

@@ -0,0 +1,2 @@
+export {default as en} from './en.ts';
+export {default as zh_CHT} from './zh_CHT.ts';

+ 1375 - 0
src/i18n/lang/zh_CHT.ts

@@ -0,0 +1,1375 @@
+const a = {
+  "          动作": "動作",
+  "单位ms,默认不延迟执行": "單位ms,默認不延遲執行",
+  "延迟": "延遲",
+  "动作类型": "動作類型",
+  "请选择": "請選擇",
+  "链接地址": "鏈接地址",
+  "打开方式": "打開方式",
+  "新页面": "新頁面",
+  "当前页面": "當前頁面",
+  "视图": "視圖",
+  "对象类型": "對象類型",
+  "图元": "圖元",
+  "组": "組",
+  "播放对象": "播放對象",
+  "默认自己": "默認自己",
+  "动画名称": "動畫名稱",
+  "缺省第一个动画": "缺省第一個動畫",
+  "更改对象": "更改對象",
+  "属性数据": "屬性數據",
+  "属性名": "屬性名",
+  "属性值": "屬性值",
+  "自定义": "自定義",
+  "值": "值",
+  "暂无数据": "暫無數據",
+  "窗口标题": "窗口標題",
+  "弹框标题": "彈框標題",
+  "画面": "畫面",
+  "窗口画面URL": "窗口畫面URL",
+  "弹框位置": "彈框位置",
+  "弹框大小": "彈框大小",
+  "宽": "寬",
+  "高": "高",
+  "消息名称": "消息名稱",
+  "名称": "名稱",
+  "消息参数": "消息參數",
+  "参数": "參數",
+  "数据": "數據",
+  "数据对象": "數據對象",
+  "添加数据": "添加數據",
+  "回调": "回調",
+  "可获取": "可獲取",
+  "和": "和",
+  "参考": "參考",
+  "发送指令": "發送指令",
+  "函数名称": "函數名稱",
+  "函数参数": "函數參數",
+  "场景对象": "場景對象",
+  "必填": "必填",
+  "消息名": "消息名",
+  "消息数据": "消息數據",
+  "消息对象": "消息對象",
+  "添加消息数据": "添加消息數據",
+  "添加动作": "添加動作",
+  "在当前帧后面添加动画帧": "在當前幀後面添加動畫幀",
+  "添加属性": "添加屬性",
+  "确认删除该动画帧吗": "確認刪除該動畫幀嗎",
+  "时长": "時長",
+  "毫秒": "毫秒",
+  "添加帧": "添加幀",
+  "还没有动画帧": "還沒有動畫幀",
+  "添加动画帧": "添加動畫幀",
+  "快速发布": "快速發佈",
+  "提升工作效率": "提升工作效率",
+  "减少运维工作": "減少運維工作",
+  "降低成本": "降低成本",
+  "专注业务": "專注業務",
+  "创新无负担": "創新無負擔",
+  "原价": "原價",
+  "提交订单": "提交訂單",
+  "乐吾乐收银台": "樂吾樂收銀臺",
+  "支付完成": "支付完成",
+  "分享公开": "分享公開",
+  "不分享": "不分享",
+  "复制链接": "複製鏈接",
+  "分享到": "分享到",
+  "扫一扫": "掃一掃",
+  "微信扫一扫": "微信掃一掃",
+  "分享私有图纸请确保小程序登录的账号与": "分享私有圖紙請確保小程序登錄的賬號與",
+  "端一致": "端一致",
+  "或者将私有图纸设置为分享公开": "或者將私有圖紙設置爲分享公開",
+  "才可以正常扫码预览": "纔可以正常掃碼預覽",
+  "触发条件": "觸發條件",
+  "满足全部条件": "滿足全部條件",
+  "满足任意条件": "滿足任意條件",
+  "          条件": "條件",
+  "条件类型": "條件類型",
+  "关系条件": "關係條件",
+  "高级条件": "高級條件",
+  "关系运算": "關係運算",
+  "运算对象": "運算對象",
+  "固定值": "固定值",
+  "对象属性值": "對象屬性值",
+  "对象": "對象",
+  "属性": "屬性",
+  "添加触发条件": "添加觸發條件",
+  "添加手柄": "添加手柄",
+  "删除手柄": "刪除手柄",
+  "切换手柄": "切換手柄",
+  "一键更新我的组件": "一鍵更新我的組件",
+  "追加状态": "追加狀態",
+  "进入": "進入",
+  "可视化编辑": "可視化編輯",
+  "进入大屏可视化编辑": "進入大屏可視化編輯",
+  "替换方案": "替換方案",
+  "置顶": "置頂",
+  "置底": "置底",
+  "上一个图层": "上一個圖層",
+  "下一个图层": "下一個圖層",
+  "组合": "組合",
+  "组合为状态": "組合爲狀態",
+  "确认取消组合?(将丢失组合图元的数据)": "確認取消組合?(將丟失組合圖元的數據)",
+  "取消组合": "取消組合",
+  "解锁": "解鎖",
+  "锁定": "鎖定",
+  "删除": "刪除",
+  "变成节点": "變成節點",
+  "变成连线": "變成連線",
+  "撤销": "撤銷",
+  "重做": "重做",
+  "剪切": "剪切",
+  "复制": "複製",
+  "粘贴": "粘貼",
+  "        选中单元格(第": "選中單元格(第",
+  "{ cell.row }}行,第": "{ cell.row }}行,第",
+  "        第": "第",
+  "背景颜色": "背景顏色",
+  "文字颜色": "文字顏色",
+  "文字大小": "文字大小",
+  "文本对齐": "文本對齊",
+  "居左": "居左",
+  "水平居中": "水平居中",
+  "居右": "居右",
+  "水平偏移": "水平偏移",
+  "是否绘制": "是否繪製",
+  "关闭": "關閉",
+  "运行": "運行",
+  "group === '属性'": "group === '屬性'",
+  "导入属性列表": "導入屬性列表",
+  "新建属性": "新建屬性",
+  "我的属性列表": "我的屬性列表",
+  "请先登录": "請先登錄",
+  "在线接口": "在線接口",
+  "地址:": "地址:",
+  "请输入地址": "請輸入地址",
+  "从": "從",
+  "导入": "導入",
+  "下载": "下載",
+  "示例": "示例",
+  "导出属性列表": "導出屬性列表",
+  "下载为": "下載爲",
+  "保存为我的属性列表": "保存爲我的屬性列表",
+  "确认清空属性列表吗?": "確認清空屬性列表嗎?",
+  "清空列表": "清空列表",
+  "可批量导入数据图元到画布": "可批量導入數據圖元到畫布",
+  "批量导入到画布": "批量導入到畫布",
+  "开启全局数据模拟": "開啓全局數據模擬",
+  "开启": "開啓",
+  "搜索我的属性列表": "搜索我的屬性列表",
+  "开启单个模拟": "開啓單個模擬",
+  "确认删除吗?": "確認刪除嗎?",
+  "类型": "類型",
+  "值范围": "值範圍",
+  "group === '数据源'": "group === '數據源'",
+  "添加数据源": "添加數據源",
+  "搜索我的数据源": "搜索我的數據源",
+  "显示名称": "顯示名稱",
+  "通信方式": "通信方式",
+  "地址": "地址",
+  "group === '解析'": "group === '解析'",
+  "参考文档": "參考文檔",
+  "解析自定义格式数据": "解析自定義格式數據",
+  "属性简短描述": "屬性簡短描述",
+  "字符串": "字符串",
+  "可用做数据模拟": "可用做數據模擬",
+  "值范围说明": "值範圍說���",
+  "直接填写": "直接填寫",
+  "例如": "例如",
+  "随机值": "隨機值",
+  "范围数字": "範圍數字",
+  "最小值": "最小值",
+  "最大值": "最大值",
+  "或": "或",
+  "随机字符串": "隨機字符串",
+  "长度": "長度",
+  "同时保存到我的数据源": "同時保存到我的數據源",
+  "确定": "確定",
+  "数据监听": "數據監聽",
+  "变量列表": "變量列表",
+  "数据方式": "數據方式",
+  "请求": "請求",
+  "视图结构": "視圖結構",
+  "可编辑": "可編輯",
+  "禁止编辑": "禁止編輯",
+  "禁止编辑和移动": "禁止編輯和移動",
+  "禁止所有事件": "禁止所有事件",
+  "分组": "分組",
+  "新建分组": "新建分組",
+  "确认删除该分组吗?": "確認刪除該分組嗎?",
+  "画布": "畫布",
+  "文件名": "文件名",
+  "分类": "分類",
+  "画布尺寸": "畫布尺寸",
+  "背景图片": "背景圖片",
+  "主题": "主題",
+  "暗黑": "暗黑",
+  "预览设置": "預覽設置",
+  "缩放方式": "縮放方式",
+  "宽高中较小的铺满": "寬高中較小的鋪滿",
+  "自动铺满": "自動鋪滿",
+  "高度等比例缩放": "高度等比例縮放",
+  "宽度铺满": "寬度鋪滿",
+  "宽度等比例缩放": "寬度等比例縮放",
+  "高度铺满": "高度鋪滿",
+  "显示滚动条": "顯示滾動條",
+  "禁止移动": "禁止移動",
+  "禁止缩放": "禁止縮放",
+  "进阶设置": "進階設置",
+  "图标": "圖標",
+  "Font class方式URL": "Font class方式URL",
+  "添加": "添加",
+  "初始化动作": "初始化動作",
+  "辅助设置": "輔助設置",
+  "此功能仅对直线和折线有效": "此功能僅對直線和折線有效",
+  "连线相交弯曲": "連線相交彎曲",
+  "行为": "行爲",
+  "布局容器": "佈局容器",
+  "默认0": "默認0",
+  "靠左": "靠左",
+  "靠右": "靠右",
+  "靠上": "靠上",
+  "靠下": "靠下",
+  "展示图元": "展示圖元",
+  "图元列表": "圖元列表",
+  "操作": "操作",
+  "确认移除吗": "確認移除嗎",
+  "从布局容器中移除此图元": "從佈局容器中移除此圖元",
+  "确认删除该行为吗?": "確認刪除該行爲嗎?",
+  "                条件": "條件",
+  "添加条件": "添加條件",
+  "执行动作": "執行動作",
+  "添加行为": "添加行爲",
+  "系统资源": "系統資源",
+  "我的资源": "我的資源",
+  "结构": "結構",
+  "搜索": "搜索",
+  "展开/折叠": "展開/摺疊",
+  "加载中...": "加載中...",
+  "              activedGroup === '图片' ||": "activedGroup === '圖片' ||",
+  "                (activedGroup === '方案' || activedGroup === '模板' || activedGroup === '组件'))": "(activedGroup === '方案' || activedGroup === '模板' || activedGroup === '組件'))",
+  "新建文件夹": "新建文件夾",
+  "item.canEdited && activedGroup === '图片'": "item.canEdited && activedGroup === '圖片'",
+  "new": "new",
+  "['组件', '方案', '模板'].includes(activedGroup)": "['組件', '方案', '模板'].includes(activedGroup)",
+  "确认删除该文件夹吗": "確認刪除該文件夾嗎",
+  "移动到": "移動到",
+  "方案": "方案",
+  "模板": "模板",
+  "['方案', '模板'].includes(activedGroup)": "['方案', '模板'].includes(activedGroup)",
+  "subMenu in moveGroups[activedGroup==='方案'?'模板':'方案']": "subMenu in moveGroups[activedGroup==='方案'?'模板':'方案']",
+  "图片": "圖片",
+  "编辑": "編輯",
+  "检测到该图纸正在被编辑,": "檢測到該圖紙正在被編輯,",
+  "画布将被清空,": "畫布將被清空,",
+  "{current?$t('检测到该图纸正在被编辑,'):''}}确定删除该数据吗?": "{current?$t('檢測到該圖紙正在被編輯,'):''}}確定刪除該數據嗎?",
+  "管理": "管理",
+  "文件": "文件",
+  "新建文件": "新建文件",
+  "打开文件": "打開文件",
+  "导入文件": "導入文件",
+  "保存": "保存",
+  "另存为": "另存爲",
+  "仅保存": "僅保存",
+  "导出为": "導出爲",
+  "下载离线部署包": "下載離線部署包",
+  "组件包": "組件包",
+  "明亮主题": "明亮主題",
+  "暗黑主题": "暗黑主題",
+  "全选": "全選",
+  "工具": "工具",
+  "窗口大小": "窗口大小",
+  "放大": "放大",
+  "缩小": "縮小",
+  "鹰眼地图": "鷹眼地圖",
+  "放大镜": "放大鏡",
+  "自动锚点": "自動錨點",
+  "显示锚点": "顯示錨點",
+  "删除锚点": "刪除錨點",
+  "帮助": "幫助",
+  "账户中心": "賬戶中心",
+  "大屏可视化": "大屏可視化",
+  "可视化": "可視化",
+  "我的大屏": "我的大屏",
+  "我的团队": "我的團隊",
+  "账号信息": "賬號信息",
+  "安全设置": "安全設置",
+  "退出": "退出",
+  "登录": "登錄",
+  "提示": "提示",
+  "保存后新建": "保存後新建",
+  "不保存直接新建": "不保存直接新建",
+  "当前画布数据未保存": "當前畫布數據未保存",
+  "是否保存后新建": "是否保存後新建",
+  "数据获取": "數據獲取",
+  "数据发送": "數據發送",
+  "我的数据发送": "我的數據發送",
+  "              名称: ": "名稱:",
+  "地址: ": "地址:",
+  "http": "http",
+  "必须是wss协议": "必須是wss協議",
+  "必须是ws协议": "必須是ws協議",
+  "请输入": "請輸入",
+  "请求方式": "請求方式",
+  "请求间隔": "請求間隔",
+  "默认1000 ms": "默認1000 ms",
+  "请求头": "請求頭",
+  "支持设置动态参数": "支持設置動態參數",
+  "请求体": "請求體",
+  "自动生成": "自動生成",
+  "用户名": "用戶名",
+  "密码": "密碼",
+  "保存到我的数据发送": "保存到我的數據發送",
+  "订单编号:": "訂單編號:",
+  "订单类型:": "訂單類型:",
+  "应付金额": "應付金額",
+  "余额支付": "餘額支付",
+  "当前余额": "當前餘額",
+  "扫码支付": "掃碼支付",
+  "注意": "注意",
+  "不支持退款": "不支持退款",
+  "确认支付": "確認支付",
+  "确认删除该动画吗": "確認刪除該動畫嗎",
+  "动画类型": "動畫類型",
+  "水流": "水流",
+  "水珠": "水珠",
+  "圆点": "圓點",
+  "箭头": "箭頭",
+  "水滴": "水滴",
+  "运动速度": "運動速度",
+  "动画颜色": "動畫顏色",
+  "发光效果": "發光效果",
+  "发光颜色": "發光顏色",
+  "发光模糊": "發光模糊",
+  "默认6": "默認6",
+  "轨迹宽度": "軌跡寬度",
+  "轨迹间隔": "軌跡間隔",
+  "默认100": "默認100",
+  "反向流动": "反向流動",
+  "播放次数": "播放次數",
+  "无限": "無限",
+  "缺省无限循环播放": "缺省無限循環播放",
+  "自动播放": "自動播放",
+  "下个动画类型": "下個動畫類型",
+  "当前动画结束后自动播放下一个对象的动画": "當前動畫結束後自動播放下一個對象的動畫",
+  "下个动画": "下個動畫",
+  "无": "無",
+  "动画": "動畫",
+  "结束状态": "結束狀態",
+  "初始状态": "初始狀態",
+  "当前状态": "當前狀態",
+  "线性播放": "線性播放",
+  "仅支持数字属性匀速线性播放": "僅支持數字屬性勻速線性播放",
+  "是": "是",
+  "否": "否",
+  "添加动画": "添加動畫",
+  "还没有动画": "還沒有動畫",
+  "数据源": "數據源",
+  "API接口": "API接口",
+  "CSV文件": "CSV文件",
+  "从Excel导入": "從Excel導入",
+  "                当前选中单元格  (第": "當前選中單元格  (第",
+  "                当前选中行  (第": "當前選中行  (第",
+  "快捷绑定": "快捷綁定",
+  "关联设备": "關聯設備",
+  "设备ID": "設備ID",
+  "数据名": "數據名",
+  "绑定": "綁定",
+  "整数": "整數",
+  "浮点数": "浮點數",
+  "添加动态数据": "添加動態數據",
+  "还没有动态数据": "還沒有動態數據",
+  "ctrl+shift+点击,可选中子图元": "ctrl+shift+點擊,可選中子圖元",
+  "子图元": "子圖元",
+  "简短描述": "簡短描述",
+  "关键字": "關鍵字",
+  "动态数据设置": "動態數據設置",
+  "绑定变量": "綁定變量",
+  "当前绑定": "當前綁定",
+  "本地调试": "本地調試",
+  "模拟值": "模擬值",
+  "模拟值说明": "模擬值說明",
+  "数据状态": "數據狀態",
+  "确认删除该状态吗?": "確認刪除該狀態嗎?",
+  "满足条件": "滿足條件",
+  "所有": "所有",
+  "任意": "任意",
+  "                  条件": "條件",
+  "比较条件": "比較條件",
+  "添加状态": "添加狀態",
+  "数据编辑": "數據編輯",
+  "请输入(临时请求,不会保存)": "請輸入(臨時請求,不會保存)",
+  "确认删除该交互事件吗?": "確認刪除該交互事件嗎?",
+  "添加交互事件": "添加交互事件",
+  "还没有交互事件": "還沒有交互事件",
+  "外观": "外觀",
+  "请输入或选择分组": "請輸入或選擇分組",
+  "默认5": "默認5",
+  "画布层": "畫布層",
+  "上层图片层": "上層圖片層",
+  "主画布层": "主畫布層",
+  "下层图片层": "下層圖片層",
+  "模板层": "模板層",
+  "大屏对齐": "大屏對齊",
+  "旋转": "旋轉",
+  "固定比例": "固定比例",
+  "不固定比例": "不固定比例",
+  "圆角": "圓角",
+  "透明度": "透明度",
+  "状态": "狀態",
+  "                    状态": "狀態",
+  "点击上传": "點擊上傳",
+  "拖拽图片到此区域": "拖拽圖片到此區域",
+  "图片地址": "圖片地址",
+  "前景颜色": "前景顏色",
+  "悬停颜色": "懸停顏色",
+  "选中颜色": "選中顏色",
+  "线条": "線條",
+  "线条样式": "線條樣式",
+  "线条宽度": "線條寬度",
+  "平滑度": "平滑度",
+  "线条渐变": "線條漸變",
+  "起点箭头": "起點箭頭",
+  "终点箭头": "終點箭頭",
+  "默认": "默認",
+  "圆形": "圓形",
+  "方形": "方形",
+  "末端样式": "末端樣式",
+  "斜角": "斜角",
+  "连接样式": "連接樣式",
+  "背景": "背景",
+  "纯色": "純色",
+  "线性渐变": "線性漸變",
+  "径向渐变": "徑向漸變",
+  "渐变半径": "漸變半徑",
+  "选中": "選中",
+  "阴影": "陰影",
+  "文字阴影": "文字陰影",
+  "X偏移": "X偏移",
+  "Y偏移": "Y偏移",
+  "模糊": "模糊",
+  "模糊大小": "模糊大小",
+  "文字": "文字",
+  "字体名": "字體名",
+  "字体大小": "字體大小",
+  "顶部对齐": "頂部對齊",
+  "垂直居中": "垂直居中",
+  "底部对齐": "底部對齊",
+  "悬停": "懸停",
+  "前景": "前景",
+  "换行": "換行",
+  "省略号": "省略號",
+  "行高": "行高",
+  "显示时保留小数位数": "顯示時保留小數位數",
+  "小数": "小數",
+  "垂直偏移": "垂直偏移",
+  "只读": "只讀",
+  "隐藏文字": "隱藏文字",
+  "自动调整": "自動調整",
+  "文本内容": "文本內容",
+  "自适应": "自適應",
+  "转动图": "轉動圖",
+  "选择": "選擇",
+  "选择图标": "選擇圖標",
+  "进度": "進度",
+  "垂直进度": "垂直進度",
+  "反向进度": "反向進度",
+  "进度渐变": "進度漸變",
+  "水平翻转": "水平翻轉",
+  "垂直翻转": "垂直翻轉",
+  "锚点半径": "錨點半徑",
+  "禁止": "禁止",
+  "禁用": "禁用",
+  "禁用背景": "禁用背景",
+  "禁用颜色": "禁用顏色",
+  "禁用文字颜色": "禁用文字顏色",
+  "禁止旋转": "禁止旋轉",
+  "禁用锚点": "禁用錨點",
+  "鼠标提示": "鼠標提示",
+  "函数": "函數",
+  "支持": "支持",
+  "格式": "格式",
+  "交互": "交互",
+  "选中了": "選中了",
+  "对齐": "對齊",
+  "区域对齐": "區域對齊",
+  "以最后选中图元对齐": "以最後選中圖元對齊",
+  "居中": "居中",
+  "状态场景名": "狀態場景名",
+  "还没有状态场景": "還沒有狀態場景",
+  "添加状态场景": "添加狀態場景",
+  "状态名": "狀態名",
+  "对象属性": "對象屬性",
+  "group === '图层'": "group === '圖層'",
+  "上一层": "上一層",
+  "下一层": "下一層",
+  "折叠": "摺疊",
+  "展开": "展開",
+  "dom": "dom",
+  "DOM元素": "DOM元素",
+  "": "",
+  "group === '分组'": "group === '分組'",
+  "新建": "新建",
+  "保存为方案": "保存爲方案",
+  "保存为模板": "保存爲模板",
+  "保存为我的组件": "保存爲我的組件",
+  "格式化(双击可连续使用)": "格式化(雙擊可連續使用)",
+  "清除格式": "清除格式",
+  "直线": "直線",
+  "铅笔": "鉛筆",
+  "钢笔(双击可连续使用)": "鋼筆(雙擊可連續使用)",
+  "视图大小": "視圖大小",
+  "100%视图": "100%視圖",
+  "允许缩放": "允許縮放",
+  "自适应设置": "自適應設置",
+  "浏览模式": "瀏覽模式",
+  "编辑模式": "編輯模式",
+  "运行(预览)": "運行(預覽)",
+  "分享": "分享",
+  "当前项目为本地编辑模式": "當前項目爲本地編輯模式",
+  "请保存为大屏项目后访问": "請保存爲大屏項目後訪問",
+  "仅支持手机访问大屏项目": "僅支持手機訪問大屏項目",
+  "云发布": "雲發佈",
+  "数据管理": "數據管理",
+  "搜索我的数据获取": "搜索我的數據獲取",
+  "添加数据获取": "添加數據獲取",
+  "返回": "返回",
+  "新建变量": "新建變量",
+  "导入变量": "導入變量",
+  "选择变量": "選擇變量",
+  "我的变量列表": "我的變量列表",
+  "选择变量列表": "選擇變量列表",
+  "点击图标或回车获取数据": "點擊圖標或回車獲取數據",
+  "同时保存到我的数据获取": "同時保存到我的數據獲取",
+  "同时保存为我的变量列表": "同時保存爲我的變量列表",
+  "另存为新变量列表": "另存爲新變量列表",
+  "开启模拟数据": "開啓模擬數據",
+  "保存为我的变量列表": "保存爲我的變量列表",
+  "完成": "完成",
+  "项目名称": "項目名稱",
+  "发布状态": "發佈狀態",
+  "已过期": "已過期",
+  "正在运行": "正在運行",
+  "                有效期至:": "有效期至:",
+  "需要开通高级会员": "需要開通高級會員",
+  "未发布": "未發佈",
+  "乐吾乐域名": "樂吾樂域名",
+  "子域名": "子域名",
+  "随机生成": "隨機生成",
+  "访问域名": "訪問域名",
+  "支持自定义域名": "支持自定義域名",
+  "点击访问": "點擊訪問",
+  "手机访问": "手機訪問",
+  "仅支持": "僅支持",
+  "小时免费试用": "小時免費試用",
+  "到期后需要续费使用": "到期後需要續費使用",
+  "自定义域名": "自定義域名",
+  "在域名服务商的": "在域名服務商的",
+  "控制台设置好对应的": "控制檯設置好對應的",
+  "值为乐吾乐域名": "值爲樂吾樂域名",
+  "更多帮助": "更多幫助",
+  "发布": "發佈",
+  "取消发布": "取消發佈",
+  "云发布续费": "雲發佈續費",
+  "变量简短描述": "變量簡短描述",
+  "变量名": "變量名",
+  "方案列表": "方案列表",
+  "复制链接成功!": "複製鏈接成功!",
+  "请先保存!": "請先保存!",
+  "分享成功!": "分享成功!",
+  "取消分享成功": "取消分享成功",
+  "获取二维码失败!": "獲取二維碼失敗!",
+  "获取微信小程序码失败!": "獲取微信小程序碼失敗!",
+  "打开链接": "打開鏈接",
+  "打开视图": "打開視圖",
+  "播放动画": "播放動畫",
+  "暂停动画": "暫停動畫",
+  "停止动画": "停止動畫",
+  "更改属性": "更改屬性",
+  "打开弹框": "打開彈框",
+  "发送消息": "發送消息",
+  "发送数据": "發送數據",
+  "播放视频": "播放視頻",
+  "暂停视频": "暫停視頻",
+  "停止视频": "停止視頻",
+  "自定义函数": "自定義函數",
+  "全局函数": "全局函數",
+  "向场景发送消息": "向場景發送消息",
+  "向父窗口发送消息": "向父窗口發送消息",
+  "显示": "顯示",
+  "颜色": "顏色",
+  "进度颜色": "進度顏色",
+  "单选选中值": "單選選中值",
+  "网页地址": "網頁地址",
+  "缩放": "縮放",
+  "缩放比例": "縮放比例",
+  "X位移": "X位移",
+  "Y位移": "Y位移",
+  "背景类型": "背景類型",
+  "0 - 1之间": "0 - 1之間",
+  "背景渐变半径": "背景漸變半徑",
+  "线条渐变颜色": "線條漸變顏色",
+  "显示阴影": "顯示陰影",
+  "新宋体": "新宋體",
+  "微软雅黑": "微軟雅黑",
+  "黑体": "黑體",
+  "楷体": "楷體",
+  "文字背景": "文字背景",
+  "文字倾斜": "文字傾斜",
+  "正常": "正常",
+  "倾斜": "傾斜",
+  "文字加粗": "文字加粗",
+  "加粗": "加粗",
+  "阴影颜色": "陰影顏色",
+  "阴影模糊半径": "陰影模糊半徑",
+  "正数": "正數",
+  "阴影X偏移": "陰影X偏移",
+  "阴影Y偏移": "陰影Y偏移",
+  "包含": "包含",
+  "不包含": "不包含",
+  "选中单元格": "選中單元格",
+  "第": "第",
+  "行": "行",
+  "列": "列",
+  "样式": "樣式",
+  "行样式": "行樣式",
+  "列样式": "列樣式",
+  "数据不满足json格式": "數據不滿足json格式",
+  "编辑数据": "編輯數據",
+  "显示名称不能为空!": "顯示名稱不能爲空!",
+  "显示名称重复!": "顯示名稱重複!",
+  "属性名不能为空!": "屬性名不能爲空!",
+  "属性名重复!": "屬性名重複!",
+  "请填写名称": "請填寫名稱",
+  "请填写数据ID": "請填寫數據ID",
+  "设备": "設備",
+  "属性列表不能为空!": "屬性列表不能爲空!",
+  "未命名": "未命名",
+  "名称不能为空": "名稱不能爲空",
+  "属性列表不能为空": "屬性列表不能爲空",
+  "编辑数据源": "編輯數據源",
+  "URL地址不能为空!": "URL地址不能爲空!",
+  "名称不能为空!": "名稱不能爲空!",
+  "请先选择数据": "請先選擇數據",
+  "变量名不能为空!": "變量名不能爲空!",
+  "变量名重复!": "變量名重複!",
+  "导入Excel": "導入Excel",
+  "下载Excel示例": "下載Excel示例",
+  "已经存在相同分组!": "已經存在相同分組!",
+  "/大屏/图片/默认": "/大屏/圖片/默認",
+  "智慧物联": "智慧物聯",
+  "电力能源": "電力能源",
+  "智慧水务": "智慧水務",
+  "智慧工厂": "智慧工廠",
+  "智慧校园": "智慧校園",
+  "智慧园区": "智慧園區",
+  "智慧交通": "智慧交通",
+  "智慧城市": "智慧城市",
+  "智慧农业": "智慧農業",
+  "电信机房": "電信機房",
+  "航空航天": "航空航天",
+  "智能家居": "智能家居",
+  "明亮": "明亮",
+  "大屏": "大屏",
+  "网页": "網頁",
+  "平板Mini": "平板Mini",
+  "华为P8": "華爲P8",
+  "华为P40": "華爲P40",
+  "手机1": "手機1",
+  "手机2": "手機2",
+  "请先登录!": "請先登錄!",
+  "请填写以.css结尾的font-class引用方式的URL地址": "請填寫以.css結尾的font-class引用方式的URL地址",
+  "行为${i + 1}": "行爲${i + 1}",
+  "确定删除该数据吗?": "確定刪除該數據嗎?",
+  "删除后不可恢复!": "刪除後不可恢復!",
+  "语言": "語言",
+  "新建项目": "新建項目",
+  "简体中文": "簡體中文",
+  "繁体中文": "繁體中文",
+  "可二次编辑但转换存在损失,若作为图片使用,请使用右侧属性面板的上传图片功能": "可二次編輯但轉換存在損失,若作爲圖片使用,請使用右側屬性面板的上傳圖片功能",
+  "打开文件只支持 json,svg,zip 格式": "打開文件只支持 json,svg,zip 格式",
+  "svg转换成功,请点击画布决定放置位置": "svg轉換成功,請點擊畫布決定放置位置",
+  "需要开通会员~": "需要開通會員~",
+  "正在读取...": "正在讀取...",
+  "正在上传文件...": "正在上傳文件...",
+  "导入成功!": "導入成功!",
+  "需要开通普通会员~": "需要開通普通會員~",
+  "画布没有画笔!": "畫布沒有畫筆!",
+  "正在下载打包中,可能需要几分钟,请耐心等待...": "正在下載打包中,可能需要幾分鐘,請耐心等待...",
+  "下载成功,请在浏览器下载列表中查看": "下載成功,請在瀏覽器下載列表中查看",
+  "无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制": "無法下載,寬度不合法,畫布可能沒有畫筆/畫布大小超出瀏覽器最大限制",
+  "请先加载乐吾乐官网下的canvas2svg.js": "請先加載樂吾樂官網下的canvas2svg.js",
+  "正在下载中,可能需要几分钟,请耐心等待...": "正在下載中,可能需要幾分鐘,請耐心等待...",
+  "支付成功": "支付成功",
+  "保存成功!": "保存成功!",
+  "动画名不能为空!": "動畫名不能爲空!",
+  "已存在同名动画!": "已存在同名動畫!",
+  "闪烁": "閃爍",
+  "逆向旋转": "逆向旋轉",
+  "上下跳动": "上下跳動",
+  "左右跳动": "左右跳動",
+  "颜色变化": "顏色變化",
+  "背景变化": "背景變化",
+  "文字变化": "文字變化",
+  "乐吾乐": "樂吾樂",
+  "状态变化": "狀態變化",
+  "翻转": "翻轉",
+  "当前选中单元格": "當前選中單元格",
+  "当前选中行": "當前選中行",
+  "查看状态": "查看狀態",
+  "自定义状态": "自定義狀態",
+  "移除": "移除",
+  "数据名或属性名不能为空!": "數據名或屬性名不能爲空!",
+  "已经存在相同属性数据!": "已經存在相同屬性數據!",
+  "编辑动态数据": "編輯動態數據",
+  "请输入数组格式数据": "請輸入數組格式數據",
+  "请输入严格的JSON格式数据": "請輸入嚴格的JSON格式數據",
+  "状态场景${pen.triggers.length + 1}": "狀態場景${pen.triggers.length + 1}",
+  "状态1": "狀態1",
+  "状态2": "狀態2",
+  "条件告警": "條件告警",
+  "条件动画": "條件動畫",
+  "状态切换": "狀態切換",
+  "满足条件,切换到状态1": "滿足條件,切換到狀態1",
+  "默认显示状态": "默認顯示��態",
+  "满足条件,触发告警": "滿足條件,觸發告警",
+  "恢复默认": "恢復默認",
+  "满足条件,触发动画执行": "滿足條件,觸發動畫執行",
+  "恢复默认状态": "恢復默認狀態",
+  "状态场景${props.pen.triggers.length + 1}": "狀態場景${props.pen.triggers.length + 1}",
+  "第${cell.value.row}行,第${cell.value.col}列": "第${cell.value.row}行,第${cell.value.col}列",
+  "第${cell.value.row}行": "第${cell.value.row}行",
+  "数据格式必需是二维数组": "數據格式必需是二維數組",
+  "请输入API地址": "請輸入API地址",
+  "导入成功": "導入成功",
+  "数据格式必需是数组类型": "數據格式必需是數組類型",
+  "状态场景": "狀態場景",
+  "单击": "單擊",
+  "双击": "雙擊",
+  "输入完成": "輸入完成",
+  "输入": "輸入",
+  "鼠标右键": "鼠標右鍵",
+  "鼠标移入": "鼠標移入",
+  "鼠标移出": "鼠標移出",
+  "获得焦点": "獲得焦點",
+  "失去焦点": "失去焦點",
+  "鼠标按下": "鼠標按下",
+  "鼠标抬起": "鼠標擡起",
+  "监听全局消息": "監聽全局消息",
+  "选择完成": "選擇完成",
+  "左对齐": "左對齊",
+  "垂直居中对齐": "垂直居中對齊",
+  "右对齐": "右對齊",
+  "水平居中对齐": "水平居中對齊",
+  "id 不能为空": "id 不能爲空",
+  "id 修改失败,请检查 id 是否重复": "id 修改失敗,請檢查 id 是否重複",
+  "上传的图片不能大于5M": "上傳的圖片不能大於5M",
+  "水平等距": "水平等距",
+  "垂直等距": "垂直等距",
+  "相同大小": "相同大小",
+  "确认删除这条状态场景吗?": "確認刪除這條狀態場景嗎?",
+  "编辑状态": "編輯狀態",
+  "图层": "圖層",
+  "底层图片层": "底層圖片層",
+  "模版层": "模版層",
+  "请先选中图元": "請先選中圖元",
+  "值1,值2,": "值1,值2,",
+  "解析的svg图元不允许编辑!": "解析的svg圖元不允許編輯!",
+  "曲线": "曲線",
+  "线段": "線段",
+  "脑图曲线": "腦圖曲線",
+  "URL地址": "URL地址",
+  "变量列表不能为空": "變量列表不能爲空",
+  "保存新增成功!": "保存新增成功!",
+  "保存更新成功!": "保存更新成功!",
+  "变量列表不能为空!": "變量列表不能爲空!",
+  "组件不允许分享!": "組件不允許分享!",
+  "请填写子域名": "請填寫子域名",
+  "已经存在相同子域名": "已經存在相同子域名",
+  "请选择将要发布的方案": "請選擇將要發佈的方案",
+  "dom层级(z-index)": "dom層級(z-index)",
+  "默认4": "默認4",
+  "可操作x": "可操作x",
+  "范围0-1": "範圍0-1",
+  "可操作y": "可操作y",
+  "可操作宽度": "可操作寬度",
+  "可操作高度": "可操作高度",
+  "背景模糊": "背景模糊",
+  "毛玻璃颜色": "毛玻璃顏色",
+  "基本形状": "基本形狀",
+  "正方形": "正方形",
+  "矩形": "矩形",
+  "圆": "圓",
+  "三角形": "三角形",
+  "菱形": "菱形",
+  "五边形": "五邊形",
+  "六边形": "六邊形",
+  "五角星": "五角星",
+  "左箭头": "左箭頭",
+  "右箭头": "右箭頭",
+  "双向箭头": "雙向箭頭",
+  "云": "雲",
+  "消息框": "消息框",
+  "立方体": "立方體",
+  "<= 1 即宽度的比例": "<= 1 即寬度的比例",
+  "前背景色": "前背景色",
+  "顶背景色": "頂背景色",
+  "右背景色": "右背景色",
+  "人": "人",
+  "脑图": "腦圖",
+  "子主题": "子主題",
+  "流程图": "流程圖",
+  "开始/结束": "開始/結束",
+  "流程": "流程",
+  "判定": "判定",
+  "斜率": "斜率",
+  "准备": "準備",
+  "子流程": "子流程",
+  "数据库": "數據庫",
+  "文档": "文檔",
+  "内部存储": "內部存儲",
+  "外部存储": "外部存儲",
+  "队列": "隊列",
+  "手动输入": "手動輸入",
+  "展示": "展示",
+  "并行模式": "並行模式",
+  "注释": "註釋",
+  "活动图": "活動圖",
+  "开始": "開始",
+  "结束": "結束",
+  "活动": "活動",
+  "决策/合并": "決策/合併",
+  "垂直泳道": "垂直泳道",
+  "水平泳道": "水平泳道",
+  "垂直分岔/汇合": "垂直分岔/匯合",
+  "水平分岔/汇合": "水平分岔/匯合",
+  "时序图和类图": "時序圖和類圖",
+  "生命线": "生命線",
+  "激活": "激活",
+  "简单类": "簡單類",
+  "类": "類",
+  "故障树": "故障樹",
+  "与门": "與門",
+  "基本事件": "基本事件",
+  "未展开事件": "未展開事件",
+  "优先AND门": "優先AND門",
+  "禁止门": "禁止門",
+  "事件": "事件",
+  "开关事件": "開關事件",
+  "条件事件": "條件事件",
+  "转移符号": "轉移符號",
+  "或门": "或門",
+  "异或门": "異或門",
+  "表决门": "表決門",
+  "基础": "基礎",
+  "文本": "文本",
+  "乐吾乐le5le - 大屏可视化": "樂吾樂le5le - 大屏可視化",
+  "文本自动大小": "文本自動大小",
+  "数字": "數字",
+  "进度条": "進度條",
+  "/png/电信机房/防火墙.gif": "/png/電信機房/防火牆.gif",
+  "头像": "頭像",
+  "图片圆角半径": "圖片圓角半徑",
+  "徽标": "徽標",
+  "标签": "標籤",
+  "音视频": "音視頻",
+  "视频": "視頻",
+  "视频地址": "視頻地址",
+  "FLV视频流": "FLV視頻流",
+  "媒体数据源": "媒體數據源",
+  "具体配置参考:https://github.com/bilibili/flv.js/blob/master/docs/api.md": "具體配置參考:https://github.com/bilibili/flv.js/blob/master/docs/api.md",
+  "配置": "配置",
+  "音频": "音頻",
+  "音频地址": "音頻地址",
+  "摄像头": "攝像頭",
+  "Webrtc(低延迟,仅支持H264格式)": "Webrtc(低延遲,僅支持H264格式)",
+  "MSE(支持H265格式,需最新chrome)": "MSE(支持H265格式,需最新chrome)",
+  "流服务": "流服務",
+  "时间": "時間",
+  "当前时间": "當前時間",
+  "显示格式": "顯示格式",
+  "补0": "補0",
+  "倒计时": "倒計時",
+  "截止时间": "截止時間",
+  "水平时间轴": "水平時間軸",
+  "事件一": "事件一",
+  "事件二": "事件二",
+  "事件三": "事件三",
+  "事件四": "事件四",
+  "时间轴": "時間軸",
+  "标签分布": "標籤分佈",
+  "同侧": "同側",
+  "交叉": "交叉",
+  "标签对齐": "標籤對齊",
+  "顶部": "頂部",
+  "底部": "底部",
+  "垂直时间轴": "垂直時間軸",
+  "日历(日期)": "日曆(日期)",
+  "8月": "8月",
+  "日历(日期时间)": "日曆(日期時間)",
+  "面板": "面板",
+  "列表": "列表",
+  "列表标题": "列表標題",
+  "列表内容的描述性文字": "列表內容的描述性文字",
+  "标题大小": "標題大小",
+  "标题颜色": "標題顏色",
+  "表格": "表格",
+  "列宽": "列寬",
+  "行头": "行頭",
+  "列头": "列頭",
+  "边框": "邊框",
+  "垂直线": "垂直線",
+  "水平线": "水平線",
+  "最大展示数": "最大展示數",
+  "列配置": "列配置",
+  "斑马纹表格": "斑馬紋表格",
+  "一级告警": "一級告警",
+  "二级告警": "二級告警",
+  "三级告警": "三級告警",
+  "设备 ID": "設備 ID",
+  "设备名称": "設備名稱",
+  "数据协议": "數據協議",
+  "级别": "級別",
+  "湿度传感器": "溼度傳感器",
+  "物联网设备": "物聯網設備",
+  "物联网设备/智能家居/智慧城市": "物聯網設備/智能家居/智慧城市",
+  "显示斑马纹": "顯示斑馬紋",
+  "斑马纹颜色": "斑馬紋顏色",
+  "外边框": "外邊框",
+  "有无表头": "有無表頭",
+  "{一级告警,二级告警,三级告警}": "{一級告警,二級告警,三級告警}",
+  "触发器1": "觸發器1",
+  "触发器2": "觸發器2",
+  "触发器3": "觸發器3",
+  "滚动表格": "滾動表格",
+  "处理中": "處理中",
+  "已完成": "已完成",
+  "待处理": "待處理",
+  "序号": "序號",
+  "事件内容": "事件內容",
+  "处理状态": "處理狀態",
+  "是否轮播": "是否輪播",
+  "表格分页": "表格分頁",
+  "场景": "場景",
+  "图纸id": "圖紙id",
+  "冷源群控系统": "冷源羣控系統",
+  "中央空调模拟演示台系统": "中央空調模擬演示臺系統",
+  "换热站远程监控系统": "換熱站遠程監控系統",
+  "变电站主接线图": "變電站主接線圖",
+  "制冷站": "製冷站",
+  "废水处理": "廢水處理",
+  "数据中心": "數據中心",
+  "破碎筛分监控": "破碎篩分監控",
+  "光伏系统": "光伏系統",
+  "点击查看": "點擊查看",
+  "分页配置": "分頁配置",
+  "最大展示数量": "最大展示數量",
+  "多功能表格": "多功能表格",
+  "选项一": "選項一",
+  "选项二": "選項二",
+  "选项三": "選項三",
+  "树": "樹",
+  "展开全部节点": "展開全部節點",
+  "提醒": "提醒",
+  "业务指标": "業務指標",
+  "全局消息": "全局消息",
+  "用于表示普通操作信息提示": "用於表示普通操作信息提示",
+  "文本颜色": "文本顏色",
+  "通知": "��知",
+  "通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;通知具体内容;": "通知具體內容;通知具體內容;通知具體內容;通知具體內容;通知具體內容;通知具體內容;通知具體內容;通知具體內容;通知具體內容;",
+  "标题名称": "標題名稱",
+  "标题": "標題",
+  "标题加粗": "標題加粗",
+  "对话框": "對話框",
+  "轮播": "輪播",
+  "水平轮播": "水平輪播",
+  "轮播第一次数据": "輪播第一次數據",
+  "轮播第二次数据": "輪播第二次數據",
+  "轮播第三次数据": "輪播第三次數據",
+  "轮播时间": "輪播時間",
+  "垂直轮播": "垂直輪播",
+  "轮播图": "輪播圖",
+  "轮播页面": "輪播頁面",
+  "导航": "導航",
+  "链接": "鏈接",
+  "乐吾乐2D编辑器": "樂吾樂2D編輯器",
+  "锚点": "錨點",
+  "定位图元": "定位圖元",
+  "回到顶部": "回到頂部",
+  "面包屑": "麪包屑",
+  "页面1": "頁面1",
+  "页面2": "頁面2",
+  "页面3": "頁面3",
+  "间距": "間距",
+  "下拉菜单": "下拉菜單",
+  "个人中心": "個人中心",
+  "测试测试": "測試測試",
+  "安全运行": "安全運行",
+  "智慧能源": "智慧能源",
+  "数据分析": "數據分析",
+  "运维管理": "運維管理",
+  "字体颜色": "字體顏色",
+  "图标大小": "圖標大小",
+  "图标位置": "圖標位置",
+  "图标右间距": "圖標右間距",
+  "选项宽度": "選項寬度",
+  "选项背景图": "選項背景圖",
+  "选项高度": "選項高度",
+  "hover背景色": "hover背景色",
+  "hover字体颜色": "hover字體顏色",
+  "选中背景色": "選中背景色",
+  "选中字体颜色": "選中字體顏色",
+  "下拉内容背景色": "下拉內容背景色",
+  "是否渲染二级菜单": "是否渲染二級菜單",
+  "关联Iframe": "關聯Iframe",
+  "导航菜单": "導航菜單",
+  "实时监测": "實時監測",
+  "站点看板": "站點看板",
+  "三级标题": "三級標題",
+  "监控画面": "監控畫面",
+  "设备监控": "設備監控",
+  "控制中心": "控制中心",
+  "告警管理": "告警管理",
+  "分页": "分頁",
+  "数据总条数": "數據總條數",
+  "每页数据量": "每頁數據量",
+  "分页大小控制器": "分頁大小控制器",
+  "最多显示页码数按钮数": "最多顯示頁碼數按鈕數",
+  "步骤条": "步驟條",
+  "已完成的步骤": "已完成的步驟",
+  "这里是提示文字": "這裏是提示文字",
+  "出错的步骤": "出錯的步驟",
+  "进行中的步骤": "進行中的步驟",
+  "未完成的步骤": "未完成的步驟",
+  "各个状态颜色": "各個狀態顏色",
+  "方向": "方向",
+  "水平": "水平",
+  "垂直": "垂直",
+  "快速选项卡": "快速選項卡",
+  "场景一": "場景一",
+  "场景二": "場景二",
+  "场景三": "場景三",
+  "场景四": "場景四",
+  "间隔": "間隔",
+  "按钮宽度": "按鈕寬度",
+  "按钮高度": "按鈕高度",
+  "选中背景": "選中背景",
+  "选中边框": "選中邊框",
+  "选中文字": "選中文字",
+  "选中背景图片": "選中背景圖片",
+  "(未选中)背景": "(未選中)背景",
+  "(未选中)边框": "(未選中)邊框",
+  "(未选中)文字": "(未選中)文字",
+  "(未选中)背景图片": "(未選中)背景圖片",
+  "显示拖拽范围": "顯示拖拽範圍",
+  "基本选项卡": "基本選項卡",
+  "卡片选项卡": "卡片選項卡",
+  "全部(15)": "全部(15)",
+  "正常运行(7)": "正常運行(7)",
+  "故障告警(0)": "故障告警(0)",
+  "通讯异常(8)": "通訊異常(8)",
+  "多选选项卡": "多選選項卡",
+  "按钮": "按鈕",
+  "按下颜色": "按下顏色",
+  "按下背景": "按下背景",
+  "状态按钮": "狀態按鈕",
+  "文本输入框": "文本輸入框",
+  "输入文本": "輸入文本",
+  "数字输入框": "數字輸入框",
+  "输入数字": "輸入數字",
+  "单选框": "單選框",
+  "选项示例二": "選項示例二",
+  "排列方向": "排列方向",
+  "横向": "橫向",
+  "纵向": "縱向",
+  "模式": "模式",
+  "通用模式": "通用模式",
+  "按钮模式": "按鈕模式",
+  "多选框": "多選框",
+  "下拉选择器": "下拉選擇器",
+  "选项1": "選項1",
+  "选项2": "選項2",
+  "选项3": "選項3",
+  "下拉列表": "下拉列表",
+  "下拉背景": "下拉背景",
+  "下拉颜色": "下拉顏色",
+  "下拉悬停背景": "下拉懸停背景",
+  "下拉悬停颜色": "下拉懸停顏色",
+  "密码输入框": "密碼輸入框",
+  "时间选择器": "時間選擇器",
+  "日期选择器": "日期選擇器",
+  "颜色选择器": "顏色選擇器",
+  "开关": "開關",
+  "开颜色": "開顏色",
+  "关颜色": "關顏色",
+  "开描边颜色": "開描邊顏色",
+  "关描边颜色": "關描邊顏色",
+  "是否禁用": "是否禁用",
+  "开(禁)颜色": "開(禁)顏色",
+  "关(禁)颜色": "關(禁)顏色",
+  "滑块": "滑塊",
+  "工控": "工控",
+  "圆柱水位": "圓柱水位",
+  "水位": "水位",
+  "水位颜色": "水位顏色",
+  "球形水位": "球形水位",
+  ">最大颜色": ">最大顏色",
+  "<最小颜色": "<最小顏色",
+  "刻度显示": "刻度顯示",
+  "宽幅,推荐值0-10": "寬幅,推薦值0-10",
+  "默认2": "默認2",
+  "高幅,推荐值1-10": "高幅,推薦值1-10",
+  "液边距": "液邊距",
+  "水箱": "水箱",
+  "指示灯": "指示燈",
+  "动画1": "動畫1",
+  "显示状态": "顯示狀態",
+  "开": "開",
+  "关": "關",
+  "圆形按钮": "圓形按鈕",
+  "开时颜色": "開時顏色",
+  "关时颜色": "關時顏色",
+  "开时阴影颜色": "開時陰影顏色",
+  "关时阴影颜色": "關時陰影顏色",
+  "船型开关": "船型開關",
+  "转换开关": "轉換開關",
+  "闸刀": "閘刀",
+  "拨动开关": "撥動開關",
+  "空气开关": "空氣開關",
+  "水柱温度计": "水柱溫度計",
+  "当前值": "當前值",
+  "扁平温度计": "扁平溫度計",
+  "电池": "電池",
+  "默认1": "默認1",
+  "分段数": "分段數",
+  "间隔占比": "間隔佔比",
+  "航天航空": "航天航空",
+  "布局": "佈局",
+  "帧": "幀",
+  "请先登录,否则无法保存!": "請先登錄,否則無法保存!",
+  "请开通vip,即将跳转到开通页面...": "請開通vip,即將跳轉到開通頁面...",
+  "状态情况": "狀態情況",
+  "产品介绍": "產品介紹",
+  "快速上手": "快速上手",
+  "使用手册": "使用手冊",
+  "快捷键": "快捷鍵",
+  "企业服务与支持": "企業服務與支持",
+  "关于我们": "關於我們",
+  "画布为空,无法保存!": "畫布爲空,無法保存!",
+  "无法下载,宽度不合法,可能没有选中画笔/选中画笔大小超出浏览器最大限制": "無法下載,寬度不合法,可能沒有選中畫筆/選中畫筆大小超出瀏覽器最大限制",
+  "成功保存为组件!": "成功保存爲組件!",
+  "系统可能不会保存您所做的更改,是否继续?": "系統可能不會保存您所做的更改,是否繼續?",
+  "未登录,系统可能不会保存您的文件,是否继续?": "未登錄,系統可能不會保存您的文件,是否繼續?",
+  "当前文件未保存,是否继续?(开通vip可享受自动保存服务)": "當前文件未保存,是否繼續?(開通vip可享受自動保存服務)",
+  "布尔": "布爾",
+  "数组": "數組",
+  "场景状态": "場景狀態",
+  "折线图": "折線圖",
+  "基础折线图-hover": "基礎折線圖-hover",
+  "系列1": "系列1",
+  "1月": "1月",
+  "2月": "2月",
+  "3月": "3月",
+  "4月": "4月",
+  "5月": "5月",
+  "6月": "6月",
+  "单位": "單位",
+  "echarts配置": "echarts配置",
+  "基础折线图": "基礎折線圖",
+  "多折线图": "多折線圖",
+  "折线一的1月": "折線一的1月",
+  "折线二的1月": "折線二的1月",
+  "折线一的2月": "折線一的2月",
+  "折线二的2月": "折線二的2月",
+  "折线一的3月": "折線一的3月",
+  "折线二的3月": "折線二的3月",
+  "折线一的4月": "折線一的4月",
+  "折线二的4月": "折線二的4月",
+  "折线一的5月": "折線一的5月",
+  "折线二的5月": "折線二的5月",
+  "折线一的6月": "折線一的6月",
+  "折线二的6月": "折線二的6月",
+  "折线趋势图": "折線趨勢圖",
+  "数据点": "數據點",
+  "基础曲线图": "基礎曲線圖",
+  "多曲线图": "多曲線圖",
+  "曲线趋势图": "曲線趨勢圖",
+  "渐变单曲线图1": "漸變單曲線圖1",
+  "单位:kwh ": "單位:kwh",
+  "渐变单曲线图2": "漸變單曲線圖2",
+  "单位:A ": "單位:A",
+  "渐变单曲线图3": "漸變單曲線圖3",
+  "单位:V": "單位:V",
+  "阶梯折线图": "階梯折線圖",
+  "面积图": "面積圖",
+  "基础面积图": "基礎面積圖",
+  "堆叠面积图": "堆疊面積圖",
+  "柱状图": "柱狀圖",
+  "基础柱状图": "基礎柱狀圖",
+  "分组柱状图": "分組柱狀圖",
+  "分组一的1月": "分組一的1月",
+  "分组二的1月": "分組二的1月",
+  "分组一的2月": "分組一的2月",
+  "分组二的2月": "分組二的2月",
+  "分组一的3月": "分組一的3月",
+  "分组二的3月": "分組二的3月",
+  "分组一的4月": "分組一的4月",
+  "分组二的4月": "分組二的4月",
+  "分组一的5月": "分組一的5月",
+  "分组二的5月": "分組二的5月",
+  "分组一的6月": "分組一的6月",
+  "分组二的6月": "分組二的6月",
+  "堆叠柱状图": "堆���柱狀圖",
+  "渐变柱状图": "漸變柱狀圖",
+  "单位:万kwh": "單位:萬kwh",
+  "条形图": "條形圖",
+  "基础条形图": "基礎條形圖",
+  "分组条形图": "分組條形圖",
+  "堆叠条形图": "堆疊條形圖",
+  "正负条形图": "正負條形圖",
+  "分组三的1月": "分組三的1月",
+  "分组三的2月": "分組三的2月",
+  "分组三的3月": "分組三的3月",
+  "分组三的4月": "分組三的4月",
+  "分组三的5月": "分組三的5月",
+  "分组三的6月": "分組三的6月",
+  "饼环图": "餅環圖",
+  "饼图": "餅圖",
+  "物联网平台": "物聯網平臺",
+  "图形库": "圖形庫",
+  "环图": "環圖",
+  "圆角环图": "圓角環圖",
+  "散点图": "散點圖",
+  "点1.X": "點1.X",
+  "点1.Y": "點1.Y",
+  "点2.X": "點2.X",
+  "点2.Y": "點2.Y",
+  "点3.X": "點3.X",
+  "点3.Y": "點3.Y",
+  "涟漪散点图": "漣漪散點圖",
+  "雷达图": "雷達圖",
+  "销售": "銷售",
+  "开发": "開發",
+  "营销": "營銷",
+  "预算": "預算",
+  "消费": "消費",
+  "预算.销售": "預算.銷售",
+  "预算.管理": "預算.管理",
+  "预算.数据": "預算.數據",
+  "预算.支持": "預算.支持",
+  "预算.开发": "預算.開發",
+  "预算.营销": "預算.營銷",
+  "圆形雷达图": "圓形雷達圖",
+  "关系图": "關係圖",
+  "力引导布局": "力引導佈局",
+  "知识图谱": "知識圖譜",
+  "操作系统": "操作系統",
+  "浏览器": "瀏覽器",
+  "实现": "實現",
+  "属于": "屬於",
+  "关联": "關聯",
+  "桑葚图": "桑葚圖",
+  "桑基图": "桑基圖",
+  "自定义桑基图": "自定義桑基圖",
+  "华中": "華中",
+  "华南": "華南",
+  "华东": "華東",
+  "华北": "華北",
+  "西北": "西北",
+  "西南": "西南",
+  "北京": "北京",
+  "上海": "上海",
+  "武汉": "武漢",
+  "济南": "濟南",
+  "东莞": "東莞",
+  "珠海": "珠海",
+  "青岛": "青島",
+  "无锡": "無錫",
+  "厦门": "廈門",
+  "成都": "成都",
+  "杭州": "杭州",
+  "金华": "金華",
+  "南京": "南京",
+  "西安": "西安",
+  "中山": "中山",
+  "天津": "天津",
+  "苏州": "蘇州",
+  "威海": "威海",
+  "银川": "銀川",
+  "贵阳": "貴陽",
+  "佛山": "佛山",
+  "东营": "東營",
+  "舟山": "舟山",
+  "郑州": "鄭州",
+  "烟台": "煙臺",
+  "嘉兴": "嘉興",
+  "三亚": "三亞",
+  "宁波": "寧波",
+  "潍坊": "濰坊",
+  "合肥": "合肥",
+  "湖州": "湖州",
+  "枣庄": "棗莊",
+  "太原": "太原",
+  "海口": "海口",
+  "长沙": "長沙",
+  "淄博": "淄博",
+  "聊城": "聊城",
+  "常州": "常州",
+  "济宁": "濟寧",
+  "南宁": "南寧",
+  "梅州": "梅州",
+  "遵义": "遵義",
+  "南昌": "南昌",
+  "宿迁": "宿遷",
+  "福州": "福州",
+  "桂林": "桂林",
+  "广州": "廣州",
+  "深圳": "深圳",
+  "惠州": "惠州",
+  "拉萨": "拉薩",
+  "武汉->华中": "武漢->華中",
+  "仪表盘": "儀表盤",
+  "基础仪表盘": "基礎儀表盤",
+  "圆盘仪表盘": "圓盤儀表盤",
+  "最外部进度条": "最外部進度條",
+  "指针上的圆": "指針上的圓",
+  "外层透明圆": "外層透明圓",
+  "内圆": "內圓",
+  "进度仪表盘": "進度儀表盤",
+  "最外部环": "最外部環",
+  "蓝色科技1": "藍色科技1",
+  "蓝色科技2": "藍色科技2",
+  "蓝色科技3": "藍色科技3",
+  "刻度线": "刻度線",
+  "地图": "地圖",
+  "中国地图": "中國地圖",
+  "涟漪散点": "漣漪散點",
+  "散点": "散點",
+  "湖北地图": "湖北地圖",
+  "涟漪": "漣漪",
+  "襄阳": "襄陽",
+  "宜昌": "宜昌",
+  "荆州": "荊州",
+  "统计:{b}": "統計:{b}",
+  "地图·流量": "地圖·流量",
+  "乐吾乐Charts": "樂吾樂Charts",
+  "调色盘色值列表": "調色盤色值列表",
+  "横坐标轴数据": "橫座標軸數據",
+  "纵坐标数据": "縱座標數據",
+  "平滑线": "平滑線",
+  "半径范围": "半徑範圍",
+  "起始角": "起始角",
+  "结束角": "結束角",
+  "时钟": "時鐘",
+  "3d-饼图": "3d-餅圖",
+  "导入的excel文件不可为空!": "導入的excel文件不可爲空!",
+  "导入成功!": "導入成功!",
+  "导出成功!": "導出成功!",
+  "正在更新...": "正在更新...",
+  "此为付费数据,请购买后访问": "此爲付費數據,請購買後訪問",
+  "请求错误,不合法的请求!": "請求錯誤,不合法的請求!",
+  "访问数据不存在,请检查后重试!": "訪問數據不存在,請檢查後重試!",
+  "请求服务错误,请稍后重试!": "請求服務錯誤,請稍後重試!",
+  "网络超时,请检测你的网络!": "網絡超時,請檢測你的網絡!",
+  "未知网络错误!": "未知網絡錯誤!"
+};export default a

+ 2 - 0
src/main.ts

@@ -8,9 +8,11 @@ import relativeTime from 'dayjs/plugin/relativeTime';
 import zh from 'dayjs/locale/zh-cn';
 
 import './styles/index.css';
+import i18n from "./i18n";
 
 dayjs.extend(relativeTime);
 dayjs.locale(zh.name);
 
 const app = createApp(App).use(router).use(TDesign);
+app.use(i18n)
 app.mount('#app');

+ 29 - 28
src/services/common.ts

@@ -15,7 +15,8 @@ import { deepClone, isDomShapes } from '@meta2d/core';
 import { useSelection } from '@/services/selections';
 import { rootDomain } from './defaults';
 import { updateObject } from './object';
-
+import i18n from '../i18n';
+const $t = i18n.global.t;
 const { select } = useSelection();
 
 const assets = reactive({
@@ -25,29 +26,29 @@ const assets = reactive({
   '2d': `https://2d${rootDomain}`,
   helps_v: [
     {
-      name: '产品介绍',
+      name:$t( '产品介绍'),
       url: `https://doc${rootDomain}/document/118756411`,
     },
     {
-      name: '快速上手',
+      name: $t('快速上手'),
       url: `https://doc${rootDomain}/document/119363000`,
     },
     {
-      name: '使用手册',
+      name: $t('使用手册'),
       url: `https://doc${rootDomain}/document/118764244`,
     },
     {
-      name: '快捷键',
+      name: $t('快捷键'),
       url: `https://doc${rootDomain}/document/119620214`,
       divider: true,
     },
     {
-      name: '企业服务与支持',
+      name: $t('企业服务与支持'),
       url: `https://doc${rootDomain}/document/119296274`,
       divider: true,
     },
     {
-      name: '关于我们',
+      name: $t('关于我们'),
       url: `https://${rootDomain.slice(1)}/about.html`,
     },
   ],
@@ -74,7 +75,7 @@ export const useAssets = () => {
 };
 
 const meta2dData = reactive({
-  name:'新建项目'
+  name:$t('新建项目')
 });
 
 export const useMeta2dData = () => {
@@ -160,7 +161,7 @@ export const save = async (
   }
   const data: Meta2dBackData = meta2d.data();
   if(!data.pens.length){
-    MessagePlugin.warning('画布为空,无法保存!');
+    MessagePlugin.warning($t('画布为空,无法保存!'));
     return;
   }
   if (!(user && user.id)) {
@@ -192,7 +193,7 @@ export const save = async (
       blob = dataURLtoBlob(meta2d.activeToPng(10) + '');
     } catch (e) {
       MessagePlugin.error(
-        '无法下载,宽度不合法,可能没有选中画笔/选中画笔大小超出浏览器最大限制'
+        $t('无法下载,宽度不合法,可能没有选中画笔/选中画笔大小超出浏览器最大限制')
       );
       return;
     }
@@ -227,7 +228,7 @@ export const save = async (
     if (ret.error) {
       return;
     }
-    MessagePlugin.success('成功保存为组件!');
+    MessagePlugin.success($t('成功保存为组件!'));
     meta2d.emit('business-save', vType);
     return;
   }
@@ -314,7 +315,7 @@ export const save = async (
       blob = dataURLtoBlob(meta2d.toPng(10) + '');
     } catch (e) {
       MessagePlugin.error(
-        '无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制'
+        $t('无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制')
       );
       return;
     }
@@ -438,7 +439,7 @@ export const save = async (
     });
   }
 
-  notice && MessagePlugin.success('保存成功!');
+  notice && MessagePlugin.success($t('保存成功!'));
   meta2d.emit('business-save', vType);
   dot.value = false;
   localforage.removeItem(localStorageName);
@@ -529,9 +530,9 @@ export const showMap = () => {
   map.value = meta2d.map?.isShow;
 };
 
-export const title = '系统可能不会保存您所做的更改,是否继续?';
-export const unLogin = '未登录,系统可能不会保存您的文件,是否继续?';
-export const unsave = '当前文件未保存,是否继续?(开通vip可享受自动保存服务)';
+export const title = $t( '系统可能不会保存您所做的更改,是否继续?');
+export const unLogin = $t('未登录,系统可能不会保存您的文件,是否继续?');
+export const unsave = $t('当前文件未保存,是否继续?(开通vip可享受自动保存服务)');
 
 export function autoSave(force = false) {
   if (!dot.value && (!force || router.currentRoute.value.query.id)) {
@@ -801,27 +802,27 @@ export const delAttrs = [
 
 export const typeOptions = [
   {
-    label: '字符串',
+    label: $t('字符串'),
     value: 'string',
   },
   {
-    label: '整数',
+    label: $t('整数'),
     value: 'integer',
   },
   {
-    label: '浮点数',
+    label: $t('浮点数'),
     value: 'float',
   },
   {
-    label: '布尔',
+    label: $t('布尔'),
     value: 'bool',
   },
   {
-    label: '对象',
+    label: $t('对象'),
     value: 'object',
   },
   {
-    label: '数组',
+    label: $t('数组'),
     value: 'array',
   },
 ];
@@ -899,7 +900,7 @@ export function dealDataBeforeOpen(data){
       if (!pen.type && pen.frames) {
         pen.animations = [
           {
-            name: '动画1',
+            name: $t('动画1'),
             temType: 'id',
             animate: 'custom',
             frames: deepClone(pen.frames),
@@ -914,7 +915,7 @@ export function dealDataBeforeOpen(data){
       } else if (pen.type && pen.lineAnimateType !== undefined) {
         pen.animations = [
           {
-            name: '动画1',
+            name: $t('动画1'),
             temType: 'id',
             animateSpan: pen.animateSpan || 1,
             lineAnimateType: pen.lineAnimateType,
@@ -982,7 +983,7 @@ export function dealDataBeforeOpen(data){
                 pen.triggers = [];
               }
               let trigger = {
-                name: '状态1',
+                name: $t('状态1'),
                 conditionType: 'and',
                
                 conditions: [
@@ -1016,7 +1017,7 @@ export function dealDataBeforeOpen(data){
               }else{
                 pen.triggers.push({
                   temKey:event.where?.key,
-                  name:`场景状态${i+1}`,
+                  name:$t('场景状态') + (i+1),
                   status:[trigger]
                 });
               }
@@ -1033,7 +1034,7 @@ export function dealDataBeforeOpen(data){
                   key: 'value',
                   triggers: [
                     {
-                      name: '状态1',
+                      name: $t('状态1'),
                       conditionType: 'and',
                       conditions: [],
                       actions: [
@@ -1106,7 +1107,7 @@ export function dealDataBeforeOpen(data){
         });
         if(realTime.triggers?.length){
           pen.triggers.push({
-            name:`状态情况${index+1}`,
+            name: $t('状态情况') + (index+1),
             status:deepClone(realTime.triggers)
           });
         }

File diff suppressed because it is too large
+ 141 - 140
src/services/defaults.ts


File diff suppressed because it is too large
+ 122 - 121
src/services/echarts.ts


+ 9 - 8
src/services/enterprise.ts

@@ -1,7 +1,8 @@
 import { reactive } from 'vue';
 import axios from 'axios';
 import { rootDomain } from './defaults';
-
+import i18n from '../i18n';
+const $t = i18n.global.t;
 const getUrl = (path: string) => {
   if (import.meta.env.BASE_URL[0] === '/') {
     return location.protocol + '//' + location.host + '/' + path;
@@ -11,7 +12,7 @@ const getUrl = (path: string) => {
 }
 
 const enterprise = reactive({
-  name: '乐吾乐',
+  name: $t('乐吾乐'),
   home: `https://${rootDomain.slice(1)}`,
   account: getUrl('account'),
   v: getUrl('v'),
@@ -20,29 +21,29 @@ const enterprise = reactive({
   admin: getUrl('admin'),
   helps_v: [
     {
-      name: '产品介绍',
+      name: $t('产品介绍'),
       url: `https://doc${rootDomain}/document/118756411`,
     },
     {
-      name: '快速上手',
+      name: $t('快速上手'),
       url: `https://doc${rootDomain}/document/119363000`,
     },
     {
-      name: '使用手册',
+      name: $t('使用手册'),
       url: `https://doc${rootDomain}/document/118764244`,
     },
     {
-      name: '快捷键',
+      name: $t('快捷键'),
       url: `https://doc${rootDomain}/document/119620214`,
       divider: true,
     },
     {
-      name: '企业服务与支持',
+      name: $t('企业服务与支持'),
       url: `https://doc${rootDomain}/document/120608083`,
       divider: true,
     },
     {
-      name: '关于我们',
+      name: $t('关于我们'),
       url: `https://${rootDomain.slice(1)}/us`,
     },
   ],

+ 5 - 4
src/services/excel.ts

@@ -1,7 +1,8 @@
 import ExcelJS from 'exceljs';
 import { saveAs } from 'file-saver';
 import { MessagePlugin } from 'tdesign-vue-next';
-
+import i18n from '../i18n';
+const $t = i18n.global.t;
 export async function importExcel(columns?: any[]) {
   return new Promise((resolve, reject) => {
     const input = document.createElement('input');
@@ -23,7 +24,7 @@ export async function importExcel(columns?: any[]) {
           // 获取sheet1的所有rows
           const rows = worksheet.getSheetValues();
           if (rows.length === 0) {
-            MessagePlugin.warning('导入的excel文件不可为空!');
+            MessagePlugin.warning($t('导入的excel文件不可为空!'));
             return;
           }
           let data: any = [];
@@ -57,7 +58,7 @@ export async function importExcel(columns?: any[]) {
             });
           }
           resolve(data);
-          MessagePlugin.success('导入成功!');
+          MessagePlugin.success($t('导入成功!'));
         };
       }
     };
@@ -86,6 +87,6 @@ export function saveAsExcel(
       type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8',
     });
     saveAs(blob, fileName);
-    MessagePlugin.success('导出成功!');
+    MessagePlugin.success($t('导出成功!'));
   });
 }

+ 3 - 1
src/services/file.ts

@@ -1,5 +1,7 @@
 import axios from 'axios';
 import { MessagePlugin } from 'tdesign-vue-next';
+import i18n from '../i18n';
+const $t = i18n.global.t;
 
 export async function upload(
   blob: Blob,
@@ -124,7 +126,7 @@ export async function importCSV() {
             resolve(results.data); // 输出二维数组
           }
         });
-        MessagePlugin.success('导入成功!');
+        MessagePlugin.success($t('导入成功!'));
       }
     };
     input.click();

+ 3 - 1
src/services/updateC.ts

@@ -2,8 +2,10 @@ import { deepClone, getAllChildren } from '@meta2d/core';
 
 import axios from 'axios';
 import { MessagePlugin } from 'tdesign-vue-next';
+import i18n from '../i18n';
+const $t = i18n.global.t;
 export async function updateC() {
-  MessagePlugin.loading('正在更新...',2000);
+  MessagePlugin.loading($t('正在更新...'),2000);
   const scale = meta2d.store.data.scale;
   //所有需要更新的自定义组件
   let cPens = meta2d.store.data.pens.filter(

+ 6 - 5
src/services/utils.ts

@@ -3,8 +3,9 @@ import { MessagePlugin, NotifyPlugin, Button } from 'tdesign-vue-next';
 import { h, ref } from 'vue';
 import { upCdn } from './api';
 import axios from 'axios';
-
-export const noLoginTip = '请先登录,否则无法保存!';
+import i18n from '../i18n';
+const $t = i18n.global.t;
+export const noLoginTip = $t('请先登录,否则无法保存!');
 export const localStorageName = 'le5leV';
 
 export interface Meta2dBackData extends Meta2dData {
@@ -52,7 +53,7 @@ export function showNotification(title: string): Promise<boolean> {
     };
     if (!notification.value) {
       notification.value = NotifyPlugin.info({
-        title: '提示',
+        title: $t('提示'),
         content: title,
         closeBtn: true,
         onCloseBtnClick: () => {
@@ -73,7 +74,7 @@ export function showNotification(title: string): Promise<boolean> {
             },
             onClick: btnClick,
           },
-          '确定'
+          $t('确定')
         ),
       });
     }
@@ -122,7 +123,7 @@ export async function dealwithFormatbeforeOpen(data: Meta2dBackData) {
 
 export function gotoAccount() {
   MessagePlugin.info({
-    content: '请开通vip,即将跳转到开通页面...',
+    content: $t('请开通vip,即将跳转到开通页面...'),
     duration: 3,
   });
   setTimeout(() => {

+ 152 - 282
src/views/components/Actions.vue

@@ -3,85 +3,55 @@
     <div v-for="(a, index) in data.actions" class="mb-12">
       <div class="flex middle between" style="position:relative;">
         <div class="flex middle">
-          动作{{ index + 1 }}
-          <t-tooltip content="单位ms,默认不延迟执行">
-          <t-input-number
-            class="input-none"
-            style="position:absolute;left:76px"
-            v-model="a.timeout"
-            theme="normal"
-            :min="1"
-            placeholder="延迟"
-          />
+{{$t('          动作')}}{{ index + 1 }}
+          <t-tooltip :content="$t('单位ms,默认不延迟执行')">
+          <t-input-number class="input-none" style="position:absolute;left:76px" v-model="a.timeout" theme="normal" :min="1" :placeholder="$t('延迟')"></t-input-number>
         </t-tooltip>
         </div>
         
-        <close-icon class="hover"
-          @click="data.actions.splice(index, 1)"/>
+        <close-icon class="hover" @click="data.actions.splice(index, 1)"></close-icon>
       </div>
       <div class="py-4">
         <div class="form-item mt-4">
-          <label>动作类型</label>
-          <t-select
-            v-model="a.action"
-            placeholder="请选择"
-            @change="onChangeAction(a)"
-          >
-            <t-option
-              v-for="option in actionOptions"
-              :key="option.value"
-              :value="option.value"
-              :label="option.label"
-            />
+          <label>{{$t('动作类型')}}</label>
+          <t-select v-model="a.action" @change="onChangeAction(a)" :placeholder="$t('请选择')">
+            <t-option v-for="option in actionOptions" :key="option.value" :value="option.value" :label="option.label"></t-option>
           </t-select>
         </div>
         <template v-if="a.action == 0">
           <div class="form-item mt-8">
-            <label>链接地址</label>
-            <t-input v-model="a.value" placeholder="URL" />
+            <label>{{$t('链接地址')}}</label>
+            <t-input v-model="a.value" placeholder="URL"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>打开方式</label>
+            <label>{{$t('打开方式')}}</label>
             <t-radio-group v-model="a.params">
-              <t-radio value="_blank">新页面</t-radio>
-              <t-radio value="_self">当前页面</t-radio>
+              <t-radio value="_blank">{{$t('新页面')}}</t-radio>
+              <t-radio value="_self">{{$t('当前页面')}}</t-radio>
             </t-radio-group>
           </div>
         </template>
         <template v-else-if="a.action == 13">
           <div class="form-item mt-8">
-            <label>视图</label>
-            <t-input v-model="a.value" placeholder="ID" />
+            <label>{{$t('视图')}}</label>
+            <t-input v-model="a.value" placeholder="ID"></t-input>
           </div>
         </template>
         <template v-else-if="a.action == 2 || a.action == 3 || a.action == 4">
           <div class="form-item mt-8">
-            <label>对象类型</label>
+            <label>{{$t('对象类型')}}</label>
             <t-radio-group v-model="a.targetType" @change="a.value = ''">
-              <t-radio value="id">图元</t-radio>
-              <t-radio value="tag">组</t-radio>
+              <t-radio value="id">{{$t('图元')}}</t-radio>
+              <t-radio value="tag">{{$t('')}}</t-radio>
             </t-radio-group>
           </div>
           <div class="form-item mt-8">
-            <label>播放对象</label>
-            <t-tree-select
-              v-if="a.targetType === 'id'"
-              v-model="a.value"
-              :data="penTree"
-              filterable
-              placeholder="默认自己"
-              @change="getAnimations(a.value)"
-            />
-            <t-select
-              v-else
-              v-model="a.value"
-              :options="groups"
-              placeholder="组"
-              @change="getAnimations(a.value)"
-            />
+            <label>{{$t('播放对象')}}</label>
+            <t-tree-select v-if="a.targetType === 'id'" v-model="a.value" :data="penTree" filterable @change="getAnimations(a.value)" :placeholder="$t('默认自己')"></t-tree-select>
+            <t-select v-else v-model="a.value" :options="groups" @change="getAnimations(a.value)" :placeholder="$t('组')"></t-select>
           </div>
           <div class="form-item mt-8">
-            <label>动画名称</label>
+            <label>{{$t('动画名称')}}</label>
             <t-select-input
               v-model:inputValue="a.params"
               :value="a.params"
@@ -91,15 +61,11 @@
               @clear="a.params = undefined"
               @focus="a.popupVisible = true"
               @blur="a.popupVisible = false"
-              placeholder="缺省第一个动画"
+              :placeholder="$t('缺省第一个动画')"
             >
               <template #panel>
                 <ul style="padding: 8px 12px">
-                  <li
-                    v-for="item in animations"
-                    :key="item"
-                    @click="a.params = item;a.popupVisible = false;"
-                  >
+                  <li v-for="item in animations" :key="item" @click="a.params = item;a.popupVisible = false;">
                     {{ item }}
                   </li>
                 </ul>
@@ -109,14 +75,14 @@
         </template>
         <template v-else-if="a.action == 1">
           <div class="form-item mt-8">
-            <label>对象类型</label>
+            <label>{{$t('对象类型')}}</label>
             <t-radio-group v-model="a.targetType" @change="a.params = ''">
-              <t-radio value="id">图元</t-radio>
-              <t-radio value="tag">组</t-radio>
+              <t-radio value="id">{{$t('图元')}}</t-radio>
+              <t-radio value="tag">{{$t('')}}</t-radio>
             </t-radio-group>
           </div>
           <div class="form-item mt-8">
-            <label>更改对象</label>
+            <label>{{$t( '更改对象' )}}</label>
             <t-tree-select
               v-if="a.targetType === 'id'"
               v-model="a.params"
@@ -133,11 +99,11 @@
             />
           </div>
           <div class="form-item mt-8">
-            <label>属性数据</label>
+            <label>{{$t('属性数据')}}</label>
             <div class="w-full">
               <div class="prop-grid head">
-                <div>属性名</div>
-                <div>属性值</div>
+                <div>{{$t('属性名')}}</div>
+                <div>{{$t('属性值')}}</div>
                 <div class="right">
                   <t-dropdown
                     :min-column-width="160"
@@ -156,7 +122,7 @@
                         <t-input
                           v-model="a.input"
                           style="pointer-events: auto;"
-                          placeholder="自定义"
+                          :placeholder="$t('自定义')"
                           @enter="
                             onAddValue(a, { key: a.input });
                             a.input = '';
@@ -189,7 +155,7 @@
                       :title="a.value[key]"
                       v-model="a.value[key]"
                       @change="valueChange($event,a.value,key)"
-                      placeholder="值"
+                      :placeholder="$t('')"
                     />
                   </div>
                   <div class="right px-8" style="line-height: 20px">
@@ -203,123 +169,69 @@
                   </div>
                 </div>
               </template>
-              <div v-else class="center gray mt-8">暂无数据</div>
+              <div v-else class="center gray mt-8">{{$t('暂无数据')}}</div>
             </div>
           </div>
         </template>
         <template v-else-if="a.action == 14">
           <div class="form-item mt-8">
-            <label>窗口标题</label>
-            <t-input v-model="a.value" placeholder="弹框标题" />
+            <label>{{$t('窗口标题')}}</label>
+            <t-input v-model="a.value" :placeholder="$t('弹框标题')"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>画面URL</label>
-            <t-input v-model="a.params" placeholder="窗口画面URL" />
+            <label>{{$t('画面')}}URL</label>
+            <t-input v-model="a.params" :placeholder="$t('窗口画面URL')"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>弹框位置</label>
-            <t-input
-              class="ml-4"
-              label="X"
-              placeholder="X"
-              v-model.number="a.extend.x"
-              style="width: 80px"
-              :format="decimalPlaces"
-            />
-            <t-input
-              class="ml-4"
-              label="Y"
-              placeholder="Y"
-              v-model.number="a.extend.y"
-              style="width: 80px"
-              :format="decimalPlaces"
-            />
+            <label>{{$t('弹框位置')}}</label>
+            <t-input class="ml-4" label="X" placeholder="X" v-model.number="a.extend.x" style="width: 80px" :format="decimalPlaces"></t-input>
+            <t-input class="ml-4" label="Y" placeholder="Y" v-model.number="a.extend.y" style="width: 80px" :format="decimalPlaces"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>弹框大小</label>
-            <t-input
-              class="ml-4"
-              label="W"
-              v-model.number="a.extend.width"
-              placeholder="宽"
-              min="1"
-              style="width: 80px"
-              :format="decimalPlaces"
-            />
-            <t-input
-              class="ml-4"
-              label="H"
-              placeholder="高"
-              v-model.number="a.extend.height"
-              min="1"
-              style="width: 80px"
-              :format="decimalPlaces"
-            />
+            <label>{{$t('弹框大小')}}</label>
+            <t-input class="ml-4" label="W" v-model.number="a.extend.width" min="1" style="width: 80px" :format="decimalPlaces" :placeholder="$t('宽')"></t-input>
+            <t-input class="ml-4" label="H" v-model.number="a.extend.height" min="1" style="width: 80px" :format="decimalPlaces" :placeholder="$t('高')"></t-input>
           </div>
         </template>
         <template v-else-if="a.action == 7">
           <div class="form-item mt-8">
-            <label>消息名称</label>
-            <t-input v-model="a.value" placeholder="名称" />
+            <label>{{$t('消息名称')}}</label>
+            <t-input v-model="a.value" :placeholder="$t('名称')"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>消息参数</label>
-            <t-input v-model="a.params" placeholder="参数" />
+            <label>{{$t('消息参数')}}</label>
+            <t-input v-model="a.params" :placeholder="$t('参数')"></t-input>
           </div>
         </template>
         <template v-else-if="a.action == 15">
-          <Network v-model="a.network" mode="1" />
+          <Network v-model="a.network" mode="1"></Network>
           <template v-for="(item,idx) in a.list">
           <div class="flex middle between mt-16">
-            <div class="flex middle" style="font-size:12px">数据{{ idx+1 }}</div>
-            <close-icon class="hover"  @click="a.list.splice(index, 1)"/>
+            <div class="flex middle" style="font-size:12px">{{$t('数据')}}{{ idx+1 }}</div>
+            <close-icon class="hover" @click="a.list.splice(index, 1)"></close-icon>
           </div>
           <div class="form-item mt-8">
-            <label>数据对象</label>
-            <t-tree-select
-              v-model="item.params"
-              :data="penTree"
-              filterable
-              placeholder="默认自己"
-              @change="getProps(item)"
-            />
+            <label>{{$t('数据对象')}}</label>
+            <t-tree-select v-model="item.params" :data="penTree" filterable @change="getProps(item)" :placeholder="$t('默认自己')"></t-tree-select>
           </div>
           <div class="form-item mt-8">
-            <label>属性数据</label>
+            <label>{{$t('属性数据')}}</label>
             <div class="w-full">
               <div class="prop-grid head">
-                <div>属性名</div>
-                <div>属性值</div>
+                <div>{{$t('属性名')}}</div>
+                <div>{{$t('属性值')}}</div>
                 <div class="right">
-                  <t-dropdown
-                    :min-column-width="160"
-                    @click="onAddValue(item, $event)"
-                  >
-                    <add-circle-icon class="hover"/>
+                  <t-dropdown :min-column-width="160" @click="onAddValue(item, $event)">
+                    <add-circle-icon class="hover"></add-circle-icon>
                     <!-- <t-icon name="add-circle" class="hover" /> -->
                     <t-dropdown-menu>
-                      <t-dropdown-item
-                        key="custom"
-                        value="custom"
-                        disabled="true"
-                        divider="true"
-                        class="input"
-                      >
-                        <t-input
-                          v-model="item.input"
-                          style="pointer-events: auto;"
-                          placeholder="自定义"
-                          @enter="
+                      <t-dropdown-item key="custom" value="custom" disabled="true" divider="true" class="input">
+                        <t-input v-model="item.input" style="pointer-events: auto;" @enter="
                             onAddValue(item, { key: item.input });
                             item.input = '';
-                          "
-                        />
+                          " :placeholder="$t('自定义')"></t-input>
                       </t-dropdown-item>
-                      <t-dropdown-item
-                        v-for="prop in cprops"
-                        :key="prop.value"
-                        :value="prop.value"
-                      >
+                      <t-dropdown-item v-for="prop in cprops" :key="prop.value" :value="prop.value">
                         {{ prop.label }}
                       </t-dropdown-item>
                     </t-dropdown-menu>
@@ -337,11 +249,10 @@
                     </t-tooltip>
                   </div>
                   <div class="value-input">
-                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" placeholder="值" />
+                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" :placeholder="$t('值')"></t-input>
                   </div>
                   <div class="right px-8" style="line-height: 20px">
-                    <delete-icon  class="hover"
-                      @click="delete item.value[key]"/>
+                    <delete-icon class="hover" @click="delete item.value[key]"></delete-icon>
                     <!-- <t-icon
                       name="delete"
                       class="hover"
@@ -350,7 +261,7 @@
                   </div>
                 </div>
               </template>
-              <div v-else class="center gray mt-8">暂无数据</div>
+              <div v-else class="center gray mt-8">{{$t('暂无数据')}}</div>
             </div>
           </div>
           
@@ -358,47 +269,32 @@
           <div class="form-item mt-8">
             <label></label>
             <t-button style="width:150px" @click="addData(a)">
-              添加数据
+              {{$t('添加数据')}}
             </t-button>
           </div>
           <div class="form-item mt-8" v-if="a.network&&a.network.protocol==='http'">
-            <label>回调</label>
-            <CodeEditor
-              v-model="a.callback"
-              class="mt-4"
-              style="height: 50px"
-            />
+            <label>{{$t('回调')}}</label>
+            <CodeEditor v-model="a.callback" class="mt-4" style="height: 50px"></CodeEditor>
           </div>
-          <div class="form-item mt-8 desc"  v-if="a.network&&a.network.protocol==='http'">
+          <div class="form-item mt-8 desc" v-if="a.network&&a.network.protocol==='http'">
             <label></label>
             <div>
-              可获取pen、data和context参数,参考:<a target="_blank" href="https://doc.le5le.com/document/22">发送指令</a>
+              {{$t('可获取')}}pen、data{{$t('')}}context{{$t('参数')}},{{$t('参考')}}:<a target="_blank" href="https://doc.le5le.com/document/22">{{$t('发送指令')}}</a>
             </div>
           </div>
         </template>
         <template v-else-if="a.action == 8 || a.action == 9 || a.action == 10">
           <div class="form-item mt-8">
-            <label>对象类型</label>
+            <label>{{$t('对象类型')}}</label>
             <t-radio-group v-model="a.targetType" @change="a.value = ''">
-              <t-radio value="id">图元</t-radio>
-              <t-radio value="tag">组</t-radio>
+              <t-radio value="id">{{$t('图元')}}</t-radio>
+              <t-radio value="tag">{{$t('')}}</t-radio>
             </t-radio-group>
           </div>
           <div class="form-item mt-8">
-            <label>播放对象</label>
-            <t-tree-select
-              v-if="a.targetType === 'id'"
-              v-model="a.value"
-              :data="penTree"
-              filterable
-              placeholder="默认自己"
-            />
-            <t-select
-              v-else
-              v-model="a.value"
-              :options="groups"
-              placeholder="组"
-            />
+            <label>{{$t('播放对象')}}</label>
+            <t-tree-select v-if="a.targetType === 'id'" v-model="a.value" :data="penTree" filterable :placeholder="$t('默认自己')"></t-tree-select>
+            <t-select v-else v-model="a.value" :options="groups" :placeholder="$t('组')"></t-select>
           </div>
         </template>
         <template v-else-if="a.action == 5">
@@ -406,68 +302,49 @@
             <!-- <label>函数</label> -->
             <div class="w-full">
               <div>function javascriptFn(pen) {</div>
-              <CodeEditor
-                v-model="a.value"
-                class="mt-4"
-                @change="codeChange($event,a)"
-                style="height: 200px"
-              />
+              <CodeEditor v-model="a.value" class="mt-4" @change="codeChange($event,a)" style="height: 200px"></CodeEditor>
               <div class="mt-4">}</div>
             </div>
           </div>
         </template>
         <template v-else-if="a.action == 6">
           <div class="form-item mt-8">
-            <label>函数名称</label>
-            <t-input v-model="a.value" placeholder="函数名称" />
+            <label>{{$t('函数名称')}}</label>
+            <t-input v-model="a.value" :placeholder="$t('函数名称')"></t-input>
           </div>
           <div class="form-item mt-8">
-            <label>函数参数</label>
-            <t-input v-model="a.params" placeholder="函数参数" />
+            <label>{{$t('函数参数')}}</label>
+            <t-input v-model="a.params" :placeholder="$t('函数参数')"></t-input>
           </div>
         </template>
         <template v-else-if="a.action == 16">
           <div class="form-item mt-8">
-            <label>场景对象</label>
+            <label>{{$t('场景对象')}}</label>
             <!-- <t-input v-model="a.params" placeholder="画笔id/tag" /> -->
-            <t-tree-select
-              v-model="a.params"
-              :data="iframeTree"
-              filterable
-              placeholder="必填"
-            />
+            <t-tree-select v-model="a.params" :data="iframeTree" filterable :placeholder="$t('必填')"></t-tree-select>
           </div>
           <div class="form-item mt-8">
-            <label>消息名</label>
-            <t-input v-model="a.value" placeholder="消息名" />
+            <label>{{$t('消息名')}}</label>
+            <t-input v-model="a.value" :placeholder="$t('消息名')"></t-input>
           </div>
           <template v-for="(item,idx) in a.list">
           <div class="flex middle between mt-16">
-            <div class="flex middle" style="font-size:12px">消息数据{{ idx+1 }}</div>
-            <close-icon class="hover"  @click="a.list.splice(index, 1)"/>
+            <div class="flex middle" style="font-size:12px">{{$t('消息数据')}}{{ idx+1 }}</div>
+            <close-icon class="hover" @click="a.list.splice(index, 1)"></close-icon>
           </div>
           <div class="form-item mt-8">
-            <label>消息对象</label>
-            <t-tree-select
-              v-model="item.params"
-              :data="penTree"
-              filterable
-              placeholder="默认自己"
-              @change="getProps(item)"
-            />
+            <label>{{$t('消息对象')}}</label>
+            <t-tree-select v-model="item.params" :data="penTree" filterable @change="getProps(item)" :placeholder="$t('默认自己')"></t-tree-select>
           </div>
           <div class="form-item mt-8">
-            <label>消息数据</label>
+            <label>{{$t('消息数据')}}</label>
             <div class="w-full">
               <div class="prop-grid head">
-                <div>属性名</div>
-                <div>属性值</div>
+                <div>{{$t('属性名')}}</div>
+                <div>{{$t('属性值')}}</div>
                 <div class="right">
-                  <t-dropdown
-                    :min-column-width="160"
-                    @click="onAddValue(item, $event)"
-                  >
-                    <add-circle-icon class="hover"/>
+                  <t-dropdown :min-column-width="160" @click="onAddValue(item, $event)">
+                    <add-circle-icon class="hover"></add-circle-icon>
                     <t-dropdown-menu>
                       <t-dropdown-item
                         key="custom"
@@ -479,7 +356,7 @@
                         <t-input
                           v-model="item.input"
                           style="pointer-events: auto;"
-                          placeholder="自定义"
+                          :placeholder="$t('自定义')"
                           @enter="
                             onAddValue(item, { key: item.input });
                             item.input = '';
@@ -508,7 +385,7 @@
                     </t-tooltip>
                   </div>
                   <div class="value-input">
-                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" placeholder="值" />
+                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" :placeholder="$t('值')"></t-input>
                   </div>
                   <div class="right px-8" style="line-height: 20px">
                     <delete-icon  class="hover"
@@ -516,7 +393,7 @@
                   </div>
                 </div>
               </template>
-              <div v-else class="center gray mt-8">暂无数据</div>
+              <div v-else class="center gray mt-8">{{$t('暂无数据')}}</div>
             </div>
           </div>
           
@@ -524,42 +401,33 @@
           <div class="form-item mt-8">
             <label></label>
             <t-button style="width:150px" @click="addData(a)">
-              添加消息数据
+              {{$t('添加消息数据')}}
             </t-button>
           </div>
         </template>
         <template v-else-if="a.action == 17">
           <div class="form-item mt-8">
-            <label>消息名</label>
-            <t-input v-model="a.value" placeholder="消息名" />
+            <label>{{$t('消息名')}}</label>
+            <t-input v-model="a.value" :placeholder="$t('消息名')"></t-input>
           </div>
           <template v-for="(item,idx) in a.list">
           <div class="flex middle between mt-16">
-            <div class="flex middle" style="font-size:12px">消息数据{{ idx+1 }}</div>
-            <close-icon class="hover"  @click="a.list.splice(index, 1)"/>
+            <div class="flex middle" style="font-size:12px">{{$t('消息数据')}}{{ idx+1 }}</div>
+            <close-icon class="hover" @click="a.list.splice(index, 1)"></close-icon>
           </div>
           <div class="form-item mt-8">
-            <label>消息对象</label>
-            <t-tree-select
-              v-model="item.params"
-              :data="penTree"
-              filterable
-              placeholder="默认自己"
-              @change="getProps(item)"
-            />
+            <label>{{$t('消息对象')}}</label>
+            <t-tree-select v-model="item.params" :data="penTree" filterable @change="getProps(item)" :placeholder="$t('默认自己')"></t-tree-select>
           </div>
           <div class="form-item mt-8">
-            <label>消息数据</label>
+            <label>{{$t('消息数据')}}</label>
             <div class="w-full">
               <div class="prop-grid head">
-                <div>属性名</div>
-                <div>属性值</div>
+                <div>{{$t('属性名')}}</div>
+                <div>{{$t('属性值')}}</div>
                 <div class="right">
-                  <t-dropdown
-                    :min-column-width="160"
-                    @click="onAddValue(item, $event)"
-                  >
-                    <add-circle-icon class="hover"/>
+                  <t-dropdown :min-column-width="160" @click="onAddValue(item, $event)">
+                    <add-circle-icon class="hover"></add-circle-icon>
                     <t-dropdown-menu>
                       <t-dropdown-item
                         key="custom"
@@ -571,7 +439,7 @@
                         <t-input
                           v-model="item.input"
                           style="pointer-events: auto;"
-                          placeholder="自定义"
+                          :placeholder="$t('自定义')"
                           @enter="
                             onAddValue(item, { key: item.input });
                             item.input = '';
@@ -600,7 +468,7 @@
                     </t-tooltip>
                   </div>
                   <div class="value-input">
-                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" placeholder="值" />
+                    <t-input v-model="item.value[key]" @change="valueChange($event,item.value,key)" :placeholder="$t('值')"></t-input>
                   </div>
                   <div class="right px-8" style="line-height: 20px">
                     <delete-icon  class="hover"
@@ -608,7 +476,7 @@
                   </div>
                 </div>
               </template>
-              <div v-else class="center gray mt-8">暂无数据</div>
+              <div v-else class="center gray mt-8">{{$t('暂无数据')}}</div>
             </div>
           </div>
           
@@ -616,93 +484,95 @@
           <div class="form-item mt-8">
             <label></label>
             <t-button style="width:150px" @click="addData(a)">
-              添加消息数据
+              {{$t('添加消息数据')}}
             </t-button>
           </div>
         </template>
       </div>
     </div>
     <div class="mt-8">
-      <a @click="data.actions.push({})"> + 添加动作 </a>
+      <a @click="data.actions.push({})"> + {{$t('添加动作')}} </a>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
+import {getCurrentInstance} from 'vue';
 import { onBeforeMount, ref } from 'vue';
 
 import CodeEditor from '@/views/components/common/CodeEditor.vue';
 import Network from './Network.vue';
 import { CloseIcon,AddCircleIcon,DeleteIcon,CheckIcon} from 'tdesign-icons-vue-next';
 import { getPenAnimations, getPenTree ,changeType, getIframeTree} from '@/services/common';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const { data } = defineProps<{
   data: any;
 }>();
 
 const actionOptions = [
   {
-    label: '打开链接',
+    label: $t('打开链接'),
     value: 0,
   },
   {
-    label: '打开视图',
+    label: $t('打开视图'),
     value: 13,
   },
   {
-    label: '播放动画',
+    label: $t('播放动画'),
     value: 2,
   },
   {
-    label: '暂停动画',
+    label: $t('暂停动画'),
     value: 3,
   },
   {
-    label: '停止动画',
+    label: $t('停止动画'),
     value: 4,
   },
   {
-    label: '更改属性',
+    label: $t('更改属性'),
     value: 1,
   },
   {
-    label: '打开弹框',
+    label: $t('打开弹框'),
     value: 14,
   },
   {
-    label: '发送消息',
+    label: $t('发送消息'),
     value: 7,
   },
   {
-    label: '发送数据',
+    label: $t('发送数据'),
     value: 15,
   },
   {
-    label: '播放视频',
+    label: $t('播放视频'),
     value: 8,
   },
   {
-    label: '暂停视频',
+    label: $t('暂停视频'),
     value: 9,
   },
   {
-    label: '停止视频',
+    label: $t('停止视频'),
     value: 10,
   },
   {
-    label: '自定义函数',
+    label: $t('自定义函数'),
     value: 5,
   }, 
   {
-    label: '全局函数',
+    label: $t('全局函数'),
     value: 6,
   },
   {
-    label: '向场景发送消息',
+    label: $t('向场景发送消息'),
     value: 16,
   },
   {
-    label: '向父窗口发送消息',
+    label: $t('向父窗口发送消息'),
     value: 17,
   },
 ];
@@ -792,55 +662,55 @@ let cprops = [
   },
   {
     value: 'width',
-    label: '宽',
+    label: $t('宽'),
   },
   {
     value: 'height',
-    label: '高',
+    label: $t('高'),
   },
   {
     value: 'visible',
-    label: '显示',
+    label: $t('显示'),
   },
   {
     value: 'text',
-    label: '文字',
+    label: $t('文字'),
   },
   {
     value: 'color',
-    label: '颜色',
+    label: $t('颜色'),
   },
   {
     value: 'background',
-    label: '背景颜色',
+    label: $t('背景颜色'),
   },
   {
     value: 'progress',
-    label: '进度',
+    label: $t('进度'),
   },
   {
     value: 'progressColor',
-    label: '进度颜色',
+    label: $t('进度颜色'),
   },
   {
     value: 'showChild',
-    label: '状态',
+    label: $t('状态'),
   },
   {
     value: 'rotate',
-    label: '旋转',
+    label: $t('旋转'),
   },
   {
     value: 'disabled',
-    label: '禁用',
+    label: $t('禁用'),
   },
   {
     value: 'selectedKey',
-    label: '单选选中值',
+    label: $t('单选选中值'),
   },
   {
     value: 'iframe',
-    label: '网页地址',
+    label: $t('网页地址'),
   }
 ];
 
@@ -856,31 +726,31 @@ const getProps = (c: any) => {
   //   },
   //   {
   //     value: 'width',
-  //     label: '宽',
+  //     label: $t('宽'),
   //   },
   //   {
   //     value: 'height',
-  //     label: '高',
+  //     label: $t('高'),
   //   },
   //   {
   //     value: 'visible',
-  //     label: '显示',
+  //     label: $t('显示'),
   //   },
   //   {
   //     value: 'text',
-  //     label: '文字',
+  //     label: $t('文字'),
   //   },
   //   {
   //     value: 'progress',
-  //     label: '进度',
+  //     label: $t('进度'),
   //   },
   //   {
   //     value: 'showChild',
-  //     label: '状态',
+  //     label: $t('状态'),
   //   },
   //   {
   //     value: 'rotate',
-  //     label: '旋转',
+  //     label: $t('旋转'),
   //   },
   // ];
 

+ 71 - 85
src/views/components/AnimateFrames.vue

@@ -23,49 +23,34 @@
         >
           <t-collapse-panel v-for="(item, i) in animate.frames" :value="i">
             <template #header>
-              <label style="font-weight: normal">{{ `帧${i + 1}` }}</label>
+              <label style="font-weight: normal">{{ $t('帧') + (i + 1) }}</label>
             </template>
             <template #headerRightContent>
               <t-space size="small" @click.stop>
-                <t-tooltip content="在当前帧后面添加动画帧">
-                  <folder-add-icon   class="hover ml-4"
-                    @click="addFrame(i)"/>
+                <t-tooltip :content="$t('在当前帧后面添加动画帧')">
+                  <folder-add-icon class="hover ml-4" @click="addFrame(i)"></folder-add-icon>
                   <!-- <t-icon
                     name="folder-add"
                     class="hover ml-4"
                     @click="addFrame(i)"
                   /> -->
                 </t-tooltip>
-                <t-tooltip content="添加属性">
-                  <t-dropdown
-                    :options="propOptions"
-                    @click="addProp(i, $event)"
-                    :minColumnWidth="150"
-                  >
-                    <file-add-icon   class="hover ml-4" />
+                <t-tooltip :content="$t('添加属性')">
+                  <t-dropdown :options="propOptions" @click="addProp(i, $event)" :minColumnWidth="150">
+                    <file-add-icon class="hover ml-4"></file-add-icon>
                     <!-- <t-icon name="file-add" class="hover ml-4" /> -->
                   </t-dropdown>
                 </t-tooltip>
-                <t-popconfirm
-                  content="确认删除该动画帧吗"
-                  placement="left"
-                  @confirm="animate.frames.splice(i, 1)"
-                >
-                  <delete-icon class="hover ml-4"/>
+                <t-popconfirm placement="left" @confirm="animate.frames.splice(i, 1)" :content="$t('确认删除该动画帧吗')">
+                  <delete-icon class="hover ml-4"></delete-icon>
                   <!-- <t-icon name="delete" class="hover ml-4" /> -->
                 </t-popconfirm>
               </t-space>
             </template>
             <section>
               <div class="form-item">
-                <label>时长</label>
-                <t-input-number
-                  v-model="item.duration"
-                  theme="normal"
-                  :min="1"
-                  placeholder="毫秒"
-                  suffix="ms"
-                />
+                <label>{{$t('时长')}}</label>
+                <t-input-number v-model="item.duration" theme="normal" :min="1" suffix="ms" :placeholder="$t('毫秒')"></t-input-number>
               </div>
               <div class="form-item mt-8" v-for="(prop,index) in frameProps[i]">
                 <template v-if="propDescriptions[prop]">
@@ -126,7 +111,7 @@
                         v-for="(child, i) in selections.pen.children"
                         :key="i"
                         :value="i"
-                        :label="`状态${i + 1}`"
+                        :label="`${$t('状态')}${i + 1}`"
                       />
                     </t-select>
                     <t-input
@@ -154,15 +139,15 @@
         <t-divider />
         <div class="mt-16 px-16">
           <t-button class="w-full" @click="addFrame()" style="height: 30px">
-            添加帧
+            {{$t('添加帧')}}
           </t-button>
         </div>
       </template>
       <div class="flex column center blank" v-else>
-        <img src="/img/blank.png" />
-        <div class="gray center">还没有动画帧</div>
+        <img src="/img/blank.png">
+        <div class="gray center">{{$t('还没有动画帧')}}</div>
         <div class="mt-8">
-          <t-button @click="addFrame()" style="height: 30px">添加动画帧</t-button>
+          <t-button @click="addFrame()" style="height: 30px">{{$t('添加动画帧')}}</t-button>
         </div>
       </div>
     </div>
@@ -170,12 +155,13 @@
 </template>
 
 <script lang="ts" setup>
-import { onMounted, reactive, ref } from 'vue';
+import { onMounted, reactive, ref, getCurrentInstance } from 'vue';
 
 import { useSelection } from '@/services/selections';
 import {defaultGradientColor, defaultPureColor} from "@/services/defaults";
 import {CloseIcon, FolderAddIcon, FileAddIcon, DeleteIcon} from 'tdesign-icons-vue-next';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const { animate } = defineProps<{
   animate: { name: string; frames: any[] };
 }>();
@@ -190,58 +176,58 @@ const frameProps: any = ref([]);
 
 const propDescriptions: any = {
   visible: {
-    label: '显示',
+    label: $t('显示'),
     type: 'bool',
   },
   scale: {
-    label: '缩放',
+    label: $t('缩放'),
     type: 'number',
     min: 0.01,
     max: 100,
-    placeholder: '缩放比例',
+    placeholder: $t('缩放比例'),
   },
   rotate: {
-    label: '旋转',
+    label: $t('旋转'),
     type: 'number',
     min: 0,
     max: 360,
     placeholder: '°',
   },
   x: {
-    label: 'X位移',
+    label: $t('X位移'),
     type: 'number',
     placeholder: 'px',
   },
   y: {
-    label: 'Y位移',
+    label: $t('Y位移'),
     type: 'number',
     placeholder: 'px',
   },
   color: {
-    label: '前景颜色',
+    label: $t('前景颜色'),
     type: 'color',
     colorModes: ['monochrome'],
   },
   bkType: {
-    label: '背景类型',
+    label: $t('背景类型'),
     type: 'select',
     options: [
       {
-        label: '纯色',
+        label: $t('纯色'),
         value: 0,
       },
       {
-        label: '线性渐变',
+        label: $t('线性渐变'),
         value: 1,
       },
       {
-        label: '径向渐变',
+        label: $t('径向渐变'),
         value: 2,
       },
     ],
   },
   background: {
-    label: '背景颜色',
+    label: $t('背景颜色'),
     type: 'color',
     colorModesFn: (t: number) => {
       if (t > 0) {
@@ -253,47 +239,47 @@ const propDescriptions: any = {
     colorModesBind: 'bkType',
   },
   text: {
-    label: '文字',
+    label: $t('文字'),
   },
   showChild: {
-    label: '状态',
+    label: $t('状态'),
     type: 'child',
   },
   flipX: {
-    label: '水平翻转',
+    label: $t('水平翻转'),
     type: 'bool',
   },
   flipY: {
-    label: '垂直翻转',
+    label: $t('垂直翻转'),
     type: 'bool',
   },
   progress: {
-    label: '进度',
+    label: $t('进度'),
     type: 'number',
     step: 0.1,
     min: 0,
     max: 1,
-    placeholder: '0 - 1之间',
+    placeholder: $t('0 - 1之间'),
   },
   progressColor: {
-    label: '进度颜色',
+    label: $t('进度颜色'),
     type: 'color',
     colorModes: ['monochrome'],
   },
   verticalProgress: {
-    label: '垂直进度',
+    label: $t('垂直进度'),
     type: 'bool',
   },
   globalAlpha: {
-    label: '透明度',
+    label: $t('透明度'),
     type: 'number',
     step: 0.1,
     min: 0,
     max: 1,
-    placeholder: '0 - 1之间',
+    placeholder: $t('0 - 1之间'),
   },
   dash: {
-    label: '线条样式',
+    label: $t('线条样式'),
     type: 'select',
     options: [
       {
@@ -315,46 +301,46 @@ const propDescriptions: any = {
     ],
   },
   gradientRadius: {
-    label: '背景渐变半径',
+    label: $t('背景渐变半径'),
     type: 'number',
     min: 0,
     max: 1,
-    placeholder: '0 - 1之间',
+    placeholder: $t('0 - 1之间'),
   },
   lineWidth: {
-    label: '线条宽度',
+    label: $t('线条宽度'),
     type: 'number',
     min: 1,
     placeholder: 'px',
   },
   strokeType: {
-    label: '线条渐变',
+    label: $t('线条渐变'),
     type: 'bool',
   },
   lineGradientColors: {
-    label: '线条渐变颜色',
+    label: $t('线条渐变颜色'),
     type: 'color',
     colorModes: ['linear-gradient'],
   },
   fontFamily: {
-    label: '显示阴影',
+    label: $t('显示阴影'),
     type: 'select',
     options: [
       {
-        label: '新宋体',
-        value: '新宋体',
+        label: $t('新宋体'),
+        value: $t('新宋体'),
       },
       {
-        label: '微软雅黑',
-        value: '微软雅黑',
+        label: $t('微软雅黑'),
+        value: $t('微软雅黑'),
       },
       {
-        label: '黑体',
-        value: '黑体',
+        label: $t('黑体'),
+        value: $t('黑体'),
       },
       {
-        label: '楷体',
-        value: '楷体',
+        label: $t('楷体'),
+        value: $t('楷体'),
       },
       {
         label: '-apple-system',
@@ -411,75 +397,75 @@ const propDescriptions: any = {
     ],
   },
   fontSize: {
-    label: '字体大小',
+    label: $t('字体大小'),
     type: 'number',
     min: 1,
     placeholder: 'px',
   },
   textColor: {
-    label: '文字颜色',
+    label: $t('文字颜色'),
     type: 'color',
     colorModes: ['monochrome'],
   },
   textBackground: {
-    label: '文字背景',
+    label: $t('文字背景'),
     type: 'color',
     colorModes: ['monochrome'],
   },
   fontStyle: {
-    label: '文字倾斜',
+    label: $t('文字倾斜'),
     type: 'select',
     options: [
       {
-        label: `正常`,
+        label: $t(`正常`),
         value: 'normal',
       },
       {
-        label: `倾斜`,
+        label: $t(`倾斜`),
         value: 'italic',
       },
     ],
   },
   fontWeight: {
-    label: '文字加粗',
+    label: $t('文字加粗'),
     type: 'select',
     options: [
       {
-        label: `正常`,
+        label: $t(`正常`),
         value: 'normal',
       },
       {
-        label: `加粗`,
+        label: $t(`加粗`),
         value: 'bold',
       },
     ],
   },
   textHasShadow: {
-    label: '文字阴影',
+    label: $t('文字阴影'),
     type: 'bool',
   },
   shadow: {
-    label: '显示阴影',
+    label: $t('显示阴影'),
     type: 'bool',
   },
   shadowColor: {
-    label: '阴影颜色',
+    label: $t('阴影颜色'),
     type: 'color',
     colorModes: ['monochrome'],
   },
   shadowBlur: {
-    label: '阴影模糊半径',
+    label: $t('阴影模糊半径'),
     type: 'number',
     min: 0,
-    placeholder: '正数',
+    placeholder: $t('正数'),
   },
   shadowOffsetX: {
-    label: '阴影X偏移',
+    label: $t('阴影X偏移'),
     type: 'number',
     placeholder: 'px',
   },
   shadowOffsetY: {
-    label: '阴影Y偏移',
+    label: $t('阴影Y偏移'),
     type: 'number',
     placeholder: 'px',
   },

+ 7 - 7
src/views/components/ChargeCloudPublish.vue

@@ -9,22 +9,22 @@
         @click="data.selected = index"
       >
         <h4 class="mt-16">{{ item.name }}</h4>
-        <div class="detail mt-8">快速发布,提升工作效率</div>
-        <div class="detail">减少运维工作,降低成本</div>
-        <div class="detail">专注业务,创新无负担</div>
+        <div class="detail mt-8">{{$t('快速发布')}}{{$t('提升工作效率')}}</div>
+        <div class="detail">{{$t('减少运维工作')}}{{$t('降低成本')}}</div>
+        <div class="detail">{{$t('专注业务')}}{{$t('创新无负担')}}</div>
 
         <div class="price">
           <span>¥</span>
           {{ item.price }}
         </div>
         <div v-if="item.originalPrice !== item.price" class="original-price">
-          <span>原价:¥</span>
+          <span>{{$t('原价')}}:¥</span>
           {{ item.originalPrice }}
         </div>
       </li>
     </div>
     <div class="btns">
-      <t-button @click="onSubmitOrder">提交订单</t-button>
+      <t-button @click="onSubmitOrder">{{$t('提交订单')}}</t-button>
     </div>
   </div>
 
@@ -32,11 +32,11 @@
     v-if="wechatPayDialog.show"
     v-model:visible="wechatPayDialog.show"
     class="pay-dialog"
-    header="乐吾乐收银台"
+    :header="$t('乐吾乐收银台')"
     :close-on-overlay-click="false"
     :top="95"
     :width="700"
-    confirm-btn="支付完成"
+    :confirm-btn="$t('支付完成')"
     :cancel-btn="null"
     @close="getPayResult"
     :footer="false"

+ 45 - 64
src/views/components/Conditions.vue

@@ -1,15 +1,12 @@
 <template>
   <div class="props">
-    <div
-      v-if="data.conditions && data.conditions.length > 0"
-      class="form-item banner"
-    >
-      <label>触发条件</label>
+    <div v-if="data.conditions && data.conditions.length > 0" class="form-item banner">
+      <label>{{$t('触发条件')}}</label>
       <div class="w-full flex middle between">
         <div></div>
         <t-radio-group class="ml-8" v-model="data.conditionType">
-          <t-radio value="and"> 满足全部条件 </t-radio>
-          <t-radio value="or"> 满足任意条件 </t-radio>
+          <t-radio value="and"> {{$t('满足全部条件')}} </t-radio>
+          <t-radio value="or"> {{$t('满足任意条件')}} </t-radio>
         </t-radio-group>
       </div>
     </div>
@@ -18,7 +15,7 @@
         <div class="flex middle">
           <arrow-right-icon class="mr-4" />
           <!-- <t-icon name="arrow-right" class="mr-4" /> -->
-          条件{{ index + 1 }}
+{{$t('          条件')}}{{ index + 1 }}
         </div>
           <close-icon class="hover"
             @click="data.conditions.splice(index, 1)"/>
@@ -30,15 +27,15 @@
       </div>
       <div class="">
         <div class="form-item mt-4">
-          <label>条件类型</label>
+          <label>{{$t('条件类型')}}</label>
           <t-radio-group class="ml-8" v-model="c.type">
-            <t-radio value=""> 关系条件 </t-radio>
-            <t-radio value="fn"> 高级条件 </t-radio>
+            <t-radio value> {{$t('关系条件')}} </t-radio>
+            <t-radio value="fn"> {{$t('高级条件')}} </t-radio>
           </t-radio-group>
         </div>
         <template v-if="!c.type">
           <div class="form-item mt-8">
-            <label>属性名</label>
+            <label>{{$t( '属性名' )}}</label>
             <t-select-input
               v-model:inputValue="c.key"
               :value="c.keyLabel"
@@ -70,46 +67,29 @@
             </t-select-input>
           </div>
           <div class="form-item mt-8">
-            <label>关系运算</label>
-            <t-select
-              v-model="c.operator"
-              placeholder="关系运算"
-              :options="operatorOptions"
-              clearable
-              class="shrink-0"
-            />
+            <label>{{$t('关系运算')}}</label>
+            <t-select v-model="c.operator" :options="operatorOptions" clearable class="shrink-0" :placeholder="$t('关系运算')"></t-select>
           </div>
           <div class="form-item mt-8">
-            <label>运算对象</label>
-            <t-select
-              v-model="c.valueType"
-              class="shrink-0"
-              placeholder="固定值"
-            >
-              <t-option key="" value="" label="固定值"> 固定值 </t-option>
-              <t-option key="prop" value="prop" label="对象属性值">
-                对象属性值
+            <label>{{$t('运算对象')}}</label>
+            <t-select v-model="c.valueType" class="shrink-0" :placeholder="$t('固定值')">
+              <t-option key value :label="$t('固定值')"> {{$t('固定值')}} </t-option>
+              <t-option key="prop" value="prop" :label="$t('对象属性值')">
+                {{$t('对象属性值')}}
               </t-option>
             </t-select>
           </div>
           <div v-if="!c.valueType" class="form-item mt-8 form-item-valueType">
-            <label>值</label>
+            <label>{{$t( '' )}}</label>
             <t-input v-model="c.value" @change="valueChange($event,c)" class="shrink-0" style="width: 320px" />
           </div>
           <template v-else>
             <div class="form-item mt-8">
-              <label>对象</label>
-              <t-tree-select
-                v-model="c.target"
-                :data="penTree"
-                filterable
-                placeholder="对象"
-                class="shrink-0"
-                @change="onChangeTriggerTarget(c)"
-              />
+              <label>{{$t('对象')}}</label>
+              <t-tree-select v-model="c.target" :data="penTree" filterable class="shrink-0" @change="onChangeTriggerTarget(c)" :placeholder="$t('对象')"></t-tree-select>
             </div>
             <div class="form-item mt-8">
-              <label>属性</label>
+              <label>{{$t( '属性' )}}</label>
               <t-select-input
                 v-model:inputValue="c.value"
                 :value="c.label"
@@ -149,18 +129,19 @@
       </div>
     </div>
     <div class="mt-8 mb-8">
-      <a @click="addTriggerCondition(data)"> + 添加触发条件 </a>
+      <a @click="addTriggerCondition(data)"> + {{$t('添加触发条件')}} </a>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, ref } from 'vue';
+import { onBeforeMount, ref, getCurrentInstance } from 'vue';
 
 import CodeEditor from '@/views/components/common/CodeEditor.vue';
 import { getPenTree, typeOptions, changeType} from '@/services/common';
 import {ArrowRightIcon,CloseIcon} from 'tdesign-icons-vue-next';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const penTree: any = ref([]);
 const { data } = defineProps<{
   data: any;
@@ -185,31 +166,31 @@ const onChangeTriggerTarget = (c: any) => {
   //   },
   //   {
   //     value: 'width',
-  //     label: '宽',
+  //     label: $t('宽'),
   //   },
   //   {
   //     value: 'height',
-  //     label: '高',
+  //     label: $t('高'),
   //   },
   //   {
   //     value: 'visible',
-  //     label: '显示',
+  //     label: $t('显示'),
   //   },
   //   {
   //     value: 'text',
-  //     label: '文字',
+  //     label: $t('文字'),
   //   },
   //   {
   //     value: 'progress',
-  //     label: '进度',
+  //     label: $t('进度'),
   //   },
   //   {
   //     value: 'showChild',
-  //     label: '状态',
+  //     label: $t('状态'),
   //   },
   //   {
   //     value: 'rotate',
-  //     label: '旋转',
+  //     label: $t('旋转'),
   //   },
   // ];
   const target: any = meta2d.findOne(c.target);
@@ -256,51 +237,51 @@ const cprops = ref<any>([
   },
   {
     value: 'width',
-    label: '宽',
+    label: $t('宽'),
   },
   {
     value: 'height',
-    label: '高',
+    label: $t('高'),
   },
   {
     value: 'visible',
-    label: '显示',
+    label: $t('显示'),
   },
   {
     value: 'text',
-    label: '文字',
+    label: $t('文字'),
   },
   {
     value: 'color',
-    label: '颜色',
+    label: $t('颜色'),
   },
   {
     value: 'background',
-    label: '背景颜色',
+    label: $t('背景颜色'),
   },
   {
     value: 'progress',
-    label: '进度',
+    label: $t('进度'),
   },
   {
     value: 'progressColor',
-    label: '进度颜色',
+    label: $t('进度颜色'),
   },
   {
     value: 'showChild',
-    label: '状态',
+    label: $t('状态'),
   },
   {
     value: 'rotate',
-    label: '旋转',
+    label: $t('旋转'),
   },
   {
     value: 'disabled',
-    label: '禁用',
+    label: $t('禁用'),
   },
   {
     value: 'selectedKey',
-    label: '单选选中值',
+    label: $t('单选选中值'),
   }
 ]);
 
@@ -311,8 +292,8 @@ const operatorOptions = [
   { label: '<', value: '<' },
   { label: '>=', value: '>=' },
   { label: '<=', value: '<=' },
-  { label: '包含', value: '[)' },
-  { label: '不包含', value: '![)' },
+  { label: $t('包含'), value: '[)' },
+  { label: $t('不包含'), value: '![)' },
 ];
 
 const valueChange = (e,c:any)=>{

+ 29 - 28
src/views/components/ContextMenu.vue

@@ -2,89 +2,90 @@
   <t-menu class="context-menu" @change="onMenu">
     <template v-if="props.type === 'anchor'">
       <t-menu-item value="addAnchorHand">
-        <div class="flex">添加手柄 <span class="flex-grow"></span> H</div>
+        <div class="flex">{{$t('添加手柄')}} <span class="flex-grow"></span> H</div>
       </t-menu-item>
       <t-menu-item value="removeAnchorHand">
-        <div class="flex">删除手柄 <span class="flex-grow"></span> D</div>
+        <div class="flex">{{$t('删除手柄')}} <span class="flex-grow"></span> D</div>
       </t-menu-item>
       <t-menu-item value="toggleAnchorHand">
-        <div class="flex">切换手柄 <span class="flex-grow"></span> Shift</div>
+        <div class="flex">{{$t('切换手柄')}} <span class="flex-grow"></span> Shift</div>
       </t-menu-item>
     </template>
     <template v-if="props.type === 'pen'">
-      <t-menu-item v-if="!selections.mode&&hasC()" value="updateC"> 一键更新我的组件 </t-menu-item>
-      <t-menu-item v-if="isAppend()" value="appendChild"> 追加状态 </t-menu-item>
-      <t-menu-item v-if="is3D()" value="goto3d"> 进入3D可视化编辑 </t-menu-item>
-      <t-menu-item v-if="is2D()" value="goto2d"> 进入2D可视化编辑 </t-menu-item>
-      <t-menu-item v-if="isV()" value="gotov"> 进入大屏可视化编辑 </t-menu-item>
-      <t-menu-item v-if="isIframe()" value="replaceScene"> 替换方案 </t-menu-item>
+      <t-menu-item v-if="!selections.mode&&hasC()" value="updateC"> {{$t('一键更新我的组件')}} </t-menu-item>
+      <t-menu-item v-if="isAppend()" value="appendChild"> {{$t('追加状态')}} </t-menu-item>
+      <t-menu-item v-if="is3D()" value="goto3d"> {{$t('进入')}}3D{{$t('可视化编辑')}} </t-menu-item>
+      <t-menu-item v-if="is2D()" value="goto2d"> {{$t('进入')}}2D{{$t('可视化编辑')}} </t-menu-item>
+      <t-menu-item v-if="isV()" value="gotov"> {{$t('进入大屏可视化编辑')}} </t-menu-item>
+      <t-menu-item v-if="isIframe()" value="replaceScene"> {{$t('替换方案')}} </t-menu-item>
       <!-- <t-menu-item v-if="isTableNoFocus()" value="focus"> 
         <div class="flex">进入编辑模式<span class="flex-grow"></span>Enter</div>
       </t-menu-item> -->
       <!-- <t-menu-item v-if="isTableFocus()" value="unFocus"> 
         <div class="flex">退出编辑模式 <span class="flex-grow"></span>Esc</div>
       </t-menu-item> -->
-      <t-menu-item :disabled="!selections.mode" value="top"> 置顶 </t-menu-item>
+      <t-menu-item :disabled="!selections.mode" value="top"> {{$t('置顶')}} </t-menu-item>
       <t-menu-item :disabled="!selections.mode" value="bottom">
-        置底
+        {{$t('置底')}}
       </t-menu-item>
       <t-menu-item :disabled="!selections.mode" value="up">
-        上一个图层
+        {{$t('上一个图层')}}
       </t-menu-item>
       <t-menu-item :disabled="!selections.mode" value="down">
-        下一个图层
+        {{$t('下一个图层')}}
       </t-menu-item>
-      <t-divider />
+      <t-divider></t-divider>
 
       <template v-if="selections.mode === SelectionMode.Pens">
-        <t-menu-item value="group"> 组合 </t-menu-item>
-        <t-menu-item value="states"> 组合为状态 </t-menu-item>
+        <t-menu-item value="group"> {{$t('组合')}} </t-menu-item>
+        <t-menu-item value="states"> {{$t('组合为状态')}} </t-menu-item>
       </template>
         <t-menu-item v-if="hasChildren" value="unGroup"> 
-          <t-popconfirm  content="确认取消组合?(将丢失组合图元的数据)" @cancel="onMenu('xxxx')" @confirm="onMenu('unGroup')">
+          <t-popconfirm @cancel="onMenu('xxxx')" @confirm="onMenu('unGroup')" :content="$t('确认取消组合?(将丢失组合图元的数据)')">
             <div @click.stop>
-                取消组合 
+                {{$t('取消组合')}} 
             </div>
           </t-popconfirm>
         </t-menu-item>
       <t-menu-item :disabled="!selections.mode" value="lock">
-        {{ locked ? '解锁' : '锁定' }}
+        {{ locked ? $t('解锁') : $t('锁定') }}
       </t-menu-item>
       <t-divider />
-      <t-menu-item :disabled="!selections.mode" value="del"> 删除 </t-menu-item>
+      <t-menu-item :disabled="!selections.mode" value="del"> {{$t( '删除' )}} </t-menu-item>
       <template v-if="isNameLine">
         <t-menu-item value="changeType">
-          {{ isLine ? '变成节点' : '变成连线' }}
+          {{ isLine ? $t('变成节点') : $t('变成连线') }}
         </t-menu-item>
       </template>
       <t-divider />
       <t-menu-item :disabled="cantUndo" value="undo">
-        <div class="flex">撤销<span class="flex-grow"></span>Ctrl + Z</div>
+        <div class="flex">{{$t('撤销')}}<span class="flex-grow"></span>Ctrl + Z</div>
       </t-menu-item>
       <t-menu-item :disabled="cantRedo" value="redo">
-        <div class="flex">重做<span class="flex-grow"></span>Shift + Z</div>
+        <div class="flex">{{$t('重做')}}<span class="flex-grow"></span>Shift + Z</div>
       </t-menu-item>
       <t-divider />
       <t-menu-item :disabled="!selections.mode" value="cut">
-        <div class="flex">剪切<span class="flex-grow"></span>Ctrl + X</div>
+        <div class="flex">{{$t('剪切')}}<span class="flex-grow"></span>Ctrl + X</div>
       </t-menu-item>
       <t-menu-item :disabled="!selections.mode" value="copy">
-        <div class="flex">复制<span class="flex-grow"></span>Ctrl + C</div>
+        <div class="flex">{{$t('复制')}}<span class="flex-grow"></span>Ctrl + C</div>
       </t-menu-item>
       <t-menu-item value="paste">
-        <div class="flex">粘贴<span class="flex-grow"></span>Ctrl + V</div>
+        <div class="flex">{{$t('粘贴')}}<span class="flex-grow"></span>Ctrl + V</div>
       </t-menu-item>
     </template>
   </t-menu>
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref } from 'vue';
+import { onMounted, ref, getCurrentInstance } from 'vue';
 import { LockState, Pen, PenType } from '@meta2d/core';
 import { useSelection, SelectionMode } from '@/services/selections';
 import { updateC } from '@/services/updateC';
 import { rootDomain } from '@/services/defaults';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const props = defineProps({
   type: String,
 });

+ 15 - 15
src/views/components/Custom.vue

@@ -90,23 +90,23 @@
         class="form-cell"
         v-if="cell.row !== undefined && cell.col !== undefined"
       >
-        选中单元格(第{{ cell.row }}行,第{{ cell.col }}列)样式
+        {{$t( '选中单元格' )}}{{$t( '' )}}{{ cell.row }}{{$t( '' )}}{{$t( '' )}}{{ cell.col }}{{$t( '' )}}{{$t( '样式' )}}
       </div>
       <div
         class="form-cell"
         v-else-if="cell.row !== undefined && cell.col === undefined"
       >
-        第{{ cell.row }}行样式
+        {{$t( '' )}}{{ cell.row }}{{$t( '行样式' )}}
       </div>
       <div
         class="form-cell"
         v-if="cell.row === undefined && cell.col !== undefined"
       >
-        第{{ cell.col }}列样式
+        {{$t( '' )}}{{ cell.col }}{{$t( '列样式' )}}
       </div>
       <t-space direction="vertical" size="small" class="w-full">
         <div class="form-item">
-          <label>背景颜色</label>
+          <label>{{$t( '背景颜色' )}}</label>
           <t-color-picker
             class="w-full"
             :enable-alpha="true"
@@ -120,7 +120,7 @@
           />
         </div>
         <div class="form-item">
-          <label>文字颜色</label>
+          <label>{{$t( '文字颜色' )}}</label>
           <t-color-picker
             class="w-full"
             :enable-alpha="true"
@@ -134,7 +134,7 @@
           />
         </div>
         <div class="form-item">
-          <label>文字大小</label>
+          <label>{{$t( '文字大小' )}}</label>
           <t-input-number
             class="w-full"
             v-model.number="cell.fontSize"
@@ -176,7 +176,7 @@
           >
         </div>
         <div class="form-item">
-          <label>文本对齐</label>
+          <label>{{$t( '文本对齐' )}}</label>
           <t-radio-group
             size="small"
             v-model="cell.textAlign"
@@ -184,22 +184,22 @@
             @change="changeStyles('textAlign')"
           >
             <t-radio-button value="left">
-              <t-tooltip content="居左" placement="top">
+              <t-tooltip :content="$t('居左')" placement="top">
                 <format-vertical-align-left-icon />
               </t-tooltip>
             </t-radio-button>
             <t-radio-button value="center">
-              <t-tooltip content="水平居中" placement="top">
+              <t-tooltip :content="$t('水平居中')" placement="top">
                 <format-vertical-align-center-icon />
               </t-tooltip>
             </t-radio-button>
             <t-radio-button value="right">
-              <t-tooltip content="居右" placement="top">
+              <t-tooltip :content="$t('居右')" placement="top">
                 <format-vertical-align-right-icon />
               </t-tooltip>
             </t-radio-button>
           </t-radio-group>
-          <t-tooltip content="水平偏移">
+          <t-tooltip :content="$t('水平偏移')">
             <t-input
               placeholder="X"
               v-model.number="cell.textLeft"
@@ -211,7 +211,7 @@
       </t-space>
     </div>
     <div v-if="props.pen.name === 'combine'" class="form-item">
-      <label > 是否绘制 </label>
+      <label > {{$t( '是否绘制' )}} </label>
       <t-checkbox
         class="ml-8"
         v-model="props.pen['draw']"
@@ -222,8 +222,8 @@
   <t-drawer
     v-model:visible="drawer.visible"
     :header="drawer.header"
-    cancelBtn="关闭"
-    confirmBtn="运行"
+    :cancelBtn="$t('关闭')"
+    :confirmBtn="$t('运行')"
     @confirm="onConfirmDrawer"
     :closeOnOverlayClick="false"
     :sizeDraggable="true"
@@ -329,7 +329,7 @@ const showDrawer = (item: any) => {
 
 const onConfirmDrawer = () => {
   if (!drawer.value) {
-    MessagePlugin.error('数据不满足json格式');
+    MessagePlugin.error($t('数据不满足json格式'));
     return;
   }
   props.pen[drawer.key] = drawer.value;

+ 109 - 141
src/views/components/Data.vue

@@ -1,10 +1,10 @@
 <template>
-  <div class="content" :draggable="false" v-if="group === '属性'">
+  <div class="content" :draggable="false" :v-if="group === $t('属性')">
     <div class="flex between">
-      <div class="title">{{ group }}列表</div>
+      <div class="title">{{ group }}{{$t( '列表' )}}</div>
       <div class="flex between">
         <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
-          <t-tooltip content="导入属性列表" placement="top">
+          <t-tooltip placement="top" :content="$t('导入属性列表')">
             <div class="icon-box" @mouseenter="getDatasets()">
               <!-- <FileImportIcon /> -->
               <AddIcon />
@@ -13,15 +13,15 @@
 
           <t-dropdown-menu>
             <t-dropdown-item :value="2" :divider="true" @click="showAddData()">
-              新建属性
+              {{$t('新建属性')}}
             </t-dropdown-item>
             <t-dropdown-item :value="1">
-              我的属性列表
+              {{$t('我的属性列表')}}
               <!-- </t-dropdown> -->
               <t-dropdown-menu>
-                <t-dropdown-item v-if="!user.id"> 请先登录! </t-dropdown-item>
+                <t-dropdown-item v-if="!user.id"> {{$t('请先登录')}}! </t-dropdown-item>
                 <t-dropdown-item v-else-if="!data.datasetList.length">
-                  暂无数据
+                  {{$t('暂无数据')}}
                 </t-dropdown-item>
                 <template v-else>
                   <t-dropdown-item v-for="(dataset, i) in data.datasetList">
@@ -33,7 +33,7 @@
                       <div v-if="dataset.url" class="desc">
                         {{ dataset.url }}
                       </div>
-                      <div v-else class="desc">自定义</div>
+                      <div v-else class="desc">{{$t('自定义')}}</div>
                       <!-- <t-popconfirm
                             content="确认删除吗?"
                             @confirm.stop="onDelDataset(dataset, i)"
@@ -51,7 +51,7 @@
             </t-dropdown-item>
 
             <t-dropdown-item :value="3" :divider="true">
-              在线接口
+              {{$t('在线接口')}}
 
               <t-dropdown-menu
                 class="menu-item-input"
@@ -66,9 +66,9 @@
                     style="max-width: 216px !important"
                   >
                     <t-input
-                      label="地址:"
+                      :label="$t('地址:')"
                       style="width: 216px"
-                      placeholder="请输入地址"
+                      :placeholder="$t('请输入地址')"
                       v-model="data.dataset.url"
                       @blur="getDatas"
                       @enter="getDatas"
@@ -85,7 +85,7 @@
               </t-dropdown-menu>
             </t-dropdown-item>
             <t-dropdown-item :value="2" @click="importDataset">
-              从Excel导入
+              {{$t( '从Excel导入' )}}
             </t-dropdown-item>
             <t-dropdown-item :value="4">
               <a
@@ -96,13 +96,13 @@
                 style="color: var(--td-text-color-primary)"
                 @click.stop
               >
-                下载Excel示例
+               {{$t( '下载Excel示例' )}}
               </a>
             </t-dropdown-item>
           </t-dropdown-menu>
         </t-dropdown>
         <t-dropdown :minColumnWidth="168">
-          <t-tooltip content="导出属性列表" placement="top">
+          <t-tooltip placement="top" :content="$t('导出属性列表')">
             <div class="icon-box">
               <!-- <FileExportIcon /> -->
               <Download1Icon />
@@ -110,22 +110,18 @@
           </t-tooltip>
           <t-dropdown-menu>
             <t-dropdown-item @click="downloadAsJson"
-              >下载为JSON</t-dropdown-item
+              >{{$t( '下载为JSON' )}}</t-dropdown-item
             >
             <t-dropdown-item @click="downloadAsExcel"
-              >下载为Excel</t-dropdown-item
+              >{{$t( '下载为Excel' )}}</t-dropdown-item
             >
             <t-dropdown-item @click="onOkDataset()"
-              >保存为我的属性列表</t-dropdown-item
+              >{{$t( '保存为我的属性列表' )}}</t-dropdown-item
             >
           </t-dropdown-menu>
         </t-dropdown>
-        <t-popconfirm
-          content="确认清空属性列表吗?"
-          placement="bottom"
-          @confirm="clearData"
-        >
-          <t-tooltip content="清空列表" placement="top">
+        <t-popconfirm placement="bottom" @confirm="clearData" :content="$t('确认清空属性列表吗?')">
+          <t-tooltip placement="top" :content="$t('清空列表')">
             <div class="icon-box">
               <DeleteIcon />
             </div>
@@ -139,13 +135,11 @@
       </div>
     </div>
     <div class="flex between mt-8">
-      <t-tooltip content="可批量导入数据图元到画布" placement="top">
-        <t-checkbox v-model="data.checkAll" @change="onCheckAllChange">批量导入到画布</t-checkbox>
+      <t-tooltip placement="top" :content="$t('可批量导入数据图元到画布')">
+        <t-checkbox v-model="data.checkAll" @change="onCheckAllChange">{{$t('批量导入到画布')}}</t-checkbox>
       </t-tooltip>
-      <t-tooltip content="开启全局数据模拟" placement="top">
-        <t-checkbox v-model="data.enableMock" @change="onChangeMock"
-          >开启</t-checkbox
-        >
+      <t-tooltip placement="top" :content="$t('开启全局数据模拟')">
+        <t-checkbox v-model="data.enableMock" @change="onChangeMock">{{$t('开启')}}</t-checkbox>
       </t-tooltip>
     </div>
     <div class="input-search">
@@ -153,12 +147,7 @@
         <search-icon class="hover" />
         <!-- <img src="/img/icon_search_gray.svg" /> -->
       </div>
-      <t-input
-        v-model="search"
-        @change="onSearch"
-        @enter="onSearch"
-        placeholder="搜索我的属性列表"
-      />
+      <t-input v-model="search" @change="onSearch" @enter="onSearch" :placeholder="$t('搜索我的属性列表')"></t-input>
     </div>
     <div
       id="dragElem"
@@ -226,7 +215,7 @@
           </div>
 
           <div class="flex">
-            <t-tooltip content="开启单个模拟" placement="top">
+            <t-tooltip :content="$t('开启单个模拟')" placement="top">
               <div
                 class="icon-box icon-item-box"
                 @click="device.enableMock = !device.enableMock"
@@ -241,7 +230,7 @@
             <div class="icon-box icon-item-box" @click="showAddData(device, i)">
               <Edit2Icon />
             </div>
-            <t-popconfirm content="确认删除吗?" @confirm="deleteData(i)">
+            <t-popconfirm @confirm="deleteData(i)" :content="$t('确认删除吗?')">
               <div class="icon-box icon-item-box">
                 <DeleteIcon />
               </div>
@@ -257,15 +246,15 @@
                 <div :title="device.label">{{ device.label }}</div>
               </div> -->
               <div class="form-item form-data-item">
-                <label>属性名:</label>
+                <label>{{$t('属性名')}}:</label>
                 <div :title="device.id">{{ device.id }}</div>
               </div>
               <div class="form-item form-data-item">
-                <label>类型:</label>
+                <label>{{$t('类型')}}:</label>
                 <div :title="device.type">{{ device.type }}</div>
               </div>
               <div class="form-item form-data-item">
-                <label>值范围:</label>
+                <label>{{$t('值范围')}}:</label>
                 <div :title="device.mock">{{ device.mock }}</div>
               </div>
             </div>
@@ -274,18 +263,18 @@
       </div>
     </div>
     <div class="flex column middle nodata" v-else>
-      <img src="/img/no-data.png" />
-      <div class="gray center">暂无数据</div>
+      <img src="/img/no-data.png">
+      <div class="gray center">{{$t('暂无数据')}}</div>
       <div class="mt-20">
-        <t-button theme="primary" @click="showAddData()"> 新建属性 </t-button>
+        <t-button theme="primary" @click="showAddData()"> {{$t('新建属性')}} </t-button>
       </div>
     </div>
   </div>
-  <div class="content" v-if="group === '数据源'">
+  <div class="content" :v-if="'group' === $t('数据源')">
     <div class="flex between">
       <div class="title">{{ group }}</div>
       <div class="flex between">
-        <t-tooltip content="添加数据源" placement="top">
+        <t-tooltip placement="top" :content="$t('添加数据源')">
           <div class="icon-box" @click="addNetwork()">
             <AddIcon />
           </div>
@@ -297,7 +286,7 @@
         v-model="data.networkId"
         filterable
         clearable
-        placeholder="搜索我的数据源"
+        :placeholder="$t('搜索我的数据源')"
         @focus="onInputNetwork"
         :on-search="onInputNetwork"
         @change="onSelectNetWork"
@@ -350,7 +339,7 @@
             <div class="icon-box" @click="editNetwork(network, i)">
               <Edit2Icon />
             </div>
-            <t-popconfirm content="确认删除吗?" @confirm="deleteNetwork(i)">
+            <t-popconfirm @confirm="deleteNetwork(i)" :content="$t('确认删除吗?')">
               <div class="icon-box">
                 <DeleteIcon />
               </div>
@@ -362,15 +351,15 @@
             <span class="form-line" style="height: 88px"></span>
             <div>
               <div class="form-item form-data-item mt-8">
-                <label>显示名称:</label>
+                <label>{{$t('显示名称')}}:</label>
                 <div :title="network.name">{{ network.name }}</div>
               </div>
               <div class="form-item form-data-item mt-8">
-                <label>通信方式:</label>
+                <label>{{$t('通信方式')}}:</label>
                 <div :title="network.protocol">{{ network.protocol }}</div>
               </div>
               <div class="form-item form-data-item mt-8">
-                <label>URL地址:</label>
+                <label>URL{{$t('地址')}}:</label>
                 <div :title="network.url">{{ network.url }}</div>
               </div>
             </div>
@@ -379,18 +368,18 @@
       </div>
     </div>
     <div class="flex column middle nodata" v-else>
-      <img src="/img/no-data.png" />
-      <div class="gray center">暂无数据</div>
+      <img src="/img/no-data.png">
+      <div class="gray center">{{$t('暂无数据')}}</div>
       <div class="mt-20">
         <t-button theme="primary" @click="addNetwork()">
-          添加数据源
+          {{$t('添加数据源')}}
         </t-button>
       </div>
     </div>
   </div>
-  <div class="content" v-if="group === '解析'">
+  <div class="content" v-if="group === $t('解析')">
     <div class="flex between">
-      <div class="title">数据{{ group }}</div>
+      <div class="title">{{$t('数据')}}{{ group }}</div>
     </div>
     <div class="mt-8">
       <CodeEditor
@@ -404,13 +393,9 @@
       </div>
     </div>
     <div class="mt-16">
-      参考文档:
-      <a
-        target="_blank"
-        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
-      >
-        解析自定义格式数据</a
-      >
+      {{$t('参考文档')}}:
+      <a target="_blank" href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">
+        {{$t('解析自定义格式数据')}}</a>
     </div>
   </div>
   <!-- <div class="content" v-show="group === '数据模拟'">
@@ -541,57 +526,42 @@
         <t-input v-model="addDataDialog.data.device" placeholder="设备名称" />
       </div> -->
     <div class="form-item mt-16">
-      <label>显示名称</label>
-      <t-input
-        @change="changeDataLabel($event)"
-        :value="addDataDialog.data.label"
-        placeholder="属性简短描述"
-      />
+      <label>{{$t('显示名称')}}</label>
+      <t-input @change="changeDataLabel($event)" :value="addDataDialog.data.label" :placeholder="$t('属性简短描述')"></t-input>
     </div>
     <div class="form-item mt-16">
-      <label>属性名</label>
-      <t-input
-        @change="changeDataID($event)"
-        :value="addDataDialog.data.id"
-        placeholder="属性名"
-      />
+      <label>{{$t('属性名')}}</label>
+      <t-input @change="changeDataID($event)" :value="addDataDialog.data.id" :placeholder="$t('属性名')"></t-input>
     </div>
     <div class="form-item mt-16">
-      <label>类型</label>
-      <t-select
-        class="w-full"
-        :options="typeOptions"
-        v-model="addDataDialog.data.type"
-        placeholder="字符串"
-        @change="addDataDialog.data.value = null"
-      />
+      <label>{{$t('类型')}}</label>
+      <t-select class="w-full" :options="typeOptions" v-model="addDataDialog.data.type" @change="addDataDialog.data.value = null" :placeholder="$t('字符串')"></t-select>
     </div>
     <div class="form-item mt-16">
-      <label
-        >值范围
-        <t-tooltip content="可用做数据模拟" placement="top">
-          <HelpCircleIcon style="font-size: 12px" />
+      <label>{{$t('值范围')}}
+        <t-tooltip placement="top" :content="$t('可用做数据模拟')">
+          <HelpCircleIcon style="font-size: 12px"></HelpCircleIcon>
         </t-tooltip>
       </label>
       <div class="w-full">
-        <t-input v-model="addDataDialog.data.mock" placeholder="值范围" />
-        <h6 class="desc mt-8" style="font-size: 12px">值范围说明</h6>
+        <t-input v-model="addDataDialog.data.mock" :placeholder="$t('值范围')"></t-input>
+        <h6 class="desc mt-8" style="font-size: 12px">{{$t('值范围说明')}}</h6>
         <ul class="desc ml-16" style="font-size: 12px">
           <li>
-            <label class="inline" style="width: 80px">固定值:</label>
-            直接填写,例如:10
+            <label class="inline" style="width: 80px">{{$t('固定值')}}:</label>
+            {{$t('直接填写')}}{{$t('例如')}}:10
           </li>
           <li>
-            <label class="inline" style="width: 80px">随机值:</label>
-            值1,值2,...。例如:1,2,3,4,5
+            <label class="inline" style="width: 80px">{{$t('随机值')}}:</label>
+            {{$t('')}}1,{{$t('')}}2,...。{{$t('例如')}}:1,2,3,4,5
           </li>
           <li>
-            <label class="inline" style="width: 80px">范围数字:</label>
-            最小值-最大值。例如:0-1.0 或 0-100
+            <label class="inline" style="width: 80px">{{$t('范围数字')}}:</label>
+            {{$t('最小值')}}-{{$t('最大值')}}{{$t('例如')}}:0-1.0 {{$t('')}} 0-100
           </li>
           <li>
-            <label class="inline" style="width: 80px">随机字符串:</label>
-            [长度]。例如:[8]
+            <label class="inline" style="width: 80px">{{$t('随机字符串')}}:</label>
+            [{{$t('长度')}}]。{{$t('例如')}}:[8]
           </li>
         </ul>
       </div>
@@ -609,9 +579,9 @@
     <template #footer>
       <div class="flex mr-8" style="justify-content: end">
         <t-checkbox v-model="networkDialog.save" class="mr-12">
-          同时保存到我的数据源
+          {{$t('同时保存到我的数据源')}}
         </t-checkbox>
-        <t-button @click="onOkNetwork">确定</t-button>
+        <t-button @click="onOkNetwork">{{$t('确定')}}</t-button>
       </div>
     </template>
     <div style="max-height: 450px; padding: 8px; overflow-y: auto">
@@ -621,26 +591,22 @@
   <t-dialog
     v-if="dataTransformationDialog.show"
     :visible="true"
-    header="数据监听"
+    :header="$t('数据监听')"
     @confirm="onOkDataTransformation"
     @close="dataTransformationDialog.show = false"
     :width="800"
   >
     <CodeEditor v-model="dataTransformationDialog.data" style="height: 300px" />
     <div class="mt-8">
-      参考文档:
-      <a
-        target="_blank"
-        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
-      >
-        解析自定义格式数据</a
-      >
+      {{$t('参考文档')}}:
+      <a target="_blank" href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">
+        {{$t('解析自定义格式数据')}}</a>
     </div>
   </t-dialog>
 </template>
 
 <script lang="ts" setup>
-import { reactive, defineComponent, ref, onMounted, toRaw, watch } from 'vue';
+import { reactive, defineComponent, ref, onMounted, toRaw, watch, getCurrentInstance } from 'vue';
 import {
   FileImportIcon,
   FileExportIcon,
@@ -675,6 +641,8 @@ import CodeEditor from '@/views/components/common/CodeEditor.vue';
 import { s8 } from '@/services/random';
 import { useUser } from '@/services/user';
 
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const props = defineProps<{
   group: string;
 }>();
@@ -735,11 +703,11 @@ const addDataDialog = reactive<any>({});
 
 const showAddData = (row?: any, index?: number) => {
   if (row) {
-    addDataDialog.header = '编辑数据';
+    addDataDialog.header = $t('编辑数据');
     addDataDialog.data = JSON.parse(JSON.stringify(row));
     addDataDialog.index = index;
   } else {
-    addDataDialog.header = '添加数据';
+    addDataDialog.header = $t('添加数据');
     addDataDialog.data = { type: 'string', expend: true };
   }
 
@@ -763,12 +731,12 @@ const clearData = () => {
 
 const changeDataLabel = (value) => {
   if (!value) {
-    MessagePlugin.error('显示名称不能为空!');
+    MessagePlugin.error($t('显示名称不能为空!'));
     return;
   }
   let item = data.dataset.devices?.filter((item) => item.label === value);
   if (item && item.length) {
-    MessagePlugin.error('显示名称重复!');
+    MessagePlugin.error($t('显示名称重复!'));
     return;
   }
   addDataDialog.data.label = value;
@@ -776,12 +744,12 @@ const changeDataLabel = (value) => {
 
 const changeDataID = (value) => {
   if (!value) {
-    MessagePlugin.error('属性名不能为空!');
+    MessagePlugin.error($t('属性名不能为空!'));
     return;
   }
   let item = data.dataset.devices?.filter((item) => item.id === value);
   if (item && item.length) {
-    MessagePlugin.error('属性名重复!');
+    MessagePlugin.error($t('属性名重复!'));
     return;
   }
   addDataDialog.data.id = value;
@@ -789,17 +757,17 @@ const changeDataID = (value) => {
 
 const onOkAddData = () => {
   if (!addDataDialog.data.label) {
-    MessagePlugin.error('请填写名称');
+    MessagePlugin.error($t('请填写名称'));
     return;
   }
   if (!addDataDialog.data.id) {
-    MessagePlugin.error('请填写数据ID');
+    MessagePlugin.error($t('请填写数据ID'));
     return;
   }
   if (!data.dataset.devices) {
     data.dataset.devices = [];
   }
-  if (addDataDialog.header === '添加数据') {
+  if (addDataDialog.header === $t('添加数据')) {
     data.dataset.devices.push(addDataDialog.data);
   } else {
     data.dataset.devices[addDataDialog.index] = addDataDialog.data;
@@ -825,23 +793,23 @@ const onOkAddData = () => {
 const importDataset = async () => {
   let columns: any = [
     {
-      header: '设备',
+      header: $t('设备'),
       key: 'device',
     },
     {
-      header: '显示名称',
+      header: $t('显示名称'),
       key: 'label',
     },
     {
-      header: '属性名',
+      header: $t('属性名'),
       key: 'id',
     },
     {
-      header: '类型',
+      header: $t('类型'),
       key: 'type',
     },
     {
-      header: '值范围',
+      header: $t('值范围'),
       key: 'mock',
     },
   ];
@@ -858,26 +826,26 @@ const importDataset = async () => {
 
 const downloadAsExcel = () => {
   if (!(data.dataset.devices && data.dataset.devices.length)) {
-    MessagePlugin.error('属性列表不能为空!');
+    MessagePlugin.error($t('属性列表不能为空!'));
     return;
   }
   const name = meta2d.store.data.name;
   const columns: any[] = [
     {
       key: 'label',
-      header: '显示名称',
+      header: $t('显示名称'),
     },
     {
       key: 'id',
-      header: '属性名',
+      header: $t('属性名'),
     },
     {
       key: 'type',
-      header: '类型',
+      header: $t('类型'),
     },
     {
       key: 'mock',
-      header: '值范围',
+      header: $t('值范围'),
     },
   ];
   saveAsExcel(name, columns, data.dataset.devices);
@@ -885,7 +853,7 @@ const downloadAsExcel = () => {
 
 const downloadAsJson = () => {
   if (!(data.dataset.devices && data.dataset.devices.length)) {
-    MessagePlugin.error('属性列表不能为空!');
+    MessagePlugin.error($t('属性列表不能为空!'));
     return;
   }
   import('file-saver').then(({ saveAs }) => {
@@ -893,18 +861,18 @@ const downloadAsJson = () => {
       new Blob([JSON.stringify(data.dataset)], {
         type: 'text/plain;charset=utf-8',
       }),
-      `${data.dataset.name || '未命名'}.json`
+      `${data.dataset.name || $t('未命名')}.json`
     );
   });
 };
 
 const onOkDataset = async (saveas = false) => {
   // if (!dataDialog.dataset.name) {
-  //   MessagePlugin.error('名称不能为空');
+  //   MessagePlugin.error($t('名称不能为空'));
   //   return;
   // }
   if (!(data.dataset.devices && data.dataset.devices.length)) {
-    MessagePlugin.error('属性列表不能为空');
+    MessagePlugin.error($t('属性列表不能为空'));
     return;
   }
   const dataset = JSON.parse(JSON.stringify(data.dataset));
@@ -1054,9 +1022,9 @@ const onSelDataset = async (datasetId = false) => {
 
 // 请求我的数据模型
 const getDatasets = async (name?: string) => {
-  // console.log("进入")
+  // console.log($t("进入"))
   if (!user.id) {
-    MessagePlugin.error('请先登录');
+    MessagePlugin.error($t('请先登录'));
     return;
   }
   const body: any = {
@@ -1196,7 +1164,7 @@ const editNetwork = (network: any, index: number) => {
   networkDialog.network = JSON.parse(JSON.stringify(network));
   networkDialog.editNetwork = 2;
   networkDialog.editNetworkIndex = index;
-  networkDialog.header = '编辑数据源';
+  networkDialog.header = $t('编辑数据源');
   networkDialog.show = true;
 };
 
@@ -1214,7 +1182,7 @@ const addNetwork = () => {
     },
   };
   networkDialog.editNetwork = 1;
-  networkDialog.header = '添加数据源';
+  networkDialog.header = $t('添加数据源');
   networkDialog.show = true;
 };
 
@@ -1222,11 +1190,11 @@ const onOkNetwork = async () => {
   const _data = transformData(networkDialog.network, 'toNetwork');
   if (networkDialog.editNetwork === 1) {
     if (['mqtt','websocket','http'].includes(networkDialog.network.protocol)&& !networkDialog.network.url) {
-      MessagePlugin.error('URL地址不能为空!');
+      MessagePlugin.error($t('URL地址不能为空!'));
       return;
     }
     if (!networkDialog.network.name) {
-      MessagePlugin.error('名称不能为空!');
+      MessagePlugin.error($t('名称不能为空!'));
       return;
     }
     if (networkDialog.save) {
@@ -1314,7 +1282,7 @@ const onAddShape = (e, _data) => {
     e.dataTransfer.setDragImage(dragElem, width / 2, 10);
     const checked = _data.filter((item) => item.checked);
     if(!checked.length){
-      MessagePlugin.error('请先选择数据');
+      MessagePlugin.error($t('请先选择数据'));
       return;
     }
     data = [];
@@ -1345,7 +1313,7 @@ const onAddShape = (e, _data) => {
             lineWidth:1,
             realTimes: [
               {
-                label: '文字',
+                label: $t('文字'),
                 key: 'text',
                 type: 'string',
                 bind: deepClone(item),
@@ -1374,7 +1342,7 @@ const onAddShape = (e, _data) => {
             textAlign: 'left',
             realTimes: [
               {
-                label: '文字',
+                label: $t('文字'),
                 key: 'text',
                 type: 'string',
                 bind: deepClone(item),
@@ -1411,7 +1379,7 @@ const onAddShape = (e, _data) => {
         lineWidth:1,
         realTimes: [
           {
-            label: '文字',
+            label: $t('文字'),
             key: 'text',
             type: 'string',
             bind: deepClone(_data),
@@ -1438,7 +1406,7 @@ const onAddShape = (e, _data) => {
         textAlign: 'left',
         realTimes: [
           {
-            label: '文字',
+            label: $t('文字'),
             key: 'text',
             type: 'string',
             bind: deepClone(_data),

+ 34 - 33
src/views/components/Dataset.vue

@@ -1,41 +1,41 @@
 <template>
   <div class="dataset-component">
     <div class="form-item mt-8">
-      <label>变量列表</label>
-      <t-input v-model="modelValue.name" placeholder="名称" />
+      <label>{{$t('变量列表')}}</label>
+      <t-input v-model="modelValue.name" :placeholder="$t('名称')"></t-input>
     </div>
 
     <div class="form-item mt-8">
-      <label>数据方式</label>
+      <label>{{$t('数据方式')}}</label>
       <t-radio-group v-model="modelValue.mode">
-        <t-radio value="api">HTTP请求</t-radio>
-        <t-radio value="">自定义</t-radio>
+        <t-radio value="api">HTTP{{$t('请求')}}</t-radio>
+        <t-radio value>{{$t('自定义')}}</t-radio>
       </t-radio-group>
     </div>
     <div v-if="modelValue.mode === 'api'" class="form-item mt-8">
-      <label>URL地址</label>
-      <t-input v-model="modelValue.url" @blur="getDatas" @enter="getDatas" />
+      <label>URL{{$t('地址')}}</label>
+      <t-input v-model="modelValue.url" @blur="getDatas" @enter="getDatas"></t-input>
     </div>
     <template v-else>
       <div class="form-item mt-8">
-        <label>从Excel导入</label>
+        <label>{{$t( '从Excel导入' )}}</label>
         <div class="flex middle w-full">
           <t-button
             class="shrink-0"
             style="width: 90px; height: 30px"
             @click="importDataset"
           >
-            导入Excel
+            {{$t( '导入Excel' )}}
           </t-button>
           <a
             :href="cdn ? cdn + '/v/data.xlsx' : '/data.xlsx'"
             download
             class="ml-12 mt-4 nowrap"
           >
-            下载Excel示例
+            {{$t( '下载Excel示例' )}}
           </a>
           <span class="flex-grow"></span>
-          <a class="ml-12 mt-4 nowrap" @click="showAddData()"> + 添加数据 </a>
+          <a class="ml-12 mt-4 nowrap" @click="showAddData()"> + {{$t('添加数据')}} </a>
         </div>
       </div>
     </template>
@@ -51,9 +51,8 @@
         {{ row.type || 'string' }}
       </template>
       <template v-if="!modelValue.mode" #actions="{ row, rowIndex }">
-        <edit-icon class="hover" @click="showAddData(row, rowIndex)"/>
-        <delete-icon class="ml-12 hover"
-          @click="modelValue.devices.splice(rowIndex, 1)"/>
+        <edit-icon class="hover" @click="showAddData(row, rowIndex)"></edit-icon>
+        <delete-icon class="ml-12 hover" @click="modelValue.devices.splice(rowIndex, 1)"></delete-icon>
         <!-- <t-icon name="edit" class="hover" @click="showAddData(row, rowIndex)" />
         <t-icon
           name="delete"
@@ -130,7 +129,7 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, reactive, ref } from 'vue';
+import { onBeforeMount, reactive, ref, getCurrentInstance } from 'vue';
 import axios from 'axios';
 import { MessagePlugin } from 'tdesign-vue-next';
 
@@ -145,36 +144,38 @@ const { modelValue } = defineProps<{
 }>();
 
 const emit = defineEmits(['update:modelValue', 'change']);
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 
 const datasetColumns = ref([
   // {
   //   colKey: 'device',
-  //   title: '设备',
+  //   title: $t('设备'),
   //   ellipsis: true,
   // },
   {
     colKey: 'label',
-    title: '显示名称',
+    title: $t('显示名称'),
     ellipsis: true,
   },
   {
     colKey: 'id',
-    title: '变量名',
+    title: $t('变量名'),
     ellipsis: true,
   },
   {
     colKey: 'type',
-    title: '类型',
+    title: $t('类型'),
     ellipsis: true,
   },
   {
     colKey: 'mock',
-    title: '值范围',
+    title: $t('值范围'),
     ellipsis: true,
   },
   {
     colKey: 'actions',
-    title: '操作',
+    title: $t('操作'),
     width: 100,
   },
 ]);
@@ -233,23 +234,23 @@ const flattenTree = (root) =>{
 const importDataset = async () => {
   let columns: any = [
     // {
-    //   header: '设备',
+    //   header: $t('设备'),
     //   key: 'device',
     // },
     {
-      header: '显示名称',
+      header: $t('显示名称'),
       key: 'label',
     },
     {
-      header: '变量名',
+      header: $t('变量名'),
       key: 'id',
     },
     {
-      header: '类型',
+      header: $t('类型'),
       key: 'type',
     },
     {
-      header: '值范围',
+      header: $t('值范围'),
       key: 'mock',
     },
   ];
@@ -261,11 +262,11 @@ const importDataset = async () => {
 
 const showAddData = (row?: any, index?: number) => {
   if (row) {
-    addDataDialog.header = '编辑数据';
+    addDataDialog.header = $t('编辑数据');
     addDataDialog.data = JSON.parse(JSON.stringify(row));
     addDataDialog.index = index;
   } else {
-    addDataDialog.header = '添加数据';
+    addDataDialog.header = $t('添加数据');
     addDataDialog.data = { type: 'string' };
   }
 
@@ -274,14 +275,14 @@ const showAddData = (row?: any, index?: number) => {
 
 const onOkAddData = () => {
   if (!addDataDialog.data.label) {
-    MessagePlugin.error('请填写名称');
+    MessagePlugin.error($t('请填写名称'));
     return;
   }
   if (!addDataDialog.data.id) {
-    MessagePlugin.error('请填写数据ID');
+    MessagePlugin.error($t('请填写数据ID'));
     return;
   }
-  if (addDataDialog.header === '添加数据') {
+  if (addDataDialog.header === $t('添加数据')) {
     modelValue.devices.push(addDataDialog.data);
   } else {
     modelValue.devices[addDataDialog.index] = addDataDialog.data;
@@ -306,12 +307,12 @@ const onOkAddData = () => {
 
 const changeDataID = (value) => {
   if (!value) {
-    MessagePlugin.error('变量名不能为空!');
+    MessagePlugin.error($t('变量名不能为空!'));
     return;
   }
   let item = modelValue.devices.filter((item) => item.id === value);
   if (item && item.length) {
-    MessagePlugin.error('变量名重复!');
+    MessagePlugin.error($t('变量名重复!'));
     return;
   }
   addDataDialog.data.id = value;

+ 16 - 40
src/views/components/ElementTree.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="elements">
-    <div class="title" style="margin: 8px 0 0 12px">视图结构</div>
+    <div class="title" style="margin: 8px 0 0 12px">{{$t('视图结构')}}</div>
 
     <t-tree
       class="flex-grow"
@@ -54,44 +54,23 @@
           style="width: 36px; height: 16px"
         >
           <t-tag theme="primary" variant="light-outline">
-            {{ node.data.tag }}</t-tag
-          >
-          <t-tooltip
-            class="mr-4"
-            v-if="!node.data.locked"
-            content="可编辑"
-            placement="top"
-          >
+            {{ node.data.tag }}</t-tag>
+          <t-tooltip class="mr-4" v-if="!node.data.locked" placement="top" :content="$t('可编辑')">
             <svg class="l-icon" aria-hidden="true" @click="lock(node, 1)">
               <use xlink:href="#l-unlock"></use>
             </svg>
           </t-tooltip>
-          <t-tooltip
-            class="mr-4"
-            v-else-if="node.data.locked == 1"
-            content="禁止编辑"
-            placement="top"
-          >
+          <t-tooltip class="mr-4" v-else-if="node.data.locked == 1" placement="top" :content="$t('禁止编辑')">
             <svg class="l-icon" aria-hidden="true" @click="lock(node, 2)">
               <use xlink:href="#l-lock"></use>
             </svg>
           </t-tooltip>
-          <t-tooltip
-            class="mr-4"
-            v-else-if="node.data.locked == 2"
-            content="禁止编辑和移动"
-            placement="top"
-          >
+          <t-tooltip class="mr-4" v-else-if="node.data.locked == 2" placement="top" :content="$t('禁止编辑和移动')">
             <svg class="l-icon" aria-hidden="true" @click="lock(node, 10)">
               <use xlink:href="#l-wufayidong"></use>
             </svg>
           </t-tooltip>
-          <t-tooltip
-            class="mr-4"
-            v-else-if="node.data.locked == 10"
-            content="禁止所有事件"
-            placement="top"
-          >
+          <t-tooltip class="mr-4" v-else-if="node.data.locked == 10" placement="top" :content="$t('禁止所有事件')">
             <svg class="l-icon" aria-hidden="true" @click="lock(node, 0)">
               <use xlink:href="#l-jinyong"></use>
             </svg>
@@ -109,8 +88,8 @@
     </t-tree>
     <div class="groups-panel" style="padding: 8px 0">
       <div class="flex middle between" style="padding: 0 12px">
-        <div class="title">分组</div>
-        <a @click="addGroup"> +新建分组</a>
+        <div class="title">{{$t('分组')}}</div>
+        <a @click="addGroup"> +{{$t('新建分组')}}</a>
       </div>
       <div class="groups">
         <div
@@ -144,14 +123,8 @@
             @click="visibleGroup(item, false)"
           />
           <t-icon v-else name="browse-off" @click="visibleGroup(item, true)" /> -->
-          <t-popconfirm
-            content="确认删除该分组吗?"
-            @confirm="delGroup"
-            @cancel="data.deleteGroup = undefined"
-          >
-            <delete-icon class="ml-8"
-              :class="{ block: i == data.deleteGroup }"
-              @click="data.deleteGroup = i"/>
+          <t-popconfirm @confirm="delGroup" @cancel="data.deleteGroup = undefined" :content="$t('确认删除该分组吗?')">
+            <delete-icon class="ml-8" :class="{ block: i == data.deleteGroup }" @click="data.deleteGroup = i"></delete-icon>
             <!-- <t-icon
               name="delete"
               class="ml-8"
@@ -166,7 +139,7 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, onMounted, onBeforeUnmount, reactive, ref } from 'vue';
+import { onBeforeMount, onMounted, onBeforeUnmount, reactive, ref, getCurrentInstance } from 'vue';
 import { MessagePlugin } from 'tdesign-vue-next';
 
 import { LockState, Pen } from '@meta2d/core';
@@ -180,6 +153,9 @@ const data = reactive<any>({
   groups: [],
   hiddenGroups: [],
 });
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
+
 
 onMounted(() => {
   meta2d.on('opened', getTree);
@@ -358,7 +334,7 @@ const onDescription = (node: any) => {
 
 const addGroup = () => {
   const i = data.groups.length + 1;
-  data.group = '组' + i;
+  data.group = $t('组') + i;
   data.groups.push(data.group);
   data.activedGroup = data.editedGroup = i;
 };
@@ -383,7 +359,7 @@ const setGroup = () => {
   }
 
   if (data.groups.includes(data.group)) {
-    MessagePlugin.error('已经存在相同分组!');
+    MessagePlugin.error($t('已经存在相同分组!'));
     return;
   }
 

+ 86 - 207
src/views/components/FileProps.vue

@@ -1,55 +1,25 @@
 <template>
   <div class="props">
     <t-tabs v-model="data.tab">
-      <t-tab-panel :value="1" label="画布">
+      <t-tab-panel :value="1" :label="$t('画布')">
         <t-space direction="vertical" size="small" class="panel">
           <div class="form-item">
-            <label>文件名</label>
-            <t-input
-              class="w-full"
-              placeholder="文件名"
-              :value="meta2dData.name"
-              @change="changeName($event, 'name')"
-            />
+            <label>{{$t('文件名')}}</label>
+            <t-input class="w-full" :value="meta2dData.name" @change="changeName($event, 'name')" :placeholder="$t('文件名')"></t-input>
           </div>
           <div class="form-item">
-            <label>分类</label>
-            <t-select
-              v-model="data.meta2dData.case"
-              @change="changeValue($event, 'case')"
-            >
+            <label>{{$t('分类')}}</label>
+            <t-select v-model="data.meta2dData.case" @change="changeValue($event, 'case')">
               <t-option v-for="_case in cases " :value="_case.value" :label="_case.label"> {{ _case.label }} </t-option>
             </t-select>
           </div>
           <t-divider style="margin-left: -16px;width: 120%; " />
           <div class="form-item">
-            <label>画布尺寸</label>
-            <t-input-number
-              label="W"
-              :value="data.meta2dData.width"
-              placeholder="宽"
-              theme="normal"
-              min="1"
-              style="width: 80px"
-              @change="changeValue($event, 'width')"
-            />
-            <t-input-number
-              class="ml-8"
-              label="H"
-              placeholder="高"
-              theme="normal"
-              min="1"
-              :value="data.meta2dData.height"
-              style="width: 80px"
-              @change="changeValue($event, 'height')"
-            />
-            <t-dropdown
-              :minColumnWidth="180"
-              :maxHeight="500"
-              :delay2="[10, 150]"
-              overlayClassName="header-dropdown"
-            >
-              <more-icon class="ml-8 hover"/>
+            <label>{{$t('画布尺寸')}}</label>
+            <t-input-number label="W" :value="data.meta2dData.width" theme="normal" min="1" style="width: 80px" @change="changeValue($event, 'width')" :placeholder="$t('宽')"></t-input-number>
+            <t-input-number class="ml-8" label="H" theme="normal" min="1" :value="data.meta2dData.height" style="width: 80px" @change="changeValue($event, 'height')" :placeholder="$t('高')"></t-input-number>
+            <t-dropdown :minColumnWidth="180" :maxHeight="500" :delay2="[10, 150]" overlayClassName="header-dropdown">
+              <more-icon class="ml-8 hover"></more-icon>
               <!-- <t-icon name="more" class="ml-8 hover" /> -->
               <t-dropdown-menu>
                 <t-dropdown-item
@@ -70,103 +40,45 @@
           </div>
 
           <div class="form-item">
-            <label>背景颜色</label>
-            <t-color-picker
-              class="w-full"
-              format="CSS"
-              :recent-colors="null"
-              :enable-alpha="true"
-              :swatch-colors="defaultPureColor"
-              :color-modes="['monochrome']"
-              :show-primary-color-preview="false"
-              v-model="data.meta2dData.background"
-              @change="changeValue($event, 'background')"
-            />
+            <label>{{$t('背景颜色')}}</label>
+            <t-color-picker class="w-full" format="CSS" :recent-colors="null" :enable-alpha="true" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.meta2dData.background" @change="changeValue($event, 'background')"></t-color-picker>
           </div>
           <div class="form-item">
-            <label>背景图片</label>
-            <t-upload
-              class="ml-8"
-              v-model="data.background"
-              action="/api/image/upload"
-              theme="image"
-              accept="image/*"
-              :headers="headers"
-              :data="updataData"
-              :auto-upload="true"
-              :before-upload="beforeUpload"
-              :upload-all-files-in-one-request="false"
-              @success="fileSuccessed"
-              @remove="fileRemoved"
-            />
+            <label>{{$t('背景图片')}}</label>
+            <t-upload class="ml-8" v-model="data.background" action="/api/image/upload" theme="image" accept="image/*" :headers="headers" :data="updataData" :auto-upload="true" :before-upload="beforeUpload" :upload-all-files-in-one-request="false" @success="fileSuccessed" @remove="fileRemoved"></t-upload>
           </div>
           <div class="form-item">
-            <label>主题</label>
-            <t-select
-              v-model="data.theme"
-              placeholder="暗黑"
-              :options="themeOptions"
-              @change="changeTheme"
-              clearable
-              class="shrink-0"
-            />
+            <label>{{$t('主题')}}</label>
+            <t-select v-model="data.theme" :options="themeOptions" @change="changeTheme" clearable class="shrink-0" :placeholder="$t('暗黑')"></t-select>
           </div>
         </t-space>
         <t-space direction="vertical" size="small" class="mt-8">
-          <t-collapse
-            :defaultValue="['1', '2','3']"
-            expandIconPlacement="right"
-            :borderless="true"
-          >
-            <t-collapse-panel value="1" header="预览设置">
+          <t-collapse :defaultValue="['1', '2','3']" expandIconPlacement="right" :borderless="true">
+            <t-collapse-panel value="1" :header="$t('预览设置')">
               <t-space direction="vertical" size="small">
                 <div class="form-item">
-                  <label>缩放方式</label>
-                  <t-radio-group
-                    class="ml-8"
-                    v-model="data.meta2dData.scaleMode"
-                    @change="changeValue($event, 'scaleMode')"
-                  >
-                    <t-radio
-                      value="1"
-                      title="宽高中较小的铺满"
-                      style="width: 200px"
-                    >
-                      自动铺满
+                  <label>{{$t('缩放方式')}}</label>
+                  <t-radio-group class="ml-8" v-model="data.meta2dData.scaleMode" @change="changeValue($event, 'scaleMode')">
+                    <t-radio value="1" style="width: 200px" :title="$t('宽高中较小的铺满')">
+                      {{$t('自动铺满')}}
                     </t-radio>
-                    <t-radio
-                      value="2"
-                      title="高度等比例缩放"
-                      style="width: 200px"
-                    >
-                      宽度铺满
+                    <t-radio value="2" style="width: 200px" :title="$t('高度等比例缩放')">
+                      {{$t('宽度铺满')}}
                     </t-radio>
-                    <t-radio value="3" title="宽度等比例缩放">高度铺满</t-radio>
+                    <t-radio value="3" :title="$t('宽度等比例缩放')">{{$t('高度铺满')}}</t-radio>
                   </t-radio-group>
                 </div>
                 <div class="form-item">
-                  <label>显示滚动条</label>
-                  <t-checkbox
-                    v-model="data.meta2dData.scroll"
-                    @change="changeValue($event, 'scroll')"
-                    class="ml-8"
-                  />
+                  <label>{{$t('显示滚动条')}}</label>
+                  <t-checkbox v-model="data.meta2dData.scroll" @change="changeValue($event, 'scroll')" class="ml-8"></t-checkbox>
                 </div>
                 <div class="form-item">
-                  <label>禁止移动</label>
-                  <t-checkbox
-                    v-model="data.meta2dData.isDisableTranslate"
-                    @change="changeValue($event, 'isDisableTranslate')"
-                    class="ml-8"
-                  />
+                  <label>{{$t('禁止移动')}}</label>
+                  <t-checkbox v-model="data.meta2dData.isDisableTranslate" @change="changeValue($event, 'isDisableTranslate')" class="ml-8"></t-checkbox>
                 </div>
                 <div class="form-item">
-                  <label>禁止缩放</label>
-                  <t-checkbox
-                    v-model="data.meta2dData.isDisableScale"
-                    @change="changeValue($event, 'isDisableScale')"
-                    class="ml-8"
-                  />
+                  <label>{{$t('禁止缩放')}}</label>
+                  <t-checkbox v-model="data.meta2dData.isDisableScale" @change="changeValue($event, 'isDisableScale')" class="ml-8"></t-checkbox>
                 </div>
                 <!-- <template v-if="data.scroll">
                   <div class="form-item">
@@ -188,11 +100,11 @@
                 </template> -->
               </t-space>
             </t-collapse-panel>
-            <t-collapse-panel value="2" header="进阶设置">
+            <t-collapse-panel value="2" :header="$t('进阶设置')">
               <t-space direction="vertical" size="small">
                 <div class="form-item">
                   <label>
-                    图标URL
+                    {{$t('图标')}}URL
                     <span>
                       <!-- <label
                         class="vip-label"
@@ -222,17 +134,9 @@
                       </div>
                     </template>
                     <div class="flex middle">
-                      <t-input
-                        v-model="data.iconUrl"
-                        placeholder="Font class方式URL"
-                        style="width: 150px; margin-left: -8px"
-                      />
-                      <t-button
-                        variant="outline"
-                        style="padding: 4px 8px; margin-left: 8px"
-                        @click="addIconUrl"
-                      >
-                        添加
+                      <t-input v-model="data.iconUrl" style="width: 150px; margin-left: -8px" :placeholder="$t('Font class方式URL')"></t-input>
+                      <t-button variant="outline" style="padding: 4px 8px; margin-left: 8px" @click="addIconUrl">
+                        {{$t('添加')}}
                       </t-button>
                     </div>
                     <!-- <div v-else class="desc mt-4">
@@ -243,13 +147,9 @@
                   </div>
                 </div>
                 <div class="form-item">
-                  <label>初始化动作</label>
-                  <t-button
-                    variant="outline"
-                    style="padding: 0 4px; margin: 2px 8px"
-                    @click="showInitFnDialog"
-                  >
-                    <ellipsis-icon />
+                  <label>{{$t('初始化动作')}}</label>
+                  <t-button variant="outline" style="padding: 0 4px; margin: 2px 8px" @click="showInitFnDialog">
+                    <ellipsis-icon></ellipsis-icon>
                     <!-- <t-icon name="ellipsis" /> -->
                   </t-button>
                 </div>
@@ -265,58 +165,36 @@
                 </div> -->
               </t-space>
             </t-collapse-panel>
-            <t-collapse-panel value="3" header="辅助设置">
+            <t-collapse-panel value="3" :header="$t('辅助设置')">
               <t-space direction="vertical" size="small">
                 <div class="form-item">
-                  <label title="此功能仅对直线和折线有效">连线相交弯曲</label>
-                  <t-switch
-                      :value="extendData.lineIntersect"
-                      class="ml-8 mt-8"
-                      size="small"
-                      @change="changeLineIntersect"
-                    />
+                  <label :title="$t('此功能仅对直线和折线有效')">{{$t('连线相交弯曲')}}</label>
+                  <t-switch :value="extendData.lineIntersect" class="ml-8 mt-8" size="small" @change="changeLineIntersect"></t-switch>
                 </div>
               </t-space>
             </t-collapse-panel>
           </t-collapse>
         </t-space>
       </t-tab-panel>
-      <t-tab-panel v-if="isShow" :value="3" label="行为">
-        <GlobalStates />
+      <t-tab-panel v-if="isShow" :value="3" :label="$t('行为')">
+        <GlobalStates></GlobalStates>
       </t-tab-panel>
       <!-- <t-tab-panel :value="2" label="结构">
         <ElementTree />
       </t-tab-panel> -->
     </t-tabs>
-    <t-dialog
-      v-if="initFnDialog.show"
-      :visible="true"
-      header="初始化动作"
-      @confirm="onOkInitFn"
-      @close="initFnDialog.show = false"
-      :width="700"
-    >
-      <CodeEditor v-model="initFnDialog.data" style="height: 300px" />
+    <t-dialog v-if="initFnDialog.show" :visible="true" @confirm="onOkInitFn" @close="initFnDialog.show = false" :width="700" :header="$t('初始化动作')">
+      <CodeEditor v-model="initFnDialog.data" style="height: 300px"></CodeEditor>
     </t-dialog>
 
-    <t-dialog
-      v-if="dataTransformationDialog.show"
-      :visible="true"
-      header="数据监听"
-      @confirm="onOkDataTransformation"
-      @close="dataTransformationDialog.show = false"
-      :width="700"
-    >
-      <CodeEditor
-        v-model="dataTransformationDialog.data"
-        style="height: 300px"
-      />
+    <t-dialog v-if="dataTransformationDialog.show" :visible="true" @confirm="onOkDataTransformation" @close="dataTransformationDialog.show = false" :width="700" :header="$t('数据监听')">
+      <CodeEditor v-model="dataTransformationDialog.data" style="height: 300px"></CodeEditor>
     </t-dialog>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { onMounted, reactive, onUnmounted } from 'vue';
+import { onMounted, reactive, onUnmounted, getCurrentInstance } from 'vue';
 import { useUser } from '@/services/user';
 import { getCookie } from '@/services/cookie';
 // import ElementTree from './ElementTree.vue';
@@ -334,7 +212,8 @@ import GlobalStates from './GlobalStates.vue';
 const { getEnterprise } = useEnterprise();
 const { meta2dData, setMeta2dData } = useMeta2dData();
 const { extendData, setExtendData } = useExtendData();
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const headers = {
   Authorization: 'Bearer ' + (getCookie('token') || ''),
 };
@@ -355,74 +234,74 @@ const data = reactive<any>({
 
 const cases = [
   {
-    label:'智慧物联',
-    value:'智慧物联'
+    label:$t('智慧物联'),
+    value:$t('智慧物联')
   },
   {
-    label:'电力能源',
-    value:'电力能源'
+    label:$t('电力能源'),
+    value:$t('电力能源')
   },
   {
-    label:'智慧水务',
-    value:'智慧水务'
+    label:$t('智慧水务'),
+    value:$t('智慧水务')
   },
   {
-    label:'智慧工厂',
-    value:'智慧工厂'
+    label:$t('智慧工厂'),
+    value:$t('智慧工厂')
   },
   {
-    label:'智慧校园',
-    value:'智慧校园'
+    label:$t('智慧校园'),
+    value:$t('智慧校园')
   },
   {
-    label:'智慧园区',
-    value:'智慧园区'
+    label:$t('智慧园区'),
+    value:$t('智慧园区')
   },
   {
-    label:'智慧交通',
-    value:'智慧交通'
+    label:$t('智慧交通'),
+    value:$t('智慧交通')
   },
   {
-    label:'智慧城市',
-    value:'智慧城市'
+    label:$t('智慧城市'),
+    value:$t('智慧城市')
   },
   {
-    label:'智慧农业',
-    value:'智慧农业'
+    label:$t('智慧农业'),
+    value:$t('智慧农业')
   },
   {
-    label:'电信机房',
-    value:'电信机房'
+    label:$t('电信机房'),
+    value:$t('电信机房')
   },
   {
-    label:'航空航天',
-    value:'航空航天'
+    label:$t('航空航天'),
+    value:$t('航空航天')
   },
   {
-    label:'智能家居',
-    value:'智能家居'
+    label:$t('智能家居'),
+    value:$t('智能家居')
   }
 ];
 
 const themeOptions = [
   {
-    label: '暗黑',
+    label: $t('暗黑'),
     value: 'dark',
   },
   {
-    label: '明亮',
+    label: $t('明亮'),
     value: 'light',
   },
 ];
 
 const screenList = reactive([
   {
-    name: '大屏',
+    name: $t('大屏'),
     width: 1920,
     height: 1080,
   },
   {
-    name: '网页',
+    name: $t('网页'),
     width: 1440,
     height: 1024,
   },
@@ -437,27 +316,27 @@ const screenList = reactive([
     height: 1194,
   },
   {
-    name: '平板Mini',
+    name: $t('平板Mini'),
     width: 768,
     height: 1024,
   },
   {
-    name: '华为P8',
+    name: $t('华为P8'),
     width: 360,
     height: 640,
   },
   {
-    name: '华为P40',
+    name: $t('华为P40'),
     width: 395,
     height: 856,
   },
   {
-    name: '手机1',
+    name: $t('手机1'),
     width: 430,
     height: 932,
   },
   {
-    name: '手机2',
+    name: $t('手机2'),
     width: 375,
     height: 812,
   },
@@ -484,7 +363,7 @@ const selectedSreen = (item: any) => {
 
 const beforeUpload = (file: any) => {
   if (!(user && user.id)) {
-    MessagePlugin.warning('请先登录!');
+    MessagePlugin.warning($t('请先登录!'));
     return false;
   }
   return true;
@@ -601,7 +480,7 @@ const onOkDataTransformation = () => {
 
 const addIconUrl = () => {
   if (!data.iconUrl || data.iconUrl.substr(-4) !== '.css') {
-    MessagePlugin.error('请填写以.css结尾的font-class引用方式的URL地址');
+    MessagePlugin.error($t('请填写以.css结尾的font-class引用方式的URL地址'));
     return;
   }
   if (!data.meta2dData.iconUrls) {

+ 25 - 58
src/views/components/FitProps.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="props">
     <t-tabs v-model="data.tab">
-      <t-tab-panel :value="1" label="布局容器">
+      <t-tab-panel :value="1" :label="$t('布局容器')">
         <t-space direction="vertical" class="py-16 w-full">
           <div class="form-item px-12">
             <label style="width: 67px">ID</label>
@@ -10,96 +10,63 @@
             </div>
           </div>
           <div class="form-item px-12" style="margin-top: -12px">
-            <label style="width: 50px">名称</label>
+            <label style="width: 50px">{{$t('名称')}}</label>
             <div style="padding-left: 8px; line-height: 30px">
-              <t-input
-                class="ml-8"
-                v-model="data.fit.name"
-                placeholder="默认0"
-              />
+              <t-input class="ml-8" v-model="data.fit.name" :placeholder="$t('默认0')"></t-input>
             </div>
           </div>
           <div class="form-item px-12">
-            <label>靠左</label>
+            <label>{{$t('靠左')}}</label>
             <div class="flex center" style="align-items: center">
-              <t-switch size="small" v-model="data.fit.left" />
-              <t-input-number
-                theme="normal"
-                class="ml-8"
-                @change="onFitChange"
-                v-model="data.fit.leftValue"
-                placeholder="默认0"
-              />
+              <t-switch size="small" v-model="data.fit.left"></t-switch>
+              <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.leftValue" :placeholder="$t('默认0')"></t-input-number>
             </div>
           </div>
           <div class="form-item px-12">
-            <label>靠右</label>
+            <label>{{$t('靠右')}}</label>
             <div class="flex center" style="align-items: center">
-              <t-switch size="small" v-model="data.fit.right" />
-              <t-input-number
-                theme="normal"
-                class="ml-8"
-                @change="onFitChange"
-                v-model="data.fit.rightValue"
-                placeholder="默认0"
-              />
+              <t-switch size="small" v-model="data.fit.right"></t-switch>
+              <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.rightValue" :placeholder="$t('默认0')"></t-input-number>
             </div>
           </div>
           <div class="form-item px-12">
-            <label>靠上</label>
+            <label>{{$t('靠上')}}</label>
             <div class="flex center" style="align-items: center">
-              <t-switch size="small" v-model="data.fit.top" />
-              <t-input-number
-                theme="normal"
-                class="ml-8"
-                @change="onFitChange"
-                v-model="data.fit.topValue"
-                placeholder="默认0"
-              />
+              <t-switch size="small" v-model="data.fit.top"></t-switch>
+              <t-input-number theme="normal" class="ml-8" @change="onFitChange" v-model="data.fit.topValue" :placeholder="$t('默认0')"></t-input-number>
             </div>
           </div>
           <div class="form-item px-12">
-            <label>靠下</label>
+            <label>{{$t('靠下')}}</label>
             <div class="flex center" style="align-items: center">
-              <t-switch size="small" v-model="data.fit.bottom" />
-              <t-input-number
-                theme="normal"
-                class="ml-8"
-                v-model="data.fit.bottomValue"
-                @change="onFitChange"
-                placeholder="默认0"
-              />
+              <t-switch size="small" v-model="data.fit.bottom"></t-switch>
+              <t-input-number theme="normal" class="ml-8" v-model="data.fit.bottomValue" @change="onFitChange" :placeholder="$t('默认0')"></t-input-number>
             </div>
           </div>
           <div class="form-item px-12">
-            <label>展示图元</label>
+            <label>{{$t('展示图元')}}</label>
             <div>
-              <t-switch size="small" @change="fitPenVisible" />
+              <t-switch size="small" @change="fitPenVisible"></t-switch>
             </div>
           </div>
           <div class="px-12">
-            <div class="mb-8">图元列表</div>
+            <div class="mb-8">{{$t('图元列表')}}</div>
             <div class="grid head">
-              <div class="title">名称</div>
-              <div class="title">图元id</div>
-              <div class="title">操作</div>
+              <div class="title">{{$t('名称')}}</div>
+              <div class="title">{{$t('图元')}}id</div>
+              <div class="title">{{$t('操作')}}</div>
             </div>
             <div class="body">
-              <div
-                :data-penid="item.value"
-                v-for="(item, i) in data.list"
-                class="grid"
-                :class="data.active.includes(item.value) ? 'active' : ''"
-              >
+              <div :data-penid="item.value" v-for="(item, i) in data.list" class="grid" :class="data.active.includes(item.value) ? 'active' : ''">
                 <span class="hover" @click="doActive(item.value)">
                   {{ item.label }}
                 </span>
                 <span class="hover" @click="doActive(item.value)">
                   {{ item.value }}
                 </span>
-                <t-popconfirm content="确认移除吗" @confirm="doRemove(i)">
-                  <t-tooltip content="从布局容器中移除此图元">
-                    <div class="hover"><delete-icon /></div>
+                <t-popconfirm @confirm="doRemove(i)" :content="$t('确认移除吗')">
+                  <t-tooltip :content="$t('从布局容器中移除此图元')">
+                    <div class="hover"><delete-icon></delete-icon></div>
                   </t-tooltip>
                 </t-popconfirm>
               </div>

+ 57 - 106
src/views/components/GlobalStates.vue

@@ -1,39 +1,31 @@
 <template>
   <div class="props">
-    <t-collapse
-      :borderless="true"
-      :expand-on-row-click="false"
-      v-model="openedCollapses"
-    >
+    <t-collapse :borderless="true" :expand-on-row-click="false" v-model="openedCollapses">
       <t-collapse-panel v-for="(trigger, i) in data.triggers" :value="i + 1">
         <template #header>
-          <t-input v-model="trigger.name" class="mr-12" />
+          <t-input v-model="trigger.name" class="mr-12"></t-input>
         </template>
         <template #headerRightContent>
-          <t-popconfirm
-            content="确认删除该行为吗?"
-            @confirm="data.triggers.splice(i, 1)"
-            :popup-props="{ placement: 'left' }"
-          >
-            <delete-icon class="hover" />
+          <t-popconfirm @confirm="data.triggers.splice(i, 1)" :popup-props="{ placement: 'left' }" :content="$t('确认删除该行为吗?')">
+            <delete-icon class="hover"></delete-icon>
           </t-popconfirm>
         </template>
         <section>
           <div class="form-item banner">
-            <label>触发条件</label>
+            <label>{{$t('触发条件')}}</label>
             <div class="w-full flex middle between">
               <div></div>
               <t-radio-group v-model="trigger.conditionType">
-                <t-radio value="and"> 满足全部条件 </t-radio>
-                <t-radio value="or"> 满足任意条件 </t-radio>
+                <t-radio value="and"> {{$t('满足全部条件')}} </t-radio>
+                <t-radio value="or"> {{$t('满足任意条件')}} </t-radio>
               </t-radio-group>
             </div>
           </div>
           <div v-for="(c, index) in trigger.conditions" class="mb-12">
             <div class="flex middle between head">
               <div class="flex middle">
-                <arrow-right-icon class="mr-4" />
-                条件{{ index + 1 }}
+                <arrow-right-icon class="mr-4"></arrow-right-icon>
+{{$t('                条件')}}{{ index + 1 }}
               </div>
               <close-icon
                 class="hover"
@@ -42,26 +34,19 @@
             </div>
             <div class="py-4">
               <div class="form-item mt-8">
-                <label>对象</label>
-                <t-tree-select
-                  v-model="c.source"
-                  :data="penTree"
-                  filterable
-                  placeholder="对象"
-                  class="shrink-0"
-                  @change="onChangeTriggerTarget(c)"
-                />
+                <label>{{$t('对象')}}</label>
+                <t-tree-select v-model="c.source" :data="penTree" filterable class="shrink-0" @change="onChangeTriggerTarget(c)" :placeholder="$t('对象')"></t-tree-select>
               </div>
               <div class="form-item mt-4">
-                <label>条件类型</label>
+                <label>{{$t('条件类型')}}</label>
                 <t-radio-group v-model="c.type">
-                  <t-radio value=""> 关系条件 </t-radio>
-                  <t-radio value="fn"> 高级条件 </t-radio>
+                  <t-radio value=""> {{$t( '关系条件' )}} </t-radio>
+                  <t-radio value="fn"> {{$t( '高级条件' )}} </t-radio>
                 </t-radio-group>
               </div>
               <template v-if="!c.type">
                 <div class="form-item mt-8">
-                  <label>属性名</label>
+                  <label>{{$t( '属性名' )}}</label>
                   <t-select-input
                     v-model:inputValue="c.key"
                     :value="c.keyLabel"
@@ -93,66 +78,30 @@
                   </t-select-input>
                 </div>
                 <div class="form-item mt-8">
-                  <label>关系运算</label>
-                  <t-select
-                    v-model="c.operator"
-                    placeholder="关系运算"
-                    :options="operatorOptions"
-                    clearable
-                    class="shrink-0"
-                  />
+                  <label>{{$t('关系运算')}}</label>
+                  <t-select v-model="c.operator" :options="operatorOptions" clearable class="shrink-0" :placeholder="$t('关系运算')"></t-select>
                 </div>
                 <div class="form-item mt-8">
-                  <label>运算对象</label>
-                  <t-select
-                    v-model="c.valueType"
-                    class="shrink-0"
-                    placeholder="固定值"
-                  >
-                    <t-option key="" value="" label="固定值"> 固定值 </t-option>
-                    <t-option key="prop" value="prop" label="对象属性值">
-                      对象属性值
+                  <label>{{$t('运算对象')}}</label>
+                  <t-select v-model="c.valueType" class="shrink-0" :placeholder="$t('固定值')">
+                    <t-option key value :label="$t('固定值')"> {{$t('固定值')}} </t-option>
+                    <t-option key="prop" value="prop" :label="$t('对象属性值')">
+                      {{$t('对象属性值')}}
                     </t-option>
                   </t-select>
                 </div>
-                <div
-                  v-if="!c.valueType"
-                  class="form-item mt-8 form-item-valueType"
-                >
-                  <label>值</label>
-                  <t-input
-                    v-model="c.value"
-                    @change="valueChange($event, c)"
-                    class="shrink-0"
-                    style="width: 320px"
-                  />
+                <div v-if="!c.valueType" class="form-item mt-8 form-item-valueType">
+                  <label>{{$t('值')}}</label>
+                  <t-input v-model="c.value" @change="valueChange($event, c)" class="shrink-0" style="width: 320px"></t-input>
                 </div>
                 <template v-else>
                   <div class="form-item mt-8">
-                    <label>对象</label>
-                    <t-tree-select
-                      v-model="c.target"
-                      :data="penTree"
-                      filterable
-                      placeholder="对象"
-                      class="shrink-0"
-                      @change="onChangeTriggerTarget(c)"
-                    />
+                    <label>{{$t('对象')}}</label>
+                    <t-tree-select v-model="c.target" :data="penTree" filterable class="shrink-0" @change="onChangeTriggerTarget(c)" :placeholder="$t('对象')"></t-tree-select>
                   </div>
                   <div class="form-item mt-8">
-                    <label>属性</label>
-                    <t-select-input
-                      v-model:inputValue="c.value"
-                      :value="c.label"
-                      v-model:popupVisible="c.popupVisible"
-                      allow-input
-                      clearable
-                      @clear="c.label = undefined"
-                      @focus="c.popupVisible = true"
-                      @blur="c.popupVisible = false"
-                      @input-change="onInput(c)"
-                      class="shrink-0"
-                    >
+                    <label>{{$t('属性')}}</label>
+                    <t-select-input v-model:inputValue="c.value" :value="c.label" v-model:popupVisible="c.popupVisible" allow-input clearable @clear="c.label = undefined" @focus="c.popupVisible = true" @blur="c.popupVisible = false" @input-change="onInput(c)" class="shrink-0">
                       <template #panel>
                         <ul style="padding: 8px 12px">
                           <li
@@ -184,11 +133,11 @@
             </div>
           </div>
           <div class="mt-8">
-            <a @click="addTriggerCondition(trigger)"> + 添加条件 </a>
+            <a @click="addTriggerCondition(trigger)"> + {{$t('添加条件')}} </a>
           </div>
 
           <div class="form-item banner mt-16">
-            <label>执行动作</label>
+            <label>{{$t('执行动作')}}</label>
           </div>
           <Actions class="mt-8" :data="trigger" />
         </section>
@@ -198,8 +147,8 @@
     <div class="mt-8 ml-16">
       <!-- <a @click="onAddTrigger"> + 添加行为 </a> -->
       <t-button @click="onAddTrigger" style="width: 90%;" variant="outline">
-        <template #icon><add-icon /></template>
-        添加行为
+        <template #icon><add-icon></add-icon></template>
+        {{$t('添加行为')}}
       </t-button>
     </div>
   </div>
@@ -228,6 +177,8 @@ onBeforeMount(() => {
 const data = reactive({
   triggers: [],
 });
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 
 onMounted(() => {
   const d = meta2d.store.data as any;
@@ -258,8 +209,8 @@ const operatorOptions = ref<any>([
   { label: '<', value: '<' },
   { label: '>=', value: '>=' },
   { label: '<=', value: '<=' },
-  { label: '包含', value: '[)' },
-  { label: '不包含', value: '![)' },
+  { label: $t('包含'), value: '[)' },
+  { label: $t('不包含'), value: '![)' },
 ]);
 
 const cProps = [
@@ -273,51 +224,51 @@ const cProps = [
   },
   {
     value: 'width',
-    label: '宽',
+    label: $t('宽'),
   },
   {
     value: 'height',
-    label: '高',
+    label: $t('高'),
   },
   {
     value: 'visible',
-    label: '显示',
+    label: $t('显示'),
   },
   {
     value: 'text',
-    label: '文字',
+    label: $t('文字'),
   },
   {
     value: 'color',
-    label: '颜色',
+    label: $t('颜色'),
   },
   {
     value: 'background',
-    label: '背景颜色',
+    label: $t('背景颜色'),
   },
   {
     value: 'progress',
-    label: '进度',
+    label: $t('进度'),
   },
   {
     value: 'progressColor',
-    label: '进度颜色',
+    label: $t('进度颜色'),
   },
   {
     value: 'showChild',
-    label: '状态',
+    label: $t('状态'),
   },
   {
     value: 'rotate',
-    label: '旋转',
+    label: $t('旋转'),
   },
   {
     value: 'disabled',
-    label: '禁用',
+    label: $t('禁用'),
   },
   {
     value: 'selectedKey',
-    label: '单选选中值',
+    label: $t('单选选中值'),
   }
 ];
 
@@ -338,31 +289,31 @@ const onChangeTriggerTarget = (c: any) => {
     },
     {
       value: 'width',
-      label: '宽',
+      label: $t('宽'),
     },
     {
       value: 'height',
-      label: '高',
+      label: $t('高'),
     },
     {
       value: 'visible',
-      label: '显示',
+      label: $t('显示'),
     },
     {
       value: 'text',
-      label: '文字',
+      label: $t('文字'),
     },
     {
       value: 'progress',
-      label: '进度',
+      label: $t('进度'),
     },
     {
       value: 'showChild',
-      label: '状态',
+      label: $t('状态'),
     },
     {
       value: 'rotate',
-      label: '旋转',
+      label: $t('旋转'),
     },
   ];*/
 
@@ -403,7 +354,7 @@ const codeChange = (e: any, a: any) => {
 const onAddTrigger = () => {
   const i = data.triggers.length;
   data.triggers.push({
-    name: `行为${i + 1}`,
+    name: $t('行为')+ (i + 1),
     conditionType: 'and',
     conditions: [],
     actions: [],

+ 18 - 18
src/views/components/Graphics.vue

@@ -6,10 +6,10 @@
         @change="assetsChange"
         variant="primary-filled"
       >
-        <t-radio-button value="system">系统资源</t-radio-button>
-        <t-radio-button value="user">我的资源</t-radio-button>
-        <t-radio-button value="data">数据</t-radio-button>
-        <t-radio-button value="structure">结构</t-radio-button>
+        <t-radio-button value="system">{{$t( '系统资源' )}}</t-radio-button>
+        <t-radio-button value="user">{{$t( '我的资源' )}}</t-radio-button>
+        <t-radio-button value="data">{{$t( '数据' )}}</t-radio-button>
+        <t-radio-button value="structure">{{$t( '结构' )}}</t-radio-button>
       </t-radio-group>
     </div>
     <div class="groups-panel">
@@ -56,11 +56,11 @@
             v-model="search"
             @change="onSearch"
             @enter="onSearch"
-            placeholder="搜索"
+            :placeholder="$t('搜索')"
           />
 
           <div class="ml-16">
-            <t-tooltip content="展开/折叠">
+            <t-tooltip :content="$t('展开/折叠')">
               <menu-fold-icon class="hover"
                 style="font-size: 16px"
                 @click="onFold"/>
@@ -74,7 +74,7 @@
           </div>
         </div>
         <div v-if="loading" class="center mt-16">
-          <t-loading text="加载中..." size="small" :indicator="false" />
+          <t-loading :text="$t('加载中...')" size="small" :indicator="false" />
         </div>
         <template v-else>
           <div
@@ -85,7 +85,7 @@
             "
             class="px-16 mt-12 mb-8 ml-4"
           >
-            <a @click="onCreateFolder">+ 新建文件夹</a>
+            <a @click="onCreateFolder">+ {{$t( '新建文件夹' )}}</a>
           </div>
           <t-collapse v-model="activedPanels[activedGroup]">
             <t-collapse-panel
@@ -149,7 +149,7 @@
                       @click="onEditHeader(item)"
                     /> -->
                     <t-popconfirm
-                      content="确认删除该文件夹吗"
+                      :content="$t('确认删除该文件夹吗')"
                       placement="left"
                       @confirm="delFolder(item)"
                     >
@@ -195,7 +195,7 @@
                 class="gray"
                 style="white-space: nowrap; margin-left: 34px"
               >
-                暂无数据
+                {{$t( '暂无数据' )}}
               </div>
             </t-collapse-panel>
           </t-collapse>
@@ -229,7 +229,7 @@
       >
         <t-submenu
           value="move"
-          title="移动到"
+          :title="$t('移动到')"
           v-if="contextmenu.subMenus.length"
           :disabled="contextmenu.component['3d']"
         >
@@ -254,10 +254,10 @@
           </t-menu-item>
         </t-submenu>
         <t-menu-item value="edit" :disabled="activedGroup === '图片'">
-          编辑
+          {{$t( '编辑' )}}
         </t-menu-item>
         <t-menu-item value="del" :disabled="contextmenu.component['3d']">
-          删除
+          {{$t( '删除' )}}
         </t-menu-item>
       </t-menu>
     </div>
@@ -265,12 +265,12 @@
     <t-dialog
       v-if="delDialog.show"
       theme="danger"
-      header="删除"
+      :header="$t('删除')"
       :visible="true"
       @close="delDialog.show = false"
       @confirm="delComponent"
     >
-      {{current?'检测到该图纸正在被编辑,':''}}确定删除该数据吗?{{current?'画布将被清空,':''}}删除后不可恢复!
+      {{current?$t('检测到该图纸正在被编辑,'):''}}{{$t( '确定删除该数据吗?' )}}{{current?$t('画布将被清空,'):''}}{{$t( '删除后不可恢复!' )}}
     </t-dialog>
     <!-- <t-dialog
       v-if="chargeDialog.show"
@@ -317,11 +317,11 @@
       v-if="wechatPayDialog.show"
       v-model:visible="wechatPayDialog.show"
       class="pay-dialog"
-      header="乐吾乐收银台"
+      :header="$t('乐吾乐收银台')"
       :close-on-overlay-click="false"
       :top="95"
       :width="700"
-      confirm-btn="支付完成"
+      :confirm-btn="$t('支付完成')"
       :cancel-btn="null"
       @close="getPayResult"
       :footer="false"
@@ -376,7 +376,7 @@
               class="gray"
               style="white-space: nowrap; margin-left: 34px"
             >
-              暂无数据
+              {{$t( '暂无数据' )}}
             </div>
           </t-collapse-panel>
         </t-collapse>

+ 113 - 109
src/views/components/Header.vue

@@ -1,43 +1,37 @@
 <template>
   <div class="app-header">
     <a class="logo" :href="enterprise.home" target="_blank">
-      <img src="/favicon.ico" />
-      <span> {{ enterprise.name }}</span>
+      <img src="/favicon.ico">
+      <span> {{ $t(enterprise.name) }}</span>
     </a>
-    <t-dropdown
-      :minColumnWidth="200"
-      :maxHeight="560"
-      :delay2="[10, 150]"
-      overlayClassName="header-dropdown"
-      trigger1="click"
-    >
-      <a> 文件 </a>
+    <t-dropdown :minColumnWidth="200" :maxHeight="560" :delay2="[10, 150]" overlayClassName="header-dropdown" trigger1="click">
+      <a> {{$t('文件')}} </a>
       <t-dropdown-menu>
         <t-dropdown-item @click="newFile">
-          <a>新建文件</a>
+          <a>{{$t('新建文件')}}</a>
         </t-dropdown-item>
         <t-dropdown-item @click="load(true)">
-          <a>打开文件</a>
+          <a>{{$t('打开文件')}}</a>
         </t-dropdown-item>
         <t-dropdown-item divider="true" @click="load()">
-          <a>导入文件</a>
+          <a>{{$t('导入文件')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="save(SaveType.Save,'',true)">保存</a>
+          <a @click="save(SaveType.Save,'',true)">{{$t('保存')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="save(SaveType.SaveAs, '', true, 1)">另存为</a>
+          <a @click="save(SaveType.SaveAs, '', true, 1)">{{$t('另存为')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="save(SaveType.Save, '', true, undefined, true)">仅保存JSON数据</a>
+          <a @click="save(SaveType.Save, '', true, undefined, true)">{{$t('仅保存')}}JSON{{$t('数据')}}</a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
-          <a @click="downloadJson">下载JSON文件</a>
+          <a @click="downloadJson">{{$t('下载')}}JSON{{$t('文件')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="downloadZip">
             <div class="flex">
-              导出为ZIP文件 <span class="flex-grow"></span>
+              {{$t('导出为')}}ZIP{{$t('文件')}} <span class="flex-grow"></span>
               <!-- <span><label>VIP</label></span> -->
             </div>
           </a>
@@ -45,7 +39,7 @@
         <t-dropdown-item>
           <a @click="downloadHtml">
             <div class="flex">
-              下载离线部署包 <span class="flex-grow"></span>
+              {{$t('下载离线部署包')}} <span class="flex-grow"></span>
               <!-- <span><label>企</label></span> -->
             </div>
           </a>
@@ -53,7 +47,7 @@
         <t-dropdown-item>
           <a @click="downloadVue3">
             <div class="flex">
-              下载Vue3组件包 <span class="flex-grow"></span>
+              {{$t('下载')}}Vue3{{$t('组件包')}} <span class="flex-grow"></span>
               <!-- <span><label>企</label></span> -->
             </div>
           </a>
@@ -61,7 +55,7 @@
         <t-dropdown-item>
           <a @click="downloadVue2">
             <div class="flex">
-              下载Vue2组件包 <span class="flex-grow"></span>
+              {{$t('下载')}}Vue2{{$t('组件包')}} <span class="flex-grow"></span>
               <!-- <span><label>企</label></span> -->
             </div>
           </a>
@@ -69,135 +63,125 @@
         <t-dropdown-item divider="true">
           <a @click="downloadReact">
             <div class="flex">
-              下载React组件包 <span class="flex-grow"></span>
+              {{$t('下载')}}React{{$t('组件包')}} <span class="flex-grow"></span>
               <!-- <span><label>企</label></span> -->
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="downloadPng">下载为PNG</a>
+          <a @click="downloadPng">{{$t('下载为')}}PNG</a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
-          <a @click="downloadSvg">下载为SVG</a>
+          <a @click="downloadSvg">{{$t('下载为')}}SVG</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="switchTheme('light')">明亮主题</a>
+          <a @click="switchTheme('light')">{{$t('明亮主题')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="switchTheme('dark')">暗黑主题</a>
+          <a @click="switchTheme('dark')">{{$t('暗黑主题')}}</a>
         </t-dropdown-item>
       </t-dropdown-menu>
     </t-dropdown>
-    <t-dropdown
-      :minColumnWidth="180"
-      :maxHeight="500"
-      :delay2="[10, 150]"
-      overlayClassName="header-dropdown"
-    >
-      <a> 编辑 </a>
+    <t-dropdown :minColumnWidth="180" :maxHeight="500" :delay2="[10, 150]" overlayClassName="header-dropdown">
+      <a> {{$t('编辑')}} </a>
       <t-dropdown-menu>
         <t-dropdown-item>
           <a @click="onUndo">
             <div class="flex">
-              撤销 <span class="flex-grow"></span> Ctrl + Z
+              {{$t('撤销')}} <span class="flex-grow"></span> Ctrl + Z
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
           <a @click="onRedo">
             <div class="flex">
-              重做 <span class="flex-grow"></span> Ctrl + Y
+              {{$t('重做')}} <span class="flex-grow"></span> Ctrl + Y
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="onCut">
             <div class="flex">
-              剪切 <span class="flex-grow"></span> Ctrl + X
+              {{$t('剪切')}} <span class="flex-grow"></span> Ctrl + X
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="onCopy">
             <div class="flex">
-              复制 <span class="flex-grow"></span> Ctrl + C
+              {{$t('复制')}} <span class="flex-grow"></span> Ctrl + C
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
           <a @click="onPaste">
             <div class="flex">
-              粘贴 <span class="flex-grow"></span> Ctrl + V
+              {{$t('粘贴')}} <span class="flex-grow"></span> Ctrl + V
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="onAll">
             <div class="flex">
-              全选 <span class="flex-grow"></span> Ctrl + A
+              {{$t('全选')}} <span class="flex-grow"></span> Ctrl + A
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="onDelete">
-            <div class="flex">删除 <span class="flex-grow"></span> DELETE</div>
+            <div class="flex">{{$t('删除')}} <span class="flex-grow"></span> DELETE</div>
           </a>
         </t-dropdown-item>
       </t-dropdown-menu>
     </t-dropdown>
-    <t-dropdown
-      :minColumnWidth="180"
-      :maxHeight="500"
-      :delay2="[10, 150]"
-      overlayClassName="header-dropdown"
-    >
-      <a> 工具 </a>
+    <t-dropdown :minColumnWidth="180" :maxHeight="500" :delay2="[10, 150]" overlayClassName="header-dropdown">
+      <a> {{$t('工具')}} </a>
       <t-dropdown-menu>
         <t-dropdown-item>
-          <a @click="onScaleWindow">窗口大小</a>
+          <a @click="onScaleWindow">{{$t('窗口大小')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="onScaleUp">放大</a>
+          <a @click="onScaleUp">{{$t('放大')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="onScaleDown">缩小</a>
+          <a @click="onScaleDown">{{$t('缩小')}}</a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
-          <a @click="onScaleFull">100%视图</a>
+          <a @click="onScaleFull">100%{{$t('视图')}}</a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="showMap">
             <div class="flex middle">
-              鹰眼地图 <span class="flex-grow"></span>
+              {{$t('鹰眼地图')}} <span class="flex-grow"></span>
               <!-- <t-icon v-show="map" name="check" /> -->
-              <check-icon v-show="map" />
+              <check-icon v-show="map"></check-icon>
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
           <a @click="showMagnifier">
             <div class="flex middle">
-              放大镜 <span class="flex-grow"></span>
+              {{$t('放大镜')}} <span class="flex-grow"></span>
               <!-- <t-icon v-show="magnifier" name="check" /> -->
-              <check-icon v-show="magnifier" />
+              <check-icon v-show="magnifier"></check-icon>
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a @click="onAutoAnchor">
             <div class="flex middle">
-              自动锚点 <span class="flex-grow"></span>
+              {{$t('自动锚点')}} <span class="flex-grow"></span>
               <!-- <t-icon v-show="autoAnchor" name="check" /> -->
-              <check-icon v-show="autoAnchor" />
+              <check-icon v-show="autoAnchor"></check-icon>
             </div>
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
           <a @click="onDisableAnchor">
             <div class="flex middle">
-              显示锚点 <span class="flex-grow"></span>
+              {{$t('显示锚点')}} <span class="flex-grow"></span>
               <!-- <t-icon v-show="showAnchor" name="check" /> -->
-              <check-icon v-show="showAnchor" />
+              <check-icon v-show="showAnchor"></check-icon>
             </div>
           </a>
         </t-dropdown-item>
@@ -207,9 +191,8 @@
               class="flex"
               :style="{
                 color: showAnchor ? '' : '#4f5b75',
-              }"
-            >
-              添加/删除锚点 <span class="flex-grow"></span> A
+              }">
+              {{$t('添加')}}/{{$t('删除锚点')}} <span class="flex-grow"></span> A
             </div>
           </a>
         </t-dropdown-item>
@@ -221,7 +204,7 @@
       :delay2="[10, 150]"
       overlayClassName="header-dropdown"
     >
-      <a> 帮助 </a>
+      <a> {{$t( '帮助' )}} </a>
       <t-dropdown-menu>
         <t-dropdown-item
           v-for="item in enterprise.helps_v"
@@ -232,28 +215,41 @@
       </t-dropdown-menu>
     </t-dropdown>
 
+    <t-dropdown
+        :minColumnWidth="180"
+        :maxHeight="500"
+        :delay2="[10, 150]"
+        overlayClassName="header-dropdown">
+      <a> {{$t('语言')}} </a>
+      <t-dropdown-menu>
+        <t-dropdown-item v-for="item in languages">
+          <div @click="changeLanguage(item.value)">{{ item.name }}</div>
+        </t-dropdown-item>
+      </t-dropdown-menu>
+    </t-dropdown>
+
     <!-- <div style="width: 148px; flex-shrink: 0"></div> -->
     <input v-model="meta2dData.name" @change="onInputName($event)" />
 
     <a :href="enterprise.account" target="_blank">
       <!-- <t-icon name="home" /> -->
-      <home-icon />
-      账户中心
+      <home-icon></home-icon>
+      {{$t('账户中心')}}
     </a>
     <a :href="enterprise['v']" target="_blank" class="active">
       <!-- <t-icon name="desktop" /> -->
-      <desktop-icon />
-      大屏可视化
+      <desktop-icon></desktop-icon>
+      {{$t('大屏可视化')}}
     </a>
     <a :href="enterprise['3d']" target="_blank">
       <!-- <t-icon name="control-platform" /> -->
-      <control-platform-icon />
-      3D可视化
+      <control-platform-icon></control-platform-icon>
+      3D{{$t('可视化')}}
     </a>
     <a :href="enterprise['2d']" target="_blank">
       <!-- <t-icon name="app" /> -->
-      <app-icon />
-      2D可视化
+      <app-icon></app-icon>
+      2D{{$t('可视化')}}
     </a>
     <t-dropdown
       v-if="user.id"
@@ -283,31 +279,31 @@
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
-          <a :href="`${enterprise.account}/v`" target="_blank"> 我的大屏 </a>
+          <a :href="`${enterprise.account}/v`" target="_blank"> {{$t('我的大屏')}} </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a :href="`${enterprise.account}/account/teams`" target="_blank">
-            我的团队
+            {{$t('我的团队')}}
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
           <a :href="`${enterprise.account}/account/info`" target="_blank">
-            账号信息
+            {{$t('账号信息')}}
           </a>
         </t-dropdown-item>
         <t-dropdown-item divider="true">
           <a :href="`${enterprise.account}/account/security`" target="_blank">
-            安全设置
+            {{$t('安全设置')}}
           </a>
         </t-dropdown-item>
         <t-dropdown-item>
-          <a @click="logout">退出</a>
+          <a @click="logout">{{$t('退出')}}</a>
         </t-dropdown-item>
       </t-dropdown-menu>
     </t-dropdown>
     <div class="flex middle" v-else>
       <a class="button primary solid" style="width: 80px" :href="login()">
-        登录
+        {{$t('登录')}}
       </a>
     </div>
   </div>
@@ -480,16 +476,8 @@
       @success="onSuccess"
     />
   </t-dialog> -->
-  <t-dialog
-    v-model:visible="newFileDialog.show"
-    header="提示"
-    confirm-btn="保存后新建"
-    cancel-btn="不保存直接新建"
-    @close="newFileDialog.show = false"
-    @confirm="saveNewfile"
-    @cancel="nosaveNewfile"
-  >
-    当前画布数据未保存,是否保存后新建?
+  <t-dialog v-model:visible="newFileDialog.show" @close="newFileDialog.show = false" @confirm="saveNewfile" @cancel="nosaveNewfile" :header="$t('提示')" :confirm-btn="$t('保存后新建')" :cancel-btn="$t('不保存直接新建')">
+    {{$t('当前画布数据未保存')}},{{$t('是否保存后新建')}}?
   </t-dialog>
 </template>
 
@@ -501,6 +489,7 @@ import {
   onUnmounted,
   nextTick,
   computed,
+  getCurrentInstance
 } from 'vue';
 import { useRouter, useRoute } from 'vue-router';
 import { useUser } from '@/services/user';
@@ -581,11 +570,15 @@ const route = useRoute();
 const { meta2dData, setMeta2dData } = useMeta2dData();
 const baseUrl = import.meta.env.BASE_URL || '/';
 // const { assets, getAssets } = useAssets();
+import {useI18n} from "vue-i18n";
 
 const { user, signout } = useUser();
 const { setDot, dot } = useDot();
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
+
 const data = reactive<any>({
-  name: '新建项目',
+  name: $t('新建项目'),
   order: {
     codeUrl: '',
     id: '', //订单id
@@ -607,7 +600,18 @@ const data = reactive<any>({
   },
   payGoods:{},
 });
-
+const { locale } = useI18n()
+const languages = [{
+  name:$t("简体中文"),value:"zh",
+},{
+  name:$t("繁体中文"),value:"zh_CHT",
+},{
+  name:"English",value:"en"
+}]
+function changeLanguage(v) {
+  locale.value = v
+  localStorage.setItem('i18n',v)
+}
 onBeforeMount(async () => {
   // getAssets();
   // getNetJsDiagram();
@@ -625,7 +629,7 @@ const onInputName = (e) => {
 
 const initMeta2dName = () => {
   data.name = (meta2d.store.data as Meta2dBackData).name || '';
-  setMeta2dData({ name: (meta2d.store.data as Meta2dBackData).name || '新建项目' });
+  setMeta2dData({ name: (meta2d.store.data as Meta2dBackData).name || $t('新建项目') });
 };
 
 let downloadList = new Set<any>();
@@ -762,7 +766,7 @@ function load(isNew = false) {
         }
       } else if (elem.files[0].name.endsWith('.svg')) {
         MessagePlugin.info(
-          '可二次编辑但转换存在损失,若作为图片使用,请使用右侧属性面板的上传图片功能'
+          $t('可二次编辑但转换存在损失,若作为图片使用,请使用右侧属性面板的上传图片功能')
         );
         openSvg(elem.files[0]);
       } else if (elem.files[0].name.endsWith('.zip')) {
@@ -779,7 +783,7 @@ function load(isNew = false) {
           openZip(elem.files[0]);
         }, 500);
       } else {
-        MessagePlugin.info('打开文件只支持 json,svg,zip 格式');
+        MessagePlugin.info($t('打开文件只支持 json,svg,zip 格式'));
       }
     }
   };
@@ -822,7 +826,7 @@ const openSvg = async (file: File) => {
   const text = await readFile(file);
   const pens: Pen[] = parseSvg(text);
   meta2d.canvas.addCaches = pens;
-  MessagePlugin.info('svg转换成功,请点击画布决定放置位置');
+  MessagePlugin.info($t('svg转换成功,请点击画布决定放置位置'));
 };
 
 const openZip = async (file: File) => {
@@ -836,11 +840,11 @@ const openZip = async (file: File) => {
   //   return;
   // }
   // if (!user.vip) {
-  //   MessagePlugin.info('需要开通会员~');
+  //   MessagePlugin.info($t('需要开通会员~'));
   //   gotoAccount();
   //   return;
   // }
-  MessagePlugin.loading('正在读取...',0);
+  MessagePlugin.loading($t('正在读取...'),0);
   const { default: JSZip } = await import('jszip');
   const zip = new JSZip();
   await zip.loadAsync(file,{base64:true});
@@ -863,7 +867,7 @@ const openZip = async (file: File) => {
   const imgReplaceArr = [];
   const _2dDataMap ={};
   const _3dDataMap ={};
-  MessagePlugin.loading('正在上传文件...',0);
+  MessagePlugin.loading($t('正在上传文件...'),0);
   for (const key in zip.files) {
     if (zip.files[key].dir) {
       continue;
@@ -938,7 +942,7 @@ const openZip = async (file: File) => {
           const ret:any = await addCollection('v',{
             data:idata,
             image:idata.image||'xxx',
-            name:idata.name||'新建项目',
+            name:idata.name||$t('新建项目'),
             folder:idata.folder,
             // userFlag:2,
             system:false,
@@ -997,7 +1001,7 @@ const openZip = async (file: File) => {
       dealDataBeforeOpen(data)
       meta2d.open(data);
       MessagePlugin.closeAll();
-      MessagePlugin.success('导入成功!');
+      MessagePlugin.success($t('导入成功!'));
     }
   } catch (e) {
     return false;
@@ -1015,7 +1019,7 @@ const _openZip = async (file: File) => {
   //   return;
   // }
   // if (!user.vip) {
-  //   MessagePlugin.info('需要开通普通会员~');
+  //   MessagePlugin.info($t('需要开通普通会员~'));
   //   gotoAccount();
   //   return;
   // }
@@ -1185,7 +1189,7 @@ const downloadZip = async () => {
   //   return;
   // }
   if(!meta2d.store.data.pens.length){
-    MessagePlugin.info('画布没有画笔!');
+    MessagePlugin.info($t('画布没有画笔!'));
     return;
   }
   // if (!user.vip) {
@@ -1345,7 +1349,7 @@ const preDoDownloadZip = async ()=>{
 
 const doDownloadZip = async ()=>{
   // downloadZipDialog.show = false;
-  MessagePlugin.info('正在下载打包中,可能需要几分钟,请耐心等待...',0);
+  MessagePlugin.info($t('正在下载打包中,可能需要几分钟,请耐心等待...'),0);
   const [{ default: JSZip }, { saveAs }] = await Promise.all([
     import('jszip'),
     import('file-saver'),
@@ -1384,7 +1388,7 @@ const doDownloadZip = async ()=>{
   const blob = await zip.generateAsync({ type: 'blob' });
   saveAs(blob, `${_fileName}.zip`);
   MessagePlugin.closeAll();
-  MessagePlugin.success('下载成功,请在浏览器下载列表中查看');
+  MessagePlugin.success($t('下载成功,请在浏览器下载列表中查看'));
   // downloadZipDialog.show = false;
   // MessagePlugin.info('正在下载打包中,可能需要几分钟,请耐心等待...');
   // const [{ default: JSZip }, { saveAs }] = await Promise.all([
@@ -2122,7 +2126,7 @@ const saveDownload = async () => {
   const blob = await zip.generateAsync({ type: 'blob' });
   saveAs(blob, `${_fileName}.zip`);
   MessagePlugin.closeAll();
-  MessagePlugin.success('下载成功,请在浏览器下载列表中查看');
+  MessagePlugin.success($t('下载成功,请在浏览器下载列表中查看'));
 };
 
 // const _downloadHtml = async () => {
@@ -2515,7 +2519,7 @@ async function downloadAsFrame(type: Frame) {
 // }
 
 const downloadImageTips =
-  '无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制';
+  $t('无法下载,宽度不合法,画布可能没有画笔/画布大小超出浏览器最大限制');
 
 const downloadPng = () => {
   if (!meta2d.store.data.pens.length) {
@@ -2545,7 +2549,7 @@ const downloadSvg = async () => {
     }
   }
   if (!C2S) {
-    MessagePlugin.error('请先加载乐吾乐官网下的canvas2svg.js');
+    MessagePlugin.error($t('请先加载乐吾乐官网下的canvas2svg.js'));
     return;
   }
 
@@ -2782,13 +2786,13 @@ const prePay = async () => {
 };
 
 const downloadTrial = () => {
-  MessagePlugin.info('正在下载中,可能需要几分钟,请耐心等待...');
+  MessagePlugin.info($t('正在下载中,可能需要几分钟,请耐心等待...'));
   //下载试用版
   window.open(payListDialog.downloadUrl, '_blank');
 }
 const skipPay = () => {
   //跳过支付,直接下载
-  MessagePlugin.info('正在下载打包中,可能需要几分钟,请耐心等待...');
+  MessagePlugin.info($t('正在下载打包中,可能需要几分钟,请耐心等待...'));
   if (downloadType === Frame.html) {
     preDownload();
   } else {
@@ -2802,7 +2806,7 @@ const finishPay = async () => {
   //   id,
   // });
   // if (result && result.state) {
-    MessagePlugin.success('支付成功');
+    MessagePlugin.success($t('支付成功'));
     wechatPayDialog.show = false;
     if(wechatPayDialog.isZip){
       // downloadZipDialog.show = false;
@@ -2810,7 +2814,7 @@ const finishPay = async () => {
       doDownloadZip();
     }else{
     payListDialog.show = false;
-    MessagePlugin.loading('正在下载打包中,可能需要几分钟,请耐心等待...',0);
+    MessagePlugin.loading($t('正在下载打包中,可能需要几分钟,请耐心等待...'),0);
     if (downloadType === Frame.html) {
       preDownload();
     } else {

+ 34 - 54
src/views/components/Network.vue

@@ -2,13 +2,13 @@
   <div class="network-component">
     <div class="form-item mt-8">
       <label>
-        {{ modelValue.type === 'subscribe' ? '数据获取' : '数据发送' }}
+        {{ modelValue.type === 'subscribe' ? $t('数据获取') : $t('数据发送') }}
       </label>
       <t-select-input
         v-if="mode"
         v-model:inputValue="modelValue.name"
         :value="modelValue.name"
-        placeholder="我的数据发送"
+        :placeholder="$t('我的数据发送')"
         allow-input
         clearable
         v-model:popup-visible="popupVisible"
@@ -22,15 +22,9 @@
       >
         <template #panel>
           <ul style="padding: 4px">
-            <li
-              class="hover-background item"
-              style="line-height: 1.5; padding: 8px; border-radius: 2px"
-              v-for="(item, i) in networkList"
-              :key="item.url"
-              @click="() => onSelect(item)"
-            >
-              名称: {{ item.name }}
-              <div class="desc">地址: {{ item.url }}</div>
+            <li class="hover-background item" style="line-height: 1.5; padding: 8px; border-radius: 2px" v-for="(item, i) in networkList" :key="item.url" @click="() => onSelect(item)">
+{{$t('              名称: ')}}{{ item.name }}
+              <div class="desc">{{$t('地址: ')}}{{ item.url }}</div>
 
               <span class="del" @click.stop="onDelNetWork(item, i)">
                 <delete-icon />
@@ -44,21 +38,17 @@
             >
               <div class="desc">...</div>
             </li>
-            <li
-              v-if="!networkList.length"
-              style="line-height: 1.5; padding: 8px; border-radius: 2px"
-              :key="-1"
-            >
-              <div class="desc">暂无数据</div>
+            <li v-if="!networkList.length" style="line-height: 1.5; padding: 8px; border-radius: 2px" :key="-1">
+              <div class="desc">{{$t('暂无数据')}}</div>
             </li>
           </ul>
         </template>
       </t-select-input>
-      <t-input v-else v-model="modelValue.name" placeholder="名称" />
+      <t-input v-else v-model="modelValue.name" :placeholder="$t('名称')"></t-input>
     </div>
 
     <div class="form-item mt-8">
-      <label>通信方式</label>
+      <label>{{$t( '通信方式' )}}</label>
       <t-select
         v-model="modelValue.protocol"
         placeholder="MQTT"
@@ -70,18 +60,14 @@
       </t-select>
     </div>
     <div class="form-item mt-8">
-      <label>URL地址</label>
-      <t-input
-        :format="urlFormat"
-        :placeholder="
-          modelValue.protocol !== 'http'
+      <label>URL{{$t('地址')}}</label>
+      <t-input :format="urlFormat" :placeholder="
+          modelValue.protocol !== $t('http')
             ? isSafeProtocol()
-              ? '必须是wss协议'
-              : '必须是ws协议'
-            : '请输入'
-        "
-        v-model="modelValue.url"
-      />
+              ? $t('必须是wss协议')
+              : $t('必须是ws协议')
+            : $t('请输入')
+        " v-model="modelValue.url"></t-input>
     </div>
     <template v-if="modelValue.protocol === 'websocket'">
       <div class="form-item mt-8">
@@ -91,22 +77,18 @@
     </template>
     <template v-else-if="modelValue.protocol === 'http'">
       <div class="form-item mt-8">
-        <label>请求方式</label>
+        <label>{{$t('请求方式')}}</label>
         <t-select v-model="modelValue.method" @change="httpMethodChange">
           <t-option key="GET" value="GET" label="GET" />
           <t-option key="POST" value="POST" label="POST" />
         </t-select>
       </div>
       <div v-if="modelValue.type === 'subscribe'" class="form-item mt-8">
-        <label>请求间隔</label>
-        <t-input-number
-          theme="column"
-          v-model="modelValue.interval"
-          placeholder="默认1000 ms"
-        />
+        <label>{{$t('请求间隔')}}</label>
+        <t-input-number theme="column" v-model="modelValue.interval" :placeholder="$t('默认1000 ms')"></t-input-number>
       </div>
       <div class="form-item mt-8">
-        <label>请求头</label>
+        <label>{{$t('请求头')}}</label>
         <!-- <t-textarea
           v-model="modelValue.headers"
           :autosize="{ minRows: 3, maxRows: 5 }"
@@ -122,10 +104,10 @@
       </div>
       <div class="form-item mt-8 desc">
         <label></label>
-        支持设置动态参数,例如:{"Authorization": "Bearer ${token}"}
+        {{$t('支持设置动态参数')}}{{$t('例如')}}:{"Authorization": "Bearer ${token}"}
       </div>
       <div v-if="!mode && modelValue.method === 'POST'" class="form-item mt-8">
-        <label>请求体</label>
+        <label>{{$t('请求体')}}</label>
         <!-- <t-textarea
           v-model="modelValue.body"
           :autosize="{ minRows: 3, maxRows: 5 }"
@@ -144,7 +126,7 @@
         class="form-item mt-8 desc"
       >
         <label></label>
-        支持设置动态参数,例如:{"value": "${value}"}
+        {{$t('支持设置动态参数')}}{{$t('例如')}}:{"value": "${value}"}
       </div>
     </template>
     <template v-else>
@@ -153,20 +135,16 @@
         <t-input v-model="modelValue.options.clientId" />
       </div>
       <div class="form-item mt-8">
-        <label>自动生成</label>
-        <t-switch
-          class="mt-8 ml-8"
-          v-model="modelValue.options.customClientId"
-          size="small"
-        />
+        <label>{{$t('自动生成')}}</label>
+        <t-switch class="mt-8 ml-8" v-model="modelValue.options.customClientId" size="small"></t-switch>
       </div>
       <div class="form-item mt-8">
-        <label>用户名</label>
-        <t-input v-model="modelValue.options.username" />
+        <label>{{$t('用户名')}}</label>
+        <t-input v-model="modelValue.options.username"></t-input>
       </div>
       <div class="form-item mt-8">
-        <label>密码</label>
-        <t-input v-model="modelValue.options.password" />
+        <label>{{$t('密码')}}</label>
+        <t-input v-model="modelValue.options.password"></t-input>
       </div>
       <div class="form-item mt-8">
         <label>Topics</label>
@@ -176,14 +154,14 @@
     <div class="form-item mt-8" v-if="mode">
       <label> </label>
       <div>
-        <t-button @click="onSave">保存到我的数据发送</t-button>
+        <t-button @click="onSave">{{$t('保存到我的数据发送')}}</t-button>
       </div>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, ref } from 'vue';
+import { onBeforeMount, ref,getCurrentInstance } from 'vue';
 import axios from 'axios';
 import { debounce } from '@/services/debouce';
 import { MessagePlugin } from 'tdesign-vue-next';
@@ -195,6 +173,8 @@ const { modelValue, mode } = defineProps<{
   modelValue: any;
   mode?: any;
 }>();
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 
 const emit = defineEmits(['update:modelValue', 'change']);
 const popupVisible = ref<boolean>(false);
@@ -249,7 +229,7 @@ const onSave = async () => {
   }
 
   if (ret) {
-    MessagePlugin.success('保存成功!');
+    MessagePlugin.success($t('保存成功!'));
   }
 };
 

+ 11 - 13
src/views/components/Pay.vue

@@ -2,11 +2,11 @@
   <div class="wechat-pay">
     <div class="order">
       <div>
-        <div>订单编号:{{ props.order.id }}</div>
-        <div>订单类型:{{ props.order.goods.type }}</div>
+        <div>{{$t('订单编号:')}}{{ props.order.id }}</div>
+        <div>{{$t('订单类型:')}}{{ props.order.goods.type }}</div>
       </div>
       <div class="flex items-center">
-        应付金额:
+        {{$t('应付金额')}}
         <span style="font-size: 20px; color: #f5222d">
           ¥{{ props.order.amount }}</span
         >
@@ -20,12 +20,11 @@
           @click="
             payType = 0;
             hideQrPay();
-          "
-        >
-          <h5>余额支付</h5>
+          ">
+          <h5>{{$t('余额支付')}}</h5>
         </t-radio>
         <div class="pl-3 mt-3 ml-3">
-          当前余额:<span class="bland">¥ {{ user.amount }} 元</span>
+          {{$t('当前余额')}}:<span class="bland">¥ {{ user.amount }} 元</span>
         </div>
       </div>
 
@@ -35,9 +34,8 @@
           @click="
             payType = 1;
             showQrPay();
-          "
-        >
-          <h5>扫码支付</h5>
+          ">
+          <h5>{{$t('扫码支付')}}</h5>
         </t-radio>
         <div class="flex pl-3 ml-3" v-show="payType === 1">
           <div class="code">
@@ -62,14 +60,14 @@
         </div>
       </div>
 
-      <div class="mt-5 bland">【注意】不支持退款</div>
+      <div class="mt-5 bland">【{{$t('注意')}}{{$t('不支持退款')}}</div>
     </div>
     <div style="padding: 20px"></div>
     <div class="buttons">
       <t-button v-if="payType === 0" @click="payByAmount" :loading="payLoading">
-        确认支付
+        {{$t('确认支付')}}
       </t-button>
-      <t-button v-if="payType === 1" @click="getPayResult"> 支付完成 </t-button>
+      <t-button v-if="payType === 1" @click="getPayResult"> {{$t('支付完成')}} </t-button>
     </div>
   </div>
 </template>

+ 94 - 211
src/views/components/PenAnimates.vue

@@ -56,7 +56,7 @@
               /> -->
 
               <t-popconfirm
-                content="确认删除该动画吗"
+                :content="$t('确认删除该动画吗')"
                 placement="left"
                 @confirm="delAnimate(i)"
               >
@@ -67,227 +67,109 @@
           </template>
           <template v-if="props.pen.type">
             <div class="form-item">
-              <label>动画类型</label>
-              <t-select v-model="item.lineAnimateType" placeholder="水流"  @change="changeValue(i)">
-                <t-option :key="0" :value="0" label="水流" />
-                <t-option :key="1" :value="1" label="水珠" />
-                <t-option :key="2" :value="2" label="圆点" />
-                <t-option  v-if="['polyline','line'].includes(props.pen.lineName)" :key="3" :value="3" label="箭头" />
-                <t-option  v-if="['polyline','line'].includes(props.pen.lineName)" :key="4" :value="4" label="水滴" />
+              <label>{{$t('动画类型')}}</label>
+              <t-select v-model="item.lineAnimateType" @change="changeValue(i)" :placeholder="$t('水流')">
+                <t-option :key="0" :value="0" :label="$t('水流')"></t-option>
+                <t-option :key="1" :value="1" :label="$t('水珠')"></t-option>
+                <t-option :key="2" :value="2" :label="$t('圆点')"></t-option>
+                <t-option v-if="['polyline','line'].includes(props.pen.lineName)" :key="3" :value="3" :label="$t('箭头')"></t-option>
+                <t-option v-if="['polyline','line'].includes(props.pen.lineName)" :key="4" :value="4" :label="$t('水滴')"></t-option>
               </t-select>
             </div>
 
             <div class="form-item mt-8">
-              <label>运动速度</label>
-              <t-slider
-                class="ml-12"
-                v-model="item.animateSpan"
-                :show-tooltip="true"
-                :min="1"
-                :max="10"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('运动速度')}}</label>
+              <t-slider class="ml-12" v-model="item.animateSpan" :show-tooltip="true" :min="1" :max="10" @change="changeValue(i)"></t-slider>
             </div>
             <div class="form-item mt-8">
-              <label>动画颜色</label>
-              <t-color-picker
-                class="w-full"
-                format="CSS"
-                :enable-alpha="true"
-                :recent-colors="null"
-                :swatch-colors="defaultPureColor"
-                :color-modes="['monochrome']"
-                :show-primary-color-preview="false"
-                :clearable="true"
-                v-model="item.animateColor"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('动画颜色')}}</label>
+              <t-color-picker class="w-full" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" :clearable="true" v-model="item.animateColor" @change="changeValue(i)"></t-color-picker>
             </div>
             <div class="form-item mt-8">
-              <label>发光效果</label>
-              <t-switch
-                class="ml-8 mt-8"
-                size="small"
-                v-model="item.animateShadow"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('发光效果')}}</label>
+              <t-switch class="ml-8 mt-8" size="small" v-model="item.animateShadow" @change="changeValue(i)"></t-switch>
             </div>
             <div v-if="item.animateShadow" class="form-item mt-8">
-              <label>发光颜色</label>
-              <t-color-picker
-                class="w-full"
-                format="CSS"
-                :enable-alpha="true"
-                :recent-colors="null"
-                :swatch-colors="defaultPureColor"
-                :color-modes="['monochrome']"
-                :show-primary-color-preview="false"
-                :clearable="true"
-                v-model="item.animateShadowColor"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('发光颜色')}}</label>
+              <t-color-picker class="w-full" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" :clearable="true" v-model="item.animateShadowColor" @change="changeValue(i)"></t-color-picker>
             </div>
-            <div  v-if="item.animateShadow"  class="form-item mt-8">
-              <label>发光模糊</label>
-              <t-input-number
-                v-model="item.animateShadowBlur"
-                theme="column"
-                :min="1"
-                placeholder="默认6"
-                @change="changeValue(i)"
-              />
+            <div v-if="item.animateShadow" class="form-item mt-8">
+              <label>{{$t('发光模糊')}}</label>
+              <t-input-number v-model="item.animateShadowBlur" theme="column" :min="1" @change="changeValue(i)" :placeholder="$t('默认6')"></t-input-number>
             </div>
             <div class="form-item mt-8">
-              <label>轨迹宽度</label>
-              <t-input-number
-                v-model="item.animateLineWidth"
-                theme="column"
-                :min="1"
-                placeholder="默认6"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('轨迹宽度')}}</label>
+              <t-input-number v-model="item.animateLineWidth" theme="column" :min="1" @change="changeValue(i)" :placeholder="$t('默认6')"></t-input-number>
             </div>
             <div v-if="item.lineAnimateType===3||item.lineAnimateType===4" class="form-item mt-8">
-              <label>轨迹间隔</label>
-              <t-input-number
-                v-model="item.animateInterval"
-                theme="column"
-                :min="1"
-                placeholder="默认100"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('轨迹间隔')}}</label>
+              <t-input-number v-model="item.animateInterval" theme="column" :min="1" @change="changeValue(i)" :placeholder="$t('默认100')"></t-input-number>
             </div>
             <div class="form-item mt-8">
-              <label>反向流动</label>
-              <t-switch
-                class="ml-8 mt-8"
-                size="small"
-                v-model="item.animateReverse"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('反向流动')}}</label>
+              <t-switch class="ml-8 mt-8" size="small" v-model="item.animateReverse" @change="changeValue(i)"></t-switch>
             </div>
             <div class="form-item mt-8">
-              <label>播放次数</label>
-              <t-input-number
-                v-model="item.animateCycle"
-                theme="column"
-                :min="1"
-                placeholder="无限"
-                title="缺省无限循环播放"
-                @change="changeValue(i)"
-              />
+              <label>{{$t('播放次数')}}</label>
+              <t-input-number v-model="item.animateCycle" theme="column" :min="1" @change="changeValue(i)" :placeholder="$t('无限')" :title="$t('缺省无限循环播放')"></t-input-number>
             </div>
             <div class="form-item mt-8">
-              <label>自动播放</label>
-              <t-switch
-                class="ml-8 mt-8"
-                size="small"
-                v-model="item.autoPlay"
-                @change="changeAnimateAutoPlay($event, item)"
-              />
+              <label>{{$t('自动播放')}}</label>
+              <t-switch class="ml-8 mt-8" size="small" v-model="item.autoPlay" @change="changeAnimateAutoPlay($event, item)"></t-switch>
             </div>
-            <div
-              class="form-item mt-8"
-            >
-              <label>下个动画类型</label>
+            <div class="form-item mt-8">
+              <label>{{$t('下个动画类型')}}</label>
               <t-radio-group class="ml-8" v-model="item.temType" @change="item.nextAnimate = ''">
-                <t-radio value="id">图元</t-radio>
-                <t-radio value="tag">组</t-radio>
+                <t-radio value="id">{{$t('图元')}}</t-radio>
+                <t-radio value="tag">{{$t('')}}</t-radio>
               </t-radio-group>
             </div>
-            <div
-              class="form-item mt-8"
-              title="当前动画结束后自动播放下一个对象的动画"
-            >
-              <label>下个动画</label>
-              <t-tree-select
-                v-if="item.temType === 'id'"
-                v-model="item.nextAnimate"
-                :data="penTree"
-                filterable
-                placeholder="无"
-              />
-              <t-select
-              v-else
-              v-model="item.nextAnimate"
-              :options="groups"
-              placeholder="组"
-            />
+            <div class="form-item mt-8" :title="$t('当前动画结束后自动播放下一个对象的动画')">
+              <label>{{$t('下个动画')}}</label>
+              <t-tree-select v-if="item.temType === 'id'" v-model="item.nextAnimate" :data="penTree" filterable :placeholder="$t('无')"></t-tree-select>
+              <t-select v-else v-model="item.nextAnimate" :options="groups" :placeholder="$t('组')"></t-select>
             </div>
           </template>
           <template v-else>
             <div class="form-item">
-              <label>动画类型</label>
-              <t-select
-                v-model="item.animate"
-                clearable
-                placeholder="动画"
-                :options="animateList"
-                @change="changeAnimate(item)"
-              />
+              <label>{{$t('动画类型')}}</label>
+              <t-select v-model="item.animate" clearable :options="animateList" @change="changeAnimate(item)" :placeholder="$t('动画')"></t-select>
             </div>
             <div class="form-item mt-8">
-              <label>播放次数</label>
-              <t-input-number
-                v-model="item.animateCycle"
-                theme="column"
-                :min="1"
-                placeholder="无限"
-                title="缺省无限循环播放"
-              />
+              <label>{{$t('播放次数')}}</label>
+              <t-input-number v-model="item.animateCycle" theme="column" :min="1" :placeholder="$t('无限')" :title="$t('缺省无限循环播放')"></t-input-number>
             </div>
             <div class="form-item mt-8">
-              <label>结束状态</label>
-              <t-select v-model="item.keepAnimateState" placeholder="初始状态">
-                <t-option :key="false" :value="false" label="初始状态" />
-                <t-option :key="true" :value="true" label="当前状态" />
+              <label>{{$t('结束状态')}}</label>
+              <t-select v-model="item.keepAnimateState" :placeholder="$t('初始状态')">
+                <t-option :key="false" :value="false" :label="$t('初始状态')"></t-option>
+                <t-option :key="true" :value="true" :label="$t('当前状态')"></t-option>
               </t-select>
             </div>
             <div class="form-item mt-8">
-              <label>线性播放</label>
-              <t-tooltip content="仅支持数字属性匀速线性播放" placement="top">
-                <t-select v-model="item.linear" placeholder="是">
-                  <t-option :key="true" :value="true" label="是" />
-                  <t-option :key="false" :value="false" label="否" />
+              <label>{{$t('线性播放')}}</label>
+              <t-tooltip placement="top" :content="$t('仅支持数字属性匀速线性播放')">
+                <t-select v-model="item.linear" :placeholder="$t('')">
+                  <t-option :key="true" :value="true" :label="$t('是')"></t-option>
+                  <t-option :key="false" :value="false" :label="$t('否')"></t-option>
                 </t-select>
               </t-tooltip>
             </div>
             <div class="form-item mt-8">
-              <label>自动播放</label>
-              <t-switch
-                class="ml-8 mt-8"
-                size="small"
-                v-model="item.autoPlay"
-                @change="changeAnimateAutoPlay($event, item)"
-              />
+              <label>{{$t('自动播放')}}</label>
+              <t-switch class="ml-8 mt-8" size="small" v-model="item.autoPlay" @change="changeAnimateAutoPlay($event, item)"></t-switch>
             </div>
-            <div
-              class="form-item mt-8"
-            >
-              <label>下个动画类型</label>
+            <div class="form-item mt-8">
+              <label>{{$t('下个动画类型')}}</label>
               <t-radio-group class="ml-8" v-model="item.temType" @change="item.nextAnimate = ''">
-                <t-radio value="id">图元</t-radio>
-                <t-radio value="tag">组</t-radio>
+                <t-radio value="id">{{$t('图元')}}</t-radio>
+                <t-radio value="tag">{{$t('')}}</t-radio>
               </t-radio-group>
             </div>
-            <div
-              class="form-item mt-8"
-              title="当前动画结束后自动播放下一个对象的动画"
-            >
-              <label>下个动画</label>
-              <t-tree-select
-                v-if="item.temType === 'id'"
-                v-model="item.nextAnimate"
-                :data="penTree"
-                filterable
-                placeholder="无"
-              />
-              <t-select
-              v-else
-              v-model="item.nextAnimate"
-              :options="groups"
-              placeholder="组"
-            />
+            <div class="form-item mt-8" :title="$t('当前动画结束后自动播放下一个对象的动画')">
+              <label>{{$t('下个动画')}}</label>
+              <t-tree-select v-if="item.temType === 'id'" v-model="item.nextAnimate" :data="penTree" filterable :placeholder="$t('无')"></t-tree-select>
+              <t-select v-else v-model="item.nextAnimate" :options="groups" :placeholder="$t('组')"></t-select>
             </div>
           </template>
         </t-collapse-panel>
@@ -295,15 +177,15 @@
       <t-divider />
       <div class="p-16">
         <t-button class="w-full" @click="addAnimate" style="height: 30px">
-          添加动画
+          {{$t('添加动画')}}
         </t-button>
       </div>
     </template>
     <div class="flex column center blank" v-else>
-      <img src="/img/blank.png" />
-      <div class="gray center">还没有动画</div>
+      <img src="/img/blank.png">
+      <div class="gray center">{{$t('还没有动画')}}</div>
       <div class="mt-8">
-        <t-button @click="addAnimate" style="height: 30px">添加动画</t-button>
+        <t-button @click="addAnimate" style="height: 30px">{{$t('添加动画')}}</t-button>
       </div>
     </div>
   </div>
@@ -315,7 +197,7 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, ref, watch, onUnmounted,onBeforeUnmount } from 'vue';
+import { onBeforeMount, ref, watch, onUnmounted,onBeforeUnmount,getCurrentInstance } from 'vue';
 
 import { getPenTree } from '@/services/common';
 import { deepClone } from '@meta2d/core';
@@ -324,7 +206,8 @@ import AnimateFrames from './AnimateFrames.vue';
 import { defaultPureColor } from '@/services/defaults';
 import { MessagePlugin } from 'tdesign-vue-next';
 import {StopCircleIcon, PlayCircleIcon, EditIcon, DeleteIcon} from 'tdesign-icons-vue-next';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const props = defineProps<{
   pen: any;
 }>();
@@ -352,7 +235,7 @@ function changeAnimateAutoPlay(value, item) {
 }
 const checkAnimateName = (item:any) => {
   if(!item.name) {
-    MessagePlugin.warning('动画名不能为空!');
+    MessagePlugin.warning($t('动画名不能为空!'));
     item.name = animateNameBak;
   }
 }
@@ -364,7 +247,7 @@ const changeAnimateName = (event, item) => {
     (animation) => animation.name === event
   );
   if (result && result.length) {
-    MessagePlugin.warning('已存在同名动画!');
+    MessagePlugin.warning($t('已存在同名动画!'));
     return;
   } else {
     item.name = event;
@@ -380,8 +263,8 @@ const animate: any = ref(undefined);
 
 const animateList = [
   {
-    label: '闪烁',
-    value: '闪烁',
+    label: $t('闪烁'),
+    value: $t('闪烁'),
     data: [
       {
         visible: true,
@@ -394,8 +277,8 @@ const animateList = [
     ],
   },
   {
-    label: '缩放',
-    value: '缩放',
+    label: $t('缩放'),
+    value: $t('缩放'),
     data: [
       {
         scale: 1.1,
@@ -408,8 +291,8 @@ const animateList = [
     ],
   },
   {
-    label: '旋转',
-    value: '旋转',
+    label: $t('旋转'),
+    value: $t('旋转'),
     data: [
       {
         rotate: 360,
@@ -418,8 +301,8 @@ const animateList = [
     ],
   },
   {
-    label: '逆向旋转',
-    value: '逆向旋转',
+    label: $t('逆向旋转'),
+    value: $t('逆向旋转'),
     data: [
       {
         rotate: -360,
@@ -428,8 +311,8 @@ const animateList = [
     ],
   },
   {
-    label: '上下跳动',
-    value: '上下跳动',
+    label: $t('上下跳动'),
+    value: $t('上下跳动'),
     data: [
       {
         y: -10,
@@ -440,8 +323,8 @@ const animateList = [
     ],
   },
   {
-    label: '左右跳动',
-    value: '左右跳动',
+    label: $t('左右跳动'),
+    value: $t('左右跳动'),
     data: [
       {
         x: -10,
@@ -466,47 +349,47 @@ const animateList = [
     ],
   },
   {
-    label: '颜色变化',
-    value: '颜色变化',
+    label: $t('颜色变化'),
+    value: $t('颜色变化'),
     data: [
       { color: '#4583ff', duration: 200 },
       { color: '#ff4000', duration: 200 },
     ],
   },
   {
-    label: '背景变化',
-    value: '背景变化',
+    label: $t('背景变化'),
+    value: $t('背景变化'),
     data: [
       { background: '#4583ff', duration: 200 },
       { background: '#ff4000', duration: 200 },
     ],
   },
   {
-    label: '文字变化',
-    value: '文字变化',
+    label: $t('文字变化'),
+    value: $t('文字变化'),
     data: [
-      { text: '乐吾乐', duration: 200 },
+      { text: $t('乐吾乐'), duration: 200 },
       { text: 'le5le', duration: 200 },
     ],
   },
   {
-    label: '状态变化',
-    value: '状态变化',
+    label: $t('状态变化'),
+    value: $t('状态变化'),
     data: [
       { showChild: 0, duration: 200 },
       { showChild: 1, duration: 200 },
     ],
   },
   {
-    label: '翻转',
-    value: '翻转',
+    label: $t('翻转'),
+    value: $t('翻转'),
     data: [
       { flipX: true, flipY: true, duration: 200 },
       { flipX: false, flipY: false, duration: 200 },
     ],
   },
   {
-    label: '自定义',
+    label: $t('自定义'),
     value: 'custom',
     data: [],
   },
@@ -562,7 +445,7 @@ const watcher = watch(
 const addAnimate = () => {
   openedCollapses.value.push(props.pen.animations.length);
   props.pen.animations.push({
-    name: '动画' + (props.pen.animations.length + 1),
+    name: $t('动画') + (props.pen.animations.length + 1),
     temType: 'id'
   });
 };

File diff suppressed because it is too large
+ 160 - 261
src/views/components/PenDatas.vue


+ 36 - 43
src/views/components/PenEvents.vue

@@ -21,17 +21,13 @@
                 v-if="item.name === 'message'"
                 style="width: 93px;margin-left: 20px;"
                 v-model="item.message"
-                placeholder="消息名"
+                :placeholder="$t('消息名')"
               />
             </div>
           </template>
           <template #headerRightContent>
             <t-space size="small" @click.stop>
-              <t-popconfirm
-                content="确认删除该交互事件吗?"
-                placement="left"
-                @confirm="props.pen.events.splice(i, 1)"
-              >
+              <t-popconfirm placement="left" @confirm="props.pen.events.splice(i, 1)" :content="$t('确认删除该交互事件吗?')">
                 <!-- <t-icon name="delete" class="hover" /> -->
                 <delete-icon class="hover"/>
               </t-popconfirm>
@@ -51,22 +47,17 @@
           :maxHeight="360"
         >
           <t-button class="w-full" style="height: 30px">
-            添加交互事件
+            {{$t('添加交互事件')}}
           </t-button>
         </t-dropdown>
       </div>
     </div>
     <div class="flex column center blank" v-else>
-      <img src="/img/blank.png" />
-      <div class="gray center">还没有交互事件</div>
+      <img src="/img/blank.png">
+      <div class="gray center">{{$t('还没有交互事件')}}</div>
       <div class="mt-8">
-        <t-dropdown
-          :options="options"
-          @click="addEvent"
-          :minColumnWidth="150"
-          :maxHeight="360"
-        >
-          <t-button style="height: 30px"> 添加交互事件 </t-button>
+        <t-dropdown :options="options" @click="addEvent" :minColumnWidth="150" :maxHeight="360">
+          <t-button style="height: 30px"> {{$t('添加交互事件')}} </t-button>
         </t-dropdown>
       </div>
     </div>
@@ -74,12 +65,14 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, onUnmounted, ref, computed } from 'vue';
+import { onBeforeMount, onUnmounted, ref, computed, getCurrentInstance } from 'vue';
 
 import Actions from './Actions.vue';
 import Conditions from './Conditions.vue';
 import { DeleteIcon } from 'tdesign-icons-vue-next';
 import { initEvent } from '@meta2d/chart-diagram';
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 
 const props = defineProps<{
   pen: any;
@@ -88,56 +81,56 @@ const props = defineProps<{
 // const options = ref<any>([
 //   {
 //     value: 'click',
-//     content: '单击',
+//     content: $t('单击'),
 //   },
 //   {
 //     value: 'dblclick',
-//     content: '双击',
+//     content: $t('双击'),
 //     divider: true,
 //   },
 //   {
 //     value: 'change',
-//     content: '输入完成',
+//     content: $t('输入完成'),
 //   },
 //   {
 //     value: 'input',
-//     content: '输入',
+//     content: $t('输入'),
 //     divider: true,
 //   },
 //   {
 //     value: 'contextmenu',
-//     content: '鼠标右键',
+//     content: $t('鼠标右键'),
 //   },
 //   {
 //     value: 'enter',
-//     content: '鼠标移入',
+//     content: $t('鼠标移入'),
 //   },
 //   {
 //     value: 'leave',
-//     content: '鼠标移出',
+//     content: $t('鼠标移出'),
 //     divider: true,
 //   },
 //   {
 //     value: 'active',
-//     content: '获得焦点',
+//     content: $t('获得焦点'),
 //   },
 //   {
 //     value: 'inactive',
-//     content: '失去焦点',
+//     content: $t('失去焦点'),
 //     divider: true,
 //   },
 //   {
 //     value: 'mousedown',
-//     content: '鼠标按下',
+//     content: $t('鼠标按下'),
 //   },
 //   {
 //     value: 'mouseup',
-//     content: '鼠标抬起',
+//     content: $t('鼠标抬起'),
 //     divider: true,
 //   },
 //   {
 //     value: 'message',
-//     content: '监听全局消息',
+//     content: $t('监听全局消息'),
 //   },
 // ]);
 
@@ -145,24 +138,24 @@ const options: any = computed(() => {
   const options = [
     {
       value: 'click',
-      content: '单击',
+      content: $t('单击'),
     },
     {
       value: 'dblclick',
-      content: '双击',
+      content: $t('双击'),
       divider: true,
     },
   ];
   if (props.pen.dropdownList) {
     options.push({
       value: 'change',
-      content: '选择完成',
+      content: $t('选择完成'),
       divider: true,
     });
   } else if (props.pen.name === 'inputDom') {
     options.push({
       value: 'input',
-      content: '输入',
+      content: $t('输入'),
       divider: true,
     });
   } else if (props.pen.input) {
@@ -170,11 +163,11 @@ const options: any = computed(() => {
       ...[
         {
           value: 'change',
-          content: '输入完成',
+          content: $t('输入完成'),
         },
         {
           value: 'input',
-          content: '输入',
+          content: $t('输入'),
           divider: true,
         },
       ]
@@ -185,38 +178,38 @@ const options: any = computed(() => {
     ...[
       {
         value: 'contextmenu',
-        content: '鼠标右键',
+        content: $t('鼠标右键'),
       },
       {
         value: 'enter',
-        content: '鼠标移入',
+        content: $t('鼠标移入'),
       },
       {
         value: 'leave',
-        content: '鼠标移出',
+        content: $t('鼠标移出'),
         divider: true,
       },
       {
         value: 'active',
-        content: '获得焦点',
+        content: $t('获得焦点'),
       },
       {
         value: 'inactive',
-        content: '失去焦点',
+        content: $t('失去焦点'),
         divider: true,
       },
       {
         value: 'mousedown',
-        content: '鼠标按下',
+        content: $t('鼠标按下'),
       },
       {
         value: 'mouseup',
-        content: '鼠标抬起',
+        content: $t('鼠标抬起'),
         divider: true,
       },
       {
         value: 'message',
-        content: '监听全局消息',
+        content: $t('监听全局消息'),
       },
     ]
   );

File diff suppressed because it is too large
+ 179 - 571
src/views/components/PenProps.vue


+ 51 - 69
src/views/components/PenStatus.vue

@@ -9,17 +9,13 @@
         <t-input
           style="width: 190px; margin-left: 20px"
           v-model="trigger.name"
-          placeholder="状态场景名"
+          :placeholder="$t('状态场景名')"
         />
         <div class="flex operation">
           <div class="icon-box icon-item-box" @click="onEditTrigger(trigger)">
             <Edit2Icon />
           </div>
-          <t-popconfirm
-            :content="`确认删除这条状态场景吗?`"
-            placement="bottom"
-            @confirm="delTrigger(i)"
-          >
+          <t-popconfirm :content="$t('确认删除这条状态场景吗?')" placement="bottom" @confirm="delTrigger(i)">
             <div class="icon-box">
               <DeleteIcon />
             </div>
@@ -28,8 +24,8 @@
       </div>
     </div>
     <div class="flex column center blank" v-else>
-      <img src="/img/blank.png" />
-      <div class="gray center">还没有状态场景</div>
+      <img src="/img/blank.png">
+      <div class="gray center">{{$t('还没有状态场景')}}</div>
       <!-- <div class="mt-8">
         <t-button style="height: 30px" @click="onAddTrigger">
           添加状态
@@ -37,11 +33,8 @@
       </div> -->
     </div>
     <div class="flex center mt-8">
-      <t-button
-        style="height: 30px; width: 90%; margin: 12px"
-        @click="onAddTrigger"
-      >
-        添加状态场景
+      <t-button style="height: 30px; width: 90%; margin: 12px" @click="onAddTrigger">
+        {{$t('添加状态场景')}}
       </t-button>
     </div>
   </div>
@@ -59,44 +52,32 @@
       >
         <t-collapse-panel v-for="(state, i) in trigger.status" :value="i">
           <template #header>
-            <t-input
-              v-model="state.name"
-              style="width:90%"
-              @click="panelInputClick($event)"
-              placeholder="状态名"
-            />
+            <t-input v-model="state.name" style="width:90%" @click="panelInputClick($event)" :placeholder="$t('状态名')"></t-input>
           </template>
           <template #headerRightContent>
             <t-space size="small" @click.stop>
-              <t-popconfirm
-                content="确认删除该状态吗?"
-                placement="left"
-                @confirm="trigger.status.splice(i, 1)"
-              >
-                <delete-icon class="hover" />
+              <t-popconfirm placement="left" @confirm="trigger.status.splice(i, 1)" :content="$t('确认删除该状态吗?')">
+                <delete-icon class="hover"></delete-icon>
               </t-popconfirm>
             </t-space>
           </template>
           <!-- <Conditions :key="temCKey" :data="state" /> -->
           <div class="props">
-            <div
-              v-if="state.conditions && state.conditions.length > 0"
-              class="form-item banner"
-            >
-              <label>满足条件</label>
+            <div v-if="state.conditions && state.conditions.length > 0" class="form-item banner">
+              <label>{{$t('满足条件')}}</label>
               <div class="w-full flex middle between">
                 <div></div>
                 <t-radio-group class="ml-8" v-model="state.conditionType">
-                  <t-radio value="and"> 所有 </t-radio>
-                  <t-radio value="or"> 任意 </t-radio>
+                  <t-radio value="and"> {{$t('所有')}} </t-radio>
+                  <t-radio value="or"> {{$t('任意')}} </t-radio>
                 </t-radio-group>
               </div>
             </div>
             <div v-for="(c, index) in state.conditions" class="mb-12">
               <div class="flex middle between" style="margin-top:10px;">
                 <div class="flex middle">
-                  <arrow-right-icon class="mr-4" />
-                  条件{{ index + 1 }}
+                  <arrow-right-icon class="mr-4"></arrow-right-icon>
+{{$t('                  条件')}}{{ index + 1 }}
                 </div>
                 <close-icon
                   class="hover"
@@ -105,15 +86,15 @@
               </div>
               <div class="">
                 <div class="form-item mt-4 px-16">
-                  <label>条件类型</label>
+                  <label>{{$t('条件类型')}}</label>
                   <t-radio-group class="ml-8" v-model="c.type">
-                    <t-radio value=""> 关系条件 </t-radio>
-                    <t-radio value="fn"> 高级条件 </t-radio>
+                    <t-radio value> {{$t('关系条件')}} </t-radio>
+                    <t-radio value="fn"> {{$t('高级条件')}} </t-radio>
                   </t-radio-group>
                 </div>
                 <template v-if="!c.type">
                   <div class="form-item mt-8 px-16">
-                    <label>比较条件</label>
+                    <label>{{$t( '比较条件' )}}</label>
                     <t-select-input
                       v-model:inputValue="c.key"
                       :value="c.keyLabel"
@@ -146,7 +127,7 @@
                     <t-select
                       style="width: 132px"
                       v-model="c.operator"
-                      placeholder="关系运算"
+                      :placeholder="$t('关系运算')"
                       :options="operatorOptions"
                       clearable
                       class="shrink-0"
@@ -155,13 +136,13 @@
                       style="width: 132px"
                       v-model="c.valueType"
                       class="shrink-0"
-                      placeholder="固定值"
+                      :placeholder="$t('固定值')"
                     >
-                      <t-option key="" value="" label="固定值">
-                        固定值
+                      <t-option key="" value="" :label="$t('固定值')">
+                        {{$t( '固定值' )}}
                       </t-option>
-                      <t-option key="prop" value="prop" label="对象属性值">
-                        对象属性
+                      <t-option key="prop" value="prop" :label="$t('对象属性值')">
+                        {{$t('对象属性')}}
                       </t-option>
                     </t-select>
                     <t-input
@@ -176,7 +157,7 @@
                         v-model="c.target"
                         :data="penTree"
                         filterable
-                        placeholder="对象"
+                        :placeholder="$t('对象')"
                         class="shrink-0"
                         @change="onChangeTriggerTarget(c)"
                       />
@@ -191,7 +172,7 @@
                         @blur="c.popupVisible = false"
                         @input-change="onInput(c)"
                         class="shrink-0"
-                        placeholder="属性"
+                        :placeholder="$t('属性')"
                       >
                         <template #panel>
                           <ul style="padding: 8px 12px">
@@ -226,11 +207,11 @@
               </div>
             </div>
             <div class="mt-8">
-              <a @click="addTriggerCondition(state)"> + 添加触发条件 </a>
+              <a @click="addTriggerCondition(state)"> + {{$t('添加触发条件')}} </a>
             </div>
           </div>
           <div class="form-item banner mt-16">
-            <label>执行动作</label>
+            <label>{{$t('执行动作')}}</label>
           </div>
           <Actions class="mt-8" :key="temAKey" :data="state" />
         </t-collapse-panel>
@@ -242,7 +223,7 @@
           variant="outline"
         >
         <template #icon><add-icon /></template>
-          添加状态
+          {{$t( '添加状态' )}}
         </t-button>
       </div>
     </div>
@@ -250,13 +231,14 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, defineComponent, ref } from 'vue';
+import { reactive, defineComponent, ref, getCurrentInstance } from 'vue';
 import Actions from './Actions.vue';
 // import Conditions from './Conditions.vue';
 import { Edit2Icon, DeleteIcon, ArrowRightIcon, CloseIcon, AddIcon } from 'tdesign-icons-vue-next';
 import { getPenTree, typeOptions, changeType } from '@/services/common';
 import CodeEditor from '@/views/components/common/CodeEditor.vue';
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const props = defineProps<{
   pen: any;
 }>();
@@ -264,7 +246,7 @@ const props = defineProps<{
 const trigger = ref();
 const drawer = reactive({
   visible: false,
-  header: '编辑状态',
+  header: $t('编辑状态'),
 });
 
 const openedCollapses = ref([0]);
@@ -275,10 +257,10 @@ const onAddTrigger = () => {
   }
   const i = props.pen.triggers.length;
   props.pen.triggers.push({
-    name: `状态场景${i + 1}`,
+    name: $t('状态场景')+(i + 1),
     status: [
       {
-        name: '状态1',
+        name: $t('状态1'),
         conditions: [],
         actions: [],
       },
@@ -322,7 +304,7 @@ const editLast = (index) => {
 const addTriggerStatus = (triger: any) => {
   const i = props.pen.triggers.length;
   triger.status.push({
-    name: `状态${i}`,
+    name: $t('状态') + i,
     conditionType: 'and',
     conditions: [],
     actions: [],
@@ -382,51 +364,51 @@ const cprops = ref<any>([
   },
   {
     value: 'width',
-    label: '宽',
+    label: $t('宽'),
   },
   {
     value: 'height',
-    label: '高',
+    label: $t('高'),
   },
   {
     value: 'visible',
-    label: '显示',
+    label: $t('显示'),
   },
   {
     value: 'text',
-    label: '文字',
+    label: $t('文字'),
   },
   {
     value: 'color',
-    label: '颜色',
+    label: $t('颜色'),
   },
   {
     value: 'background',
-    label: '背景颜色',
+    label: $t('背景颜色'),
   },
   {
     value: 'progress',
-    label: '进度',
+    label: $t('进度'),
   },
   {
     value: 'progressColor',
-    label: '进度颜色',
+    label: $t('进度颜色'),
   },
   {
     value: 'showChild',
-    label: '状态',
+    label: $t('状态'),
   },
   {
     value: 'rotate',
-    label: '旋转',
+    label: $t('旋转'),
   },
   {
     value: 'disabled',
-    label: '禁用',
+    label: $t('禁用'),
   },
   {
     value: 'selectedKey',
-    label: '单选选中值',
+    label: $t('单选选中值'),
   }
 ]);
 
@@ -437,8 +419,8 @@ const operatorOptions = [
   { label: '<', value: '<' },
   { label: '>=', value: '>=' },
   { label: '<=', value: '<=' },
-  { label: '包含', value: '[)' },
-  { label: '不包含', value: '![)' },
+  { label: $t('包含'), value: '[)' },
+  { label: $t('不包含'), value: '![)' },
 ];
 
 const valueChange = (e, c: any) => {

+ 129 - 330
src/views/components/PensProps.vue

@@ -1,57 +1,33 @@
 <template>
   <div class="props">
     <t-tabs v-model="data.tab">
-      <t-tab-panel :value="1" label="外观">
+      <t-tab-panel :value="1" :label="$t('外观')">
         <t-space direction="vertical" class="py-16 w-full">
           <div class="px-16 flex between" style="margin-bottom:2px;">
-            <label>选中了{{ selections.pens.length }}个图元</label>
+            <label>{{$t('选中了')}}{{ selections.pens.length }}{{$t( '个图元' )}}</label>
             <div class="icons">
-              <t-tooltip
-                class="mr-4"
-                v-if="!data.locked"
-                content="可编辑"
-                placement="top"
-              >
+              <t-tooltip class="mr-4" v-if="!data.locked" placement="top" :content="$t('可编辑')">
                 <svg class="l-icon" aria-hidden="true" @click="lock(1)">
                   <use xlink:href="#l-unlock"></use>
                 </svg>
               </t-tooltip>
-              <t-tooltip
-                class="mr-4"
-                v-else-if="data.locked == 1"
-                content="禁止编辑"
-                placement="top"
-              >
+              <t-tooltip class="mr-4" v-else-if="data.locked == 1" placement="top" :content="$t('禁止编辑')">
                 <svg class="l-icon" aria-hidden="true" @click="lock(2)">
                   <use xlink:href="#l-lock"></use>
                 </svg>
               </t-tooltip>
-              <t-tooltip
-                class="mr-4"
-                v-else-if="data.locked == 2"
-                content="禁止编辑和移动"
-                placement="top"
-              >
+              <t-tooltip class="mr-4" v-else-if="data.locked == 2" placement="top" :content="$t('禁止编辑和移动')">
                 <svg class="l-icon" aria-hidden="true" @click="lock(10)">
                   <use xlink:href="#l-wufayidong"></use>
                 </svg>
               </t-tooltip>
-              <t-tooltip
-                class="mr-4"
-                v-else-if="data.locked == 10"
-                content="禁止所有事件"
-                placement="top"
-              >
+              <t-tooltip class="mr-4" v-else-if="data.locked == 10" placement="top" :content="$t('禁止所有事件')">
                 <svg class="l-icon" aria-hidden="true" @click="lock(0)">
                   <use xlink:href="#l-jinyong"></use>
                 </svg>
               </t-tooltip>
-              <browse-icon  v-if="data.visible !== false" 
-                @click="visible(false)"
-                class="ml-8"/>
-              <browse-off-icon v-else
-                @click="visible(true)"
-                class="ml-8"/>
+              <browse-icon v-if="data.visible !== false" @click="visible(false)" class="ml-8"></browse-icon>
+              <browse-off-icon v-else @click="visible(true)" class="ml-8"></browse-off-icon>
               <!-- <t-icon
                 v-if="data.visible !== false"
                 name="browse"
@@ -67,12 +43,12 @@
             </div>
           </div>
           <div class="form-item px-16" style="margin-top: -12px">
-            <label style="width: 50px">分组</label>
+            <label style="width: 50px">{{$t( '分组' )}}</label>
             <t-select-input
               v-model:inputValue="data.inputTag"
               :value="data.tags"
               allow-input
-              placeholder="请输入或选择分组"
+              :placeholder="$t('请输入或选择分组')"
               multiple
               @tag-change="onChangeInputTag"
               @focus="data.tagPopupVisible = true"
@@ -93,26 +69,19 @@
             </t-select-input>
           </div>
           <div class="form-item px-16" style="margin-top: -12px">
-            <label style="width: 50px">画布层</label>
-            <t-select
-              v-model="data.canvasLayer"
-              @change="changeValue('canvasLayer')"
-            >
-              <t-option :key="4" :disabled="!allImg" :value="4" label="上层图片层"> 上层图片层 </t-option>
-              <t-option :key="3" :disabled="hasDom" :value="3" label="主画布层"> 主画布层 </t-option>
-              <t-option :key="2" :disabled="!allImg" :value="2" label="下层图片层"> 下层图片层 </t-option>
-              <t-option :key="1" :disabled="hasDom" :value="1" label="模板层"> 模板层 </t-option>
+            <label style="width: 50px">{{$t('画布层')}}</label>
+            <t-select v-model="data.canvasLayer" @change="changeValue('canvasLayer')">
+              <t-option :key="4" :disabled="!allImg" :value="4" :label="$t('上层图片层')"> {{$t('上层图片层')}} </t-option>
+              <t-option :key="3" :disabled="hasDom" :value="3" :label="$t('主画布层')"> {{$t('主画布层')}} </t-option>
+              <t-option :key="2" :disabled="!allImg" :value="2" :label="$t('下层图片层')"> {{$t('下层图片层')}} </t-option>
+              <t-option :key="1" :disabled="hasDom" :value="1" :label="$t('模板层')"> {{$t('模板层')}} </t-option>
             </t-select>
           </div>
-          <t-collapse
-            :defaultValue="['1', '2', '3', '4']"
-            expandIconPlacement="right"
-            :borderless="true"
-          >
-            <t-collapse-panel value="1" header="对齐">
+          <t-collapse :defaultValue="['1', '2', '3', '4']" expandIconPlacement="right" :borderless="true">
+            <t-collapse-panel value="1" :header="$t('对齐')">
               <t-space direction="vertical" size="small" class="w-full">
                 <div style="color: var(--color); margin-bottom: 2px">
-                  大屏对齐
+                  {{$t('大屏对齐')}}
                 </div>
                 <div class="icons">
                   <t-tooltip
@@ -137,7 +106,7 @@
               />
               <t-space direction="vertical" size="small" class="w-full">
                 <div style="color: var(--color); margin-bottom: 2px">
-                  区域对齐
+                  {{$t('区域对齐')}}
                 </div>
                 <div class="icons">
                   <t-tooltip
@@ -162,7 +131,7 @@
               />
               <t-space direction="vertical" size="small" class="w-full">
                 <div style="color: var(--color); margin-bottom: 2px">
-                  以最后选中图元对齐
+                  {{$t('以最后选中图元对齐')}}
                 </div>
                 <div class="icons">
                   <t-tooltip
@@ -183,58 +152,22 @@
                 </div>
               </t-space>
             </t-collapse-panel>
-            <t-collapse-panel value="2" header="外观">
+            <t-collapse-panel value="2" :header="$t('外观')">
               <t-space direction="vertical" size="small" class="w-full">
                 <div class="form-item">
-                  <t-color-picker
-                    class="simple mt-8 mr-4"
-                    format="CSS"
-                    :enable-alpha="true"
-                    :recent-colors="null"
-                    :swatch-colors="defaultPureColor"
-                    :color-modes="['monochrome']"
-                    :show-primary-color-preview="false"
-                    :clearable="true"
-                    v-model="data.color"
-                    @change="changeValue('color')"
-                  />
-                  <label style="width: 64px">前景颜色</label>
+                  <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" :clearable="true" v-model="data.color" @change="changeValue('color')"></t-color-picker>
+                  <label style="width: 64px">{{$t('前景颜色')}}</label>
 
-                  <t-color-picker
-                    class="simple mt-8 mr-4"
-                    format="CSS"
-                    :enable-alpha="true"
-                    :recent-colors="null"
-                    :swatch-colors="defaultPureColor"
-                    :color-modes="['monochrome']"
-                    :show-primary-color-preview="false"
-                    v-model="data.hoverColor"
-                    @change="changeValue('hoverColor')"
-                  />
-                  <label style="width: 64px">悬停颜色</label>
+                  <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.hoverColor" @change="changeValue('hoverColor')"></t-color-picker>
+                  <label style="width: 64px">{{$t('悬停颜色')}}</label>
 
-                  <t-color-picker
-                    class="simple mt-8 mr-4"
-                    format="CSS"
-                    :enable-alpha="true"
-                    :recent-colors="null"
-                    :swatch-colors="defaultPureColor"
-                    :color-modes="['monochrome']"
-                    :show-primary-color-preview="false"
-                    v-model="data.activeColor"
-                    @change="changeValue('activeColor')"
-                  />
-                  <label style="width: 64px">选中颜色</label>
+                  <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.activeColor" @change="changeValue('activeColor')"></t-color-picker>
+                  <label style="width: 64px">{{$t('选中颜色')}}</label>
                 </div>
 
                 <div class="form-item">
-                  <label style="width: 32px">线条 </label>
-                  <t-select
-                    v-model="data.dash"
-                    placeholder="线条样式"
-                    @change="changeValue('dash')"
-                    style="width: 80px"
-                  >
+                  <label style="width: 32px">{{$t('线条')}} </label>
+                  <t-select v-model="data.dash" @change="changeValue('dash')" style="width: 80px" :placeholder="$t('线条样式')">
                     <template #valueDisplay="{ value }">
                       <svg
                         xmlns="http://www.w3.org/2000/svg"
@@ -308,7 +241,7 @@
                   </t-select>
                   <t-input-number
                     theme="normal"
-                    placeholder="线条宽度"
+                    :placeholder="$t('线条宽度')"
                     v-model="data.lineWidth"
                     :min="1"
                     :decimalPlaces="0"
@@ -316,7 +249,7 @@
                     class="ml-4"
                     style="width: 40px"
                   />
-                  <t-tooltip content="线条渐变" placement="top">
+                  <t-tooltip :content="$t('线条渐变')" placement="top">
                     <div class="flex middle ml-8">
                       <t-checkbox
                         v-model="data.strokeType"
@@ -336,7 +269,7 @@
                         :swatch-colors="defaultGradientColor"
                         v-model="data.lineGradientColors"
                         @change="changeValue('lineGradientColors')"
-                        placeholder="无"
+                        :placeholder="$t('')"
                       />
                     </div>
                   </t-tooltip>
@@ -350,28 +283,28 @@
                       @change="changeValue('lineCap')"
                     >
                       <t-radio-button value="butt">
-                        <t-tooltip content="默认" placement="top">
+                        <t-tooltip :content="$t('默认')" placement="top">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-duandian1"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                       <t-radio-button value="round">
-                        <t-tooltip content="圆形" placement="top">
+                        <t-tooltip :content="$t('圆形')" placement="top">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-duandian2"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                       <t-radio-button value="square">
-                        <t-tooltip content="方形" placement="top">
+                        <t-tooltip placement="top" :content="$t('方形')">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-duandian3"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                     </t-radio-group>
-                    <div class="mt-4" style="font-size: 12px">末端样式</div>
+                    <div class="mt-4" style="font-size: 12px">{{$t('末端样式')}}</div>
                   </div>
                   <div class="flex column middle ml-16">
                     <t-radio-group
@@ -381,42 +314,37 @@
                       @change="changeValue('lineJoin')"
                     >
                       <t-radio-button value="miter">
-                        <t-tooltip content="默认" placement="top">
+                        <t-tooltip placement="top" :content="$t('默认')">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-jiedian1"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                       <t-radio-button value="round">
-                        <t-tooltip content="圆形" placement="top">
+                        <t-tooltip placement="top" :content="$t('圆形')">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-jiedian2"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                       <t-radio-button value="bevel">
-                        <t-tooltip content="斜角" placement="top">
+                        <t-tooltip placement="top" :content="$t('斜角')">
                           <svg class="l-icon" aria-hidden="true">
                             <use xlink:href="#l-jiedian3"></use>
                           </svg>
                         </t-tooltip>
                       </t-radio-button>
                     </t-radio-group>
-                    <div class="mt-4" style="font-size: 12px">连接样式</div>
+                    <div class="mt-4" style="font-size: 12px">{{$t('连接样式')}}</div>
                   </div>
                 </div>
                 <div class="form-item">
-                  <label style="width: 32px">背景</label>
+                  <label style="width: 32px">{{$t('背景')}}</label>
                   <div class="ml-8">
-                    <t-radio-group
-                      size="small"
-                      v-model="data.bkType"
-                      :default-value="0"
-                      @change="changeValue('bkType')"
-                    >
-                      <t-radio-button :value="0"> 纯色 </t-radio-button>
-                      <t-radio-button :value="1"> 线性渐变 </t-radio-button>
-                      <t-radio-button :value="2"> 径向渐变 </t-radio-button>
+                    <t-radio-group size="small" v-model="data.bkType" :default-value="0" @change="changeValue('bkType')">
+                      <t-radio-button :value="0"> {{$t('纯色')}} </t-radio-button>
+                      <t-radio-button :value="1"> {{$t('线性渐变')}} </t-radio-button>
+                      <t-radio-button :value="2"> {{$t('径向渐变')}} </t-radio-button>
                     </t-radio-group>
                     <div v-if="data.bkType === 0" class="mt-8 -ml-8">
                       <t-color-picker
@@ -463,7 +391,7 @@
 
                       <t-input-number
                         theme="column"
-                        placeholder="渐变半径"
+                        :placeholder="$t('渐变半径')"
                         v-model="data.gradientRadius"
                         :min="0"
                         :max="1"
@@ -476,7 +404,7 @@
                   </div>
                 </div>
                 <div class="form-item">
-                  <label style="width: 32px">阴影 </label>
+                  <label style="width: 32px">{{$t('阴影')}} </label>
                   <div class="flex middle ml-8">
                     <t-checkbox
                       v-model="data.shadow"
@@ -496,10 +424,7 @@
                       @change="changeValue('shadowColor')"
                     />
                   </div>
-                  <label
-                    v-if="data.shadow"
-                    style="width: 50px; margin-left: 25px"
-                    >文字阴影
+                  <label v-if="data.shadow" style="width: 50px; margin-left: 25px">{{$t('文字阴影')}}
                   </label>
                   <div v-if="data.shadow" class="flex middle ml-8">
                     <t-checkbox
@@ -512,45 +437,21 @@
                 <div class="form-item" v-if="data.shadow">
                   <label style="width: 28px"></label>
                   <div class="flex" style="margin-top: -8px">
-                    <t-input
-                      class="ml-4"
-                      label="X"
-                      placeholder="0"
-                      v-model.number="data.shadowOffsetX"
-                      style="width: 60px"
-                      @change="changeValue('x')"
-                      title="X偏移"
-                    />
-                    <t-input
-                      class="ml-4"
-                      label="Y"
-                      placeholder="0"
-                      v-model.number="data.shadowOffsetY"
-                      style="width: 60px"
-                      @change="changeValue('shadowOffsetY')"
-                      title="Y偏移"
-                    />
-                    <t-input
-                      class="ml-4"
-                      label="模糊"
-                      placeholder="0"
-                      v-model.number="data.shadowBlur"
-                      style="width: 64px"
-                      @change="changeValue('shadowBlur')"
-                      title="模糊大小"
-                    />
+                    <t-input class="ml-4" label="X" placeholder="0" v-model.number="data.shadowOffsetX" style="width: 60px" @change="changeValue('x')" :title="$t('X偏移')"></t-input>
+                    <t-input class="ml-4" label="Y" placeholder="0" v-model.number="data.shadowOffsetY" style="width: 60px" @change="changeValue('shadowOffsetY')" :title="$t('Y偏移')"></t-input>
+                    <t-input class="ml-4" placeholder="0" v-model.number="data.shadowBlur" style="width: 64px" @change="changeValue('shadowBlur')" :label="$t('模糊')" :title="$t('模糊大小')"></t-input>
                   </div>
                 </div>
               </t-space>
             </t-collapse-panel>
-            <t-collapse-panel value="3" header="文字">
+            <t-collapse-panel value="3" :header="$t('文字')">
               <t-space direction="vertical" size="small" class="w-full">
                 <div class="form-item">
                   <div class="flex middle" style="margin-left: -10px">
                     <t-select-input
                       :value="data.fontFamily"
                       :popup-visible="data.fontFamilyPopupVisible"
-                      placeholder="字体名"
+                      :placeholder="$t('字体名')"
                       allow-input
                       style="width: 170px"
                       @change="changeValue('fontFamily')"
@@ -578,14 +479,7 @@
                       </template>
                     </t-select-input>
 
-                    <t-input
-                      class="ml-8"
-                      placeholder="字体大小"
-                      v-model.number="data.fontSize"
-                      style="width: 80px"
-                      :format="decimalRound"
-                      @change="changeValue('fontSize')"
-                    />
+                    <t-input class="ml-8" v-model.number="data.fontSize" style="width: 80px" :format="decimalRound" @change="changeValue('fontSize')" :placeholder="$t('字体大小')"></t-input>
                   </div>
                 </div>
                 <div class="flex middle">
@@ -596,20 +490,20 @@
                     @change="changeValue('textAlign')"
                   >
                     <t-radio-button value="left">
-                      <t-tooltip content="居左" placement="top">
-                        <format-vertical-align-left-icon />
+                      <t-tooltip placement="top" :content="$t('居左')">
+                        <format-vertical-align-left-icon></format-vertical-align-left-icon>
                         <!-- <t-icon name="format-vertical-align-left" /> -->
                       </t-tooltip>
                     </t-radio-button>
                     <t-radio-button value="center">
-                      <t-tooltip content="居中" placement="top">
-                        <format-vertical-align-center-icon />
+                      <t-tooltip placement="top" :content="$t('居中')">
+                        <format-vertical-align-center-icon></format-vertical-align-center-icon>
                         <!-- <t-icon name="format-vertical-align-center" /> -->
                       </t-tooltip>
                     </t-radio-button>
                     <t-radio-button value="right">
-                      <t-tooltip content="居右" placement="top">
-                        <format-vertical-align-right-icon />
+                      <t-tooltip placement="top" :content="$t('居右')">
+                        <format-vertical-align-right-icon></format-vertical-align-right-icon>
                         <!-- <t-icon name="format-vertical-align-right" /> -->
                       </t-tooltip>
                     </t-radio-button>
@@ -622,20 +516,20 @@
                     @change="changeValue('textBaseline')"
                   >
                     <t-radio-button value="top">
-                      <t-tooltip content="顶部对齐" placement="top">
-                        <format-horizontal-align-top-icon />
+                      <t-tooltip placement="top" :content="$t('顶部对齐')">
+                        <format-horizontal-align-top-icon></format-horizontal-align-top-icon>
                         <!-- <t-icon name="format-horizontal-align-top" /> -->
                       </t-tooltip>
                     </t-radio-button>
                     <t-radio-button value="middle">
-                      <t-tooltip content="垂直居中" placement="middle">
-                        <format-horizontal-align-center-icon />
+                      <t-tooltip placement="middle" :content="$t('垂直居中')">
+                        <format-horizontal-align-center-icon></format-horizontal-align-center-icon>
                         <!-- <t-icon name="format-horizontal-align-center" /> -->
                       </t-tooltip>
                     </t-radio-button>
                     <t-radio-button value="bottom">
-                      <t-tooltip content="底部对齐" placement="top">
-                        <format-horizontal-align-bottom-icon />
+                      <t-tooltip placement="top" :content="$t('底部对齐')">
+                        <format-horizontal-align-bottom-icon></format-horizontal-align-bottom-icon>
                         <!-- <t-icon name="format-horizontal-align-bottom" /> -->
                       </t-tooltip>
                     </t-radio-button>
@@ -683,7 +577,7 @@
                     v-model="data.textColor"
                     @change="changeValue('textColor')"
                   />
-                  <label style="width: 44px">前景</label>
+                  <label style="width: 44px">{{$t( '前景' )}}</label>
                   <t-color-picker
                     class="simple mt-8 mr-4"
                     :enable-alpha="true"
@@ -695,119 +589,49 @@
                     v-model="data.textBackground"
                     @change="changeValue('textBackground')"
                   />
-                  <label style="width: 44px">背景</label>
+                  <label style="width: 44px">{{$t( '背景' )}}</label>
 
-                  <t-color-picker
-                    class="simple mt-8 mr-4"
-                    :enable-alpha="true"
-                    :recent-colors="null"
-                    format="CSS"
-                    :swatch-colors="defaultPureColor"
-                    :color-modes="['monochrome']"
-                    :show-primary-color-preview="false"
-                    v-model="data.hoverTextColor"
-                    @change="changeValue('hoverTextColor')"
-                  />
-                  <label style="width: 44px">悬停</label>
+                  <t-color-picker class="simple mt-8 mr-4" :enable-alpha="true" :recent-colors="null" format="CSS" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.hoverTextColor" @change="changeValue('hoverTextColor')"></t-color-picker>
+                  <label style="width: 44px">{{$t('悬停')}}</label>
 
-                  <t-color-picker
-                    class="simple mt-8 mr-4"
-                    format="CSS"
-                    :enable-alpha="true"
-                    :recent-colors="null"
-                    :swatch-colors="defaultPureColor"
-                    :color-modes="['monochrome']"
-                    :show-primary-color-preview="false"
-                    v-model="data.activeTextColor"
-                    @change="changeValue('activeTextColor')"
-                  />
-                  <label style="width: 44px">选中</label>
+                  <t-color-picker class="simple mt-8 mr-4" format="CSS" :enable-alpha="true" :recent-colors="null" :swatch-colors="defaultPureColor" :color-modes="['monochrome']" :show-primary-color-preview="false" v-model="data.activeTextColor" @change="changeValue('activeTextColor')"></t-color-picker>
+                  <label style="width: 44px">{{$t('选中')}}</label>
                 </div>
                 <div class="form-item">
-                  <t-checkbox
-                    v-model="data.whiteSpace"
-                    @change="changeValue('whiteSpace')"
-                    style="width: 64px"
-                  >
-                    换行
+                  <t-checkbox v-model="data.whiteSpace" @change="changeValue('whiteSpace')" style="width: 64px">
+                    {{$t('换行')}}
                   </t-checkbox>
-                  <t-checkbox
-                    v-model="data.ellipsis"
-                    @change="changeValue('ellipsis')"
-                    style="width: 68px"
-                  >
-                    省略号
+                  <t-checkbox v-model="data.ellipsis" @change="changeValue('ellipsis')" style="width: 68px">
+                    {{$t('省略号')}}
                   </t-checkbox>
-                  <t-tooltip content="行高">
-                    <t-input
-                      placeholder="行高"
-                      v-model.number="data.lineHeight"
-                      style="width: 40px"
-                      @change="changeValue('lineHeight')"
-                    />
+                  <t-tooltip :content="$t('行高')">
+                    <t-input v-model.number="data.lineHeight" style="width: 40px" @change="changeValue('lineHeight')" :placeholder="$t('行高')"></t-input>
                   </t-tooltip>
-                  <t-tooltip content="显示时保留小数位数">
-                    <t-input
-                      class="ml-4"
-                      placeholder="小数"
-                      v-model.number="data.keepDecimal"
-                      style="width: 60px"
-                      @change="changeValue('keepDecimal')"
-                    />
+                  <t-tooltip :content="$t('显示时保留小数位数')">
+                    <t-input class="ml-4" v-model.number="data.keepDecimal" style="width: 60px" @change="changeValue('keepDecimal')" :placeholder="$t('小数')"></t-input>
                   </t-tooltip>
                 </div>
                 <div class="form-item" style="margin-top: -4px">
-                  <t-tooltip content="水平偏移">
-                    <t-input
-                      placeholder="X"
-                      v-model.number="data.textLeft"
-                      style="width: 60px; margin-left: -8px"
-                      @change="changeValue('textLeft')"
-                    />
+                  <t-tooltip :content="$t('水平偏移')">
+                    <t-input placeholder="X" v-model.number="data.textLeft" style="width: 60px; margin-left: -8px" @change="changeValue('textLeft')"></t-input>
                   </t-tooltip>
-                  <t-tooltip content="垂直偏移">
-                    <t-input
-                      class="ml-4"
-                      placeholder="Y"
-                      v-model.number="data.textTop"
-                      style="width: 60px"
-                      @change="changeValue('textTop')"
-                    />
+                  <t-tooltip :content="$t('垂直偏移')">
+                    <t-input class="ml-4" placeholder="Y" v-model.number="data.textTop" style="width: 60px" @change="changeValue('textTop')"></t-input>
                   </t-tooltip>
-                  <t-tooltip content="宽">
-                    <t-input
-                      class="ml-4"
-                      placeholder="宽"
-                      v-model.number="data.textWidth"
-                      style="width: 60px"
-                      @change="changeValue('textWidth')"
-                    />
+                  <t-tooltip :content="$t('宽')">
+                    <t-input class="ml-4" v-model.number="data.textWidth" style="width: 60px" @change="changeValue('textWidth')" :placeholder="$t('宽')"></t-input>
                   </t-tooltip>
-                  <t-tooltip content="高">
-                    <t-input
-                      class="ml-4"
-                      placeholder="高"
-                      v-model.number="data.textHeight"
-                      style="width: 60px"
-                      @change="changeValue('textHeight')"
-                    />
+                  <t-tooltip :content="$t('高')">
+                    <t-input class="ml-4" v-model.number="data.textHeight" style="width: 60px" @change="changeValue('textHeight')" :placeholder="$t('高')"></t-input>
                   </t-tooltip>
                 </div>
                 <div class="flex middle">
-                  <t-checkbox
-                    v-model="data.disableInput"
-                    @change="changeValue('disableInput')"
-                    style="width: 64px"
-                  >
-                    只读
+                  <t-checkbox v-model="data.disableInput" @change="changeValue('disableInput')" style="width: 64px">
+                    {{$t('只读')}}
                   </t-checkbox>
 
-                  <t-checkbox
-                    v-model="data.hiddenText"
-                    @change="changeValue('hiddenText')"
-                    style="width: 90px"
-                  >
-                    隐藏文字
+                  <t-checkbox v-model="data.hiddenText" @change="changeValue('hiddenText')" style="width: 90px">
+                    {{$t('隐藏文字')}}
                   </t-checkbox>
                 </div>
               </t-space>
@@ -816,52 +640,26 @@
         </t-space>
         <t-divider style="margin-top: -8px" />
         <div class="form-item p-16">
-          <t-checkbox
-            v-model="data.flipX"
-            @change="changeValue('flipX')"
-            style="width: 90px"
-          >
-            水平翻转
+          <t-checkbox v-model="data.flipX" @change="changeValue('flipX')" style="width: 90px">
+            {{$t('水平翻转')}}
           </t-checkbox>
-          <t-checkbox
-            v-model="data.flipY"
-            @change="changeValue('flipY')"
-            style="width: 90px"
-          >
-            垂直翻转
+          <t-checkbox v-model="data.flipY" @change="changeValue('flipY')" style="width: 90px">
+            {{$t('垂直翻转')}}
           </t-checkbox>
 
-          <label style="width: 50px">锚点半径</label>
-          <input
-            class="ml-4"
-            v-model.number="data.anchorRadius"
-            style="width: 20px"
-            @change="changeValue('anchorRadius')"
-            placeholder="4"
-          />
+          <label style="width: 50px">{{$t('锚点半径')}}</label>
+          <input class="ml-4" v-model.number="data.anchorRadius" style="width: 20px" @change="changeValue('anchorRadius')" placeholder="4">
         </div>
         <t-divider />
         <div class="form-item p-16" style="margin-bottom: 20px">
-          <t-checkbox
-            v-model="data.disableRotate"
-            @change="changeValue('disableRotate')"
-            style="width: 90px"
-          >
-            禁止旋转
+          <t-checkbox v-model="data.disableRotate" @change="changeValue('disableRotate')" style="width: 90px">
+            {{$t('禁止旋转')}}
           </t-checkbox>
-          <t-checkbox
-            v-model="data.disableSize"
-            @change="changeValue('disableSize')"
-            style="width: 90px"
-          >
-            禁止缩放
+          <t-checkbox v-model="data.disableSize" @change="changeValue('disableSize')" style="width: 90px">
+            {{$t('禁止缩放')}}
           </t-checkbox>
-          <t-checkbox
-            v-model="data.disableAnchor"
-            @change="changeValue('disableAnchor')"
-            style="width: 90px"
-          >
-            禁用锚点
+          <t-checkbox v-model="data.disableAnchor" @change="changeValue('disableAnchor')" style="width: 90px">
+            {{$t('禁用锚点')}}
           </t-checkbox>
         </div>
       </t-tab-panel>
@@ -870,7 +668,7 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, onUnmounted, reactive, ref, computed } from 'vue';
+import { onBeforeMount, onUnmounted, reactive, ref, computed,getCurrentInstance } from 'vue';
 
 import { LockState, Pen, isDomShapes } from '@meta2d/core';
 
@@ -882,7 +680,8 @@ import { defaultGradientColor, defaultPureColor } from '@/services/defaults';
 import { BrowseIcon, BrowseOffIcon, ChevronDownIcon, FormatVerticalAlignLeftIcon, FormatHorizontalAlignCenterIcon, FormatVerticalAlignCenterIcon, FormatVerticalAlignRightIcon, FormatHorizontalAlignTopIcon, FormatHorizontalAlignBottomIcon  } from 'tdesign-icons-vue-next';
 
 const { selections } = useSelection();
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const data = reactive<any>({
   tab: 1,
   locked: 0,
@@ -892,32 +691,32 @@ const data = reactive<any>({
 const vAligns = [
   {
     value: 'left',
-    label: '左对齐',
+    label: $t('左对齐'),
     icon: '#l-align-left',
   },
   {
     value: 'center',
-    label: '垂直居中对齐',
+    label: $t('垂直居中对齐'),
     icon: '#l-align-center',
   },
   {
     value: 'right',
-    label: '右对齐',
+    label: $t('右对齐'),
     icon: '#l-align-right',
   },
   {
     value: 'top',
-    label: '顶部对齐',
+    label: $t('顶部对齐'),
     icon: '#l-align-top',
   },
   {
     value: 'middle',
-    label: '水平居中对齐',
+    label: $t('水平居中对齐'),
     icon: '#l-align-middle',
   },
   {
     value: 'bottom',
-    label: '底部对齐',
+    label: $t('底部对齐'),
     icon: '#l-align-bottom',
   }
 ];
@@ -925,42 +724,42 @@ const vAligns = [
 const aligns = [
   {
     value: 'left',
-    label: '左对齐',
+    label: $t('左对齐'),
     icon: '#l-align-left',
   },
   {
     value: 'center',
-    label: '垂直居中对齐',
+    label: $t('垂直居中对齐'),
     icon: '#l-align-center',
   },
   {
     value: 'right',
-    label: '右对齐',
+    label: $t('右对齐'),
     icon: '#l-align-right',
   },
   {
     value: 'top',
-    label: '顶部对齐',
+    label: $t('顶部对齐'),
     icon: '#l-align-top',
   },
   {
     value: 'middle',
-    label: '水平居中对齐',
+    label: $t('水平居中对齐'),
     icon: '#l-align-middle',
   },
   {
     value: 'bottom',
-    label: '底部对齐',
+    label: $t('底部对齐'),
     icon: '#l-align-bottom',
   },
   {
     value: 'h-distribute',
-    label: '水平等距',
+    label: $t('水平等距'),
     icon: '#l-horizontal-between',
   },
   {
     value: 'v-distribute',
-    label: '垂直等距',
+    label: $t('垂直等距'),
     icon: '#l-vertical-between',
   },
 ];
@@ -968,37 +767,37 @@ const aligns = [
 const aligns2 = [
   {
     value: 'left',
-    label: '左对齐',
+    label: $t('左对齐'),
     icon: '#l-align-left',
   },
   {
     value: 'center',
-    label: '垂直居中对齐',
+    label: $t('垂直居中对齐'),
     icon: '#l-align-center',
   },
   {
     value: 'right',
-    label: '右对齐',
+    label: $t('右对齐'),
     icon: '#l-align-right',
   },
   {
     value: 'top',
-    label: '顶部对齐',
+    label: $t('顶部对齐'),
     icon: '#l-align-top',
   },
   {
     value: 'middle',
-    label: '水平居中对齐',
+    label: $t('水平居中对齐'),
     icon: '#l-align-middle',
   },
   {
     value: 'bottom',
-    label: '底部对齐',
+    label: $t('底部对齐'),
     icon: '#l-align-bottom',
   },
   {
     value: 'same-size',
-    label: '相同大小',
+    label: $t('相同大小'),
     icon: '#l-same-size',
   },
 ];

+ 33 - 55
src/views/components/Structure.vue

@@ -1,33 +1,30 @@
 <template>
-  <div class="elements props" v-show="group === '图层'">
-    <div
-      class="flex mt-16 mb-16"
-      style="justify-content: end; padding-right: 8px"
-    >
-      <t-tooltip content="置顶" placement="top">
+  <div class="elements props" :v-show="'group' === $t('图层')">
+    <div class="flex mt-16 mb-16" style="justify-content: end; padding-right: 8px">
+      <t-tooltip placement="top" :content="$t('置顶')">
         <div class="icon-box" @click="changeActivLayer('top')">
-          <BacktopIcon />
+          <BacktopIcon></BacktopIcon>
         </div>
       </t-tooltip>
-      <t-tooltip content="置底" placement="top">
+      <t-tooltip placement="top" :content="$t('置底')">
         <div class="icon-box" @click="changeActivLayer('bottom')">
-          <Download1Icon />
+          <Download1Icon></Download1Icon>
         </div>
       </t-tooltip>
-      <t-tooltip content="上一层" placement="top">
+      <t-tooltip placement="top" :content="$t('上一层')">
         <div class="icon-box" @click="changeActivLayer('up')">
-          <ArrowUpIcon />
+          <ArrowUpIcon></ArrowUpIcon>
         </div>
       </t-tooltip>
-      <t-tooltip content="下一层" placement="top">
+      <t-tooltip placement="top" :content="$t('下一层')">
         <div class="icon-box" @click="changeActivLayer('down')">
-          <ArrowDownIcon />
+          <ArrowDownIcon></ArrowDownIcon>
         </div>
       </t-tooltip>
-      <t-tooltip :content="data.expandAll ? '折叠' : '展开'" placement="top">
+      <t-tooltip :content="data.expandAll ? $t('折叠') : $t('展开')" placement="top">
         <div class="icon-box" @click="changeExpand">
-          <MenuFoldIcon v-if="data.expandAll" />
-          <MenuUnfoldIcon v-else />
+          <MenuFoldIcon v-if="data.expandAll"></MenuFoldIcon>
+          <MenuUnfoldIcon v-else></MenuUnfoldIcon>
         </div>
       </t-tooltip>
     </div>
@@ -59,8 +56,8 @@
           <!-- <t-tooltip v-else-if="node.data.tag === 'dom'" content="DOM元素">
             <Code1Icon />
           </t-tooltip> -->
-          <t-tooltip v-else :content="node.data.tag === 'dom' ? 'DOM元素' : ''">
-            <control-platform-icon class="mr-8" />
+          <t-tooltip v-else :content="node.data.tag === $t('dom') ? $t('DOM元素') : $t('')">
+            <control-platform-icon class="mr-8"></control-platform-icon>
           </t-tooltip>
           <t-input
             v-if="node.data.edited"
@@ -91,42 +88,22 @@
           style="width: 46px; height: 16px"
         >
           <template v-if="!node.data.value.endsWith('Layer')">
-            <t-tooltip
-              class="mr-8"
-              v-if="!node.data.locked"
-              content="可编辑"
-              placement="top"
-            >
+            <t-tooltip class="mr-8" v-if="!node.data.locked" placement="top" :content="$t('可编辑')">
               <svg class="l-icon" aria-hidden="true" @click="lock(node, 1)">
                 <use xlink:href="#l-unlock"></use>
               </svg>
             </t-tooltip>
-            <t-tooltip
-              class="mr-8"
-              v-else-if="node.data.locked == 1"
-              content="禁止编辑"
-              placement="top"
-            >
+            <t-tooltip class="mr-8" v-else-if="node.data.locked == 1" placement="top" :content="$t('禁止编辑')">
               <svg class="l-icon" aria-hidden="true" @click="lock(node, 2)">
                 <use xlink:href="#l-lock"></use>
               </svg>
             </t-tooltip>
-            <t-tooltip
-              class="mr-8"
-              v-else-if="node.data.locked == 2"
-              content="禁止编辑和移动"
-              placement="top"
-            >
+            <t-tooltip class="mr-8" v-else-if="node.data.locked == 2" placement="top" :content="$t('禁止编辑和移动')">
               <svg class="l-icon" aria-hidden="true" @click="lock(node, 10)">
                 <use xlink:href="#l-wufayidong"></use>
               </svg>
             </t-tooltip>
-            <t-tooltip
-              class="mr-8"
-              v-else-if="node.data.locked == 10"
-              content="禁止所有事件"
-              placement="top"
-            >
+            <t-tooltip class="mr-8" v-else-if="node.data.locked == 10" placement="top" :content="$t('禁止所有事件')">
               <svg class="l-icon" aria-hidden="true" @click="lock(node, 0)">
                 <use xlink:href="#l-jinyong"></use>
               </svg>
@@ -142,11 +119,11 @@
       </template>
     </t-tree>
   </div>
-  <div class="elements" v-show="group === '分组'">
+  <div class="elements" :v-show="'group' === $t('分组')">
     <div class="groups-panel" style="padding: 8px 0">
       <div class="flex middle between" style="padding: 0 12px">
-        <div class="title">分组</div>
-        <t-tooltip content="新建分组" placement="top">
+        <div class="title">{{$t('分组')}}</div>
+        <t-tooltip placement="top" :content="$t('新建分组')">
           <div class="icon-box" @click="addGroup">
             <AddIcon />
           </div>
@@ -182,7 +159,7 @@
           />
           <browse-off-icon v-else @click="visibleGroup(item, true)" />
           <t-popconfirm
-            content="确认删除该分组吗?"
+            :content="$t('确认删除该分组吗?')"
             @confirm="delGroup"
             @cancel="data.deleteGroup = undefined"
           >
@@ -199,7 +176,7 @@
 </template>
 
 <script lang="ts" setup>
-import { onBeforeMount, onMounted, onBeforeUnmount, reactive, ref } from 'vue';
+import { onBeforeMount, onMounted, onBeforeUnmount, reactive, ref, getCurrentInstance} from 'vue';
 import { MessagePlugin } from 'tdesign-vue-next';
 
 import { LockState, Pen, isDomShapes } from '@meta2d/core';
@@ -224,7 +201,8 @@ import {
 const props = defineProps<{
   group: string;
 }>();
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const tree = ref<any>(null);
 const data = reactive<any>({
   tree: [],
@@ -310,25 +288,25 @@ const getPhysicalTree = () => {
 
   const list = [
     {
-      label: '上层图片层', //4
+      label: $t('上层图片层'), //4
       value: 'imageLayer',
       children: imageLayer,
       zIndex: 3.5,
     },
     {
-      label: '主画布层', //3
+      label: $t('主画布层'), //3
       value: 'mainLayer',
       children: mainLayer,
       zIndex: 2.5,
     },
     {
-      label: '底层图片层', //2
+      label: $t('底层图片层'), //2
       value: 'imageBottomLayer',
       children: imageBottomLayer,
       zIndex: 1.5,
     },
     {
-      label: '模版层', //1
+      label: $t('模版层'), //1
       value: 'templateLayer',
       children: templateLayer,
       zIndex: 0.5,
@@ -395,7 +373,7 @@ const changeActivLayer = (key: string) => {
   if (meta2d.store.active && meta2d.store.active.length) {
     meta2d[key]();
   } else {
-    MessagePlugin.info('请先选中图元');
+    MessagePlugin.info($t('请先选中图元'));
   }
 };
 
@@ -611,7 +589,7 @@ const onDescription = (node: any) => {
 
 const addGroup = () => {
   const i = data.groups.length + 1;
-  data.group = '组' + i;
+  data.group = $t('组') + i;
   data.groups.push(data.group);
   data.activedGroup = data.editedGroup = i;
 };
@@ -636,7 +614,7 @@ const setGroup = () => {
   }
 
   if (data.groups.includes(data.group)) {
-    MessagePlugin.error('已经存在相同分组!');
+    MessagePlugin.error($t('已经存在相同分组!'));
     return;
   }
 

File diff suppressed because it is too large
+ 172 - 278
src/views/components/View.vue


+ 18 - 20
src/views/components/common/ShareModal.vue

@@ -9,30 +9,27 @@
     <div class="shareModal">
       <div class="item" v-if="shareFlag">
         <t-radio-group v-model:value="isShare" @change="onChange">
-          <t-radio :value="true"> 分享公开 </t-radio>
-          <t-radio :value="false"> 不分享 </t-radio>
+          <t-radio :value="true"> {{$t('分享公开')}} </t-radio>
+          <t-radio :value="false"> {{$t('不分享')}} </t-radio>
         </t-radio-group>
       </div>
       <div class="item">
-        <t-input
-          v-model:value="link"
-          :readonly="true"
-        />
-        <t-button @click="onSearch">复制链接</t-button>
+        <t-input v-model:value="link" :readonly="true"></t-input>
+        <t-button @click="onSearch">{{$t('复制链接')}}</t-button>
       </div>
-      <div class="desc">分享到</div>
+      <div class="desc">{{$t('分享到')}}</div>
       <t-loading :loading="loading">
         <div class="code-box flex">
           <div class="code flex-1">
-            <img class="code-img" :src="qr" />
-            <p class="subdesc">扫一扫</p>
+            <img class="code-img" :src="qr">
+            <p class="subdesc">{{$t('扫一扫')}}</p>
           </div>
           <div class="code flex-1">
-            <img class="code-img" ref="codeImg" />
-            <p class="subdesc">微信扫一扫</p>
+            <img class="code-img" ref="codeImg">
+            <p class="subdesc">{{$t('微信扫一扫')}}</p>
           </div>
           <div class="remark">
-            分享私有图纸请确保小程序登录的账号与PC端一致,或者将私有图纸设置为分享公开,才可以正常扫码预览。
+            {{$t('分享私有图纸请确保小程序登录的账号与')}}PC{{$t('端一致')}}{{$t('或者将私有图纸设置为分享公开')}}{{$t('才可以正常扫码预览')}}
           </div>
         </div>
       </t-loading>
@@ -41,7 +38,7 @@
 </template>
 
 <script lang="ts" setup>
-import { defineComponent, nextTick, ref, computed, watch } from "vue";
+import { defineComponent, nextTick, ref, computed, watch, getCurrentInstance } from "vue";
 import QRCode from "qrcode";
 import { useRoute } from "vue-router";
 import { MessagePlugin } from "tdesign-vue-next";
@@ -49,7 +46,8 @@ import axios from "@/http";
 import { Meta2dBackData } from "@/services/utils";
 import { useUser } from "@/services/user";
 import { rootDomain } from "@/services/defaults";
-
+const { proxy } = getCurrentInstance();
+const $t = proxy.$t
 const props = defineProps<{
   visible: boolean;
   shared: boolean;
@@ -73,7 +71,7 @@ function onChange(e) {
 }
 function onSearch() {
   copy2clipboard(link.value);
-  MessagePlugin.success("复制链接成功!");
+  MessagePlugin.success($t("复制链接成功!"));
 }
 function copy2clipboard(copyText: string) {
   //1 手动创建可编辑元素,比如textarea,
@@ -99,7 +97,7 @@ async function share(shared: boolean) {
   const id = route.query.id;
   if (!id) {
     // 提示需要先保存
-    MessagePlugin.warning("请先保存!");
+    MessagePlugin.warning($t("请先保存!"));
     return;
   }
   const res: any = await axios.post(`/api/data/v/update`, {
@@ -110,7 +108,7 @@ async function share(shared: boolean) {
   if (res.error) {
     return;
   }
-  MessagePlugin.success(shared ? "分享成功!" : "取消分享成功");
+  MessagePlugin.success(shared ? $t("分享成功!") : $t("取消分享成功"));
 }
 async function getQRcode(url: string) {
   const q: any = await QRCode.toDataURL(url, { margin: 0 });
@@ -144,12 +142,12 @@ watch(
         try {
           await getQRcode(url);
         } catch (error) {
-          MessagePlugin.warning("获取二维码失败!");
+          MessagePlugin.warning($t("获取二维码失败!"));
         }
         try {
           await getWXCode((id as string).split("-").join(""));
         } catch (error) {
-          MessagePlugin.warning("获取微信小程序码失败!");
+          MessagePlugin.warning($t("获取微信小程序码失败!"));
           loading.value = false;
         }
         loading.value = false;

Some files were not shown because too many files changed in this diff