Compare commits

...

210 Commits

Author SHA1 Message Date
shefengchun 9cd50bc908 修复pc端操作融合带 伽马值校正时不发送数据 2023-03-14 14:26:50 +08:00
shefengchun 9b677d7828 修复 曲面校正增加点后 切换点数量不发送 添加整个融合的注释 2023-03-14 14:19:16 +08:00
shefengchun eed5964f02 放开是否禁用融合参数 显示网格 修改箭头大小 为平板增加融合带伽马值操作适配 2023-03-14 10:13:23 +08:00
miao 6bfdb69fd8 修复清屏时,依然存在的active样式 2023-03-09 19:12:20 +08:00
miao be2a23fdff 关闭全部时以及清屏清除显示器当前选择 2023-03-09 17:50:12 +08:00
miao 3d0925f444 修复删除窗口错误删除 2023-03-09 17:41:57 +08:00
miao 4ddd39864e 合并时异常,对比修改 2023-03-09 16:33:46 +08:00
miao 1379a257c7 Merge branch 'magic_wall_' into master_v2
# Conflicts:
#	src/components/FusionSettings/DensityCorrection.vue
#	src/components/FusionSettings/FourPointCalibration.vue
#	src/components/FusionSettings/SurfaceCorrection.vue
#	src/components/FusionSettingsDialog.vue
2023-03-09 16:10:43 +08:00
miao d7104f33fd 修复多次点击恢复显示器列表全部出现 2023-03-09 15:46:15 +08:00
miao 70d7a7010e 修改显示文字 2023-03-09 15:08:49 +08:00
miao 66dffac3fe 修复点恢复时,可能会恢复多次情况 2023-03-09 14:37:46 +08:00
miao ea83d8023a 修复显示器列表宽高的变化 2023-03-09 14:11:56 +08:00
miao 4821e2100c 融合修改至3.3版本 2023-03-09 13:55:47 +08:00
shefengchun 6d5a661004 在03版本的基础上修改 隐藏融合页面的 禁用融合参数 显示网格 按钮 将背景颜色从辅助放到融合界面 2023-03-09 12:43:08 +08:00
miao 6105a290b3 测试代码 2023-03-09 10:19:32 +08:00
miao ed0e427cd3 修改角度不能设置为小数 2023-03-09 10:12:35 +08:00
miao 946f2dda3f Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2
# Conflicts:
#	src/components/FusionSettings/FusionLocale.vue
2023-03-09 10:12:35 +08:00
miao 7213e6bddb 魔墙:修改角度超出问题,以及显示器列表全部设置为一样的默认值 2023-03-09 10:10:20 +08:00
miao caac3e3d60 魔墙:打开对话框时初始化变量,多选对齐完清空多选 2023-03-09 10:10:20 +08:00
miao 1f1a26de65 魔墙:加开窗避免显示为空 2023-03-09 10:10:19 +08:00
miao 8583f77627 魔墙:删除合并信息 2023-03-09 10:10:19 +08:00
miao 0f6972635c WIP on master_v2: c318910 删除合并信息 2023-03-09 10:10:19 +08:00
miao 590ea06f2f index on master_v2: c318910 删除合并信息 2023-03-09 10:10:18 +08:00
miao 7b25ddfee0 删除合并信息 2023-03-09 10:10:17 +08:00
miao b6820b4368 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2
# Conflicts:
#	src/components/ControlPanelDialog.vue
2023-03-09 10:10:09 +08:00
miao 4aef830905 魔墙:修复清屏未及时通知
# Conflicts:
#	src/components/ControlPanelDialog.vue
2023-03-09 10:09:43 +08:00
miao f0c6ad03d9 魔墙:修复清屏未及时通知 2023-03-09 10:09:24 +08:00
miao 191beed68d 魔墙:修改对话框大小 2023-03-09 10:09:24 +08:00
miao b2f2805247 魔墙:增加翻译,修复虚拟窗口选中,修改角度坐标会乱选中窗口,添加魔墙的显示器列表宽高信息,增加恢复时恢复显示器列表信息 2023-03-09 10:09:24 +08:00
miao 7a0842ea24 魔墙:保持显示器宽高不变 2023-03-09 10:09:23 +08:00
miao 67d3799550 魔墙:修复多次删除其他窗口消失 2023-03-09 10:09:23 +08:00
miao a6842221ad Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2
# Conflicts:
#	src/components/ControlPanelDialog.vue
2023-03-03 17:21:28 +08:00
miao be5bffaaff 修复点击更换数据未及时更换 2023-03-03 17:17:48 +08:00
miao 9eee4a4d1f 修复点击更换数据未及时更换 2023-03-03 17:15:41 +08:00
shefengchun 44ae08f0c1 修复疏密校正键盘操作点不移动 2023-03-03 14:19:36 +08:00
shefengchun c62a34e34b 加入键盘awsd交互 2023-03-03 14:09:59 +08:00
shefengchun 70cb05c4ce 将平板模式下的长按识别设置为15ms 2023-03-03 11:34:06 +08:00
shefengchun 12504e0ff6 优化疏密校正ui 修复融合带平板模式下 不能选中融合带的问题 2023-03-03 11:25:22 +08:00
shefengchun 55cba70a1c 为平板增加融合带操作弹窗 2023-03-03 09:52:25 +08:00
shefengchun 52dd69a9a5 增加保存配置时的删除 2023-03-02 15:58:31 +08:00
shefengchun e5a142fad4 修复投影机只显示一行的bug 2023-03-02 14:30:46 +08:00
shefengchun 33e76ee393 修复曲面校正和疏密校正多点切换时不修改当前选中的点数 2023-03-01 17:11:04 +08:00
shefengchun 0a5f561bd6 只在平板模式下语言为英语时更改ui适配 2023-03-01 15:18:07 +08:00
shefengchun 2c498c05f0 为平板模式下英文做适配 2023-03-01 15:09:50 +08:00
shefengchun 75311073cb 优化ui细节 2023-03-01 13:47:26 +08:00
shefengchun 14076866ec 修复 融合设置参数同步问题 投影机布局从后端获取 2023-03-01 11:19:56 +08:00
fangxiang 44aadff1d2 注册码可以鼠标选中复制 2023-02-28 17:15:42 +08:00
shefengchun 82fc72c185 修复快速 多次点击重置所有导致界面不显示 2023-02-28 16:08:49 +08:00
shefengchun 006d13af6a 修复疏密调整数据下发错误 2023-02-28 15:49:17 +08:00
shefengchun 1eb926d029 修复曲面校正不发送默认点数 2023-02-28 14:39:32 +08:00
shefengchun a87b1bc380 修复数据发送顺序不对导致的问题 2023-02-28 14:04:01 +08:00
shefengchun 593323a934 修复疏密数据计算错误导致的错误 2023-02-28 10:29:17 +08:00
shefengchun 039d2d2de3 平板模式下疏密不允许拖动 2023-02-28 09:31:05 +08:00
shefengchun 3f499105d9 增加平板支持 2023-02-27 17:36:04 +08:00
shefengchun 243516ca6d Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-27 10:51:11 +08:00
shefengchun 6360f499da 修改融合带值保证为偶数 2023-02-27 10:20:28 +08:00
fangxiang bb438b9eec 增加升级完后刷新浏览器或者清空缓存的提示 2023-02-27 09:59:37 +08:00
miao 61b3766012 修复文件上传不能及时看见文件 2023-02-27 09:12:38 +08:00
shefengchun f8dd60edbd 删除无效代码 2023-02-24 17:37:34 +08:00
shefengchun d59a111b0d Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-24 17:36:17 +08:00
shefengchun 48466524bb 修复首页数据 不同步 2023-02-24 17:36:13 +08:00
miao 46dee256f3 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-24 16:56:42 +08:00
miao 84ae856c71 魔墙修复多次点击恢复异常 2023-02-24 16:56:31 +08:00
shefengchun 55b518facc Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-24 16:47:50 +08:00
shefengchun 4738681294 优化提示 修改ui大小 2023-02-24 16:47:46 +08:00
miao da7a4bdd05 修复魔墙层级问题以及恢复问题 2023-02-24 16:38:42 +08:00
shefengchun 5998be5c1c 修复 投影机下发错误 2023-02-24 16:04:13 +08:00
shefengchun 5ce15fcb80 修复切换投影机布局的错误 2023-02-24 15:33:14 +08:00
shefengchun efb6f0437a 修复界面数据错误 2023-02-24 15:06:37 +08:00
shefengchun d71124dfc4 修复 切换显示排列错误 2023-02-24 14:33:10 +08:00
shefengchun 2f645fa71c 修复 四点校正 限制问题 2023-02-24 14:08:42 +08:00
shefengchun 5027ba5233 加入限制 2023-02-24 14:00:14 +08:00
shefengchun aa0e83045b 修复曲面校正不发送当前点数 2023-02-24 09:42:13 +08:00
shefengchun 77e270c6b2 增加 动态添加值细节 2023-02-23 19:47:16 +08:00
shefengchun d29ca4c6dd 修复融合参数界面同步错误问题 2023-02-23 19:32:51 +08:00
shefengchun 361bcb7719 修复 是否同步操作不保存状态 2023-02-23 17:31:41 +08:00
shefengchun ae87589a45 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-23 17:11:08 +08:00
shefengchun 800dfec98d 修复动态添加时重置全部方案数据错误 优化细节 2023-02-23 17:10:51 +08:00
fangxiang 3bc125cff0 注册协议增加attribute字段 2023-02-23 16:46:50 +08:00
shefengchun 5c7ac2a7d0 修复重置时不保存数据 2023-02-23 14:35:52 +08:00
miao 1b93f2f92a 魔墙状态主页面右键开窗适应大小 2023-02-23 11:13:01 +08:00
shefengchun 3b84db438f 更改ui 修复摄影机数量显示错误问题 2023-02-23 09:35:28 +08:00
shefengchun 1d7e4de1d1 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-22 17:44:49 +08:00
shefengchun 740ff764e5 加入 投影机最大数量限制 2023-02-22 17:44:43 +08:00
miao 9c7d961e67 添加魔墙状态主页面的轮询开窗 2023-02-22 17:00:36 +08:00
shefengchun 966fe44583 删除不必要的代码 2023-02-22 15:09:35 +08:00
shefengchun 899fdc5e66 修复获取不到数据的错误 2023-02-22 15:01:19 +08:00
ljqing 98975d4cd5 修改字符串 2023-02-22 14:55:48 +08:00
miao f0f340e9a9 修复主页面显示魔墙时开机异常 2023-02-22 14:51:38 +08:00
shefengchun 09c37b7e82 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-22 14:33:52 +08:00
shefengchun 52c375fc7d 加入鼠标滚轮交互 2023-02-22 14:33:47 +08:00
miao a380a132b7 修复主页面因关开机导致的窗口变化问题 2023-02-22 14:08:12 +08:00
fangxiang ba2594addf 解决合并错误 2023-02-21 20:05:31 +08:00
fangxiang 53ca6af019 注册细分产品 2023-02-21 19:59:37 +08:00
shefengchun 6c304fdfe6 加入投影机布局选择 2023-02-21 17:10:54 +08:00
shefengchun fdeb182c75 完成动态曲面添加 2023-02-21 14:10:48 +08:00
ljqing e4003940da 非空判断 2023-02-20 19:49:58 +08:00
fangxiang 789e80cffc 修改版本号 2023-02-20 19:00:56 +08:00
fangxiang ee37d680b2 增加GetHttpInterfaceVersion来校验兼容性 2023-02-20 18:58:34 +08:00
fangxiang 00c4056b5d 增加http接口兼容判断 2023-02-20 15:17:20 +08:00
miao a4c3a24dda Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-20 15:05:29 +08:00
miao e9cbd79d3b 修复无界状态的显示墙靠下 2023-02-20 15:05:01 +08:00
ljqing 4a8aacd710 Merge branch 'blending' into master_v2 2023-02-20 09:14:19 +08:00
shefengchun 740f175b69 修复参数不带分辨率选择时卡死 2023-02-17 17:30:23 +08:00
miao 1ce66817d4 Merge branch 'master_v2' of http://www.cloudview.work/git/fangxiang/media_player_client into master_v2 2023-02-17 14:29:46 +08:00
miao a45c188c1e 判断是否为无界,显示隐藏底图升级数据恢复等操作 2023-02-17 14:28:03 +08:00
ljqing a254c7d118 修改融合界面 2023-02-17 14:20:00 +08:00
ljqing dea3713269 修改字符串 2023-02-17 14:00:04 +08:00
ljqing 652f6bfd2e Merge branch 'blending' into master_v2 2023-02-17 09:38:52 +08:00
shefengchun ff00c6e652 更改ui 2023-02-17 09:37:37 +08:00
shefengchun b4338153f9 增加交互增加设置分辨率 2023-02-16 16:31:29 +08:00
ljqing 3fcd25ec96 增加设置投影机布局接口 2023-02-16 15:44:52 +08:00
shefengchun 7f833fd6f2 加入选择分辨率 2023-02-16 15:40:48 +08:00
shefengchun 06dfea0815 修复动态添加的bug 2023-02-16 14:53:36 +08:00
ljqing 8a197be56a 增加设置投影机分辨率 2023-02-16 14:44:43 +08:00
miao 601a95a33e 修复文件上传中列表滚动 2023-02-16 11:34:55 +08:00
miao 27f914c995 升级对话框显示服务器版本 2023-02-16 11:10:49 +08:00
ljqing 1bfb5af0a5 Merge branch 'blending' into master_v2 2023-02-15 19:42:09 +08:00
ljqing 5f3f9fd074 重置所有只发一条指令 2023-02-15 19:37:17 +08:00
ljqing 3afdf5c3bc 非空判断 2023-02-15 19:22:18 +08:00
fangxiang 80c44141e0 Merge commit 'a5df1e0635866baf7b8c1bc91c4a2334572c9298' into master_v2 2023-02-15 19:08:58 +08:00
fangxiang f9207cd6eb Merge branch 'FileManager' into master_v2 2023-02-15 19:08:18 +08:00
miao b2bd16128a 修改文件上传之后的提示 2023-02-15 18:10:38 +08:00
miao fc6b23432c 新增文件夹时添加限制 2023-02-15 18:10:38 +08:00
miao e68eb4c8d6 将数据恢复,底图上传,查看底图,升级的http转化 2023-02-15 18:10:37 +08:00
fangxiang 71abf1bba2 修改为最新的数据库备份协议 2023-02-15 18:10:20 +08:00
fangxiang a2102bdb5e 适配最新的文件上传接口 2023-02-15 18:10:20 +08:00
miao 5a1dba7a8f 检查索引的http请求改为websocket 2023-02-15 18:10:19 +08:00
miao e4827b4fe6 修改文件上传为多个 2023-02-15 18:10:18 +08:00
fangxiang 3e2a941f80 Merge remote-tracking branch 'remotes/origin/blending' into merge_fm_fusion
# Conflicts:
#	src/common/ClientConnection.ts
#	src/components/FileManageDialog.vue
#	src/entities/WSProtocol.ts
#	src/i18n/en-US/index.ts
#	src/i18n/zh-CN/index.ts
#	src/pages/TopToolBar.vue
#	src/store/index.ts
2023-02-15 18:03:06 +08:00
fangxiang a5df1e0635 WIP on merge_fm: d16df7a 合并FileManager 2023-02-15 16:36:57 +08:00
fangxiang 1273319fb6 index on merge_fm: d16df7a 合并FileManager 2023-02-15 16:36:57 +08:00
fangxiang d16df7ada8 合并FileManager 2023-02-15 16:36:51 +08:00
shefengchun 12a940a55f 修复动态添加的一些错误 2023-02-15 15:08:47 +08:00
shefengchun dbecb1ff15 增加动态添加点 2023-02-15 09:34:42 +08:00
miao c35ff719c6 判断是否为无界,显示文件对话框的上传文件 2023-02-14 10:18:13 +08:00
miao febcf00d94 升级对话框显示服务器版本 2023-02-14 09:45:09 +08:00
miao 8b6949f087 勾选融合,输出设置固定 2023-02-14 09:23:45 +08:00
miao aee328fb82 将文件管理的http请求改为websocket 2023-02-12 15:58:54 +08:00
fangxiang 2a6e8e78c0 修复网络高级设置访问未定义变量的错误 2023-02-10 17:09:38 +08:00
fangxiang f4b2e6cd15 修改在线注册的IP校验 2023-02-10 16:31:39 +08:00
fangxiang 2930add85f 修改IP、子网掩码的校验逻辑 2023-02-10 16:29:47 +08:00
fangxiang 225fbd4faf 网络设置调换子网掩码和默认网关的位置,保持和Windows网络设置的顺序一致 2023-02-10 16:29:46 +08:00
ljqing da82416bd1 添加删除控制点数量 2023-02-10 14:07:33 +08:00
miao b0751a1b18 添加融合选项在高级调试和在线注册 2023-02-10 11:03:11 +08:00
shefengchun c88033899b 删除调试信息 2023-02-10 09:56:24 +08:00
shefengchun b3cc026b41 修复键盘监听导致的输入问题 2023-02-10 09:55:11 +08:00
shefengchun e37999a924 增加辅助线和服务端数据同步 2023-02-10 09:38:20 +08:00
fangxiang 114dd2794e 升级Quasar 2023-02-09 20:06:55 +08:00
miao c6c4522be7 完善无界模式显示全屏效果 2023-02-09 20:06:55 +08:00
miao 33413fbb27 增加全屏 2023-02-09 20:06:54 +08:00
fangxiang b2aff3720c 开放云服务设置,增加加载完后通知主应用功能 2023-02-09 20:06:54 +08:00
shefengchun 15088f9d5e 增加疏密界面选择点时发送当前点 2023-02-09 16:57:08 +08:00
miao 9ad2665b0d 魔墙:修复滑动条及输入控件随键盘而改变;加中心坐标变为3840*2160;修改主界面的魔墙颜色; 2023-02-09 14:10:01 +08:00
miao 71bb5d58e7 魔墙:添加更新通知 2023-02-08 09:08:01 +08:00
miao b58ad2a4fd 魔墙:添加更新通知 2023-02-07 14:59:33 +08:00
miao 2ca40619d5 魔墙:添加栅格图按钮 2023-02-03 16:27:28 +08:00
miao e940f24b52 Merge branch 'magic_wall'
# Conflicts:
#	src/common/ClientConnection.ts
#	src/components/RegisterDialog.vue
#	src/components/SystemSettingDialog.vue
#	src/entities/MagicWallConfig.ts
#	src/entities/RectF.ts
#	src/entities/WSProtocol.ts
#	src/i18n/en-US/index.ts
#	src/i18n/zh-CN/index.ts
#	src/pages/TopToolBar.vue
#	src/store/index.ts
2023-02-01 13:41:33 +08:00
miao 3accecee65 魔墙:将导出按钮换成shift+s 2023-02-01 09:26:29 +08:00
miao 17118497e2 增加翻译 2023-01-31 14:30:55 +08:00
miao 939ce286f3 魔墙:导出格式优化 2023-01-31 14:26:51 +08:00
miao 9c211e13bf 魔墙:增加导出坐标 2023-01-31 14:17:21 +08:00
miao 6864213d67 添加更新魔墙翻译 2023-01-30 14:37:53 +08:00
miao d47ebdf1d4 魔墙:修复因恢复导致的控制台缩放导致显示错误 2023-01-30 14:35:50 +08:00
miao 3c20ba2461 添加魔墙在主页面的显示 2023-01-29 15:07:46 +08:00
fangxiang ed2632279b 更新翻译 2023-01-19 13:42:01 +08:00
fangxiang d9c0368b7b 合并钟仕骏提交的配置服务器IP界面(需要Debug) 2023-01-18 19:08:28 +08:00
fangxiang 2b60548fa9 添加无界模式初始化代码 2023-01-18 17:32:02 +08:00
fangxiang e5b8380fe3 修复信号源组修改失败的BUG 2023-01-16 09:59:28 +08:00
方 向 d37e1bfd43 Merge pull request '添加无界连接对象' (#1) from iswebserve into master
Reviewed-on: http://www.cloudview.work/git/fangxiang/media_player_client/pulls/1
2023-01-16 09:34:41 +08:00
miao 385b5a230f 添加无界连接对象 2023-01-16 09:20:28 +08:00
miao a20a1c916c 魔墙:打开及时更新 2023-01-13 08:57:39 +08:00
fangxiang a81b7bbbc4 修复无界eventBus类型错误的问题 2023-01-11 16:26:12 +08:00
miao e38899754e 魔墙:添加对齐 2023-01-11 15:52:05 +08:00
miao b64ba60922 魔墙:添加对齐 2023-01-10 15:19:01 +08:00
fangxiang e4faef2694 启用gzip压缩,编译发布版本关闭控制台输出 2023-01-10 10:05:58 +08:00
miao d41b0843b1 魔墙:修复添加宽高后出现的bug 2023-01-10 08:49:46 +08:00
fangxiang c44a2076f3 字幕默认字体强制设置为60pt 2023-01-07 16:52:03 +08:00
fangxiang 273a141823 更新Tinymce到6版本并增加wordcount插件显示字数。
增加服务端返回自定义标题功能
更新Quasar版本
更新英文翻译
2023-01-07 14:20:48 +08:00
fangxiang b8319dee50 离线注册增加功能选项 2023-01-06 14:11:33 +08:00
fangxiang 089ce906d4 Merge branch 'wujie' 2023-01-06 13:59:19 +08:00
miao cbdaa5ee92 魔墙:修复添加宽高后,控制台显示宽高不变 2023-01-06 11:29:50 +08:00
fangxiang aa43b6965b SpecialVideo 隐藏WindowSize工具栏按钮和虚拟窗口右键菜单 2023-01-06 10:47:47 +08:00
fangxiang 3a92bee88e 增加无界实例保存到store 2023-01-06 10:27:43 +08:00
miao 27dfbe138f 魔墙:显示列表添加可修改单个窗口的宽高 2023-01-05 15:19:36 +08:00
fangxiang cc8a36708d 路由懒加载全部改为一次性加载 2023-01-05 10:35:36 +08:00
miao ae6eb30af5 魔墙:添加根据输出版设置显示器个数 2023-01-05 08:59:27 +08:00
miao 35d5a3fdb9 魔墙:修改更新提示以及缩放的步长 2023-01-04 09:21:35 +08:00
miao 5f9ab983e0 魔墙:删除显示器时实时更新 2023-01-03 17:29:10 +08:00
miao 45e2e4589e 魔墙:添加实时更新提示 2023-01-03 17:14:31 +08:00
miao 4ecd2ab89d 魔墙:恢复按钮以及实时更新 2023-01-03 15:00:54 +08:00
miao c21585bdba Merge branch 'magic_wall' of http://www.cloudview.work/git/fangxiang/media_player_client into magic_wall 2022-12-30 14:05:46 +08:00
miao ddc87b464d 删除魔墙控制台输出 2022-12-30 14:04:33 +08:00
miao bbde7029d8 魔墙:修改旋转后的多选移动 2022-12-30 14:01:22 +08:00
彭 苗 a5488a0aca 更新 'src/components/ControlPanelDialog.vue'
魔墙:修复旋转后多选移动bug
2022-12-29 16:52:39 +08:00
miao 2807b58d4a 魔墙:控制台输出删除 2022-12-29 15:26:34 +08:00
miao 887407ddb9 魔墙:修复单个选中移动超出 2022-12-29 15:24:35 +08:00
miao 4f83a9b0e5 魔墙:修复未选中元素键盘上下左右报错 2022-12-28 16:30:58 +08:00
miao c0b97255d3 魔墙:添加多选的键盘移动 2022-12-28 16:25:22 +08:00
miao 330c8a205e 魔墙:添加单个可键盘上下左右移动 2022-12-28 10:48:40 +08:00
miao 5f23bf8194 修改魔墙,因旋转导致输入框限制错误 2022-12-28 09:21:46 +08:00
miao bddc61c63b 修改魔墙因旋转,中心点发生变化而引起的拖拽超出 2022-12-27 15:46:24 +08:00
miao f65ee05422 修改魔墙旋转时超出 2022-12-27 15:01:05 +08:00
miao 5f4ab631d0 修改魔墙背景为16:9 2022-12-26 11:36:53 +08:00
miao 938cb8ed83 魔墙添加上传时的参数-背景墙的分辨率 2022-12-26 10:10:29 +08:00
miao d342ba6b54 删除控制台输出调试 2022-12-22 11:45:46 +08:00
miao 7e28f2c5ea 魔墙添加缩放功能 2022-12-22 11:24:28 +08:00
miao e6fed227dc 初步基本功能实现 2022-12-16 14:59:19 +08:00
miao 2b1ab68d29 合并分支 2022-12-13 14:56:36 +08:00
miao a43188c3a1 添加魔墙对话框 2022-12-13 14:42:25 +08:00
75 changed files with 16664 additions and 10058 deletions

View File

@ -1,6 +1,6 @@
{
"name": "media_player_client",
"version": "1.5.6",
"version": "1.6.0",
"description": "A Quasar Framework app",
"productName": "MediaPlayerClient",
"author": "fangxiang <fangxiang@cloudview.work>",
@ -9,16 +9,18 @@
"test": "echo \"No test specified\" && exit 0"
},
"dependencies": {
"@quasar/cli": "^1.3.2",
"@quasar/extras": "^1.15.6",
"@quasar/cli": "^2.0.0",
"@quasar/extras": "^1.15.11",
"@tinymce/tinymce-vue": "4",
"@types/element-resize-detector": "^1.1.3",
"autoprefixer": "^10.4.2",
"axios": "^0.21.1",
"babel-loader": "^9.1.2",
"core-js": "^3.21.0",
"element-resize-detector": "^1.2.4",
"konva": "^8.4.2",
"qrcode.vue": "^3.3.3",
"quasar": "^2.10.2",
"quasar": "^2.11.6",
"reconnecting-websocket": "^4.4.0",
"sortablejs": "^1.15.0",
"to": "^0.2.9",
@ -26,8 +28,8 @@
"update": "^0.7.4",
"v-viewer": "^3.0.9",
"vue": "^3.0.0",
"vue-drag-resize": "^1.5.4",
"vue-i18n": "^9.1.9",
"vue-konva": "^3.0.2",
"vue-router": "^4.0.0",
"vue3-draggable-resizable": "^1.6.5",
"vuex": "^4.0.1",
@ -35,7 +37,7 @@
},
"devDependencies": {
"@capacitor/core": "^2.5.0",
"@quasar/app": "^3.3.3",
"@quasar/app-webpack": "^3.7.1",
"@types/node": "^10.17.15",
"workbox-webpack-plugin": "^6.4.2"
},

BIN
public/magic_bg/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -1,3 +1,5 @@
window.media_control_client_product = "LED_PLAYER";
// window.media_control_client_product = "SPECIAL_VIDEO";
// window.media_control_client_product = "RK_3568";
window.media_control_client_custom_title = "SmartPlayer";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 262 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
This is where language files should be placed.
Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/

View File

@ -0,0 +1,412 @@
/*!
* TinyMCE Language Pack
*
* Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc.
* Licensed under the Tiny commercial license. See https://www.tiny.cloud/legal/
*/
tinymce.addI18n('zh-Hans', {
"Redo": "重做",
"Undo": "撤销",
"Cut": "剪切",
"Copy": "复制",
"Paste": "粘贴",
"Select all": "全选",
"New document": "新建文档",
"Ok": "确定",
"Cancel": "取消",
"Visual aids": "网格线",
"Bold": "粗体",
"Italic": "斜体",
"Underline": "下划线",
"Strikethrough": "删除线",
"Superscript": "上标",
"Subscript": "下标",
"Clear formatting": "清除格式",
"Remove": "移除",
"Align left": "左对齐",
"Align center": "居中对齐",
"Align right": "右对齐",
"No alignment": "未对齐",
"Justify": "两端对齐",
"Bullet list": "无序列表",
"Numbered list": "有序列表",
"Decrease indent": "减少缩进",
"Increase indent": "增加缩进",
"Close": "关闭",
"Formats": "格式",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.": "你的浏览器不支持打开剪贴板请使用Ctrl+X/C/V等快捷键。",
"Headings": "标题",
"Heading 1": "一级标题",
"Heading 2": "二级标题",
"Heading 3": "三级标题",
"Heading 4": "四级标题",
"Heading 5": "五级标题",
"Heading 6": "六级标题",
"Preformatted": "预先格式化的",
"Div": "Div",
"Pre": "前言",
"Code": "代码",
"Paragraph": "段落",
"Blockquote": "引文区块",
"Inline": "文本",
"Blocks": "样式",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "当前为纯文本粘贴模式,再次点击可以回到普通粘贴模式。",
"Fonts": "字体",
"Font sizes": "字体大小",
"Class": "类型",
"Browse for an image": "浏览图像",
"OR": "或",
"Drop an image here": "拖放一张图像至此",
"Upload": "上传",
"Uploading image": "上传图片",
"Block": "块",
"Align": "对齐",
"Default": "预设",
"Circle": "空心圆",
"Disc": "实心圆",
"Square": "实心方块",
"Lower Alpha": "小写英文字母",
"Lower Greek": "小写希腊字母",
"Lower Roman": "小写罗马数字",
"Upper Alpha": "大写英文字母",
"Upper Roman": "大写罗马数字",
"Anchor...": "锚点...",
"Anchor": "锚点",
"Name": "名称",
"ID": "ID",
"ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "ID应该以英文字母开头后面只能有英文字母、数字、破折号、点、冒号或下划线。",
"You have unsaved changes are you sure you want to navigate away?": "你还有文档尚未保存,确定要离开?",
"Restore last draft": "恢复上次的草稿",
"Special character...": "特殊字符...",
"Special Character": "特殊字符",
"Source code": "源代码",
"Insert/Edit code sample": "插入/编辑代码示例",
"Language": "语言",
"Code sample...": "示例代码...",
"Left to right": "由左到右",
"Right to left": "由右到左",
"Title": "标题",
"Fullscreen": "全屏",
"Action": "动作",
"Shortcut": "快捷方式",
"Help": "帮助",
"Address": "地址",
"Focus to menubar": "移动焦点到菜单栏",
"Focus to toolbar": "移动焦点到工具栏",
"Focus to element path": "移动焦点到元素路径",
"Focus to contextual toolbar": "移动焦点到上下文菜单",
"Insert link (if link plugin activated)": "插入链接 (如果链接插件已激活)",
"Save (if save plugin activated)": "保存(如果保存插件已激活)",
"Find (if searchreplace plugin activated)": "查找(如果查找替换插件已激活)",
"Plugins installed ({0}):": "已安装插件 ({0}):",
"Premium plugins:": "优秀插件:",
"Learn more...": "了解更多...",
"You are using {0}": "你正在使用 {0}",
"Plugins": "插件",
"Handy Shortcuts": "快捷键",
"Horizontal line": "水平分割线",
"Insert/edit image": "插入/编辑图片",
"Alternative description": "替代描述",
"Accessibility": "辅助功能",
"Image is decorative": "图像是装饰性的",
"Source": "源",
"Dimensions": "尺寸",
"Constrain proportions": "保持比例",
"General": "一般",
"Advanced": "高级",
"Style": "样式",
"Vertical space": "垂直间距",
"Horizontal space": "水平间距",
"Border": "框线",
"Insert image": "插入图片",
"Image...": "图片...",
"Image list": "图片清单",
"Resize": "调整大小",
"Insert date/time": "插入日期/时间",
"Date/time": "日期/时间",
"Insert/edit link": "插入/编辑链接",
"Text to display": "要显示的文本",
"Url": "地址",
"Open link in...": "链接打开位置...",
"Current window": "当前窗口",
"None": "无",
"New window": "新窗口",
"Open link": "打开链接",
"Remove link": "移除链接",
"Anchors": "锚点",
"Link...": "链接...",
"Paste or type a link": "粘贴或输入链接",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "你所填写的URL地址为邮件地址需要加上mailto: 前缀吗?",
"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": "你所填写的URL地址属于外部链接需要加上http:// 前缀吗?",
"The URL you entered seems to be an external link. Do you want to add the required https:// prefix?": "您输入的 URL 似乎是一个外部链接。您想添加所需的 https:// 前缀吗?",
"Link list": "链接清单",
"Insert video": "插入视频",
"Insert/edit video": "插入/编辑视频",
"Insert/edit media": "插入/编辑媒体",
"Alternative source": "镜像",
"Alternative source URL": "替代来源网址",
"Media poster (Image URL)": "封面(图片地址)",
"Paste your embed code below:": "将内嵌代码粘贴在下面:",
"Embed": "内嵌",
"Media...": "多媒体...",
"Nonbreaking space": "不间断空格",
"Page break": "分页符",
"Paste as text": "粘贴为文本",
"Preview": "预览",
"Print": "打印",
"Print...": "打印...",
"Save": "保存",
"Find": "寻找",
"Replace with": "替换为",
"Replace": "替换",
"Replace all": "替换全部",
"Previous": "上一个",
"Next": "下一个",
"Find and Replace": "查找和替换",
"Find and replace...": "查找并替换...",
"Could not find the specified string.": "未找到搜索内容。",
"Match case": "大小写匹配",
"Find whole words only": "全字匹配",
"Find in selection": "在选区中查找",
"Insert table": "插入表格",
"Table properties": "表格属性",
"Delete table": "删除表格",
"Cell": "单元格",
"Row": "行",
"Column": "栏目",
"Cell properties": "单元格属性",
"Merge cells": "合并单元格",
"Split cell": "拆分单元格",
"Insert row before": "在上方插入行",
"Insert row after": "在下方插入行",
"Delete row": "删除行",
"Row properties": "行属性",
"Cut row": "剪切行",
"Cut column": "剪切列",
"Copy row": "复制行",
"Copy column": "复制列",
"Paste row before": "粘贴行到上方",
"Paste column before": "粘贴此列前",
"Paste row after": "粘贴行到下方",
"Paste column after": "粘贴后面的列",
"Insert column before": "在左侧插入列",
"Insert column after": "在右侧插入列",
"Delete column": "删除列",
"Cols": "列",
"Rows": "行数",
"Width": "宽度",
"Height": "高度",
"Cell spacing": "单元格外间距",
"Cell padding": "单元格内边距",
"Row clipboard actions": "行剪贴板操作",
"Column clipboard actions": "列剪贴板操作",
"Table styles": "表格样式",
"Cell styles": "单元格样式",
"Column header": "列标题",
"Row header": "行头",
"Table caption": "表格标题",
"Caption": "标题",
"Show caption": "显示标题",
"Left": "左",
"Center": "居中",
"Right": "右",
"Cell type": "储存格别",
"Scope": "范围",
"Alignment": "对齐",
"Horizontal align": "水平对齐",
"Vertical align": "垂直对齐",
"Top": "上方对齐",
"Middle": "居中对齐",
"Bottom": "下方对齐",
"Header cell": "表头单元格",
"Row group": "行组",
"Column group": "列组",
"Row type": "行类型",
"Header": "表头",
"Body": "表体",
"Footer": "表尾",
"Border color": "框线颜色",
"Solid": "实线",
"Dotted": "虚线",
"Dashed": "虚线",
"Double": "双精度",
"Groove": "凹槽",
"Ridge": "海脊座",
"Inset": "嵌入",
"Outset": "外置",
"Hidden": "隐藏",
"Insert template...": "插入模板...",
"Templates": "模板",
"Template": "模板",
"Insert Template": "插入模板",
"Text color": "文本颜色",
"Background color": "背景颜色",
"Custom...": "自定义......",
"Custom color": "自定义颜色",
"No color": "无",
"Remove color": "移除颜色",
"Show blocks": "显示区块边框",
"Show invisible characters": "显示不可见字符",
"Word count": "字数",
"Count": "计数",
"Document": "文档",
"Selection": "选择",
"Words": "单词",
"Words: {0}": "字数:{0}",
"{0} words": "{0} 字",
"File": "文件",
"Edit": "编辑",
"Insert": "插入",
"View": "查看",
"Format": "格式",
"Table": "表格",
"Tools": "工具",
"Powered by {0}": "由{0}驱动",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "编辑区。按ALT-F9打开菜单按ALT-F10打开工具栏按ALT-0查看帮助",
"Image title": "图片标题",
"Border width": "边框宽度",
"Border style": "边框样式",
"Error": "错误",
"Warn": "警告",
"Valid": "有效",
"To open the popup, press Shift+Enter": "按Shitf+Enter键打开对话框",
"Rich Text Area": "富文本区域",
"Rich Text Area. Press ALT-0 for help.": "编辑区。按Alt+0键打开帮助。",
"System Font": "系统字体",
"Failed to upload image: {0}": "图片上传失败: {0}",
"Failed to load plugin: {0} from url {1}": "插件加载失败: {0} 来自链接 {1}",
"Failed to load plugin url: {0}": "插件加载失败 链接: {0}",
"Failed to initialize plugin: {0}": "插件初始化失败: {0}",
"example": "示例",
"Search": "搜索",
"All": "全部",
"Currency": "货币",
"Text": "文字",
"Quotations": "引用",
"Mathematical": "数学",
"Extended Latin": "拉丁语扩充",
"Symbols": "符号",
"Arrows": "箭头",
"User Defined": "自定义",
"dollar sign": "美元符号",
"currency sign": "货币符号",
"euro-currency sign": "欧元符号",
"colon sign": "冒号",
"cruzeiro sign": "克鲁赛罗币符号",
"french franc sign": "法郎符号",
"lira sign": "里拉符号",
"mill sign": "密尔符号",
"naira sign": "奈拉符号",
"peseta sign": "比塞塔符号",
"rupee sign": "卢比符号",
"won sign": "韩元符号",
"new sheqel sign": "新谢克尔符号",
"dong sign": "越南盾符号",
"kip sign": "老挝基普符号",
"tugrik sign": "图格里克符号",
"drachma sign": "德拉克马符号",
"german penny symbol": "德国便士符号",
"peso sign": "比索符号",
"guarani sign": "瓜拉尼符号",
"austral sign": "澳元符号",
"hryvnia sign": "格里夫尼亚符号",
"cedi sign": "塞地符号",
"livre tournois sign": "里弗弗尔符号",
"spesmilo sign": "spesmilo符号",
"tenge sign": "坚戈符号",
"indian rupee sign": "印度卢比",
"turkish lira sign": "土耳其里拉",
"nordic mark sign": "北欧马克",
"manat sign": "马纳特符号",
"ruble sign": "卢布符号",
"yen character": "日元字样",
"yuan character": "人民币元字样",
"yuan character, in hong kong and taiwan": "元字样(港台地区)",
"yen/yuan character variant one": "元字样(大写)",
"Emojis": "Emojis",
"Emojis...": "Emojis...",
"Loading emojis...": "正在加载Emojis...",
"Could not load emojis": "无法加载Emojis",
"People": "人类",
"Animals and Nature": "动物和自然",
"Food and Drink": "食物和饮品",
"Activity": "活动",
"Travel and Places": "旅游和地点",
"Objects": "物件",
"Flags": "旗帜",
"Characters": "字符",
"Characters (no spaces)": "字符(无空格)",
"{0} characters": "{0} 个字符",
"Error: Form submit field collision.": "错误: 表单提交字段冲突。",
"Error: No form element found.": "错误: 没有表单控件。",
"Color swatch": "颜色样本",
"Color Picker": "选色器",
"Invalid hex color code: {0}": "十六进制颜色代码无效: {0}",
"Invalid input": "无效输入",
"R": "R",
"Red component": "红色部分",
"G": "G",
"Green component": "绿色部分",
"B": "B",
"Blue component": "白色部分",
"#": "#",
"Hex color code": "十六进制颜色代码",
"Range 0 to 255": "范围0至255",
"Turquoise": "青绿色",
"Green": "绿色",
"Blue": "蓝色",
"Purple": "紫色",
"Navy Blue": "海军蓝",
"Dark Turquoise": "深蓝绿色",
"Dark Green": "深绿色",
"Medium Blue": "中蓝色",
"Medium Purple": "中紫色",
"Midnight Blue": "深蓝色",
"Yellow": "黄色",
"Orange": "橙色",
"Red": "红色",
"Light Gray": "浅灰色",
"Gray": "灰色",
"Dark Yellow": "暗黄色",
"Dark Orange": "深橙色",
"Dark Red": "深红色",
"Medium Gray": "中灰色",
"Dark Gray": "深灰色",
"Light Green": "浅绿色",
"Light Yellow": "浅黄色",
"Light Red": "浅红色",
"Light Purple": "浅紫色",
"Light Blue": "浅蓝色",
"Dark Purple": "深紫色",
"Dark Blue": "深蓝色",
"Black": "黑色",
"White": "白色",
"Switch to or from fullscreen mode": "切换全屏模式",
"Open help dialog": "打开帮助对话框",
"history": "历史",
"styles": "样式",
"formatting": "格式化",
"alignment": "对齐",
"indentation": "缩进",
"Font": "字体",
"Size": "字号",
"More...": "更多...",
"Select...": "选择...",
"Preferences": "首选项",
"Yes": "是",
"No": "否",
"Keyboard Navigation": "键盘指引",
"Version": "版本",
"Code view": "代码视图",
"Open popup menu for split buttons": "打开弹出式菜单,用于拆分按钮",
"List Properties": "列表属性",
"List properties...": "标题字体属性",
"Start list at number": "以数字开始列表",
"Line height": "行高",
"Dropped file type is not supported": "此文件类型不支持拖放",
"Loading...": "加载中...",
"ImageProxy HTTP error: Rejected request": "图片代理请求错误:请求被拒绝",
"ImageProxy HTTP error: Could not find Image Proxy": "图片代理请求错误:无法找到图片代理",
"ImageProxy HTTP error: Incorrect Image Proxy URL": "图片代理请求错误:图片代理地址错误",
"ImageProxy HTTP error: Unknown ImageProxy error": "图片代理请求错误:未知的图片代理错误"
});

View File

@ -1,417 +0,0 @@
tinymce.addI18n('zh_CN',{
"Redo": "恢复",
"Undo": "撤销",
"Cut": "剪切",
"Copy": "复制",
"Paste": "粘贴",
"Select all": "全选",
"New document": "新建文档",
"Ok": "确定",
"Cancel": "取消",
"Visual aids": "网格线",
"Bold": "粗体",
"Italic": "斜体",
"Underline": "下划线",
"Strikethrough": "删除线",
"Superscript": "上标",
"Subscript": "下标",
"Clear formatting": "清除格式",
"Align left": "左对齐",
"Align center": "居中",
"Align right": "右对齐",
"Justify": "两端对齐",
"Bullet list": "符号列表",
"Numbered list": "数字列表",
"Decrease indent": "减少缩进",
"Increase indent": "增加缩进",
"Close": "关闭",
"Formats": "格式",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "当前浏览器不支持访问剪贴板请使用快捷键Ctrl+X/C/V复制粘贴",
"Headers": "标题",
"Header 1": "标题1",
"Header 2": "标题2",
"Header 3": "标题3",
"Header 4": "标题4",
"Header 5": "标题5",
"Header 6": "标题6",
"Headings": "标题",
"Heading 1": "标题1",
"Heading 2": "标题2",
"Heading 3": "标题3",
"Heading 4": "标题4",
"Heading 5": "标题5",
"Heading 6": "标题6",
"Preformatted": "预格式化",
"Div": "Div区块",
"Pre": "预格式文本",
"Code": "代码",
"Paragraph": "段落",
"Blockquote": "引用",
"Inline": "文本",
"Blocks": "区块",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "当前为纯文本粘贴模式,再次点击可以回到普通粘贴模式。",
"Fonts": "字体",
"Font Sizes": "字号",
"Class": "Class",
"Browse for an image": "浏览图像",
"OR": "或",
"Drop an image here": "拖放一张图片文件至此",
"Upload": "上传",
"Block": "块",
"Align": "对齐",
"Default": "默认",
"Circle": "空心圆",
"Disc": "实心圆",
"Square": "方块",
"Lower Alpha": "小写英文字母",
"Lower Greek": "小写希腊字母",
"Lower Roman": "小写罗马字母",
"Upper Alpha": "大写英文字母",
"Upper Roman": "大写罗马字母",
"Anchor...": "锚点...",
"Name": "名称",
"Id": "id",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "id应该以字母开头后跟字母、数字、横线、点、冒号或下划线。",
"You have unsaved changes are you sure you want to navigate away?": "你对文档的修改尚未保存,确定离开吗?",
"Restore last draft": "恢复上次的草稿",
"Special characters...": "特殊字符...",
"Source code": "HTML源码",
"Insert\/Edit code sample": "插入/编辑代码示例",
"Language": "语言",
"Code sample...": "代码示例...",
"Color Picker": "选取颜色",
"R": "R",
"G": "G",
"B": "B",
"Left to right": "从左到右",
"Right to left": "从右到左",
"Emoticons...": "表情符号...",
"Metadata and Document Properties": "元数据和文档属性",
"Title": "标题",
"Keywords": "关键词",
"Description": "描述",
"Robots": "机器人",
"Author": "作者",
"Encoding": "编码",
"Fullscreen": "全屏",
"Action": "操作",
"Shortcut": "快捷键",
"Help": "帮助",
"Address": "地址",
"Focus to menubar": "移动焦点到菜单栏",
"Focus to toolbar": "移动焦点到工具栏",
"Focus to element path": "移动焦点到元素路径",
"Focus to contextual toolbar": "移动焦点到上下文菜单",
"Insert link (if link plugin activated)": "插入链接 (如果链接插件已激活)",
"Save (if save plugin activated)": "保存(如果保存插件已激活)",
"Find (if searchreplace plugin activated)": "查找(如果查找替换插件已激活)",
"Plugins installed ({0}):": "已安装插件 ({0})",
"Premium plugins:": "优秀插件:",
"Learn more...": "了解更多...",
"You are using {0}": "你正在使用 {0}",
"Plugins": "插件",
"Handy Shortcuts": "快捷键",
"Horizontal line": "水平分割线",
"Insert\/edit image": "插入/编辑图片",
"Image description": "图片描述",
"Source": "地址",
"Dimensions": "大小",
"Constrain proportions": "保持宽高比",
"General": "常规",
"Advanced": "高级",
"Style": "样式",
"Vertical space": "垂直边距",
"Horizontal space": "水平边距",
"Border": "边框",
"Insert image": "插入图片",
"Image...": "图片...",
"Image list": "图片列表",
"Rotate counterclockwise": "逆时针旋转",
"Rotate clockwise": "顺时针旋转",
"Flip vertically": "垂直翻转",
"Flip horizontally": "水平翻转",
"Edit image": "编辑图片",
"Image options": "图片选项",
"Zoom in": "放大",
"Zoom out": "缩小",
"Crop": "裁剪",
"Resize": "调整大小",
"Orientation": "方向",
"Brightness": "亮度",
"Sharpen": "锐化",
"Contrast": "对比度",
"Color levels": "色阶",
"Gamma": "伽马值",
"Invert": "反转",
"Apply": "应用",
"Back": "后退",
"Insert date\/time": "插入日期/时间",
"Date\/time": "日期/时间",
"Insert\/Edit Link": "插入/编辑链接",
"Insert\/edit link": "插入/编辑链接",
"Text to display": "显示文字",
"Url": "地址",
"Open link in...": "链接打开方式...",
"Current window": "当前窗口打开",
"None": "在当前窗口/框架打开",
"New window": "在新窗口打开",
"Remove link": "删除链接",
"Anchors": "锚点",
"Link...": "链接...",
"Paste or type a link": "粘贴或输入链接",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "你所填写的URL地址为邮件地址需要加上mailto:前缀吗?",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "你所填写的URL地址属于外部链接需要加上http://:前缀吗?",
"Link list": "链接列表",
"Insert video": "插入视频",
"Insert\/edit video": "插入/编辑视频",
"Insert\/edit media": "插入/编辑媒体",
"Alternative source": "替代资源",
"Alternative image URL": "资源备用地址",
"Media poster (Image URL)": "封面(图片地址)",
"Paste your embed code below:": "将内嵌代码粘贴在下面:",
"Embed": "内嵌",
"Media...": "多媒体...",
"Nonbreaking space": "不间断空格",
"Page break": "分页符",
"Paste as text": "粘贴为文本",
"Preview": "预览",
"Print...": "打印...",
"Save": "保存",
"Find": "查找",
"Replace with": "替换为",
"Replace": "替换",
"Replace all": "替换全部",
"Previous": "上一个",
"Next": "下一个",
"Find and replace...": "查找并替换...",
"Could not find the specified string.": "未找到搜索内容。",
"Match case": "区分大小写",
"Find whole words only": "全单词匹配",
"Spell check": "拼写检查",
"Ignore": "忽略",
"Ignore all": "忽略全部",
"Finish": "完成",
"Add to Dictionary": "添加到字典",
"Insert table": "插入表格",
"Table properties": "表格属性",
"Delete table": "删除表格",
"Cell": "单元格",
"Row": "行",
"Column": "列",
"Cell properties": "单元格属性",
"Merge cells": "合并单元格",
"Split cell": "拆分单元格",
"Insert row before": "在上方插入",
"Insert row after": "在下方插入",
"Delete row": "删除行",
"Row properties": "行属性",
"Cut row": "剪切行",
"Copy row": "复制行",
"Paste row before": "粘贴到上方",
"Paste row after": "粘贴到下方",
"Insert column before": "在左侧插入",
"Insert column after": "在右侧插入",
"Delete column": "删除列",
"Cols": "列",
"Rows": "行",
"Width": "宽",
"Height": "高",
"Cell spacing": "单元格外间距",
"Cell padding": "单元格内边距",
"Show caption": "显示标题",
"Left": "左对齐",
"Center": "居中",
"Right": "右对齐",
"Cell type": "单元格类型",
"Scope": "范围",
"Alignment": "对齐方式",
"H Align": "水平对齐",
"V Align": "垂直对齐",
"Top": "顶部对齐",
"Middle": "垂直居中",
"Bottom": "底部对齐",
"Header cell": "表头单元格",
"Row group": "行组",
"Column group": "列组",
"Row type": "行类型",
"Header": "表头",
"Body": "表体",
"Footer": "表尾",
"Border color": "边框颜色",
"Insert template...": "插入模板...",
"Templates": "模板",
"Template": "模板",
"Text color": "文字颜色",
"Background color": "背景色",
"Custom...": "自定义...",
"Custom color": "自定义颜色",
"No color": "无",
"Remove color": "删除颜色",
"Table of Contents": "目录",
"Show blocks": "显示区块边框",
"Show invisible characters": "显示不可见字符",
"Word count": "字数统计",
"Words: {0}": "字数:{0}",
"{0} words": "{0} 个字",
"File": "文件",
"Edit": "编辑",
"Insert": "插入",
"View": "查看",
"Format": "格式",
"Table": "表格",
"Tools": "工具",
"Powered by {0}": "Powered by {0}",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "在编辑区按ALT+F9打开菜单按ALT+F10打开工具栏按ALT+0查看帮助",
"Image title": "图片标题",
"Border width": "边框宽度",
"Border style": "边框样式",
"Error": "错误",
"Warn": "警告",
"Valid": "有效",
"To open the popup, press Shift+Enter": "此快捷为软回车(插入<br>",
"Rich Text Area. Press ALT-0 for help.": "编辑区. 按Alt+0键打开帮助",
"System Font": "默认字体",
"Failed to upload image: {0}": "图片上传失败: {0}",
"Failed to load plugin: {0} from url {1}": "插件加载失败: {0} - {1}",
"Failed to load plugin url: {0}": "插件加载失败: {0}",
"Failed to initialize plugin: {0}": "插件初始化失败: {0}",
"example": "示例",
"Search": "查找",
"All": "全部",
"Currency": "货币",
"Text": "文本",
"Quotations": "引用",
"Mathematical": "数学运算符",
"Extended Latin": "拉丁语扩充",
"Symbols": "符号",
"Arrows": "箭头",
"User Defined": "自定义",
"dollar sign": "美元",
"currency sign": "货币",
"euro-currency sign": "欧元",
"colon sign": "冒号",
"cruzeiro sign": "克鲁赛罗币",
"french franc sign": "法郎",
"lira sign": "里拉",
"mill sign": "密尔",
"naira sign": "奈拉",
"peseta sign": "比塞塔",
"rupee sign": "卢比",
"won sign": "韩元",
"new sheqel sign": "新谢克尔",
"dong sign": "越南盾",
"kip sign": "老挝基普",
"tugrik sign": "图格里克",
"drachma sign": "德拉克马",
"german penny symbol": "德国便士",
"peso sign": "比索",
"guarani sign": "瓜拉尼",
"austral sign": "澳元",
"hryvnia sign": "格里夫尼亚",
"cedi sign": "塞地",
"livre tournois sign": "里弗弗尔",
"spesmilo sign": "一千spesoj的货币符号该货币未使用",
"tenge sign": "坚戈",
"indian rupee sign": "印度卢比",
"turkish lira sign": "土耳其里拉",
"nordic mark sign": "北欧马克",
"manat sign": "马纳特",
"ruble sign": "卢布",
"yen character": "日元",
"yuan character": "人民币元",
"yuan character, in hong kong and taiwan": "元的繁体字",
"yen\/yuan character variant one": "元(大写)",
"Loading emoticons...": "正在加载表情文字...",
"Could not load emoticons": "不能加载表情文字",
"People": "人类",
"Animals and Nature": "动物和自然",
"Food and Drink": "食物和饮品",
"Activity": "活动",
"Travel and Places": "旅游和地点",
"Objects": "物件",
"Flags": "旗帜",
"Characters": "字数",
"Characters (no spaces)": "字数(不含空格)",
"Error: Form submit field collision.": "错误: 表单提交字段冲突.",
"Error: No form element found.": "错误: 未找到可用的form.",
"Update": "更新",
"Color swatch": "颜色样本",
"Turquoise": "青绿",
"Green": "绿色",
"Blue": "蓝色",
"Purple": "紫色",
"Navy Blue": "海军蓝",
"Dark Turquoise": "深蓝绿色",
"Dark Green": "暗绿",
"Medium Blue": "中蓝",
"Medium Purple": "中紫",
"Midnight Blue": "深蓝",
"Yellow": "黄色",
"Orange": "橙色",
"Red": "红色",
"Light Gray": "浅灰",
"Gray": "灰色",
"Dark Yellow": "暗黄",
"Dark Orange": "暗橙",
"Dark Red": "暗红",
"Medium Gray": "中灰",
"Dark Gray": "深灰",
"Black": "黑色",
"White": "白色",
"Switch to or from fullscreen mode": "切换全屏模式",
"Open help dialog": "打开帮助对话框",
"history": "历史",
"styles": "样式",
"formatting": "格式化",
"alignment": "对齐",
"indentation": "缩进",
"permanent pen": "记号笔",
"comments": "注释",
"Anchor": "锚点",
"Special character": "特殊字符",
"Code sample": "代码示例",
"Color": "颜色",
"Emoticons": "表情",
"Document properties": "文档属性",
"Image": "图片",
"Insert link": "插入链接",
"Target": "目标",
"Link": "链接",
"Poster": "封面",
"Media": "音视频",
"Print": "打印",
"Prev": "上一个",
"Find and replace": "查找并替换",
"Whole words": "全字匹配",
"Spellcheck": "拼写检查",
"Caption": "标题",
"Insert template": "插入模板",
//以下为补充汉化内容 by 莫若卿
"Code view": "代码区域",
"Select...": "选择...",
"Format Painter": "格式刷",
"No templates defined.": "无内置模板",
"Special character...": "特殊字符...",
"Open link": "打开链接",
"None": "无",
"Count": "统计",
"Document": "整个文档",
"Selection": "选取部分",
"Words": "字词数",
"{0} characters": "{0} 个字符",
"Alternative source URL": "替代资源地址",
"Alternative description": "替代说明文字",
"Accessibility": "可访问性",
"Image is decorative": "仅用于装饰",
//5.6新增
"Line height": "行高",
"Cut column": "剪切列",
"Copy column": "复制列",
"Paste column before": "粘贴到前方",
"Paste column after": "粘贴到后方",
"Copy column": "复制列",
//帮助窗口内的文字
"Version": "版本",
"Keyboard Navigation": "键盘导航",
"Open popup menu for split buttons": "该组合键的作用是软回车插入br",
});

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -41,9 +41,12 @@ module.exports = configure(function (ctx) {
// Full list of options: https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build
build: {
vueRouterMode: "hash", // available values: 'hash', 'history'
uglifyOptions: {
compress: {
drop_console: true,
},
},
// transpile: false,
// Add dependencies for transpiling with Babel (Array of string/regex)
// (from node_modules, which are by default not transpiled).
// Applies only if "transpile" is set to true.
@ -52,7 +55,7 @@ module.exports = configure(function (ctx) {
// rtl: true, // https://v2.quasar.dev/options/rtl-support
// preloadChunks: true,
// showProgress: false,
// gzip: true,
gzip: true,
// analyze: true,
// Options below are automatically set depending on the env, set them if you want to override

View File

@ -10,10 +10,13 @@ import { SessionStorage, Cookies, useQuasar, setCssVar } from "quasar";
import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import { useStore } from "src/store";
import { IWuJieInterface, useStore } from "src/store";
import GlobalData from "./common/GlobalData";
import { EProductNames } from "./entities/ProductNames";
import { api } from "./boot/axios";
import { WuJieInitializer } from "./common/WuJieInitializer";
import ClientConnection from "./common/ClientConnection";
import { Common } from "./common/Common";
export default defineComponent({
name: "App",
@ -23,6 +26,12 @@ export default defineComponent({
const $store = useStore();
const $q = useQuasar();
if ((window as any).$wujie) {
const $wujie = (window as any).$wujie as IWuJieInterface;
$store.commit("setWuJie", $wujie);
WuJieInitializer.initialize($wujie, $store, $q, $t);
}
document.title = $t.t("title");
if (!navigator.cookieEnabled) {
@ -63,7 +72,12 @@ export default defineComponent({
(<any>window).media_control_client_product == EProductNames.LED_PLAYER ||
(<any>window).media_control_client_product == EProductNames.OLD_LED_PLAYER
) {
document.title = $t.t("LedPlayer") + "WebApp";
const custom_title = (<any>window).media_control_client_custom_title;
if (custom_title && typeof custom_title == "string") {
document.title = custom_title;
} else {
document.title = $t.t("LedPlayer") + "WebApp";
}
} else if (
(<any>window).media_control_client_product == EProductNames.SPECIAL_VIDEO
) {
@ -272,6 +286,40 @@ export default defineComponent({
});
}
EventBus.getInstance().on(
EventNamesDefine.CurrentConnectConnected,
async (connection: ClientConnection) => {
const show_version_tip = () =>
$q.dialog({
persistent: true,
title: $t.t("Version Mismatch !"),
message: $t.t(
"Version Mismatch ! Please Upgrade The Software Again ! Otherwise, The File Function Cannot Be Used !"
),
});
if (connection) {
let count = 0;
while (
connection &&
!connection.is_login &&
count < (1000 * 10) / 100 /* 10 S */
) {
await Common.waitFor(100);
}
if (count < (1000 * 10) / 100) {
try {
const response = await connection.getHttpInterfaceVersion();
if (!response || response.version != 2) {
show_version_tip();
}
} catch (e) {
show_version_tip();
}
}
}
}
);
return {};
},
});

View File

@ -16,6 +16,7 @@ import JointActionEquipmentTableEntity from "src/entities/JointActionEquipmentTa
import { CustomProtocol } from "src/entities/WSProtocolCustom";
import ClientConnectionCustom from "./ClientConnectionCustom";
import MagicWallConfig from "src/entities/MagicWallConfig";
import WuJieReconnectingWebSocket from "./WuJieReconnectingWebSocket";
class _RpcInfo {
send_timestamp: number;
@ -45,7 +46,7 @@ class _RpcInfo {
}
export default class ClientConnection {
ws: ReconnectingWebSocket | null = null;
ws: ReconnectingWebSocket | null | WuJieReconnectingWebSocket = null;
url = "";
user_name = "";
password = "";
@ -67,14 +68,17 @@ export default class ClientConnection {
this.url = url;
this.user_name = user_name ?? "";
this.password = password ?? "";
const $wujie = (window as any).$wujie;
if (this.ws) {
this.ws.close();
}
this.ws = new ReconnectingWebSocket(url);
if ($wujie) {
this.ws = new WuJieReconnectingWebSocket();
} else {
this.ws = new ReconnectingWebSocket(url);
}
this.initializeWs();
setInterval(() => {
this.checkRpcTimeout();
}, 1000);
@ -104,13 +108,13 @@ export default class ClientConnection {
initializeWs() {
if (this.ws) {
this.ws.onclose = (ev) => {
this.ws.onclose = (ev: any) => {
this.onClose(ev);
};
this.ws.onerror = (ev) => {
this.ws.onerror = (ev: any) => {
this.onError(ev);
};
this.ws.onopen = (ev) => {
this.ws.onopen = (ev: any) => {
this.onOpen(ev);
};
this.ws.onmessage = (ev) => {
@ -706,6 +710,23 @@ export default class ClientConnection {
)
);
}
public setMagicWallList(list:any) {
this.ws?.send(
JSON.stringify(
new Protocol.SetApplicationConfigRequestEntity(
0,
"magic_list",
typeof (list) == 'string' ? list : JSON.stringify(list)
)
)
);
}
public setConfigure(k: string, v: string) {
this.ws?.send(
JSON.stringify(new Protocol.SetApplicationConfigRequestEntity(0, k, v))
);
}
public setUserName(user_name: string) {
this.ws?.send(
@ -813,6 +834,7 @@ export default class ClientConnection {
active_code: string,
online: boolean,
active_forever: boolean,
attribute: number,
secret_key?: string,
hour?: number
) {
@ -823,6 +845,7 @@ export default class ClientConnection {
active_code,
online,
active_forever,
attribute,
secret_key,
hour,
0
@ -1242,7 +1265,6 @@ export default class ClientConnection {
console.error(e);
}
}
public async setMagicWallConfig(config: MagicWallConfig) {
try {
return await this.doRpc<Protocol.RpcSetMagicWallConfigResponseEntity>(
@ -1252,7 +1274,26 @@ export default class ClientConnection {
console.error(e);
}
}
//
public async getMagicWallGridState() {
try {
return await this.doRpc<Protocol.RpcGetMagicWallGridStateResponseEntity>(
new Protocol.RpcGetMagicWallGridStateRequestEntity()
);
} catch (e) {
console.error(e);
}
}
public async setMagicWallGridState(show_grid: boolean) {
try {
return await this.doRpc<Protocol.RpcSetMagicWallGridStateResponseEntity>(
new Protocol.RpcSetMagicWallGridStateRequestEntity(show_grid)
);
} catch (e) {
console.error(e);
}
}
public async testA(
x: number,
y: number,
@ -1315,6 +1356,12 @@ export default class ClientConnection {
);
}
public async getHttpInterfaceVersion() {
return await this.doRpc<Protocol.RpcGetHttpInterfaceVersionResponseEntity>(
new Protocol.RpcGetHttpInterfaceVersionRequestEntity()
);
}
public async setJointActionEquipment(
entity: JointActionEquipmentTableEntity
) {
@ -1333,6 +1380,7 @@ export default class ClientConnection {
row: number,
column: number,
correction_type: number,
control_point_count: number,
control_point: number,
x: number,
y: number
@ -1342,6 +1390,7 @@ export default class ClientConnection {
row,
column,
correction_type,
control_point_count,
control_point,
x,
y
@ -1397,13 +1446,9 @@ export default class ClientConnection {
);
}
public async EnableBlending(
enable: boolean
) {
public async EnableBlending(enable: boolean) {
return await this.doRpc<Protocol.NoneResponse>(
new Protocol.EnableBlendingRequestEntity(
enable
)
new Protocol.EnableBlendingRequestEntity(enable)
);
}
@ -1412,7 +1457,8 @@ export default class ClientConnection {
column: number,
location: number,
enable: boolean,
width: number
width: number,
auto_sync: boolean,
) {
return await this.doRpc<Protocol.NoneResponse>(
new Protocol.SetBlendingOverlapRequestEntity(
@ -1420,7 +1466,8 @@ export default class ClientConnection {
column,
location,
enable,
width
width,
auto_sync
)
);
}
@ -1440,6 +1487,7 @@ export default class ClientConnection {
public async SetBlendingHorDensity(
row: number,
column: number,
control_point_count: number,
control_point: number,
value: number
) {
@ -1447,6 +1495,7 @@ export default class ClientConnection {
new Protocol.SetBlendingHorDensityRequestEntity(
row,
column,
control_point_count,
control_point,
value
)
@ -1456,6 +1505,7 @@ export default class ClientConnection {
public async SetBlendingVerDensity(
row: number,
column: number,
control_point_count: number,
control_point: number,
value: number
) {
@ -1463,6 +1513,7 @@ export default class ClientConnection {
new Protocol.SetBlendingVerDensityRequestEntity(
row,
column,
control_point_count,
control_point,
value
)
@ -1475,15 +1526,9 @@ export default class ClientConnection {
);
}
public async SetBlendingOption(
id: string,
value: string
) {
public async SetBlendingOption(id: string, value: string) {
return await this.doRpc<Protocol.NoneResponse>(
new Protocol.SetBlendingOptionRequestEntity(
id,
value
)
new Protocol.SetBlendingOptionRequestEntity(id, value)
);
}
@ -1505,6 +1550,52 @@ export default class ClientConnection {
);
}
public async AddBlendingCtrlPoint(
type: string,
row: number,
column: number,
count: number
) {
return await this.doRpc<Protocol.GetBlendingConfigResponseEntity>(
new Protocol.AddBlendingCtrlPointRequestEntity(type, row, column, count)
);
}
public async DelBlendingCtrlPoint(
type: string,
row: number,
column: number,
count: number
) {
return await this.doRpc<Protocol.GetBlendingConfigResponseEntity>(
new Protocol.DelBlendingCtrlPointRequestEntity(type, row, column, count)
);
}
public async SetProjectorResolution(width: number, height: number) {
return await this.doRpc<Protocol.GetBlendingConfigResponseEntity>(
new Protocol.SetProjectorResolutionRequestEntity(width, height)
);
}
public async SetProjectorLayout(row: number, column: number) {
return await this.doRpc<Protocol.GetBlendingConfigResponseEntity>(
new Protocol.SetProjectorLayoutRequestEntity(row, column)
);
}
public async setCloudServerSetting(
cloud_server_address: string,
cloud_server_verify_key: string,
cloud_server_use_wss: boolean,
cloud_server_enable: boolean
) {
this.setConfigure("cloud_server_address", cloud_server_address);
this.setConfigure("cloud_server_verify_key", cloud_server_verify_key);
this.setConfigure("cloud_server_use_wss", cloud_server_use_wss ? "1" : "0");
this.setConfigure("cloud_server_enable", cloud_server_enable ? "1" : "0");
}
public destory() {
this.ws?.close();
if (this.ws) {
@ -1515,6 +1606,59 @@ export default class ClientConnection {
}
this.ws = null;
}
public async getFileListFileManager(dir_path: string) {
try {
return await this.doRpc<Protocol.RpcFileManagerGetFileListResponse>(
new Protocol.RpcFileManagerGetFileListRequest(dir_path)
);
} catch (e) {
console.error(e);
}
}
public async RenameFileManager(
base_dir: string,
file_name: string,
new_file_name: string
) {
try {
return await this.doRpc<Protocol.RpcFileManagerRenameResponse>(
new Protocol.RpcFileManagerRenameRequest(
base_dir,
file_name,
new_file_name
)
);
} catch (e) {
console.error(e);
}
}
public async DeleteFileManager(base_dir: string, file_name: string) {
try {
return await this.doRpc<Protocol.RpcFileManagerDeleteResponse>(
new Protocol.RpcFileManagerDeleteRequest(base_dir, file_name)
);
} catch (e) {
console.error(e);
}
}
public async CreateDirectoryFileManager(base_dir: string, dir_name: string) {
try {
return await this.doRpc<Protocol.RpcFileManagerCreateDirectoryResponse>(
new Protocol.RpcFileManagerCreateDirectoryRequest(base_dir, dir_name)
);
} catch (e) {
console.error(e);
}
}
public async CheckModeIndex(mode_index: number) {
try {
return await this.doRpc<Protocol.RpcCheckModeIndexResponseEntity>(
new Protocol.RpcCheckModeIndexRequestEntity(mode_index)
);
} catch (e) {
console.error(e);
}
}
}
export interface NotifyMessage {

View File

@ -21,6 +21,10 @@ export default class GlobalData {
return 61428;
}
public static get kDefaultHttpPort() {
return 80;
}
private _current_client_name = "";
public static getInstance() {

View File

@ -0,0 +1,59 @@
export default class ValidationUtil {
static isIpAddress(str: string): boolean {
return (
str == "localhost" ||
/^([1-9]|[1-9][0-9]|1\d\d|2[0-2][0-3])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.([1-9]|[1-9][0-9]|1\d\d|2[0-4]\d|25[0-4])$/.test(
str
)
);
}
static isHost(str: string): boolean {
return (
str == "localhost" ||
/^([1-9]|[1-9][0-9]|1\d\d|2[0-2][0-3])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.([1-9]|[1-9][0-9]|1\d\d|2[0-4]\d|25[0-4])$/.test(
str
) ||
/^([1-9]|[1-9][0-9]|1\d\d|2[0-2][0-3])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])\.([1-9]|[1-9][0-9]|1\d\d|2[0-4]\d|25[0-4])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$/.test(
str
)
);
}
static isMacAddress(str: string): boolean {
return /([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}/.test(str);
}
static isMaskAddress(str: string): boolean {
return /^(254|252|248|240|224|192|128|0)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)$/.test(
str
);
}
static isHexStr(str: string): boolean {
if (str != null && str != undefined && typeof str == "string") {
str = str.trim();
if (str.length == 0) {
return true;
}
for (const item of str.split(" ")) {
if (item.length > 4) {
return false;
}
if (!/^0[xX][A-Fa-f0-9]{1,2}/.test(item)) {
return false;
}
}
return true;
}
return false;
}
static isResolution(str: string): boolean {
return /([0-9]{1,5})[x|X]([0-9]{1,5}@[0-9]{1,3}$)/.test(str);
}
static isEnglishOrNum(str: string): boolean {
return /^[0-9a-zA-Z_\-]+$/.test(str);
}
}

View File

@ -0,0 +1,92 @@
import GlobalData from "src/common/GlobalData";
import {
LocaleMessage,
DateTimeFormat,
NumberFormat,
} from "@intlify/core-base";
import { QVueGlobals } from "quasar";
import { Composer, VueMessageType } from "vue-i18n";
import { Store } from "vuex";
import { IWuJieInterface, StateInterface } from "./../store/index";
import EventBus, { EventNamesDefine } from "./EventBus";
import Initializer from "./Initializer";
import ClientConnection from "./ClientConnection";
export class WuJieInitializer {
public static initialize(
$wujie: IWuJieInterface,
$store: Store<StateInterface>,
$q: QVueGlobals,
$t: Composer<
{
[x: string]: LocaleMessage<VueMessageType>;
},
{
[x: string]: DateTimeFormat;
},
{
[x: string]: NumberFormat;
},
string,
string,
string
>
) {
if ($wujie) {
$wujie.bus.$on("initialize_app", (device_sn: string) => {
WuJieInitializer.onInitializeApp(device_sn, $wujie, $store, $q, $t);
});
setTimeout(() => {
$wujie.bus.$emit("client_mounted");
}, 500);
}
}
private static onInitializeApp(
device_sn: string,
$wujie: IWuJieInterface,
$store: Store<StateInterface>,
$q: QVueGlobals,
$t: Composer<
{
[x: string]: LocaleMessage<VueMessageType>;
},
{
[x: string]: DateTimeFormat;
},
{
[x: string]: NumberFormat;
},
string,
string,
string
>
) {
setTimeout(() => {
const global_data = GlobalData.getInstance();
const client = global_data.getCurrentClient();
if (!client) {
const client_name = "WuJie@" + device_sn;
console.log(client_name);
global_data.addClient(client_name, new ClientConnection("", "", ""));
global_data.setCurrentClientName(client_name);
}
if (client) {
client._is_login = true;
}
new Initializer({
$t,
$store,
$q,
})
.initialize()
.then(() => {
$store.commit("setInitialized");
if ($wujie) {
$wujie.bus.$emit("client_initialize_end");
}
});
EventBus.getInstance().emit(EventNamesDefine.WebSocketConnected, this);
}, 0);
}
}

View File

@ -0,0 +1,59 @@
import { IWuJieInterface } from "./../store/index";
import { store } from "quasar/wrappers";
export default class WuJieReconnectingWebSocket {
readyState: number;
$wujie: IWuJieInterface;
constructor() {
this.readyState = WebSocket.OPEN;
this.onclose = (ev: any) => {};
this.onerror = (ev: any) => {};
this.onmessage = (ev: any) => {};
this.onopen = (ev: any) => {};
this.$wujie = (window as any).$wujie;
if (this.$wujie) {
this.$wujie.bus.$on("onclose", this.onclose);
this.$wujie.bus.$on("onerror", this.onerror);
this.$wujie.bus.$on("onmessage", (ev: any) => {
if (this.onmessage) {
this.onmessage(ev);
}
});
this.$wujie.bus.$on("onopen", this.onopen);
setTimeout(() => {
if (this.onopen) {
this.onopen(null);
}
}, 500);
}
}
onclose: ((event: any) => void) | null;
/**
* An event listener to be called when an error occurs
*/
onerror: ((event: any) => void) | null;
/**
* An event listener to be called when a message is received from the server
*/
onmessage: ((event: MessageEvent) => void) | null;
/**
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
* this indicates that the connection is ready to send and receive data
*/
onopen: ((event: any) => void) | null;
/**
* Closes the WebSocket connection or connection attempt, if any. If the connection is already
* CLOSED, this method does nothing
*/
close(code?: number, reason?: string) {}
/**
* Enqueue specified data to be transmitted to the server over the WebSocket connection
*/
send(data: string) {
if (this.$wujie) {
this.$wujie.bus.$emit("send_to", data);
}
}
}

View File

@ -11,7 +11,7 @@
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 40vw">
<q-form>
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
@ -37,8 +37,67 @@
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-card-section style="max-height: 60vh; width: 40vw" class="scroll">
<q-list>
<q-item>
<q-item-section avatar>{{ $t("product") }}</q-item-section>
<q-item-section>
<q-radio
v-model="selected_product"
val=""
:label="$t('normal')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</q-item-section>
<q-item-section>
<q-radio
v-model="selected_product"
val="magic_wall"
:label="$t('magic wall')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</q-item-section>
<q-item-section>
<q-radio
v-model="selected_product"
val="fusion"
:label="$t('fusion')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</q-item-section>
</q-item>
<q-item v-if="selected_product == 'fusion'">
<q-item-section avatar>{{ $t("fusion") }}</q-item-section>
<q-item-section>
<div class="row" v-for="(row, row_index) in 3" :key="row">
<q-radio
v-for="(item, item_index) in 3"
:key="row_index * 3 + item"
v-model="function_fusion_count"
:val="row_index * 3 + item"
:label="
(row_index * 3 + item).toString() +
$t(' ') +
$t('fusion out')
"
color="cyan"
class="col"
:class="item_index ? 'offset-md-1 ' : ''"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>{{ $t("function") }}</q-item-section>
<q-item-section>
@ -69,15 +128,6 @@
:disable="loading"
/>
</q-item-section>
<q-item-section avatar>
<q-btn
@click="setDeviceAttribute"
:label="$t('commit')"
no-caps
outline
color="primary"
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar></q-item-section>
@ -85,13 +135,28 @@
<q-checkbox
v-model="function_custom_ISV"
:label="$t('Custom ISV')"
class="offset-md-1 col"
color="cyan"
class="col"
:loading="loading"
:disable="loading"
/>
</q-item-section>
</q-item>
<q-item>
<q-item-section> </q-item-section>
<q-item-section>
<q-btn
@click="setDeviceAttributeAndProduct"
:label="$t('commit')"
no-caps
outline
class="q-px-lg"
color="primary"
/>
</q-item-section>
<q-item-section> </q-item-section>
</q-item>
<q-separator />
<q-item>
<q-item-section avatar>
{{ $t("language") }}
@ -128,7 +193,6 @@
/>
</q-item-section>
</q-item>
<q-separator class="q-mt-md" />
<q-item class="q-mt-md">
@ -174,8 +238,10 @@ import { useStore } from "src/store";
import { useQuasar, date as $date } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { Protocol } from "src/entities/WSProtocol";
import { EDeviceAttribute } from "src/entities/EDeviceAttribute";
import {
EDeviceAttribute,
EDeviceAttributeHelper,
} from "src/entities/EDeviceAttribute";
export default defineComponent({
name: "ComponentAdvancedDebugDialog",
@ -198,7 +264,47 @@ export default defineComponent({
const function_mirroring_output = ref(
$store.state.custom_defines.function_mirroring_output
);
const function_magic_wall = ref(
$store.state.custom_defines.function_magic_wall
);
const function_fusion = ref($store.state.custom_defines.function_fusion);
const function_fusion_count = ref(0);
const target_language = ref("zh-CN");
const selected_product = ref("");
watch(
() => selected_product.value,
(newValue) => {
function_fusion.value = newValue == "fusion";
function_magic_wall.value = newValue == "magic_wall";
}
);
const getFinalAttribute = () => {
let attribute = EDeviceAttribute.None;
if (function_center_control.value) {
attribute |= EDeviceAttribute.CenterControl;
}
if (function_output_board.value) {
attribute |= EDeviceAttribute.OutputBoard;
}
if (function_mirroring_output.value) {
attribute |= EDeviceAttribute.MirroringOutput;
}
if (function_custom_ISV.value) {
attribute |= EDeviceAttribute.CustomISV;
}
if (function_magic_wall.value) {
attribute |= EDeviceAttribute.ProductMagicWall;
}
if (function_fusion.value) {
attribute |= EDeviceAttributeHelper.getProdictFusionAttributeByIndex(
function_fusion_count.value
);
}
return attribute;
};
return {
show_dialog,
@ -206,8 +312,12 @@ export default defineComponent({
function_center_control,
function_output_board,
function_custom_ISV,
function_magic_wall,
function_fusion,
function_fusion_count,
function_mirroring_output,
target_language,
selected_product,
showDialog() {
show_dialog.value = true;
@ -219,6 +329,20 @@ export default defineComponent({
$store.state.custom_defines.function_output_board;
function_mirroring_output.value =
$store.state.custom_defines.function_mirroring_output;
function_magic_wall.value =
$store.state.custom_defines.function_magic_wall;
function_fusion.value = $store.state.custom_defines.function_fusion;
function_fusion_count.value =
EDeviceAttributeHelper.getProductFusionOutputCountDefault(
$store.state.device_attribute,
1
);
if (function_magic_wall.value) {
selected_product.value = "magic_wall";
} else if (function_fusion.value) {
selected_product.value = "fusion";
}
},
resetData() {
loading.value = false;
@ -227,6 +351,9 @@ export default defineComponent({
function_output_board.value = false;
function_mirroring_output.value = false;
function_custom_ISV.value = false;
function_magic_wall.value = false;
function_fusion.value = false;
selected_product.value = "";
},
restartDevice() {
@ -304,21 +431,22 @@ export default defineComponent({
</div>`,
});
},
setDeviceAttribute() {
let attribute = EDeviceAttribute.None;
if (function_center_control.value) {
attribute |= EDeviceAttribute.CenterControl;
}
if (function_output_board.value) {
attribute |= EDeviceAttribute.OutputBoard;
}
if (function_mirroring_output.value) {
attribute |= EDeviceAttribute.MirroringOutput;
}
setDeviceAttributeAndProduct() {
let attribute = getFinalAttribute();
GlobalData.getInstance()
.getCurrentClient()
?.setDeviceAttribute(attribute);
if (function_custom_ISV.value) {
attribute |= EDeviceAttribute.CustomISV;
}
$q.notify({
color: "positive",
icon: "done",
message: $t.t("set device function") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
},
setDeviceAttribute() {
let attribute = getFinalAttribute();
GlobalData.getInstance()
.getCurrentClient()
@ -344,6 +472,16 @@ export default defineComponent({
timeout: 1500,
});
},
changeMagic() {
if (function_magic_wall.value) {
function_fusion.value = false;
}
},
changeFusion() {
if (function_fusion.value) {
function_magic_wall.value = false;
}
},
};
},
});

View File

@ -20,14 +20,7 @@
</div>
<q-space />
<div>
<q-btn
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-btn flat round icon="close" color="red" v-close-popup>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
@ -88,7 +81,8 @@
(val) =>
(val && val.length > 0) || $t('Please type something'),
(val) =>
isIpAddress(val) || $t('Please input vaild ip address'),
isMaskAddress(val) ||
$t('Please input vaild netmask address'),
]"
lazy-rules
/>
@ -162,12 +156,12 @@
</style>
<script lang="ts">
import { defineComponent, ref, Ref, reactive } from "vue";
import { defineComponent, ref } from "vue";
import { useStore } from "src/store";
import { useQuasar, copyToClipboard, uid } from "quasar";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { AdvancedIpAddressEntity } from "src/entities/AdvancedIpAddressEntity";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentSystenSettingAdvancedNetworkDialog",
@ -267,12 +261,10 @@ export default defineComponent({
} catch {}
},
isIpAddress(str: string) {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
)
);
return ValidationUtil.isIpAddress(str);
},
isMaskAddress(str: string) {
return ValidationUtil.isMaskAddress(str);
},
checkFilterListIp(str: string) {
if (Array.isArray(ip_filter_list)) {

View File

@ -1,256 +1,226 @@
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-11 text-h6">
{{ $t("background image") }}
</div>
<div class="col-1">
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-uploader
class="full-width"
ref="uploader"
:url="upload_url"
method="post"
:headers="generatorFileUploadHeaders"
:label="$t('select background image') + ':'"
:accept="$store.state.isSpecialVideo() ? '.svdoj' : 'image/*'"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="left">
<q-btn
v-if="$store.state.isLedPlayer()"
flat
no-caps
:loading="loading"
color="primary"
@click="showBackgroundImage"
:label="$t('view current background image')"
/>
<q-space />
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
no-caps
:loading="loading"
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { api as viewerApi } from "v-viewer";
export default defineComponent({
name: "ComponentBackgroundImageDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader: any = ref(null);
let loading = ref(false);
let upload_url = ref("");
let file_count = ref(0);
return {
show_dialog,
loading,
upload_url,
uploader,
file_count,
loga(a: any) {
console.log(a);
},
generatorFileUploadHeaders(files: File[]) {
if (files.length > 0) {
return [
{
name: HttpProtocol.kHeaderXProductName,
value: HttpProtocol.getProductName($store),
},
{
name: HttpProtocol.kHeaderXFileLength,
value: files[0].size,
},
];
}
return [];
},
showDialog() {
show_dialog.value = true;
let client = GlobalData.getInstance().getCurrentClient();
if (client) {
let url = new URL(client.url);
url.port =
GlobalData.getInstance().applicationConfig?.httpserver_port ??
HttpProtocol.DefaultHttpPort.toString();
url.pathname = HttpProtocol.RequestUploadFile;
url.protocol = "http:";
url.searchParams.append(
"type",
HttpProtocol.UploadTypeBackgroundImage
);
upload_url.value = url.toString();
}
},
resetData() {
loading.value = false;
upload_url.value = "";
file_count.value = 0;
},
showBackgroundImage() {
const temp_port =
GlobalData.getInstance().applicationConfig?.httpserver_port ??
HttpProtocol.DefaultHttpPort.toString();
try {
const url = new URL(
GlobalData.getInstance().getCurrentClient()?.url ??
"http://127.0.0.1:" + temp_port
);
url.protocol = "http";
url.port = temp_port.toString();
url.pathname = "/static/background_image.png";
viewerApi({
options: {
toolbar: true,
url: "data-source",
initialViewIndex: 0,
},
images: [
{
src: url.toString(),
"data-source": url.toString(),
},
],
});
} catch {}
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
$q.dialog({
title: $t.t("Confirm"),
message: $t.t("use this image to background image") + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
uploader.value.upload();
})
.onCancel(() => {
loading.value = false;
});
} catch {}
},
onUploaded() {
$q.notify({
type: "positive",
message: $t.t("upload background image") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
show_dialog.value = false;
},
onFailed(info: any) {
console.log(info);
$q.notify({
type: "warning",
message: $t.t("upload background image") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-11 text-h6">
{{ $t("background image") }}
</div>
<div class="col-1">
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-uploader
class="full-width"
ref="uploader"
:url="upload_url"
method="post"
:label="$t('select background image') + ':'"
:accept="$store.state.isSpecialVideo() ? '.svdoj' : 'image/*'"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
<!-- :headers="generatorFileUploadHeaders" -->
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="left">
<q-btn
v-if="$store.state.isLedPlayer()"
flat
no-caps
:loading="loading"
color="primary"
@click="showBackgroundImage()"
:label="$t('view current background image')"
/>
<q-space />
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
no-caps
:loading="loading"
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { api as viewerApi } from "v-viewer";
export default defineComponent({
name: "ComponentBackgroundImageDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader: any = ref(null);
let loading = ref(false);
let upload_url = ref("");
let file_count = ref(0);
return {
show_dialog,
loading,
upload_url,
uploader,
file_count,
loga(a: any) {
console.log(a);
},
showDialog() {
show_dialog.value = true;
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = "/upload_background_image_file";
upload_url.value = url.toString();
}
},
resetData() {
loading.value = false;
upload_url.value = "";
file_count.value = 0;
},
showBackgroundImage() {
try {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = "/get_background_image_file";
viewerApi({
options: {
toolbar: true,
url: "data-source",
initialViewIndex: 0,
},
images: [
{
src: url.toString(),
"data-source": url.toString(),
},
],
});
}
} catch {}
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
$q.dialog({
title: $t.t("Confirm"),
message: $t.t("use this image to background image") + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
uploader.value.upload();
})
.onCancel(() => {
loading.value = false;
});
} catch {}
},
onUploaded() {
$q.notify({
type: "positive",
message: $t.t("upload background image") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
show_dialog.value = false;
},
onFailed(info: any) {
console.log(info);
$q.notify({
type: "warning",
message: $t.t("upload background image") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>

View File

@ -139,6 +139,7 @@ import { useQuasar, copyToClipboard } from "quasar";
import { useI18n } from "vue-i18n";
import { ExternalControlTableEntity } from "src/entities/ExternalControlTableEntity";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentCenterControlButtonDialog",
@ -246,22 +247,7 @@ export default defineComponent({
show_dialog.value = false;
},
isHexStr(val: string) {
if (val != null && val != undefined && typeof val == "string") {
val = val.trim();
if (val.length == 0) {
return true;
}
for (const item of val.split(" ")) {
if (item.length > 4) {
return false;
}
if (!/^0[xX][A-Fa-f0-9]{1,2}/.test(item)) {
return false;
}
}
return true;
}
return false;
return ValidationUtil.isHexStr(val);
},
};
},

View File

@ -406,6 +406,7 @@ import {
SerialPortConfigEntity,
} from "src/entities/SerialPortConfigEntity";
import { Protocol } from "src/entities/WSProtocol";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentCenterControlDialog",
@ -733,12 +734,7 @@ export default defineComponent({
}
},
isIpAddress(str: string) {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
)
);
return ValidationUtil.isIpAddress(str);
},
};
},

File diff suppressed because it is too large Load Diff

View File

@ -152,6 +152,7 @@ import { api } from "boot/axios";
import { HttpProtocol } from "src/entities/HttpProtocol";
import JointActionEquipmentTableEntity from "src/entities/JointActionEquipmentTableEntity";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentEditJointActionEquipmentDialog",
@ -330,15 +331,7 @@ export default defineComponent({
}
},
isHost(str: string) {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
) ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$/.test(
str
)
);
return ValidationUtil.isHost(str);
},
};
},

View File

@ -156,7 +156,7 @@
</q-btn>
<q-btn
flat
v-if="!uploading"
v-if="!uploading &&!iswujie"
no-caps
icon="upload"
:label="$t('upload file')"
@ -192,6 +192,7 @@
($q.platform.is.ipad && $store.state.landspace ? '61' : '68') +
'vh',
}"
class="q-mb-md"
v-show="!uploading"
:rows="files"
:columns="columns"
@ -221,10 +222,11 @@
style="color: #ffbe4a; font-size: 2.5em"
></q-icon>
{{
props.value.length > 60
? props.value.substr(0, 60) + "..."
props.value.length > 25
? props.value.substr(0, 25) + "..."
: props.value
}}
<q-tooltip> {{ props.value }} </q-tooltip>
</div>
<div v-else-if="props.col.name == 'file_size'">
@ -345,14 +347,12 @@
style="height: 69vh; width: 70%"
:disable="uploader_loading"
:url="getUrl"
method="post"
:headers="generatorFileUploadHeaders"
multiple
method="POST"
:label="$t('select file') + ':'"
:accept="uploader_accept"
@start="onStartUpload"
@uploaded="onUploaded"
@failed="onFailed"
@added="/*onFileAdded*/ null"
@finish="onfinish"
>
</q-uploader>
<q-space />
@ -623,41 +623,25 @@ export default defineComponent({
label: $t.t("operator"),
},
];
const _request_list_files = async (path: string) => {
loading.value = true;
let client = GlobalData.getInstance().getCurrentClient();
if (client) {
let url = new URL(client.url);
url.port =
GlobalData.getInstance().applicationConfig?.httpserver_port ??
HttpProtocol.DefaultHttpPort.toString();
url.pathname = HttpProtocol.RequestPathListFile;
url.protocol = "http:";
url.searchParams.append("path", path);
return await api.get(url.toString());
let file_list = await GlobalData.getInstance()
.getCurrentClient()
?.getFileListFileManager(path);
return file_list;
}
loading.value = false;
return null;
};
const _show_files = (response: any) => {
if (response) {
if (response.status == 200) {
interface IRsponseData {
files: FileEntity[];
free: number;
}
if (response.success) {
let file_entitys: FileEntity[] = [];
let free = 0;
if (Array.isArray(response.data)) {
file_entitys = response.data as FileEntity[];
} else {
const resposne_data = response.data as IRsponseData;
file_entitys = resposne_data.files;
free = resposne_data.free;
}
file_entitys = response.files;
free = response.free;
free_space.value = free;
if (Array.isArray(file_entitys)) {
directory_count.value = 0;
@ -822,7 +806,10 @@ export default defineComponent({
console.log(e);
}
};
let iswujie=ref(false)
if ((window as any).$wujie) {
iswujie.value=true
}
//
// watch(
// () => filters.value,
@ -860,6 +847,7 @@ export default defineComponent({
refresh_file_list_async,
status,
filters,
iswujie,
showDialogAsync(
in_status: string,
no_filter = true,
@ -892,21 +880,6 @@ export default defineComponent({
resolve = _resolve;
});
},
generatorFileUploadHeaders(files: File[]) {
if (files.length > 0) {
return [
{
name: HttpProtocol.kHeaderXProductName,
value: HttpProtocol.getProductName($store),
},
{
name: HttpProtocol.kHeaderXFileLength,
value: files[0].size,
},
];
}
return [];
},
resetData() {
loading.value = false;
uploading.value = false;
@ -922,83 +895,134 @@ export default defineComponent({
resolve_value = null;
},
async onCreateNewFolder() {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
$q.dialog({
title: $t.t("create folder"),
message: $t.t("input folder name") + ":",
prompt: {
model: "",
isValid: (val: string) => !!val && val.trim().length > 0,
type: "text",
},
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
}).onOk(async (data: string) => {
if (url) {
url.pathname = HttpProtocol.RequestPathCreateDirectory;
let response = (
await api.post(url.toString(), {
base_dir: path.value,
dir_name: data,
})
).data as NormalResult;
if (response && response.success) {
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("create folder") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
} else {
$q.notify({
type: "warning",
message:
$t.t("create folder") +
$t.t("fail") +
"!" +
(response ? response.message : ""),
position: "top",
timeout: 1500,
});
}
}
});
}
},
selectFile,
async deleteFile(file: FileEntity) {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = HttpProtocol.RequestPathDeleteFile;
let response = null;
try {
response = (
await api.delete(url.toString(), {
data: {
base_dir: path.value,
file_name: file.name,
},
})
).data as NormalResult;
} catch (e) {
console.log(e);
}
$q.dialog({
title: $t.t("create folder"),
message: $t.t("input folder name") + ":",
prompt: {
model: "",
isValid: (val: string) =>
!!val && val.trim().length > 0&& val.indexOf(".") != 0 ,
type: "text",
},
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
}).onOk(async (data: string) => {
const response = await GlobalData.getInstance()
.getCurrentClient()
?.CreateDirectoryFileManager(path.value, data);
if (response && response.success) {
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("delete file") + $t.t("success") + "!",
message: $t.t("create folder") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
} else {
// if (
// response?.error_message ==
// "the folder name cannot start with a '.'"
// ) {
// $q.notify({
// type: "warning",
// message:
// $t.t("create folder") +
// $t.t("fail") +
// "!" +
// $t.t("the folder name cannot start with a '.'"),
// position: "top",
// timeout: 1500,
// });
// }
// else {
if (response) {
$q.notify({
type: "warning",
message:
$t.t("create folder") +
$t.t("fail") +
"! " +
$t.t(response.error_message),
position: "top",
timeout: 1500,
});
}
}
});
},
selectFile,
async deleteFile(file: FileEntity) {
let response = null;
try {
response = await GlobalData.getInstance()
.getCurrentClient()
?.DeleteFileManager(path.value, file.name);
} catch (e) {
console.log(e);
}
if (response && response.success) {
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("delete file") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
} else {
$q.notify({
type: "warning",
message:
$t.t("delete file") +
$t.t("fail") +
"!" +
(response ? response.error_message : ""),
position: "top",
timeout: 1500,
});
}
},
renameFile(file: FileEntity) {
$q.dialog({
title: $t.t("rename"),
message: $t.t("input new file name") + ":",
prompt: {
model: file.name,
isValid: (val: string) => !!val && val.trim().length > 0,
type: "text",
},
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
}).onOk(async (data: string) => {
if (data == file.name) {
return;
}
let response = await GlobalData.getInstance()
.getCurrentClient()
?.RenameFileManager(path.value, file.name, data);
if (response && response.success) {
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("file rename") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
@ -1006,79 +1030,15 @@ export default defineComponent({
$q.notify({
type: "warning",
message:
$t.t("delete file") +
$t.t("file rename") +
$t.t("fail") +
"!" +
(response ? response.message : ""),
(response ? response.error_message : ""),
position: "top",
timeout: 1500,
});
}
}
},
renameFile(file: FileEntity) {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
$q.dialog({
title: $t.t("rename"),
message: $t.t("input new file name") + ":",
prompt: {
model: file.name,
isValid: (val: string) => !!val && val.trim().length > 0,
type: "text",
},
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
}).onOk(async (data: string) => {
if (data == file.name) {
return;
}
if (url) {
url.pathname = HttpProtocol.RequestPathRenameFile;
url.searchParams.append(
"type",
HttpProtocol.RequestPathRenameFile
);
let response = (
await api.put(url.toString(), {
base_dir: path.value,
file_name: file.name,
new_file_name: data,
})
).data as NormalResult;
if (response && response.success) {
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("file rename") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
} else {
$q.notify({
type: "warning",
message:
$t.t("file rename") +
$t.t("fail") +
"!" +
(response ? response.message : ""),
position: "top",
timeout: 1500,
});
}
}
});
}
});
},
copyStringToClipboard(value: string) {
copyToClipboard(value);
@ -1110,8 +1070,8 @@ export default defineComponent({
getUrl(file: File[]) {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = HttpProtocol.RequestUploadFile;
url.searchParams.append("type", HttpProtocol.HttpUploadTypeNormal);
url.pathname = "/upload_media_file"; //HttpProtocol.RequestUploadFile;
// url.searchParams.append("type", HttpProtocol.HttpUploadTypeNormal);
url.searchParams.append("base_dir", path.value);
return url.toString();
}
@ -1120,101 +1080,19 @@ export default defineComponent({
onStartUpload() {
loading.value = true;
},
async onFileAdded(files: File[] | File) {
setTimeout(async () => {
const onError = async (file: File | null) => {
await nextTick(() => {});
uploader.value.reset();
async onfinish(info: any) {
setTimeout(() => {
$q.notify({
color: "negative",
icon: "warning",
message: $t.t("load file error") + "!",
type: "positive",
message: $t.t("file upload") + $t.t("finish") + "!",
position: "top",
timeout: 3000,
timeout: 1500,
});
};
let file: File | null = null;
try {
if (Array.isArray(files)) {
if (files.length > 0) {
file = files[0];
}
} else {
file = files;
}
if (file) {
const file_name = file.name;
const blob = file.slice(0, 1024 * 1024 * 1); // 1 MB
uploader_loading.value = true;
try {
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = HttpProtocol.RequestPathCheckFileSupport;
// if (FileSuffixHelper.isVideoPath(file_name)) {
// }
const data = new FormData();
data.append(
"file",
new File([blob], file_name, {
lastModified: file.lastModified,
})
);
const response = await api.post(url.toString(), data, {
headers: {
"Content-Type": "multipart/form-data",
},
});
if (response && response.data && response.data.is_support) {
} else {
onError(file);
}
console.log(response);
} else {
throw "";
}
} catch (e) {
console.error(e);
onError(file);
}
uploader_loading.value = false;
return;
}
} catch (e) {
console.error(e);
onError(file);
}
}, 1);
},
onUploaded() {
uploading.value = false;
uploader.value.reset();
refresh_file_list();
$q.notify({
type: "positive",
message: $t.t("file upload") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
onFailed(info: any) {
console.log(info);
$q.notify({
type: "warning",
message: $t.t("file upload") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
loading.value = false;
loading.value = false;
uploading.value = false;
refresh_file_list()
uploader.value.reset()
}, 500);
},
copyFile(file: FileEntity) {
if (file) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,15 +11,33 @@
<q-toggle class="float-right" v-model="array[0].isshow" label="" />
</div>
<div class="col-6">
<q-input dense filled type="number" :autofocus="group == 0" :bg-color="group == 0 ? 'cyan-1' : ''"
@focus="group = 0" v-model="array[0].value" :label="$t('upper fusion zone parameters')" lazy-rules
:rules="[
<q-input v-show="ispad" dense filled type="number" :autofocus="group == 0"
:bg-color="group == 0 ? 'cyan-1' : ''" @focus="group = 0" v-model.number="array[0].value"
:label="$t('upper fusion zone parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 0 }"
:readonly="url.indexOf('pad') != -1" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.height) || $t('Please enter 0-100'),
]" />
<q-input v-show="!ispad" dense filled type="number" :autofocus="group == 0"
:bg-color="group == 0 ? 'cyan-1' : ''" @focus="() => { group = 0; input_focus[0] = true }"
v-model.number="array[0].value" :label="$t('upper fusion zone parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 0 }"
:readonly="url.indexOf('pad') != -1" @blur="input_focus[0] = false" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.height) || $t('Please enter 0-100'),
]">
<template v-if="input_focus[0]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="mousedown('+', 0)" @mouseup="mouseup" />
<q-icon name="arrow_downward" @mousedown="mousedown('-', 0)" @mouseup="mouseup" />
</template>
</q-input>
</div>
</div>
</div>
@ -30,39 +48,75 @@
<div class="col-6">
<div class="row">
<div class="col-3">
<q-toggle class="float-right" v-model="array[1].isshow" label="" />
<q-toggle class="float-right" @click="group = 1" v-model="array[1].isshow" label="" />
</div>
<div class="col-6">
<q-input dense filled type="number" :autofocus="group == 1" :bg-color="group == 1 ? 'cyan-1' : ''"
@focus="group = 1" v-model="array[1].value" :label="$t('Left fusion Band Parameters')" lazy-rules
:rules="[
<q-input v-show="ispad" dense filled type="number" :autofocus="group == 1"
:bg-color="group == 1 ? 'cyan-1' : ''" @focus="group = 1" v-model.number="array[1].value"
:label="$t('Left fusion Band Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 1 }"
:readonly="url.indexOf('pad') != -1" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.width) || $t('Please enter 0-100'),
]" />
<q-input v-show="!ispad" dense filled type="number" :autofocus="group == 1"
:bg-color="group == 1 ? 'cyan-1' : ''" @focus="() => { group = 1; input_focus[1] = true }"
v-model.number="array[1].value" :label="$t('Left fusion Band Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 1 }"
:readonly="url.indexOf('pad') != -1" @blur="input_focus[1] = false" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.width) || $t('Please enter 0-100'),
]">
<template v-if="input_focus[1]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="mousedown('+', 1)" @mouseup="mouseup" />
<q-icon name="arrow_downward" @mousedown="mousedown('-', 1)" @mouseup="mouseup" />
</template>
</q-input>
</div>
</div>
</div>
<div class="col-6">
<div class="row">
<div class="col-3">
<q-toggle class="float-right" v-model="array[2].isshow" label="" />
<q-toggle class="float-right" @click="group = 2" v-model="array[2].isshow" label="" />
</div>
<div class="col-6">
<q-input dense filled type="number" :autofocus="group == 2" :bg-color="group == 2 ? 'cyan-1' : ''"
@focus="group = 2" v-model="array[2].value" :label="$t('Right fusion Band Parameters')" lazy-rules
:rules="[
<q-input v-show="ispad" dense filled type="number" :autofocus="group == 2"
:bg-color="group == 2 ? 'cyan-1' : ''" @focus="group = 2" v-model.number="array[2].value"
:label="$t('Right fusion Band Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 2 }"
:readonly="url.indexOf('pad') != -1" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.width) || $t('Please enter 0-100'),
]" />
<q-input v-show="!ispad" dense filled type="number" :autofocus="group == 2"
:bg-color="group == 2 ? 'cyan-1' : ''" @focus="() => { group = 2; input_focus[2] = true }"
v-model.number="array[2].value" :label="$t('Right fusion Band Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 2 }"
:readonly="url.indexOf('pad') != -1" @blur="input_focus[2] = false" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.width) || $t('Please enter 0-100'),
]">
<template v-if="input_focus[2]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="mousedown('+', 2)" @mouseup="mouseup" />
<q-icon name="arrow_downward" @mousedown="mousedown('-', 2)" @mouseup="mouseup" />
</template>
</q-input>
</div>
<div class="col-3"><span>{{ $t('Whether to operate synchronously') }}</span><q-checkbox
v-model="auto_sync" /></div>
v-model="auto_sync" @update:model-value="() => { }" /></div>
</div>
</div>
</div>
@ -75,15 +129,33 @@
<q-toggle class="float-right" v-model="array[3].isshow" label="" />
</div>
<div class="col-6">
<q-input dense filled type="number" :autofocus="group == 3" :bg-color="group == 3 ? 'cyan-1' : ''"
@focus="group = 3" v-model="array[3].value" :label="$t('Lower fusion Zone Parameters')" lazy-rules
:rules="[
<q-input v-show="ispad" dense filled type="number" :autofocus="group == 3"
:bg-color="group == 3 ? 'cyan-1' : ''" @focus="group = 3" v-model.number="array[3].value"
:label="$t('Lower fusion Zone Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 3 }"
:readonly="url.indexOf('pad') != -1" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.height) || $t('Please enter 0-100'),
]" />
<q-input v-show="!ispad" dense filled type="number" :autofocus="group == 3"
:bg-color="group == 3 ? 'cyan-1' : ''" @focus="() => { group = 3; input_focus[3] = true }"
v-model.number="array[3].value" :label="$t('Lower fusion Zone Parameters')" lazy-rules
@click="() => { url.indexOf('pad') != -1 ? ipad_chang = true : ''; group = 3 }"
:readonly="url.indexOf('pad') != -1" @blur="input_focus[3] = false" :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val < config.height) || $t('Please enter 0-100'),
]">
<template v-if="input_focus[3]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="handlerTouchstart('+')" @mouseup="handlerTouchend" />
<q-icon name="arrow_downward" @mousedown="handlerTouchstart('-')" @mouseup="handlerTouchend" />
</template>
</q-input>
</div>
</div>
</div>
@ -91,20 +163,38 @@
</div>
</div>
</div>
<div class="col-12" v-if="group != 4">
<div class="col-12" v-show="group != 4 || ispad">
<p class="text-center" style="margin: 0 0 8;">{{ $t("Set Fusion Band Parameters") }}</p>
<div style="display: flex; justify-content: space-evenly">
<div>
<q-slider v-model="array[group].alpha" :min="0.0" @change="chang('alpha')" :max="1" :step="0.01" color="green"
vertical reverse label-always />
<div> <q-input dense filled hide-bottom-space type="number" max="1" min="0" step="0.1"
@update:model-value="chang('alpha')" v-model="array[group].alpha" lazy-rules :rules="[
<q-slider v-model="array[group].alpha" v-show="!ispad" :min="0.0" @change="chang('alpha')" :max="1" :step="0.01"
color="green" vertical reverse label-always />
<div> <q-input v-show="ispad" dense filled hide-bottom-space type="number" max="1" min="0" step="0.1"
@update:model-value="chang('alpha')"
@click="() => { now_apg = 'alpha'; ispad ? ipad_chang_input = true : '' }" :readonly="ispad"
v-model.number="array[group].alpha" lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 1) || $t('Please enter a value within the range'),
]" />
<q-input v-show="!ispad" dense filled hide-bottom-space type="number" max="1" min="0" step="0.1"
@update:model-value="chang('alpha')"
@click="() => { now_apg = 'alpha'; ispad ? ipad_chang_input = true : '' }" :readonly="ispad"
@focus="input_focus_apg[0] = true" @blur="input_focus_apg[0] = false" v-model.number="array[group].alpha"
lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 1) || $t('Please enter a value within the range'),
]">
<template v-if="input_focus_apg[0]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="handlerTouchstart_apg('+')" @mouseup="handlerTouchend_apg" />
<q-icon name="arrow_downward" @mousedown="handlerTouchstart_apg('-')" @mouseup="handlerTouchend_apg" />
</template>
</q-input>
<p style="text-align: center;">Alpha</p>
<q-btn style="margin-top: 0.5rem;" color="white" @click="reset('alpha')" text-color="black"
:label="$t('reset')" />
@ -112,16 +202,32 @@
</div>
<div>
<q-slider v-model="array[group].p" :min="0" @change="chang('p')" :max="16" :step="0.01" color="green" vertical
reverse label-always />
<div> <q-input dense filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@update:model-value="chang('p')" v-model="array[group].p" lazy-rules :rules="[
<q-slider v-model="array[group].p" v-show="!ispad" :min="0" @change="chang('p')" :max="16" :step="0.01"
color="green" vertical reverse label-always />
<div> <q-input v-show="ispad" dense filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@update:model-value="chang('p')" @click="() => { now_apg = 'p'; ispad ? ipad_chang_input = true : '' }"
:readonly="ispad" v-model.number="array[group].p" lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 16) || $t('Please enter a value within the range'),
]" />
<q-input v-show="!ispad" dense filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@focus="input_focus_apg[1] = true" @blur="input_focus_apg[1] = false" @update:model-value="chang('p')"
@click="() => { now_apg = 'p'; ispad ? ipad_chang_input = true : '' }" :readonly="ispad"
v-model.number="array[group].p" lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 16) || $t('Please enter a value within the range'),
]">
<template v-if="input_focus_apg[1]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="handlerTouchstart_apg('+')" @mouseup="handlerTouchend_apg" />
<q-icon name="arrow_downward" @mousedown="handlerTouchstart_apg('-')" @mouseup="handlerTouchend_apg" />
</template>
</q-input>
<p style="text-align: center;">Power</p>
<q-btn style="margin-top: 0.5rem;" color="white" @click="reset('p')" text-color="black"
:label="$t('reset')" />
@ -129,17 +235,34 @@
</div>
<div>
<q-slider v-model="array[group].gamma" :min="0" @change="chang('gamma')" :max="16" :step="0.01" color="green"
vertical reverse label-always />
<q-slider v-model="array[group].gamma" v-show="!ispad" :min="0" @change="chang('gamma')" :max="16" :step="0.01"
color="green" vertical reverse label-always />
<div>
<q-input :dense="true" filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@update:model-value="chang('gamma')" v-model="array[group].gamma" lazy-rules :rules="[
<q-input v-show="ispad" :dense="true" filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@update:model-value="chang('gamma')"
@click="() => { now_apg = 'gamma'; ispad ? ipad_chang_input = true : '' }" :readonly="ispad"
v-model.number="array[group].gamma" lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 16) || $t('Please enter a value within the range'),
]" />
<q-input v-show="!ispad" :dense="true" filled hide-bottom-space type="number" max="16" min="0" step="0.1"
@update:model-value="chang('gamma')" @focus="input_focus_apg[2] = true" @blur="input_focus_apg[2] = false"
@click="() => { now_apg = 'gamma'; ispad ? ipad_chang_input = true : '' }" :readonly="ispad"
v-model.number="array[group].gamma" lazy-rules :rules="[
(val) =>
(val !== null && val !== '') ||
$t('Please enter a number'),
(val) =>
(val >= 0 && val <= 16) || $t('Please enter a value within the range'),
]">
<template v-if="input_focus_apg[2]" v-slot:append>
<q-icon name="arrow_upward" @mousedown="handlerTouchstart_apg('+')" @mouseup="handlerTouchend_apg" />
<q-icon name="arrow_downward" @mousedown="handlerTouchstart_apg('-')" @mouseup="handlerTouchend_apg" />
</template>
</q-input>
<p style="text-align: center;">Gamma</p>
<q-btn style="margin-top: 0.5rem;" color="white" @click="reset('gamma')" text-color="black"
:label="$t('reset')" />
@ -147,12 +270,88 @@
</div>
</div>
</div>
<div class="col-12">
<div class="row" style="min-height: 40px;">
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm">
<q-item>
<q-item-section avatar class="head_1">
{{ $t("background color") }}
</q-item-section>
<q-item-section>
<q-input v-model="color" :rules="['anyColor']">
<template v-slot:append>
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-color v-model="color" @change="submit" />
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</q-item-section>
</q-item>
</div>
</div>
</div>
</div>
<div style="position: absolute;bottom: 0;">
<q-checkbox v-model="auxiliary_line" @update:model-value="(value, evt)=>{send_auxiliary_line(value)}"
<q-checkbox v-model="auxiliary_line" @update:model-value="(value, evt) => { send_auxiliary_line(value) }"
:label="$t('auxiliary lines')" />
</div>
<q-dialog v-model="ipad_chang" ref="ipadref">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<!-- <div class="text-h6">{{ $t('fusion zone') + (group + 1) }}</div> -->
<div class="row">
<div class="col-4"><q-select class="q-pt-md" :label="$t('fusion zone')" :dense="true" filled v-model="group"
@update:model-value="(val) => { group = val }" :options="options" emit-value map-options /></div>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<div class="row q-pb-md">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_up"
@touchstart="handlerTouchstart('+')" @touchend="handlerTouchend" /></div>
</div>
<div class="row q-pt-md">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black"
icon="keyboard_arrow_down" @touchstart="handlerTouchstart('-')" @touchend="handlerTouchend" /></div>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('close')" color="primary" @click="ipad_chang = false" />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="ipad_chang_input">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<!-- <div class="text-h6">{{ $t('fusion zone') + options[group].label + ` ${now_apg}` }}</div> -->
<div class="row">
<div class="col-4"><q-select class="q-pt-md" :label="$t('fusion zone') + ` ${now_apg}`" :dense="true" filled v-model="group"
@update:model-value="(val) => { group = val }" :options="options" emit-value map-options /></div>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<div class="row q-pb-md">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_up"
@touchstart="handlerTouchstart_apg('+')" @touchend="handlerTouchend_apg" /></div>
</div>
<div class="row q-pt-md">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black"
icon="keyboard_arrow_down" @touchstart="handlerTouchstart_apg('-')" @touchend="handlerTouchend_apg" /></div>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('close')" color="primary" @click="ipad_chang_input = false" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<style>
@ -171,6 +370,14 @@
p {
margin: 0;
}
</style>
<!-- 取消浏览器自带的input箭头 使用q-input的图标实现 -->
<style>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
</style>
<script lang="ts">
@ -184,12 +391,11 @@ import {
onBeforeUnmount,
reactive,
onMounted,
toRefs,
} from "vue";
import { useStore } from "src/store";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { number } from "@intlify/core-base";
import { switchCase } from "@babel/types";
export default defineComponent({
name: "ComponentFusionLocale",
@ -197,7 +403,7 @@ export default defineComponent({
let set = GlobalData.getInstance().getCurrentClient();
let $store = useStore();
let $t = useI18n();
const group = ref(4);
const group = ref(2);
const set_cache: any = ref([]);
const enablefusion = ref(false);
let array: any = reactive([
@ -207,7 +413,7 @@ export default defineComponent({
{ alpha: 0, p: 0, gamma: 0, isshow: false, value: 0 },
{ alpha: 0, p: 0, gamma: 0, isshow: false, value: 0 },
]);
const auto_sync = ref(false)
const auto_sync = ref(true)
const auxiliary_line = ref(false)
const send_auxiliary_line = (val: boolean) => {
set?.SetBlendingOption("blending_grids_assistant_lines", val ? "1" : "0");
@ -221,6 +427,15 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1]
);
});
const color = ref("#ffffff");
const ispad = computed(() => {
let url = window.location.href;
return url.indexOf("pad") != -1
})
/**
* 重置数据
* @param type
*/
const reset = (type: string) => {
switch (type) {
case 'gamma':
@ -237,13 +452,24 @@ export default defineComponent({
}
chang(type)
}
/**
* 是否在切换数据 避免切换投影机是发送不该发送的数据
*/
const ste_status = ref(0);
/**
* 使用缓存
*/
const use_set_cache = () => {
if (set_cache.value[selectedprojector.value] != null) {
let tmp = JSON.parse(set_cache.value[selectedprojector.value]);
deepcopy(array, tmp);
}
};
/**
* 深度拷贝
* @param o1
* @param o2
*/
const deepcopy = (o1: any, o2: any) => {
for (let k in o2) {
if (typeof o2[k] === "object") {
@ -254,40 +480,57 @@ export default defineComponent({
}
}
};
/**
* 保存缓存
*/
const save_set_cache = () => {
set_cache.value[selectedprojector.value] = JSON.stringify(array);
};
let config = JSON.parse($store.state.fusion_configuration).projectors[0];
let config = JSON.parse($store.state.fusion_configuration).projectors[selectedprojector.value];
/**
* 当前选择的投影机
*/
const configselsect = computed(() => {
return $store.state.selected_projector;
});
/**
* 监听投影机切换
*/
watch(
() => configselsect,
(newVal, oldVal) => {
let tmp = JSON.parse($store.state.fusion_configuration);
let fortmp = null;
let i;
for (i of tmp.projectors) {
if (
i.col === $store.getters.GetTheCurrentlySelectedCamera[1] &&
i.row === $store.getters.GetTheCurrentlySelectedCamera[0]
) {
fortmp = JSON.parse(JSON.stringify(i));
set?.GetBlendingConfig("").then((res) => {
let tmp = JSON.parse(res ? res.config : "");
// let tmp = JSON.parse($store.state.fusion_configuration);
let fortmp = null;
let i;
for (i of tmp.projectors) {
if (
i.col === $store.getters.GetTheCurrentlySelectedCamera[1] &&
i.row === $store.getters.GetTheCurrentlySelectedCamera[0]
) {
fortmp = JSON.parse(JSON.stringify(i));
}
}
}
ste_status.value = 1;
ste_status.value = 1;
config = JSON.parse(JSON.stringify(fortmp));
use_server_config();
// use_set_cache();
setTimeout(() => {
ste_status.value = 0;
}, 100);
setnowindex();
});
config = JSON.parse(JSON.stringify(fortmp));
use_server_config();
use_set_cache();
setTimeout(() => {
ste_status.value = 0;
}, 100);
setnowindex();
},
{ deep: true }
);
/**
* 输入inpu数据 时发送到后端
* @param type
*/
const chang = (type: string) => {
if (ste_status.value == 1) return
if (type == "alpha") {
@ -320,6 +563,9 @@ export default defineComponent({
save_set_cache();
};
//
/**
* 初始化数据时 自动获取焦点 的判断
*/
const setnowindex = () => {
let sum = 0;
let indexx = 4;
@ -363,6 +609,9 @@ export default defineComponent({
}, 100);
setnowindex();
};
/**
* 初始化赋值
*/
const startconfig = () => {
for (let index = 0; index < array.length - 1; index++) {
array[arr[index]].gamma = Number(config.params[index].gamma.toFixed(2));
@ -371,10 +620,15 @@ export default defineComponent({
array[arr[index]].isshow = config.params[index].enable;
array[arr[index]].value = Number(config.params[index].size);
}
let tmp = JSON.parse($store.state.fusion_configuration).options;
auxiliary_line.value = tmp.blending_grids_assistant_lines == "1"
if (sessionStorage.FusionLocale) set_cache.value = JSON.parse(sessionStorage.FusionLocale);
use_set_cache();
setnowindex();
};
/**
* 使用服务端配置
*/
const use_server_config = () => {
for (let index = 0; index < array.length - 1; index++) {
array[arr[index]].gamma = Number(config.params[index].gamma.toFixed(2));
@ -385,14 +639,22 @@ export default defineComponent({
}
};
onMounted(() => {
ste_status.value = 1;
startconfig();
setTimeout(() => {
ste_status.value = 0;
}, 100);
set?.GetBlendingConfig("").then((res) => {
let tmp = JSON.parse(res ? res.config : "");
config = tmp.projectors[selectedprojector.value];
ste_status.value = 1;
color.value = tmp.blending_grids_background_color ?? "#7f7f7f"
// console.log(tmp.blending_grids_background_color )
startconfig();
setTimeout(() => {
ste_status.value = 0;
}, 100);
})
if (sessionStorage.FusionLocale_async) auto_sync.value = sessionStorage.FusionLocale_async == 'true'
}),
onBeforeUnmount(() => {
sessionStorage.FusionLocale = JSON.stringify(set_cache.value);
sessionStorage.FusionLocale_async = auto_sync.value
});
watch(
@ -404,7 +666,7 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
1,
array[0].isshow,
Number(array[0].value)
Number(array[0].value), auto_sync.value
);
save_set_cache();
@ -420,9 +682,13 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
0,
array[1].isshow,
Number(array[1].value)
Number(array[1].value), auto_sync.value
);
if (auto_sync.value) left_right_auto_add(newVal);
if (auto_sync.value) {
// left_right_auto_add(Number(newVal)%2==0?newVal:Number(newVal)+1);
}
Number(newVal) % 2 != 0 ? array[1].value = Number(array[1].value) + 1 : ''
save_set_cache();
},
{ deep: true }
@ -436,9 +702,10 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
2,
array[2].isshow,
Number(array[2].value)
Number(array[2].value), auto_sync.value
);
if (auto_sync.value) left_right_auto_add(newVal);
// if (auto_sync.value) left_right_auto_add(Number(newVal)%2==0?newVal:Number(newVal)+1);
Number(newVal) % 2 != 0 ? array[2].value = Number(array[2].value) + 1 : ''
save_set_cache();
},
{ deep: true }
@ -452,7 +719,7 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
3,
array[3].isshow,
Number(array[3].value)
Number(array[3].value), auto_sync.value
);
save_set_cache();
},
@ -469,7 +736,7 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
1,
array[0].isshow,
Number(array[0].value)
Number(array[0].value), auto_sync.value
);
save_set_cache();
},
@ -484,9 +751,9 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
0,
array[1].isshow,
Number(array[1].value)
Number(array[1].value), auto_sync.value
);
if (auto_sync.value) left_right_auto_add(-1);
// if (auto_sync.value) left_right_auto_add(-1);
save_set_cache();
},
{ deep: true }
@ -500,9 +767,9 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
2,
array[2].isshow,
Number(array[2].value)
Number(array[2].value), auto_sync.value
);
if (auto_sync.value) left_right_auto_add(-1);
// if (auto_sync.value) left_right_auto_add(-1);
save_set_cache();
},
{ deep: true }
@ -516,7 +783,7 @@ export default defineComponent({
$store.getters.GetTheCurrentlySelectedCamera[1],
3,
array[3].isshow,
Number(array[3].value)
Number(array[3].value), auto_sync.value
);
save_set_cache();
},
@ -535,71 +802,220 @@ export default defineComponent({
const changenablefusion = () => {
$store.commit("setenablefusion", enablefusion.value);
};
const left_right_auto_add = (difference: number) => {
/**
* 利用缓存手动同步
*/
// const left_right_auto_add = (difference: number) => {
// let tmpobjall = JSON.parse($store.state.fusion_configuration)
// if ($store.getters.GetTheCurrentlySelectedCamera[1] == 0&&group.value==2) {
// let tmp = set_cache.value[1] == null ? tmpobjall.projectors[1].params : JSON.parse(set_cache.value[1]);
// let set_cache_tmp: any = []
// if (tmp[1].hasOwnProperty("power")) {
// for (let index = 0; index < 4; index++) {
// let tmpobj = { alpha: Number(tmp[arr[index]].alpha.toFixed(2)), p: Number(tmp[arr[index]].power.toFixed(2)), gamma: Number(tmp[arr[index]].gamma.toFixed(2)), isshow: tmp[arr[index]].enable, value: Number(tmp[arr[index]].size) }
// set_cache_tmp.push(tmpobj)
// }
// } else {
// set_cache_tmp = tmp
// }
// if (ste_status.value == 0) {
// if (difference == -1) {
// set_cache_tmp[1].isshow = array[2].isshow
// } else {
// set_cache_tmp[1].value = difference
// }
// set?.SetBlendingOverlap(0, 1, 0, set_cache_tmp[1].isshow, Number(set_cache_tmp[1].value));
// set_cache.value[1] = JSON.stringify(set_cache_tmp);
// }
// }
// if ($store.getters.GetTheCurrentlySelectedCamera[1] == 1&&group.value==1) {
let tmpobjall = JSON.parse($store.state.fusion_configuration)
if ($store.getters.GetTheCurrentlySelectedCamera[1] == 0) {
// let tmp = set_cache.value[0] == null ? tmpobjall.projectors[0].params : JSON.parse(set_cache.value[0]);
// let set_cache_tmp: any = []
// if (tmp[0].hasOwnProperty("power")) {
// for (let index = 0; index < 4; index++) {
// let tmpobj = { alpha: Number(tmp[arr[index]].alpha.toFixed(2)), p: Number(tmp[arr[index]].power.toFixed(2)), gamma: Number(tmp[arr[index]].gamma.toFixed(2)), isshow: tmp[arr[index]].enable, value: Number(tmp[arr[index]].size) }
// set_cache_tmp.push(tmpobj)
// }
// } else {
// set_cache_tmp = tmp
// }
// if (ste_status.value == 0) {
// //set_cache_tmp[2].value = Number(set_cache_tmp[2].value) + difference
let tmp = set_cache.value[1] == null ? tmpobjall.projectors[1].params : JSON.parse(set_cache.value[1]);
let set_cache_tmp: any = []
if (tmp[1].hasOwnProperty("power")) {
for (let index = 0; index < 4; index++) {
let tmpobj = { alpha: Number(tmp[arr[index]].alpha.toFixed(2)), p: Number(tmp[arr[index]].power.toFixed(2)), gamma: Number(tmp[arr[index]].gamma.toFixed(2)), isshow: tmp[arr[index]].enable, value: Number(tmp[arr[index]].size) }
set_cache_tmp.push(tmpobj)
}
} else {
set_cache_tmp = tmp
}
if (ste_status.value == 0) {
//set_cache_tmp[1].value = Number(set_cache_tmp[1].value) + difference
// if (difference == -1) {
// set_cache_tmp[2].isshow = array[1].isshow
// } else {
// set_cache_tmp[2].value = difference
// }
// set?.SetBlendingOverlap(0, 0, 2, set_cache_tmp[2].isshow, Number(set_cache_tmp[2].value));
// set_cache.value[0] = JSON.stringify(set_cache_tmp);
// }
// }
// }
if (difference == -1) {
set_cache_tmp[1].isshow = array[2].isshow
// watch(()=>auto_sync,()=>{
// console.log(auto_sync.value)
// set?.SetBlendingOption("fusion_with_automatic_sync", auto_sync.value?'1':'0');
// },{deep:true})
/**
* 平板弹窗修改
*/
const ipad_chang = ref(false)
/**
* 当前url路径
*/
let url = window.location.href;
/**
* 长按实现
* 单击实现
*/
let loop: NodeJS.Timeout
let loop_end: NodeJS.Timeout
const handlerTouchstart = (fun: string) => {
loop_end = setTimeout(() => {
loop = setInterval(() => {
if (fun == '+') {
array[group.value].value += 2
} else {
set_cache_tmp[1].value = difference
array[group.value].value -= 2
}
set?.SetBlendingOverlap(0, 1, 0, set_cache_tmp[1].isshow, Number(set_cache_tmp[1].value));
set_cache.value[1] = JSON.stringify(set_cache_tmp);
}
}
if ($store.getters.GetTheCurrentlySelectedCamera[1] == 1) {
let tmp = set_cache.value[0] == null ? tmpobjall.projectors[0].params : JSON.parse(set_cache.value[0]);
let set_cache_tmp: any = []
if (tmp[0].hasOwnProperty("power")) {
for (let index = 0; index < 4; index++) {
let tmpobj = { alpha: Number(tmp[arr[index]].alpha.toFixed(2)), p: Number(tmp[arr[index]].power.toFixed(2)), gamma: Number(tmp[arr[index]].gamma.toFixed(2)), isshow: tmp[arr[index]].enable, value: Number(tmp[arr[index]].size) }
set_cache_tmp.push(tmpobj)
}
} else {
set_cache_tmp = tmp
}
if (ste_status.value == 0) {
//set_cache_tmp[2].value = Number(set_cache_tmp[2].value) + difference
if (difference == -1) {
set_cache_tmp[2].isshow = array[1].isshow
} else {
set_cache_tmp[2].value = difference
}
set?.SetBlendingOverlap(0, 0, 2, set_cache_tmp[2].isshow, Number(set_cache_tmp[2].value));
set_cache.value[0] = JSON.stringify(set_cache_tmp);
}
}, 30)
}, 100);
if (fun == '+') {
array[group.value].value += 2
} else {
array[group.value].value -= 2
}
}
const handlerTouchend = () => {
clearInterval(loop)
clearTimeout(loop_end)
}
const submit = () => {
set?.SetBlendingOption("blending_grids_background_color", color.value);
}
/**
* 处理平板模式下 伽马校正操作
* 手写实现pad长按点击
*/
const ipad_chang_input = ref(false)
const now_apg = ref("");
let loop__apg: NodeJS.Timeout
let loop__apg_end: NodeJS.Timeout
const handlerTouchstart_apg = (fun: string) => {
loop__apg_end = setTimeout(() => {
loop__apg = setInterval(() => {
if (fun == '+') {
array[group.value][now_apg.value] = toDecimal(array[group.value][now_apg.value] + 0.1)
} else {
array[group.value][now_apg.value] = toDecimal(array[group.value][now_apg.value] - 0.1)
}
chang(now_apg.value)
}, 30)
}, 1000);
if (fun == '+') {
array[group.value][now_apg.value] = toDecimal(array[group.value][now_apg.value] + 0.1)
} else {
array[group.value][now_apg.value] = toDecimal(array[group.value][now_apg.value] - 0.1)
}
chang(now_apg.value)
}
const handlerTouchend_apg = () => {
clearTimeout(loop__apg_end)
clearInterval(loop__apg)
}
const toDecimal = (num: number): number => {
return Math.round(num * 100) / 100;
}
let loop_start: NodeJS.Timeout
let loop_finish: NodeJS.Timeout
const input_focus = ref([false, false, false, false,])
const mousedown = (fun: string, index: number) => {
loop_start = setTimeout(() => {
loop_finish = setInterval(() => {
if (fun == '+') {
array[index].value += 2
} else {
array[index].value -= 2
}
}, 30)
}, 1000);
if (fun == '+') {
array[index].value += 2
} else {
array[index].value -= 2
}
}
const mouseup = () => {
clearTimeout(loop_start)
clearInterval(loop_finish)
}
const input_focus_apg = ref([false, false, false,])
// const ["","","",""]
/**
* 可供选择的
*/
const options = [{
label: $t.t('up'),
value: 0
}, {
label: $t.t('left'),
value: 1
}, {
label: $t.t('right'),
value: 2
}, {
label: $t.t('down'),
value: 3
}]
return {
options,
input_focus_apg,
input_focus,
mousedown,
mouseup,
now_apg,
handlerTouchstart_apg,
handlerTouchend_apg,
ipad_chang_input,
send_auxiliary_line,
group,
array,
chang,
enablefusion,
changenablefusion,
// changenablefusion,
selectedprojector,
set_cache,
auxiliary_line,
reset,
auto_sync,
config
config,
save_set_cache,
ipad_chang,
url,
handlerTouchstart,
handlerTouchend,
ispad,
color,
submit
};
},
});

View File

@ -4,8 +4,8 @@
<div class="row">
<div class="col-12">
<div class="row">
<div class="col-4"></div>
<div class="col-4 q-pt-sm"><q-select outlined v-model="model[0]"
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm"><q-select outlined v-model="model[0]"
@update:model-value="update_row_col(0, model[0])" :options="options" :dense="true" :options-dense="true"
:label="$t('wall row')" /> </div><q-checkbox @update:model-value="send_off(0)"
v-model="RowsColumns[0]" />
@ -13,8 +13,8 @@
</div>
<div class="col-12">
<div class="row">
<div class="col-4"></div>
<div class="col-4 q-pt-sm"><q-select outlined v-model="model[1]"
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm"><q-select outlined v-model="model[1]"
@update:model-value="update_row_col(1, model[1])" :options="options" :dense="true" :options-dense="true"
:label="$t('wall col')" /> </div><q-checkbox @update:model-value="send_off(1)"
v-model="RowsColumns[1]" />
@ -22,16 +22,16 @@
</div>
<div class="col-12">
<div class="row">
<div class="col-4"></div>
<div class="col-4 q-pt-sm"><q-select outlined v-model="model[2]"
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm"><q-select outlined v-model="model[2]"
@update:model-value="update_row_col(2, model[2])" :options="line_width_options" :dense="true" :options-dense="true"
:label="$t('line width')" /> </div>
</div>
</div>
<div class="col-12">
<div class="row" style="min-height: 40px;">
<div class="col-4"></div>
<div class="col-4 q-pt-sm">
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm">
<q-item>
<q-item-section avatar class="head_1">
{{ $t("line color") }}
@ -51,36 +51,14 @@
</div>
</div>
</div>
<div class="col-12">
<div class="row" style="min-height: 40px;">
<div class="col-4"></div>
<div class="col-4 q-pt-sm">
<div class="col-4 col-sm-3"></div>
<div class="col-4 col-sm-6 q-pt-sm">
<q-item>
<q-item-section avatar class="head_1">
{{ $t("background color") }}
</q-item-section>
<q-item-section>
<q-input v-model="color[1]" :rules="['anyColor']">
<template v-slot:append>
<q-icon name="colorize" class="cursor-pointer" @click="index = 1">
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-color v-model="color[1]" @change="submit" />
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</q-item-section>
</q-item>
</div>
</div>
</div>
<div class="col-12">
<div class="row" style="min-height: 40px;">
<div class="col-4"></div>
<div class="col-4 q-pt-sm">
<q-item>
<q-item-section avatar class="head_1">
{{ $t("center line color") }}
{{ $t("center circle color") }}
</q-item-section>
<q-item-section>
<q-input v-model="color[2]" :rules="['anyColor']">
@ -130,8 +108,11 @@ export default defineComponent({
const index = ref(0);
const color = reactive(["#ffffff", "#CCCCCC", "#000", "#000"]);
let model = reactive([20, 40, 20]);
let options = ref([10, 20, 30, 40, 50]);
let options = ref([10, 20, 30, 40, 50, 60 ,80]);
let line_width_options = ref([2,4,6,8,10, 20, 30, 40, 50]);
/**
* 发送颜色 根据index不同确定是那个接口
*/
const submit = () => {
switch (index.value) {
case 0:
@ -150,6 +131,11 @@ export default defineComponent({
break;
}
}
/**
* 修改 横纵 线的数量
* @param type 类型
* @param value
*/
const update_row_col = (type: number, value: number) => {
switch (type) {
case 0:
@ -165,6 +151,10 @@ export default defineComponent({
break;
}
}
/**
* 修改 单选 发送数据 使用switch 匹配多个
* @param type
*/
const send_off = (type: number) => {
setTimeout(() => {
switch (type) {
@ -186,6 +176,9 @@ export default defineComponent({
}
}, 100);
}
/**
* 使用服务端配置
*/
const use_server_config = () => {
let server_conf = JSON.parse($store.state.fusion_configuration).options
model[0] = server_conf.blending_grids_row ?? 20;
@ -203,10 +196,16 @@ export default defineComponent({
onBeforeUnmount(() => {
set_sessionStorage()
});
/**
* 保存缓存到sessionStorage
*/
const set_sessionStorage = () => {
let tmp = { RowsColumns: RowsColumns, color: color, model: model }
sessionStorage.GridSettings = JSON.stringify(tmp)
}
/**
* 获取sessionStorage
*/
const get_sessionStorage = () => {
let tmp = JSON.parse(sessionStorage.GridSettings)
for (let index = 0; index < tmp.RowsColumns.length; index++) {

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
}
}
">
<q-card class="" style="max-width: 90vw;padding: 0;">
<q-card class="" id="element" style="max-width: 90vw;padding: 0;">
<q-form>
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
@ -18,6 +18,9 @@
</div>
<q-space />
<q-btn v-show="ispad" size="sm" dense flat @click="element_full_screen" round :icon="is_pad_screen?'zoom_in_map':'zoom_out_map'" >
</q-btn>
<q-btn size="sm" dense flat round icon="close" color="red" @click="clear()" v-close-popup>
<q-tooltip>
{{ $t("close") }}
@ -28,49 +31,55 @@
<q-separator />
<!-- height: 80vh -->
<q-card-section class="scroll" style="width: 60vw;padding: 0;">
<q-card-section class="scroll" :style="{ 'width': is_pad_style, padding: 0 }">
<div class="row" style="border: 1px solid #b0bec5; text-align: center">
<div class="col-2" style="border-right: 1px solid #b0bec5">
<p class="text-center">{{ $t("Projector") }}</p>
<!-- row 在前col在后 -->
<!-- <div v-for="(item, index_row) in config.row">
<projector-item v-for="(item, index_col) in config.col" class="w-100" :llabel="
$t('Projector') + (index_row * config.col + index_col + 1)
" :lvalue="index_row + '/' + index_col"
@click="currently_selected_projector(index_row + '-' + index_col)"></projector-item>
</div> -->
<div v-for="(item, index_row) in config.row">
<projector-item v-for="(item, index_col) in config.col" class="w-100" :llabel="
$t('Projector') + (index_row * config.col + index_col + 1)
" :lvalue="index_row + '/' + index_col"
@click="currently_selected_projector(index_row + '-' + index_col)"></projector-item>
</div>
<hr>
<div>
<div class="col-3 q-px-md "> <q-select class="q-pt-md overflow-hidden" :label="$t('change resolution')"
@update:model-value="(val) => { dialog(val, set_resolution, 'resolution') }" :dense="true" filled
v-model="now_resolution" :options="options_resolution" emit-value map-options /></div>
<!-- <div class="col-3 q-px-md"> <q-select class="q-pt-md " use-input hide-selected fill-input
@filter="filterFn_projector" :label="$t('Change projector layout')"
@update:model-value="(val) => { dialog(val, send_projectorlayout, 'projector') }" :dense="true" filled
v-model="now_select_projectorlayout" :options="show_projectorlayout" emit-value map-options /></div> -->
<div class="col-3 q-px-md"> <q-select class="q-pt-md " use-input hide-selected fill-input
@filter="filterFn_projector2" :label="$t('Change projector layout')"
@update:model-value="(val) => { dialog_projectorlayout(val, send_projectorlayout2) }" :dense="true" filled
v-model="now_select_projectorlayout_tmp" :options="show_projectorlayout2" emit-value /></div>
</div>
<div class="col-12" style="text-align: center">
{{
$t("Whether to enable integration")
$t("Enable projection mode")
}}<q-checkbox v-model="EnableBlending" />
</div>
</div>
<div class="col-10">
<div class="q-ta-md">
<q-btn-toggle :disable="!$store.state.enablefusion" no-caps v-model="options" toggle-color="primary"
:options="[
{ label: $t('FusionLocale'), value: 'FusionLocale' },
{
label: $t('FourPointCalibration'),
value: 'FourPointCalibration',
},
{
label: $t('SurfaceCorrection'),
value: 'SurfaceCorrection',
},
{
label: $t('DensityCorrection'),
value: 'DensityCorrection',
},
{ label: $t('GridSettings'), value: 'GridSettings' },
]" />
:options="btn_options" />
<q-btn-toggle v-show="isdebug" no-caps v-model="options" toggle-color="primary" :options="[
{ label: $t('debugging'), value: 'Debugging' }
]" />
</div>
<div style="min-height: 72vh">
<component :is="options" />
<component ref="child" :is="options" :row="config.row" :col="config.col" />
</div>
</div>
</div>
@ -90,16 +99,16 @@
<q-btn color="white" @click="resetall" text-color="black" :label="$t('resetall config')" />
<div class="q-space" data-v-39efcd1f=""></div>
<q-btn flat :label="$t('Select saved configuration')" no-caps color="primary"
@click="select_configuration = true; get_scenes()" />
@click="select_configuration = true; select_configuration_name = ''; get_scenes()" />
<q-btn flat :label="$t('Cancel')" no-caps color="primary" v-close-popup
@click="$store.commit('setSelectedProjector', '0/0');" />
@click="$store.commit('setSelectedProjector', '0/0'); clear()" />
<q-btn flat :label="$t('save config')" no-caps color="primary" @click="save" />
</q-card-actions>
</q-form>
</q-card>
<q-dialog v-model="medium">
<q-card style="width: 700px; max-width: 80vw;">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<div class="text-h6">{{ $t('Whether to save the configuration') }}</div>
</q-card-section>
@ -119,15 +128,15 @@
</q-select>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('Cancel')" color="primary" v-close-popup />
<q-btn flat :label="$t('save')" @click="saveconfig" color="primary" v-close-popup />
<q-btn flat :label="$t('Cancel')" color="primary" @click="medium = false"/>
<q-btn flat :label="$t('save')" @click="saveconfig" color="primary" />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="select_configuration">
<q-card style="width: 700px; max-width: 80vw;">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<div class="text-h6">{{ $t('read saved configuration') }}</div>
</q-card-section>
@ -146,14 +155,14 @@
</q-select>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('Cancel')" color="primary" v-close-popup />
<q-btn flat :label="$t('apply')" @click="apply_the_selected_configuration" color="primary" v-close-popup />
<q-btn flat :label="$t('Cancel')" color="primary" @click="select_configuration=false" />
<q-btn flat :label="$t('load')" @click="apply_the_selected_configuration" color="primary" />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="del_dialog">
<q-card style="width: 700px; max-width: 80vw;">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<div class="text-h6">{{ $t('confirm delete') }}</div>
</q-card-section>
@ -161,8 +170,42 @@
{{ $t('Whether to delete') + name_to_be_deleted }}
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('Cancel')" color="primary" v-close-popup />
<q-btn flat :label="$t('ok')" @click="dialog_del_scenes" color="primary" v-close-popup />
<q-btn flat :label="$t('Cancel')" color="primary" @click="del_dialog=false" />
<q-btn flat :label="$t('ok')" @click="()=>{dialog_del_scenes();del_dialog=false}" color="primary" />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="confirm">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<div class="text-h6">{{ $t('Do you confirm the modification') }}</div>
</q-card-section>
<q-card-section class="q-pt-none">
{{ dialog_data.type == 'resolution' ? $t('Whether to modify the resolution to') +
options_resolution[dialog_data.parameter].label : $t('Whether to change the projector layout to') +
projectorlayout[dialog_data.parameter].label }}
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('Cancel')" @click="()=>{re_match_data();confirm=false}" color="primary" />
<q-btn flat :label="$t('ok')" @click="()=>{trigger_dialog();confirm=false}" color="primary" />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="confirm_projectorlayout">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<div class="text-h6">{{ $t('Do you confirm the modification') }}</div>
</q-card-section>
<q-card-section class="q-pt-none">
{{ $t('Whether to change the projector layout to') + dialog_data_projectorlayout.parameter }}
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('Cancel')" @click="()=>{re_match_data();confirm_projectorlayout=false}" color="primary" />
<q-btn flat :label="$t('ok')" @click="()=>{trigger_dialog_projectorlayout();confirm_projectorlayout=false}" color="primary" />
</q-card-actions>
</q-card>
</q-dialog>
@ -189,6 +232,7 @@ import {
computed,
onMounted,
onBeforeMount,
provide,
} from "vue";
import { useStore } from "src/store";
import { useQuasar, copyToClipboard } from "quasar";
@ -205,6 +249,7 @@ import GridSettings from "src/components/FusionSettings/GridSettings.vue";
import SurfaceCorrection from "src/components/FusionSettings/SurfaceCorrection.vue";
import DensityCorrection from "src/components/FusionSettings/DensityCorrection.vue";
import Debugging from "src/components/FusionSettings/Debugging.vue";
import { number } from "yargs";
export default defineComponent({
name: "ComponentFusionSettingsDialog",
@ -227,34 +272,133 @@ export default defineComponent({
const showDialog = async () => {
show_dialog.value = true;
};
/**
* 当前平板是否全屏
*/
const is_pad_screen = ref(false);
/**
* 计算平板和pc的样式
*/
const is_pad_style = computed(() => {
let url = window.location.href
if (url.indexOf("pad") != -1 && $t.locale.value == "en-US") {
return ""
}
if (url.indexOf("pad") != -1 && is_pad_screen.value) {
return "100vw"
}
return "60vw"
})
/**
* 选择配置的弹窗
*/
const select_configuration = ref(false)
/**
* 删除配置时弹窗
*/
const del_dialog = ref(false)
/**
* 后端获取的配置
*/
const config_projectors = ref(null)
/**
* 选择配置文件的名称
*/
const select_configuration_name = ref("")
/**
* 发送是否禁用融合参数
*/
const send_disable_blending_params = () => {
set?.SetBlendingOption(disable_blending_params_id.value, disable_blending_params.value ? "1" : "0");
};
/**
* 当前分辨率 在配置文件中的索引
*/
const now_resolution = ref(1)
// let allconfig = JSON.parse($store.state.fusion_configuration);
/**
* 模拟数据完成dom渲染再次获取真实后台数据
*/
let allconfig = JSON.parse("{\"resolution\": [{\"width\": 1920,\"height\": 1080}]}");
/**
* 计算可供选择的分辨率
*/
const options_resolution = computed(() => {
let tmp = [];
if (allconfig.resolution) {
for (let index = 0; index < allconfig.resolution.length; index++) {
tmp.push({
label: `${allconfig.resolution[index].width}*${allconfig.resolution[index].height}`,
value: index,
})
}
}
return tmp
})
/**
* 子组件
*/
const child: any = ref(null);
/**
* 开启网格时发送全部参数
*
*/
const send_show_blending_grids = () => {
let tmp = ""
switch (optionsstr.value) {
case 'FusionLocale':
tmp = '0'
break;
case 'FourPointCalibration':
tmp = '4'
break;
case 'SurfaceCorrection':
tmp = '9'
break;
case 'DensityCorrection':
tmp = 'density'
break;
default:
break;
}
switch (optionsstr.value) {
case 'FusionLocale':
tmp = '0'
break;
case 'FourPointCalibration':
tmp = '4'
break;
case 'SurfaceCorrection':
tmp = '9'
break;
case 'DensityCorrection':
if (child.value!.now_v_h == 'vertical') {
tmp = 'ver_density'
} else {
tmp = 'hor_density'
}
break;
default:
break;
}
set?.SetBlendingOption("blending_grids_select_ui", tmp)
set?.SetBlendingOption('blending_grids_select_projector', now_selsect_projector.value);
set?.SetBlendingOption(show_blending_grids_id.value, show_blending_grids.value ? "1" : "0");
switch (optionsstr.value) {
case 'FusionLocale':
break;
case 'FourPointCalibration':
set?.SetBlendingOption("blending_grids_select_point", `4:${child.value!.options_model + 1}`)
break;
case 'SurfaceCorrection':
set?.SetBlendingOption("blending_grids_select_point", `9:${child.value!.options_model + 1}`)
set?.SetBlendingOption("blending_grids_control_point_count", `${child.value!.value_point_amount}`)
break;
case 'DensityCorrection':
if (child.value!.now_v_h == 'vertical') {
set?.SetBlendingOption("blending_grids_select_point", `${child.value!.options_model_v + 1}`)
set?.SetBlendingOption("blending_grids_control_point_count", `${child.value!.value_v_point_amount}`)
} else {
set?.SetBlendingOption("blending_grids_select_point", `${child.value!.options_model_h + 1}`)
set?.SetBlendingOption("blending_grids_control_point_count", `${child.value!.value_h_point_amount}`)
}
break;
default:
break;
}
};
/**
* 重置全部参数
*/
const tmp_options = ref("")
const resetall = () => {
set?.ResetBlendingConfig().then((res) => {
let tmp = JSON.parse(res ? res.config : "");
@ -264,14 +408,19 @@ export default defineComponent({
config.value.row = tmp.row;
$store.commit("setfusion_configuration", res?.config);
});
let tmp = options.value
if (options.value.length != 0) {
tmp_options.value = options.value
}
options.value = ""
$store.commit("setSelectedProjector", "0/0");
setTimeout(() => {
clear_sessionStorage()
options.value = tmp
options.value = tmp_options.value
}, 300);
}
/**
* 清除sessionStorage缓存
*/
const clear_sessionStorage = () => {
sessionStorage.removeItem("FusionLocale");
sessionStorage.removeItem("SurfaceCorrection");
@ -279,16 +428,37 @@ export default defineComponent({
sessionStorage.removeItem("FourPointCalibration");
sessionStorage.removeItem("GridSettings");
sessionStorage.removeItem("Debugging");
sessionStorage.removeItem("FusionLocale_async");
}
/**
* 从配置文件中获取的行和列
*/
const config = ref({ col: 0, row: 0 });
/**
* 是否开启融合
*/
const EnableBlending = ref(false);
let optionsstr = ref();
optionsstr.value = "FusionLocale";
optionsstr.value = "";
/**
* 是否禁用融合参数 的参数名称
*/
const disable_blending_params_id = ref("blending@disable_blending_params");
/**
* 是否禁用融合参数
*/
const disable_blending_params = ref(false);
/**
* 是否开启网格的参数名称
*/
const show_blending_grids_id = ref("blending_grids_show");
const show_blending_grids = ref(false);
/**
* 是否开启网格
*/
const show_blending_grids = ref(true);
/**
* 是否保存配置弹窗
*/
const medium = ref(false);
const options = computed({
get() {
@ -298,35 +468,78 @@ export default defineComponent({
optionsstr.value = newValue;
},
});
/**
* 监听是否开启融合
*/
watch(
() => EnableBlending,
(newVal, oldVal) => {
(newVal) => {
$store.commit("setEnablefusion", newVal.value);
set?.EnableBlending(newVal.value);
},
{ deep: true }
);
/**
* 设置分辨率
* @param index 索引号
*/
const set_resolution = (index: number) => {
$q.loading.show({
message: 'Loading please wait'
})
let w = allconfig.resolution[index].width
let h = allconfig.resolution[index].height
set?.SetProjectorResolution(w, h).then((res) => {
$store.commit("setfusion_configuration", res?.config);
})
let tmp = options.value
options.value = ""
$store.commit("setSelectedProjector", "0/0");
setTimeout(() => {
clear_sessionStorage()
options.value = tmp
$q.loading.hide()
}, 800);
getconfig()
}
/**
* 监听ui切换
*/
watch(() => optionsstr,
(newVal) => {
let tmp = ""
switch (newVal.value) {
case 'FusionLocale':
tmp = "blending"
set?.SetBlendingOption("blending_grids_select_ui", tmp)
break;
case 'FourPointCalibration':
tmp = '4'
set?.SetBlendingOption("blending_grids_select_ui", tmp)
set?.SetBlendingOption("blending_grids_control_point_count", `4`)
set?.SetBlendingOption("blending_grids_select_point", `4:1`)
break;
case 'SurfaceCorrection':
tmp = '9'
/**
* 延迟发送不然获取不到值
*/
set?.SetBlendingOption("blending_grids_select_ui", tmp)
setTimeout(() => {
set?.SetBlendingOption("blending_grids_control_point_count", `${child.value!.value_point_amount}`)
set?.SetBlendingOption("blending_grids_select_point", `${child.value!.value_point_amount}:1`)
}, 100);
break;
case 'DensityCorrection':
tmp = 'density'
tmp = 'hor_density'
set?.SetBlendingOption("blending_grids_select_ui", tmp)
break;
default:
break;
}
if (tmp.length) set?.SetBlendingOption("blending_grids_select_ui", tmp)
// if (tmp.length) set?.SetBlendingOption("blending_grids_select_ui", tmp)
},
{ deep: true })
@ -334,9 +547,13 @@ export default defineComponent({
const save = () => {
medium.value = true
save_cover_name.value = ''
//
get_scenes()
};
/**
* 读取服务器配置
*/
const getconfig = () => {
try {
set?.GetBlendingConfig("").then((res) => {
@ -346,19 +563,31 @@ export default defineComponent({
});
} catch (error) { }
};
/**
* 点击页面取消时调用 恢复默认参数
*/
const clear = () => {
record_times.value = 0
show_blending_grids.value = false;
// show_blending_grids.value = false;
is_pad_screen.value = false
send_show_blending_grids();
$store.commit("setSelectedProjector", "0/0");
set?.SetBlendingOption("blending_grids_show", "0");
setTimeout(() => {
clear_sessionStorage()
}, 500);
getconfig()
options.value = "FusionLocale"
//getconfig()
if (config.value.col == 1 && config.value.row == 1) {
optionsstr.value = "FourPointCalibration"
} else {
optionsstr.value = "FourPointCalibration";
}
now_selsect_projector.value = "0-0"
};
/**
* 读取服务器场景
*/
const get_scenes = () => {
set?.EnumBlendingScene().then((res) => {
if (res == null || res.scenes.length == 0) return
@ -373,6 +602,7 @@ export default defineComponent({
setTimeout(() => {
set?.GetBlendingConfig("").then((res) => {
let tmp = JSON.parse(res ? res.config : "");
config_projectors.value = tmp
let local_options = [
[disable_blending_params_id, disable_blending_params],
[show_blending_grids_id, show_blending_grids]
@ -385,22 +615,81 @@ export default defineComponent({
local_opt[1].value = ("0" == opt || "false" == opt.toLowerCase() ? false : true);
}
}
show_blending_grids.value = true
EnableBlending.value = tmp.enable;
$store.commit("setEnablefusion", tmp.enable);
config.value.col = tmp.col;
config.value.row = tmp.row;
$store.commit("setfusion_configuration", res?.config);
optionsstr.value = "FourPointCalibration";
allconfig = JSON.parse($store.state.fusion_configuration);
/**
* 匹配当前分辨率的索引 没有匹配到自动加入当前分辨率
*/
if (allconfig.resolution) {
for (let index = 0; index < allconfig.resolution.length; index++) {
if (allconfig.resolution[index].width == allconfig.projector_width && allconfig.resolution[index].height == allconfig.projector_height) {
now_resolution.value = index
}
}
} else {
allconfig = { resolution: [{ width: tmp.projector_width, height: tmp.projector_height }] };
now_resolution.value = 0
}
/**
* 计算当前可供选择的 投影机布局
*/
projectorlayout.value = []
let cont = 0
for (let index = 1; index <= tmp.max_projector_count; index++) {
for (let indexx = 1; indexx <= tmp.max_projector_count; indexx++) {
if (index * indexx > tmp.max_projector_count) {
continue
} else {
projectorlayout.value.push({ label: `${index}x${indexx}`, value: cont })
cont++
projectorlayout_tmp.value.push(`${index}x${indexx}`)
}
}
}
/**
* 匹配当前投影机布局
*/
for (let index = 0; index < projectorlayout.value.length; index++) {
let arr = projectorlayout.value[index].label.split('x');
if (tmp.col == Number(arr[1]) && tmp.row == Number(arr[0])) {
now_select_projectorlayout.value = index
}
if(`${tmp.row}x${tmp.col}`==projectorlayout_tmp.value[index]){
now_select_projectorlayout_tmp.value=projectorlayout_tmp.value[index]
}
}
});
get_scenes()
set?.SetBlendingOption("blending_grids_select_ui", "blending")
// show_blending_grids.value=true
// send_show_blending_grids()
}, 1000);
// console.log(" ")
});
/**
* 保存配置的名称
*/
const save_cover_name = ref("")
/**
*
*/
const plan_list = [
''
]
/**
* 应用当前选择的配置文件
*/
const apply_the_selected_configuration = () => {
$q.loading.show({
message: 'Loading please wait'
})
set?.ApplyBlendingScene(select_configuration_name.value).then((res) => {
let tmp = JSON.parse(res ? res.config : "{}");
EnableBlending.value = tmp.enable;
@ -408,6 +697,23 @@ export default defineComponent({
config.value.col = tmp.col;
config.value.row = tmp.row;
$store.commit("setfusion_configuration", res?.config);
allconfig = tmp
for (let index = 0; index < options_resolution.value.length; index++) {
let arr = options_resolution.value[index].label.split('*');
if (tmp.projector_width == Number(arr[1]) && tmp.projector_height == Number(arr[0])) {
now_resolution.value = index
}
}
for (let index = 0; index < projectorlayout.value.length; index++) {
let arr = projectorlayout.value[index].label.split('x');
if (tmp.row == Number(arr[1]) && tmp.col == Number(arr[0])) {
now_select_projectorlayout.value = index
}
if(`${tmp.row}x${tmp.col}`==projectorlayout_tmp.value[index]){
now_select_projectorlayout_tmp.value=projectorlayout_tmp.value[index]
}
}
select_configuration.value=false
});
let tmp = options.value
@ -416,16 +722,25 @@ export default defineComponent({
setTimeout(() => {
clear_sessionStorage()
options.value = tmp
$q.loading.hide()
}, 800);
getconfig()
}
const plan_list_op = ref(plan_list)
const filterFn = (val: any, update: any, abort: any) => {
/**
* select 自动提示函数
* @param val
* @param update
*/
const filterFn = (val: any, update: any) => {
update(() => {
const needle = val.toLocaleLowerCase()
plan_list_op.value = plan_list.filter(v => v.toLocaleLowerCase().indexOf(needle) > -1)
})
}
/**
* 当前按下ctrl 次数
*/
const record_times = ref(0)
const setModel = (val: string) => {
save_cover_name.value = val
@ -433,32 +748,282 @@ export default defineComponent({
const saveconfig = () => {
set?.SaveBlendingConfig(save_cover_name.value);
medium.value = false
}
/**
* 是否开启debug页面
*/
const isdebug = computed(() => {
try {
let tmp = JSON.parse($store.state.fusion_configuration)
return record_times.value > 2
} catch (error) {
}
})
/**
* 需要删除的配置 名称
*/
const name_to_be_deleted = ref("");
/**
* 待删除配置函数
* @param name 待删除的名称
*/
const del_scenes = (name: string) => {
del_dialog.value = true;
name_to_be_deleted.value = name;
}
/**
* 正式删除配置的函数
*/
const dialog_del_scenes = () => {
set?.DeleteBlendingScene(name_to_be_deleted.value);
plan_list.splice(plan_list.findIndex(item => item === name_to_be_deleted.value), 1)
name_to_be_deleted.value = ''
select_configuration_name.value = ''
save_cover_name.value = ''
}
const now_selsect_projector=ref("0-0")
/**
* 当前选择的投影机
*/
const now_selsect_projector = ref("0-0")
/**
* 发送当前选择的投影机
* @param value
*/
const currently_selected_projector = (value: string) => {
set?.SetBlendingOption('blending_grids_select_projector', value);
now_selsect_projector.value=value
now_selsect_projector.value = value
}
/**
* 依赖注入
*/
provide("now_selsect_projector", now_selsect_projector);
/**
* 可以供选择的布局 变量
*/
let projectorlayout = ref([{ label: '1x1', value: 0 }, { label: '1x2', value: 1 }])
let projectorlayout_tmp = ref(<string[]>[])
const now_select_projectorlayout = ref(0)
const now_select_projectorlayout_tmp = ref("")
/**
* 发送当前选择的布局
* @param val
*/
const send_projectorlayout = (val: number) => {
let arr = projectorlayout.value[val].label.split('x');
set?.SetProjectorLayout(Number(arr[0]), Number(arr[1])).then(res => {
let tmpp = JSON.parse(res!.config)
config.value.row = tmpp.row;
config.value.col = tmpp.col;
$q.loading.show({
message: 'Loading please wait'
})
$store.commit("setfusion_configuration", res?.config);
for (let index = 0; index < projectorlayout.value.length; index++) {
let arr = projectorlayout.value[index].label.split('x');
if (tmpp.col == Number(arr[1]) && tmpp.row == Number(arr[0])) {
now_select_projectorlayout.value = index
}
if(`${tmpp.row}x${tmpp.col}`==projectorlayout_tmp.value[index]){
now_select_projectorlayout_tmp.value=projectorlayout_tmp.value[index]
}
}
let tmp = options.value
options.value = ""
$store.commit("setSelectedProjector", "0/0");
setTimeout(() => {
clear_sessionStorage()
options.value = tmp
$q.loading.hide()
}, 800);
getconfig()
})
}
/**
* 发送当前选择的布局
* @param val
*/
const send_projectorlayout2 = (val: string) => {
let arr = val.split('x');
set?.SetProjectorLayout(Number(arr[0]), Number(arr[1])).then(res => {
let tmpp = JSON.parse(res!.config)
config.value.row = tmpp.row;
config.value.col = tmpp.col;
$q.loading.show({
message: 'Loading please wait'
})
$store.commit("setfusion_configuration", res?.config);
for (let index = 0; index < projectorlayout.value.length; index++) {
let arr = projectorlayout.value[index].label.split('x');
if (tmpp.col == Number(arr[1]) && tmpp.row == Number(arr[0])) {
now_select_projectorlayout.value = index
}
if(`${tmpp.row}x${tmpp.col}`==projectorlayout_tmp.value[index]){
now_select_projectorlayout_tmp.value=projectorlayout_tmp.value[index]
}
}
let tmp = options.value
options.value = ""
$store.commit("setSelectedProjector", "0/0");
setTimeout(() => {
clear_sessionStorage()
options.value = tmp
$q.loading.hide()
}, 800);
getconfig()
})
}
const btn_options = computed(() => {
let tmp = []
tmp.push({ label: $t.t('FourPointCalibration'), value: 'FourPointCalibration' })
tmp.push({ label: $t.t('SurfaceCorrection'), value: 'SurfaceCorrection', })
if (now_select_projectorlayout.value != 0) {
tmp.push({ label: $t.t('FusionLocale'), value: 'FusionLocale' })
} else {
optionsstr.value = "FourPointCalibration";
}
tmp.push({ label: $t.t('DensityCorrection'), value: 'DensityCorrection', })
tmp.push({ label: $t.t('GridSettings'), value: 'GridSettings' })
return tmp
})
/**
* 计算可以显示的投影机数量
*/
const projectors_that_can_display = computed(() => {
let allconfig = JSON.parse($store.state.fusion_configuration);
let col = allconfig.projectors.length
return { col }
})
/**
* 弹窗
* 浅拷贝
*/
const confirm = ref(false)
let dialog_data: any = { parameter: "", fun: "", type: "" }
const dialog = (parameter: any, fun: any, type: string) => {
confirm.value = true
dialog_data.parameter = parameter
dialog_data.fun = fun
dialog_data.type = type
}
const trigger_dialog = () => {
dialog_data.fun(dialog_data.parameter)
}
const confirm_projectorlayout=ref(false);
let dialog_data_projectorlayout: any = { parameter: "", fun: ""}
const dialog_projectorlayout = (parameter: any, fun: any) => {
confirm_projectorlayout.value = true
dialog_data_projectorlayout.parameter = parameter
dialog_data_projectorlayout.fun = fun
}
const trigger_dialog_projectorlayout = () => {
dialog_data_projectorlayout.fun(dialog_data_projectorlayout.parameter)
}
/**
* select 组件选中就触发修改 这里是通过再次获取数据判断 显示在页面
*/
const re_match_data = () => {
let tmp = JSON.parse($store.state.fusion_configuration);
for (let index = 0; index < options_resolution.value.length; index++) {
let arr = options_resolution.value[index].label.split('*');
if (tmp.projector_width == Number(arr[0]) && tmp.projector_height == Number(arr[1])) {
now_resolution.value = index
}
}
for (let index = 0; index < projectorlayout.value.length; index++) {
let arr = projectorlayout.value[index].label.split('x');
if (tmp.row == Number(arr[0]) && tmp.col == Number(arr[1])) {
now_select_projectorlayout.value = index
}
if(`${tmp.row}x${tmp.col}`==projectorlayout_tmp.value[index]){
now_select_projectorlayout_tmp.value=projectorlayout_tmp.value[index]
}
}
}
const element: any = ref()
/**
* 手动全屏指定元素
*/
const element_full_screen = () => {
let elem = document.getElementById("element")
if (!document.fullscreenElement) {
elem!.requestFullscreen().catch((err) => {
});
is_pad_screen.value = true
} else {
document.exitFullscreen();
is_pad_screen.value = false
}
}
const ispad = computed(() => {
let url = window.location.href;
return url.indexOf("pad") != -1
})
interface projectorlayoutarray {
label: string; value: number;
}
/**
* 经过筛选的 投影机布局
*/
const show_projectorlayout = ref(<projectorlayoutarray[]>[])
/**
* 筛选投影机函数
* @param val
* @param update
*/
const filterFn_projector = (val: any, update: any) => {
update(() => {
const needle = val.toLowerCase()
show_projectorlayout.value = projectorlayout.value.filter(v => v.label.toLowerCase().indexOf(needle) > -1)
})
}
/**
* 经过筛选的 投影机布局
*/
const show_projectorlayout2 = ref(<string[]>[])
/**
* 筛选投影机函数
* @param val
* @param update
*/
const filterFn_projector2 = (val: any, update: any) => {
update(() => {
const needle = val.toLowerCase()
show_projectorlayout2.value = projectorlayout_tmp.value.filter(v => v.toLowerCase().indexOf(needle) > -1)
})
}
return {
now_select_projectorlayout_tmp,
show_projectorlayout2,
filterFn_projector2,
is_pad_screen,
dialog_data,
allconfig,
now_selsect_projector,
re_match_data,
trigger_dialog,
confirm,
dialog,
currently_selected_projector,
name_to_be_deleted,
dialog_del_scenes,
@ -490,7 +1055,27 @@ export default defineComponent({
record_times,
saveconfig,
isdebug,
del_dialog
del_dialog,
child,
options_resolution,
now_resolution,
set_resolution,
send_projectorlayout,
send_projectorlayout2,
now_select_projectorlayout,
projectorlayout,
btn_options,
projectors_that_can_display,
is_pad_style,
element,
element_full_screen,
ispad,
filterFn_projector,
show_projectorlayout,
confirm_projectorlayout,
dialog_data_projectorlayout,
dialog_projectorlayout,
trigger_dialog_projectorlayout
};
},
});

File diff suppressed because it is too large Load Diff

View File

@ -466,7 +466,7 @@ export default defineComponent({
{
align: "left",
name: "delay",
label: $t.t("delay"),
label: $t.t("duration"),
field: "delay",
sortable: false,
},

View File

@ -311,7 +311,7 @@ export default defineComponent({
{
align: "left",
name: "delay",
label: $t.t("delay"),
label: $t.t("duration"),
field: "delay",
sortable: false,
},

View File

@ -1,247 +1,225 @@
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-auto text-h6">
{{ $t("database import") }}
</div>
<q-space />
<div>
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-uploader
class="full-width"
ref="uploader"
:url="upload_url"
method="post"
:headers="generatorFileUploadHeaders"
:label="$t('select data(DBP) file') + ':'"
accept=".dbp"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
no-caps
:loading="loading"
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { api as viewerApi } from "v-viewer";
export default defineComponent({
name: "ComponentRecoveryDatabaseDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader: any = ref(null);
let loading = ref(false);
let upload_url = ref("");
let file_count = ref(0);
return {
show_dialog,
loading,
upload_url,
uploader,
file_count,
generatorFileUploadHeaders(files: File[]) {
if (files.length > 0) {
return [
{
name: HttpProtocol.kHeaderXProductName,
value: HttpProtocol.getProductName($store),
},
{
name: HttpProtocol.kHeaderXFileLength,
value: files[0].size,
},
];
}
return [];
},
showDialog() {
show_dialog.value = true;
let client = GlobalData.getInstance().getCurrentClient();
if (client) {
let url = new URL(client.url);
url.port =
GlobalData.getInstance().applicationConfig?.httpserver_port ??
HttpProtocol.DefaultHttpPort.toString();
url.pathname = HttpProtocol.RequestUploadFile;
url.protocol = "http:";
url.searchParams.append("type", HttpProtocol.UploadTypeDatabase);
upload_url.value = url.toString();
}
},
resetData() {
loading.value = false;
upload_url.value = "";
file_count.value = 0;
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
$q.dialog({
title: $t.t("Confirm"),
message: $t.t("use this file to recovery data") + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
uploader.value.upload();
})
.onCancel(() => {
loading.value = false;
});
} catch {}
},
onUploaded() {
$q.notify({
type: "positive",
message: $t.t("data import") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
$q.dialog({
title: $t.t("Confirm"),
message:
$t.t("data changes will take effect after the restart") +
"!" +
"<p class='text-red'>" +
$t.t("reboot now") +
"?" +
"</p>",
html: true,
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
GlobalData.getInstance().getCurrentClient()?.restartDevice();
$q.notify({
type: "positive",
message: $t.t("reboot device command sended") + "!",
position: "top",
timeout: 1500,
});
})
.onDismiss(() => {
loading.value = false;
show_dialog.value = false;
});
},
onFailed(info: any) {
console.log(info);
$q.notify({
type: "warning",
message: $t.t("data import") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-auto text-h6">
{{ $t("database import") }}
</div>
<q-space />
<div>
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-uploader
class="full-width"
ref="uploader"
:url="upload_url"
method="POST"
:label="$t('select data(DBP) file') + ':'"
accept=".dbp"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
no-caps
:loading="loading"
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { api as viewerApi } from "v-viewer";
export default defineComponent({
name: "ComponentRecoveryDatabaseDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader: any = ref(null);
let loading = ref(false);
let upload_url = ref("");
let file_count = ref(0);
return {
show_dialog,
loading,
upload_url,
uploader,
file_count,
showDialog() {
show_dialog.value = true;
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = "/upload_db_file";
upload_url.value = url.toString();
}
},
resetData() {
loading.value = false;
upload_url.value = "";
file_count.value = 0;
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
$q.dialog({
title: $t.t("Confirm"),
message: $t.t("use this file to recovery data") + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
uploader.value.upload();
})
.onCancel(() => {
loading.value = false;
});
} catch {}
},
onUploaded() {
$q.notify({
type: "positive",
message: $t.t("data import") + $t.t("success") + "!",
position: "top",
timeout: 1500,
});
$q.dialog({
title: $t.t("Confirm"),
message:
$t.t("data changes will take effect after the restart") +
"!" +
"<p class='text-red'>" +
$t.t("reboot now") +
"?" +
"</p>",
html: true,
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
GlobalData.getInstance().getCurrentClient()?.restartDevice();
$q.notify({
type: "positive",
message: $t.t("reboot device command sended") + "!",
position: "top",
timeout: 1500,
});
})
.onDismiss(() => {
loading.value = false;
show_dialog.value = false;
});
},
onFailed(info: any) {
console.log(info);
$q.notify({
type: "warning",
message: $t.t("data import") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>

View File

@ -73,268 +73,354 @@
<q-separator />
<q-card-section class="scroll" style="width: 70vw">
<q-list>
<q-item v-if="ext_flag">
<q-item-section avatar class="header_label">
{{ $t("register type") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-model="register_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="offline"
:label="$t('offline register')"
class="offset-md-1 col"
<q-scroll-area style="height: 65vh">
<q-list>
<q-item v-if="ext_flag">
<q-item-section avatar class="header_label">
{{ $t("register type") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-model="register_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="offline"
:label="$t('offline register')"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-radio
v-model="register_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="online"
:label="$t('online register')"
class="col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("register code") }}
</q-item-section>
<q-item-section>
<div
style="
word-break: break-all;
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
"
>
{{ register_code }}
</div>
</q-item-section>
<q-item-section avatar>
<qrcode-vue
:value="register_code"
level="H"
render-as="svg"
:size="160"
/>
</q-item-section>
<q-item-section avatar>
<q-btn
round
flat
icon="content_copy"
color="green"
:loading="loading"
:disable="loading"
/>
<q-radio
v-model="register_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="online"
:label="$t('online register')"
class="col"
@click="
copyToClipboard(register_code).then(() =>
$q.notify({
color: 'positive',
icon: 'done',
message: $t('copy') + $t('success'),
position: 'top',
timeout: 1500,
})
)
"
>
<q-tooltip>
{{ $t("copy") }}{{ $t("register code") }}
</q-tooltip>
</q-btn>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("active code") }}
</q-item-section>
<q-item-section>
<q-input
type="textarea"
v-model="active_code"
lazy-rules
autofocus
:loading="loading"
:disable="loading"
:rules="[
(val) =>
(val && val.length > 0) || $t('Please type something'),
]"
/>
</div>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("register code") }}
</q-item-section>
<q-item-section>
<div style="word-break: break-all">
{{ register_code }}
</div>
</q-item-section>
<q-item-section avatar>
<qrcode-vue
:value="register_code"
level="H"
render-as="svg"
:size="195"
/>
</q-item-section>
<q-item-section avatar>
<q-btn
round
flat
icon="content_copy"
color="green"
:loading="loading"
:disable="loading"
@click="
copyToClipboard(register_code).then(() =>
$q.notify({
color: 'positive',
icon: 'done',
message: $t('copy') + $t('success'),
position: 'top',
timeout: 1500,
})
)
"
>
<q-tooltip>
{{ $t("copy") }}{{ $t("register code") }}
</q-tooltip>
</q-btn>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("active code") }}
</q-item-section>
<q-item-section>
<q-input
type="textarea"
v-model="active_code"
lazy-rules
autofocus
:loading="loading"
:disable="loading"
:rules="[
(val) =>
(val && val.length > 0) || $t('Please type something'),
]"
/>
</q-item-section>
<q-item-section avatar>
<q-btn
icon="attach_file"
round
flat
:loading="loading"
:disable="loading"
class="rotate-90"
color="green"
@click="$refs.select_file_dialog.pickFiles($event)"
>
<q-tooltip>
{{ $t("open file") }}
</q-tooltip>
</q-btn>
</q-item-section>
</q-item>
<q-item v-if="false && register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("secret key") }}
</q-item-section>
<q-item-section>
<q-input v-model="secret_key"> </q-input>
</q-item-section>
<q-item-section avatar> ({{ $t("optional") }}) </q-item-section>
</q-item>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("server ipaddress") }}
</q-item-section>
<q-item-section>
<q-input
v-model="server_address"
autofocus
:loading="loading"
:disable="loading"
lazy-rules
:rules="[
(val) =>
isIpAddress(val) || $t('Please input vaild ip address'),
]"
/>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("active type") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-model="active_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="forever"
:label="$t('forever active')"
class="offset-md-1 col"
</q-item-section>
<q-item-section avatar>
<q-btn
icon="attach_file"
round
flat
:loading="loading"
:disable="loading"
/>
<q-radio
v-model="active_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="limit"
:label="$t('time limit active')"
class="col"
class="rotate-90"
color="green"
@click="$refs.select_file_dialog.pickFiles($event)"
>
<q-tooltip>
{{ $t("open file") }}
</q-tooltip>
</q-btn>
</q-item-section>
</q-item>
<q-item v-if="false && register_type == 'offline'">
<q-item-section avatar class="header_label">
{{ $t("secret key") }}
</q-item-section>
<q-item-section>
<q-input v-model="secret_key"> </q-input>
</q-item-section>
<q-item-section avatar> ({{ $t("optional") }}) </q-item-section>
</q-item>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("server ipaddress") }}
</q-item-section>
<q-item-section>
<q-input
v-model="server_address"
autofocus
:loading="loading"
:disable="loading"
lazy-rules
:rules="[
(val) =>
isIpAddress(val) || $t('Please input vaild ip address'),
]"
/>
</div>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'online' && active_type == 'limit'">
<q-item-section avatar class="header_label">
{{ $t("active time") }}
</q-item-section>
<q-item-section>
<q-input
v-model="active_hour"
type="number"
min="1"
max="120"
:loading="loading"
:disable="loading"
>
<template v-slot:append>
{{ $t("day") }}
</template>
</q-input>
</q-item-section>
</q-item>
</q-item-section>
</q-item>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("active type") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-model="active_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="forever"
:label="$t('forever active')"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-radio
v-model="active_type"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="limit"
:label="$t('time limit active')"
class="col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item v-if="active_type == 'limit'">
<q-item-section avatar class="header_label">
{{ $t("active time") }}
</q-item-section>
<q-item-section>
<q-input
v-model="active_hour"
type="number"
min="1"
max="120"
:loading="loading"
:disable="loading"
>
<template v-slot:append>
{{ $t("day") }}
</template>
</q-input>
</q-item-section>
</q-item>
<q-separator class="q-mt-md" />
<q-item>
<q-item-section avatar class="header_label">
{{ $t("product") }}
</q-item-section>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("function") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-checkbox
v-model="function_output_board"
:label="$t('output board')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-checkbox
v-model="function_center_control"
:label="$t('center control')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-checkbox
v-model="function_mirroring_output"
:label="$t('mirroring output')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-model="selected_product"
val=""
:label="$t('normal')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label"> </q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-checkbox
v-model="function_custom_ISV"
:label="$t('Custom ISV')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-radio
v-model="selected_product"
val="magic_wall"
:label="$t('magic wall')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-radio
v-model="selected_product"
val="fusion"
:label="$t('fusion')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item v-if="selected_product == 'fusion'">
<q-item-section avatar class="header_label">
{{ $t("fusion") }}
</q-item-section>
<q-item v-if="register_type == 'online'">
<q-item-section avatar class="header_label">
{{ $t("language") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
color="cyan"
:loading="loading"
:disable="loading"
class="offset-md-1 col"
v-model="target_language"
val="zh-CN"
:label="$t('chinese')"
/>
<q-radio
color="cyan"
:loading="loading"
:disable="loading"
class="offset-md-1 col"
v-model="target_language"
val="en-US"
:label="$t('english')"
/>
</div>
</q-item-section>
</q-item>
</q-list>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
v-for="item of 5"
:key="item"
v-model="function_fusion_count"
:val="item"
:label="item.toString() + $t(' ') + $t('fusion out')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
<div class="row q-gutter-sm">
<q-radio
v-for="item of 4"
:key="5 + item"
v-model="function_fusion_count"
:val="5 + item"
:label="
(5 + item).toString() + $t(' ') + $t('fusion out')
"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<div class="offset-md-1 col"></div>
</div>
</q-item-section>
<q-item-section avatar> </q-item-section>
</q-item>
<q-item>
<q-item-section avatar class="header_label">
{{ $t("function") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-checkbox
v-model="function_output_board"
:label="$t('output board')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-checkbox
v-model="function_center_control"
:label="$t('center control')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
<q-checkbox
v-model="function_mirroring_output"
:label="$t('mirroring output')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar class="header_label"> </q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-checkbox
v-model="function_custom_ISV"
:label="$t('Custom ISV')"
color="cyan"
class="offset-md-1 col"
:loading="loading"
:disable="loading"
/>
</div>
</q-item-section>
</q-item>
<q-item>
<q-item-section avatar class="header_label">
{{ $t("language") }}
</q-item-section>
<q-item-section>
<div class="row q-gutter-sm">
<q-radio
color="cyan"
:loading="loading"
:disable="loading"
class="offset-md-1 col"
v-model="target_language"
val="zh-CN"
:label="$t('chinese')"
/>
<q-radio
color="cyan"
:loading="loading"
:disable="loading"
class="offset-md-1 col"
v-model="target_language"
val="en-US"
:label="$t('english')"
/>
</div>
</q-item-section>
</q-item> </q-list
></q-scroll-area>
</q-card-section>
<q-separator />
@ -383,12 +469,16 @@ import {
nextTick,
} from "vue";
import { useStore } from "src/store";
import { useQuasar, copyToClipboard } from "quasar";
import { useQuasar, copyToClipboard, Cookies } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import QrcodeVue from "qrcode.vue";
import { Protocol } from "src/entities/WSProtocol";
import { EDeviceAttribute } from "src/entities/EDeviceAttribute";
import {
EDeviceAttribute,
EDeviceAttributeHelper,
} from "src/entities/EDeviceAttribute";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentRegisterDialog",
@ -419,6 +509,18 @@ export default defineComponent({
const function_output_board = ref(false);
const function_mirroring_output = ref(false);
const function_custom_ISV = ref(false);
const function_magic_wall = ref(false);
const function_fusion = ref(false);
const function_fusion_count = ref(1);
const selected_product = ref("");
watch(
() => selected_product.value,
(newValue) => {
function_fusion.value = newValue == "fusion";
function_magic_wall.value = newValue == "magic_wall";
}
);
const trial_days = ref(0);
const last_days = ref(0);
@ -436,11 +538,14 @@ export default defineComponent({
trial_days.value = 0;
register_date.value = "";
last_days.value = 0;
selected_product.value = "";
function_center_control.value = false;
function_output_board.value = false;
function_mirroring_output.value = false;
function_custom_ISV.value = false;
function_magic_wall.value = false;
function_fusion.value = false;
};
const showDialog = async () => {
@ -465,18 +570,27 @@ export default defineComponent({
show_dialog.value = false;
}
const function_custom_ISV = ref(
$store.state.custom_defines.is_custom_isv
);
const function_center_control = ref(
$store.state.custom_defines.function_center_control
);
const function_output_board = ref(
$store.state.custom_defines.function_output_board
);
const function_mirroring_output = ref(
$store.state.custom_defines.function_mirroring_output
);
function_custom_ISV.value = $store.state.custom_defines.is_custom_isv;
function_center_control.value =
$store.state.custom_defines.function_center_control;
function_output_board.value =
$store.state.custom_defines.function_output_board;
function_mirroring_output.value =
$store.state.custom_defines.function_mirroring_output;
function_magic_wall.value =
$store.state.custom_defines.function_magic_wall;
function_fusion.value = $store.state.custom_defines.function_fusion;
function_fusion_count.value =
EDeviceAttributeHelper.getProductFusionOutputCountDefault(
$store.state.device_attribute,
1
);
if (function_magic_wall.value) {
selected_product.value = "magic_wall";
} else if (function_fusion.value) {
selected_product.value = "fusion";
}
};
return {
@ -498,8 +612,12 @@ export default defineComponent({
server_address,
function_output_board,
function_custom_ISV,
function_magic_wall,
function_fusion,
function_fusion_count,
function_center_control,
function_mirroring_output,
selected_product,
target_language,
copyToClipboard,
isShow() {
@ -597,22 +715,9 @@ export default defineComponent({
}
let success = false;
const response = await GlobalData.getInstance()
.getCurrentClient()
?.registerDevice(
register_code.value,
active_code.value,
register_type.value == "online",
active_type.value == "forever",
secret_key.value,
parseInt(active_hour.value.toString())
);
if (response) {
success = response.success;
}
if (success) {
let attribute = EDeviceAttribute.None;
let attribute = EDeviceAttribute.None;
{
if (function_center_control.value) {
attribute |= EDeviceAttribute.CenterControl;
}
@ -626,14 +731,37 @@ export default defineComponent({
if (function_custom_ISV.value) {
attribute |= EDeviceAttribute.CustomISV;
}
if (function_magic_wall.value) {
attribute |= EDeviceAttribute.ProductMagicWall;
}
if (function_fusion.value) {
attribute |=
EDeviceAttributeHelper.getProdictFusionAttributeByIndex(
function_fusion_count.value
);
}
}
GlobalData.getInstance()
.getCurrentClient()
?.setDeviceAttribute(attribute);
const response = await GlobalData.getInstance()
.getCurrentClient()
?.registerDevice(
register_code.value,
active_code.value,
register_type.value == "online",
active_type.value == "forever",
attribute,
secret_key.value,
parseInt(active_hour.value.toString())
);
if (response) {
success = response.success;
}
if (success) {
GlobalData.getInstance()
.getCurrentClient()
?.setServerLanguage(target_language.value);
Cookies.remove("language");
}
$q.notify({
@ -646,7 +774,7 @@ export default defineComponent({
position: "top",
timeout: 1500,
});
show_dialog.value = false;
show_dialog.value = !success;
} catch {}
loading.value = false;
},
@ -663,12 +791,7 @@ export default defineComponent({
}
},
isIpAddress(str: string) {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
)
);
return ValidationUtil.isIpAddress(str);
},
};
},

View File

@ -255,7 +255,7 @@ export default defineComponent({
(e) => e && e.uuid == options.data?.uuid
);
if (signal_item_data_) {
selected.value = signal_item_data_.uuid;
selected.value = signal_item_data_.parent_uuid;
} else {
selected.value = "";
}

View File

@ -216,6 +216,7 @@ export default defineComponent({
const editor_config = reactive({
plugins: [
"fullscreen",
"wordcount",
/*'lists link image paste help wordcount'*/
],
mobile: {
@ -223,8 +224,9 @@ export default defineComponent({
},
font_size_formats: get_font_size_formarts(),
skin: "tinymce-5",
language: i18n.locale.value == "zh-CN" ? "zh_CN" : "en_US",
language: i18n.locale.value == "zh-CN" ? "zh-Hans" : "en_US",
menubar: false,
content_style: "p {font-size:60pt;margin:0px;}", // (12px, editor.execCommand)
branding: false,
toolbar_mode: "wrap",
toolbar:
@ -264,6 +266,32 @@ export default defineComponent({
loading.value = false;
},
editorInited(event: any, editor: any) {
// editor : https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.editor/#execCommand
editor.focus();
{
// wordcount
const buttons = document.getElementsByClassName(
"tox-statusbar__wordcount"
);
if (buttons && buttons.length) {
for (let i = 0; i < buttons.length; ++i) {
const item = <any>buttons.item(i);
if (item && typeof item.click == "function") {
item.click();
}
}
}
}
//
const text = editor.getContent({ format: "text" });
try {
if (text && typeof text == "string" && text.trim().length != 0) {
return; //
}
} catch (e) {
console.log(e);
}
// // ( content_style)
editor.execCommand("FontSize", false, "60pt");
},
onShow() {

View File

@ -62,9 +62,10 @@
<q-tab
v-if="
$store.state.advanced_debug ||
/*!$store.state.custom_defines.is_custom_isv */ (!$store.state
.custom_defines.function_output_board &&
$store.state.isLedPlayer())
/*!$store.state.custom_defines.is_custom_isv */
(!$store.state.custom_defines.function_output_board &&
$store.state.isLedPlayer()) ||
$store.state.custom_defines.function_fusion
"
name="graphics"
no-caps
@ -76,6 +77,7 @@
"
:disable="loading"
/>
<q-tab
name="timing_task"
no-caps
@ -96,6 +98,7 @@
:label="$t('output board setting')"
:disable="loading"
/>
<q-tab
name="other"
no-caps
@ -103,6 +106,13 @@
:label="$t('other setting')"
:disable="loading"
/>
<q-tab
name="cloud_server"
no-caps
icon="cloud"
:label="$t('cloud server')"
:disable="loading"
/>
<q-tab
name="user"
no-caps
@ -170,21 +180,21 @@
v-if="true || auto_ip != $t('enable')"
>
<q-item-section avatar class="width_5_1">{{
$t("gateway") + ":"
$t("netmask") + ":"
}}</q-item-section>
<q-item-section>
<q-input
:loading="loading"
:disable="auto_ip == $t('enable') || loading"
v-model="gateway"
v-model="netmask"
maxlength="15"
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
isIpAddress(val) ||
$t('Please input vaild ip address'),
isMaskAddress(val) ||
$t('Please input vaild netmask address'),
]"
lazy-rules
/>
@ -195,13 +205,13 @@
v-if="true || auto_ip != $t('enable')"
>
<q-item-section avatar class="width_5_1">{{
$t("netmask") + ":"
$t("gateway") + ":"
}}</q-item-section>
<q-item-section>
<q-input
:loading="loading"
:disable="auto_ip == $t('enable') || loading"
v-model="netmask"
v-model="gateway"
maxlength="15"
:rules="[
(val) =>
@ -408,7 +418,10 @@
</q-item-section>
</q-item>
<q-item
v-if="!$store.state.custom_defines.function_output_board"
v-if="
!$store.state.custom_defines.function_output_board ||
$store.state.custom_defines.function_fusion
"
>
<q-item-section avatar class="width_5_2_2"
>{{ $t("output type") }}:</q-item-section
@ -453,8 +466,10 @@
</q-item>
<q-item
v-if="
!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'EDID'
(!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'EDID') ||
($store.state.custom_defines.function_fusion &&
device_resolution_type.toUpperCase() == 'EDID')
"
>
<q-item-section avatar class="width_5_2_2"
@ -471,8 +486,10 @@
</q-item>
<q-item
v-if="
!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'CVT'
(!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'CVT') ||
($store.state.custom_defines.function_fusion &&
device_resolution_type.toUpperCase() == 'CVT')
"
>
<q-item-section avatar class="width_5_2_2"
@ -489,8 +506,10 @@
</q-item>
<q-item
v-if="
!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'CUSTOM'
(!$store.state.custom_defines.function_output_board &&
device_resolution_type.toUpperCase() == 'CUSTOM') ||
($store.state.custom_defines.function_fusion &&
device_resolution_type.toUpperCase() == 'CUSTOM')
"
>
<q-item-section avatar class="width_5_2_2"
@ -804,7 +823,8 @@
class="_panel"
v-if="
$store.state.custom_defines.function_output_board ||
$store.state.advanced_debug
$store.state.advanced_debug ||
$store.state.custom_defines.function_fusion
"
>
<q-card class="fit">
@ -1023,6 +1043,103 @@
</q-card>
</q-tab-panel>
<q-tab-panel name="cloud_server" class="_panel">
<q-card class="fit">
<q-card-section>
<q-form ref="cloud_server_form" @submit="applyCloudServer">
<q-list>
<q-item class="q-pa-none">
<q-item-section avatar class="width_5_1">{{
$t("enable") + $t(" ") + $t("server") + ":"
}}</q-item-section>
<q-item-section>
<q-select
v-model="cloud_server_enable"
:options="[$t('enable'), $t('disable')]"
:loading="loading"
:disable="loading"
@update:model-value="autoIpChanged"
/>
</q-item-section>
</q-item>
<q-item
class="q-pa-none"
:disable="cloud_server_enable != $t('enable')"
>
<q-item-section avatar class="width_5_1">{{
$t("server address") + ":"
}}</q-item-section>
<q-item-section>
<q-input
v-model="cloud_server_address"
:loading="loading"
:disable="
cloud_server_enable != $t('enable') || loading
"
maxlength="15"
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
isIpAddress(val) ||
$t('Please input vaild ip address'),
]"
lazy-rules
/>
</q-item-section>
</q-item>
<q-item
class="q-pa-none"
:disable="cloud_server_enable != $t('enable')"
>
<q-item-section avatar class="width_5_1">{{
$t("device verify key") + ":"
}}</q-item-section>
<q-item-section>
<q-input
:loading="loading"
:disable="
cloud_server_enable != $t('enable') || loading
"
v-model="cloud_server_verify_key"
maxlength="6"
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
(val && val.length == 6) ||
$t('verify key length is 6'),
]"
lazy-rules
/>
</q-item-section>
</q-item>
<q-item
class="q-pa-none"
:disable="cloud_server_enable != $t('enable')"
>
<q-item-section avatar class="width_5_1">{{
$t("use wss") + ":"
}}</q-item-section>
<q-item-section>
<q-select
v-model="cloud_server_use_wss"
:options="[$t('enable'), $t('disable')]"
:loading="loading"
:disable="
cloud_server_enable != $t('enable') || loading
"
/>
</q-item-section>
</q-item>
</q-list>
</q-form>
</q-card-section>
</q-card>
</q-tab-panel>
<q-tab-panel name="user" class="_panel">
<q-card class="fit">
<q-card-section>
@ -1167,6 +1284,7 @@
<div
v-if="
click_count >= target_click_count ||
click_count >= target_click_count ||
$store.state.advanced_debug
"
@ -1349,7 +1467,7 @@ import TimingTaskDialog from "src/components/TimingTaskDialog.vue";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
import ValidationUtil from "src/common/ValidationUtil";
import { date } from "quasar";
import { Protocol } from "src/entities/WSProtocol";
import TimingTaskEntity, {
@ -1395,41 +1513,45 @@ import vue3ResizeDrag from "src/third_lib/vue3-resize-drag/components/vue3-resiz
export default defineComponent({
name: "ComponentSystemSettingDialog",
components: { TimingTaskDialog, SystenSettingAdvancedNetworkDialog ,vue3ResizeDrag},
components: {
TimingTaskDialog,
SystenSettingAdvancedNetworkDialog,
vue3ResizeDrag,
},
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
const $store = useStore();
const $q = useQuasar();
const $t = useI18n();
let show_dialog = ref(false);
let loading = ref(false);
const show_dialog = ref(false);
const loading = ref(false);
const timing_task_dialog: Ref<any> = ref(null);
const system_setting_advanced_network_dialog: Ref<any> = ref(null);
let tab = ref("network");
const tab = ref("network");
let auto_ip = ref($t.t("enable"));
let ip_address = ref("127.0.0.1");
let gateway = ref("127.0.0.1");
let netmask = ref("127.0.0.1");
let dns1 = ref();
let dns2 = ref();
let mac_address = ref("11:22:33:44:55:66");
const auto_ip = ref($t.t("enable"));
const ip_address = ref("127.0.0.1");
const gateway = ref("127.0.0.1");
const netmask = ref("127.0.0.1");
const dns1 = ref();
const dns2 = ref();
const mac_address = ref("11:22:33:44:55:66");
let ip_address_list: AdvancedIpAddressEntity[] = [];
let host_name = "player";
let brightness = ref(0);
let contrast = ref(0);
let hue = ref(0);
const brightness = ref(0);
const contrast = ref(0);
const hue = ref(0);
const mirroring_output = ref(false);
let device_resolution = ref("");
let device_resolution_options: Ref<string[]> = ref([]);
let device_rotate = ref(0);
let device_rotate_options = ref([
const device_resolution = ref("");
const device_resolution_options: Ref<string[]> = ref([]);
const device_rotate = ref(0);
const device_rotate_options = ref([
{
label: "0°",
value: 0,
@ -1463,8 +1585,8 @@ export default defineComponent({
// value: 7,
// },
]);
let device_resolution_type = ref("EDID");
let device_resolution_type_options = ref([
const device_resolution_type = ref("EDID");
const device_resolution_type_options = ref([
{ label: "EDID", value: "EDID" },
{ label: $t.t("force output") /*+ "(CVT)"*/, value: "CVT" },
{
@ -1472,61 +1594,67 @@ export default defineComponent({
value: "CUSTOM",
},
]);
let device_resolution_timing = ref("");
const device_resolution_timing = ref("");
let output_board_resolution = ref("");
let output_board_resolution_options = ref(["1", "2", "3"]);
const output_board_resolution = ref("");
const output_board_resolution_options = ref(["1", "2", "3"]);
let system_muted = ref($t.t("off"));
let system_volume = ref(100);
let output_audio_card_options = ref([
const system_muted = ref($t.t("off"));
const system_volume = ref(100);
const output_audio_card_options = ref([
{ label: $t.t("all"), value: "all" },
{ label: "3.5mm", value: "3.5mm" },
{ label: "HDMI1", value: "HDMI1" },
]);
let old_output_audio_card = "";
let output_audio_card = ref(output_audio_card_options.value[0].value);
let use_ntp = ref($t.t("enable"));
let ntp_server = ref("");
let ntp_sync_delay = ref(180);
let current_date = ref("");
let current_time = ref("");
let time_zone = ref("");
let time_zone_options: Ref<string[]> = ref([]);
const output_audio_card = ref(output_audio_card_options.value[0].value);
const use_ntp = ref($t.t("enable"));
const ntp_server = ref("");
const ntp_sync_delay = ref(180);
const current_date = ref("");
const current_time = ref("");
const time_zone = ref("");
const time_zone_options: Ref<string[]> = ref([]);
for (const item of _time_zones) {
time_zone_options.value.push($t.t(item));
}
let network_form: Ref<any> = ref(null);
let other_form: Ref<any> = ref(null);
let graphics_form: Ref<any> = ref(null);
let output_board_form: Ref<any> = ref(null);
const network_form: Ref<any> = ref(null);
const other_form: Ref<any> = ref(null);
const graphics_form: Ref<any> = ref(null);
const output_board_form: Ref<any> = ref(null);
const user_form: Ref<any> = ref(null);
const cloud_server_form: Ref<any> = ref(null);
let output_board_wall_row = ref(2);
let output_board_wall_col = ref(2);
let output_board_splicing = ref($t.t("on"));
let output_board_vertical_blanking = ref(0);
let output_board_horizon_blanking = ref(0);
let output_board_rotate = ref(0);
const output_board_wall_row = ref(2);
const output_board_wall_col = ref(2);
const output_board_splicing = ref($t.t("on"));
const output_board_vertical_blanking = ref(0);
const output_board_horizon_blanking = ref(0);
const output_board_rotate = ref(0);
const output_board_rotate_options = ref([
{ label: "0°", value: 0 },
{ label: "180°", value: 1 },
]);
let output_board_volume = ref(100);
let output_board_mute = ref($t.t("on"));
const output_board_volume = ref(100);
const output_board_mute = ref($t.t("on"));
const timing_tasks: Ref<TimingTaskEntity[]> = ref([]);
let click_count = ref(0);
const click_count = ref(0);
const target_click_count = ref(20);
let client_version = ref(version);
let server_version = ref("unknow");
let server_commit_hash = ref("unknow");
let server_build_date = ref("unknow");
let server_branch_name = ref("unknow");
let kernel_version = ref("unknow");
let rootfs_version = ref("unknow");
const client_version = ref(version);
const server_version = ref("unknow");
const server_commit_hash = ref("unknow");
const server_build_date = ref("unknow");
const server_branch_name = ref("unknow");
const kernel_version = ref("unknow");
const rootfs_version = ref("unknow");
const cloud_server_enable = ref($t.t("enable"));
const cloud_server_address = ref("");
const cloud_server_verify_key = ref("");
const cloud_server_use_wss = ref($t.t("enable"));
const refresh_network = () => {
const config = GlobalData.getInstance()?.applicationConfig;
@ -1606,7 +1734,6 @@ export default defineComponent({
current_time.value = date.formatDate(timeStamp, "HH:mm:ss");
}
};
const refresh_output_board = async () => {
const settings = await GlobalData.getInstance()
.getCurrentClient()
@ -1643,11 +1770,28 @@ export default defineComponent({
}
};
const refresh_cloud_server = () => {
const config = GlobalData.getInstance()?.applicationConfig;
if (config) {
cloud_server_enable.value = parseInt(config.cloud_server_enable)
? $t.t("enable")
: $t.t("disable");
cloud_server_address.value =
config.cloud_server_address || "192.168.1.1";
cloud_server_verify_key.value =
config.cloud_server_verify_key || "123456";
cloud_server_use_wss.value = parseInt(config.cloud_server_use_wss)
? $t.t("enable")
: $t.t("disable");
}
};
const refresh_all = () => {
refresh_network();
refresh_graphics();
refresh_other();
refresh_output_board();
refresh_cloud_server();
};
const wait_for = async (delay_ms: number) => {
@ -1889,6 +2033,9 @@ export default defineComponent({
const applyOutputBoard = async () => {
loading.value = true;
const request = new Protocol.SetOutputBoardSettingRequestEntity();
const response = await GlobalData.getInstance()
.getCurrentClient()
?.getMagicWallConfig();
request.wall_col = parseInt(output_board_wall_col.value.toString());
request.wall_row = parseInt(output_board_wall_row.value.toString());
request.splicing = output_board_splicing.value == $t.t("on");
@ -1902,13 +2049,24 @@ export default defineComponent({
request.volume = parseInt(output_board_volume.value.toString());
request.mute = output_board_mute.value == $t.t("on");
request.output_board_resolution = output_board_resolution.value;
let success = false;
try {
await GlobalData.getInstance()
.getCurrentClient()
?.setOutputBoardSetting(request);
success = true;
if (
$store.state.custom_defines.function_magic_wall &&
response &&
success
) {
const output_length =
parseInt(output_board_wall_col.value.toString()) *
parseInt(output_board_wall_row.value.toString());
if (output_length != response.config.col * response.config.row) {
$store.commit("setShowMonitorList", []);
}
}
} catch {}
$q.notify({
color: success ? "positive" : "negative",
@ -1938,15 +2096,49 @@ export default defineComponent({
case "output_board":
output_board_form.value.submit();
break;
case "cloud_server":
cloud_server_form.value.submit();
break;
case "user":
user_form.value.submit();
break;
}
};
const applyCloudServer = async () => {
loading.value = true;
let success = false;
try {
await GlobalData.getInstance()
.getCurrentClient()
?.setCloudServerSetting(
cloud_server_address.value,
cloud_server_verify_key.value,
cloud_server_use_wss.value == $t.t("enable"),
cloud_server_enable.value == $t.t("enable")
);
success = true;
} catch {}
$q.notify({
color: success ? "positive" : "negative",
icon: success ? "done" : "warning",
message:
$t.t("set cloud server setting") +
$t.t(" ") +
(success ? $t.t("success") : $t.t("fail")) +
"!",
position: "top",
timeout: 2500,
});
loading.value = false;
};
const applyUser = async () => {
loading.value = true;
console.log("zzz");
const request = new Protocol.SetOutputBoardSettingRequestEntity();
request.wall_col = parseInt(output_board_wall_col.value.toString());
request.wall_row = parseInt(output_board_wall_row.value.toString());
@ -2117,6 +2309,7 @@ export default defineComponent({
other_form,
graphics_form,
output_board_form,
cloud_server_form,
user_form,
mirroring_output,
click_count,
@ -2128,6 +2321,10 @@ export default defineComponent({
server_branch_name,
kernel_version,
rootfs_version,
cloud_server_enable,
cloud_server_address,
cloud_server_verify_key,
cloud_server_use_wss,
user_name,
old_password,
new_password,
@ -2140,6 +2337,7 @@ export default defineComponent({
applyGraphics,
applyOther,
applyOutputBoard,
applyCloudServer,
applyUser,
loga(a: any) {
console.log(a);
@ -2327,20 +2525,17 @@ export default defineComponent({
}
},
isIpAddress(str: string) {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
)
);
return ValidationUtil.isIpAddress(str);
},
isMacAddress(str: string) {
return /([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}/.test(str);
return ValidationUtil.isMacAddress(str);
},
isMaskAddress(str: string) {
return ValidationUtil.isMaskAddress(str);
},
checkResolution(str: string) {
const reg = /([0-9]{1,5})[x|X]([0-9]{1,5}@[0-9]{1,3}$)/;
return (
reg.test(str) ||
ValidationUtil.isResolution(str) ||
$t.t("the resolution format is incorrect,") +
$t.t("for example: ") +
"1920x1080@60"

View File

@ -20,14 +20,7 @@
</div>
<q-space />
<div>
<q-btn
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-btn flat round icon="close" color="red" v-close-popup>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
@ -174,7 +167,7 @@
<q-btn
:disable="old_http_port == http_port"
no-caps
:label="$t('commit')"
:label="$t('apply')"
@click="commitHttpPort"
/>
</q-item-section>
@ -213,7 +206,7 @@
<q-btn
:disable="old_websocket_port == websocket_port"
no-caps
:label="$t('commit')"
:label="$t('apply')"
@click="commitWebsocketPort"
/>
</q-item-section>
@ -294,6 +287,7 @@ import AdvancedIpAddressDialog from "src/components/AdvancedIpAddressDialog.vue"
import { AdvancedIpAddressEntity } from "src/entities/AdvancedIpAddressEntity";
import { api } from "src/boot/axios";
import { HttpProtocol } from "src/entities/HttpProtocol";
import ValidationUtil from "src/common/ValidationUtil";
export default defineComponent({
name: "ComponentSystenSettingAdvancedNetworkDialog",
@ -310,12 +304,12 @@ export default defineComponent({
const advance_ip_table_selected: Ref<AdvancedIpAddressEntity[]> = ref([]);
const host_name = ref("player");
const old_http_port = ref(80);
const http_port = ref(80);
const real_http_port = ref(80);
const old_websocket_port = ref(GlobalData.kDefaultWebsocektPort);
const http_port = ref(GlobalData.kDefaultHttpPort);
const old_http_port = ref(GlobalData.kDefaultHttpPort);
const real_http_port = ref(GlobalData.kDefaultHttpPort);
const websocket_port = ref(GlobalData.kDefaultWebsocektPort);
const real_websocket_port = ref(80);
const old_websocket_port = ref(GlobalData.kDefaultWebsocektPort);
const real_websocket_port = ref(GlobalData.kDefaultWebsocektPort);
const advance_ip_columns = [
{
@ -353,15 +347,6 @@ export default defineComponent({
const advance_ip_rows: Ref<AdvancedIpAddressEntity[]> = ref([]);
const isIpAddress = (str: string) => {
return (
str == "localhost" ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
str
)
);
};
let _resolove: any = null;
return {
@ -629,7 +614,7 @@ export default defineComponent({
});
},
isEnglishOrNum(str: string) {
return /^[0-9a-zA-Z_\-]+$/.test(str);
return ValidationUtil.isEnglishOrNum(str);
},
};
},

View File

@ -1,278 +1,282 @@
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-auto text-h6">
{{ upgrade_type }}{{ $t("upgrade") }}
</div>
<q-space />
<div>
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-select
:label="$t('upgrade type')"
:hint="$t('please input ') + $t('upgrade type') + ':'"
:options="select_options"
v-model="upgrade_type"
@update:model-value="file_count = 0"
>
</q-select>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-uploader
v-show="upgrade_type == $t('software')"
class="full-width"
ref="uploader_software"
:url="upload_url_software"
method="post"
:headers="generatorFileUploadHeaders"
:label="$t('select software upgrade file') + ':'"
accept=".zip,.tar,.tar.gz"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
<q-uploader
v-show="upgrade_type == $t('rootfs')"
class="full-width"
ref="uploader_rootfs"
:url="upload_url_rootfs"
method="post"
:headers="generatorFileUploadHeaders"
:label="$t('select rootfs upgrade file') + ':'"
accept=".img"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
:loading="loading"
no-caps
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
export default defineComponent({
name: "ComponentUpgradeDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader_software: any = ref(null);
let uploader_rootfs: any = ref(null);
let loading = ref(false);
let upload_url_software = ref("");
let upload_url_rootfs = ref("");
let file_count = ref(0);
let select_options = [$t.t("software"), $t.t("rootfs")];
let upgrade_type = ref($t.t("software"));
return {
show_dialog,
loading,
upload_url_software,
upload_url_rootfs,
uploader_software,
uploader_rootfs,
file_count,
upgrade_type,
select_options,
generatorFileUploadHeaders(files: File[]) {
if (files.length > 0) {
return [
{
name: HttpProtocol.kHeaderXProductName,
value: HttpProtocol.getProductName($store),
},
{
name: HttpProtocol.kHeaderXFileLength,
value: files[0].size,
},
];
}
return [];
},
loga(a: any) {
console.log(a);
},
showDialog() {
show_dialog.value = true;
let client = GlobalData.getInstance().getCurrentClient();
if (client) {
let url = new URL(client.url);
url.port =
GlobalData.getInstance().applicationConfig?.httpserver_port ??
HttpProtocol.DefaultHttpPort.toString();
url.pathname = HttpProtocol.RequestUploadFile;
url.protocol = "http:";
url.searchParams.append("type", HttpProtocol.UploadTypeRootFS);
upload_url_rootfs.value = url.toString();
url.searchParams.set("type", HttpProtocol.UploadTypeSoftware);
upload_url_software.value = url.toString();
}
},
resetData() {
loading.value = false;
upload_url_software.value = "";
upload_url_rootfs.value = "";
file_count.value = 0;
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
let upgrader =
upgrade_type.value == $t.t("software")
? uploader_software.value
: uploader_rootfs.value;
$q.dialog({
title: $t.t("Confirm"),
message: $t.t("use this file to upgrade") + "?",
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
upgrader.upload();
})
.onCancel(() => {
loading.value = false;
loading.value = false;
});
} catch {}
},
onUploaded() {
loading.value = false;
let upgrader =
upgrade_type.value == $t.t("software")
? uploader_software.value
: uploader_rootfs.value;
if (upgrader) {
console.log(upgrader);
upgrader.removeUploadedFiles();
}
$q.notify({
type: "positive",
icon: "done",
message:
$t.t("update file upload") +
$t.t("success") +
"! \n" +
upgrade_type.value +
$t.t("automatically restarts after the upgrade is complete"),
position: "top",
timeout: 1500,
});
setTimeout(() => {
window.location.reload();
}, 2000);
},
onFailed(info: any) {
$q.notify({
type: "warning",
message: $t.t("update file upload") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>
<template>
<q-dialog
persistent
v-model="show_dialog"
@before-hide="resetData"
@keydown="
(evt) => {
if (!loading && evt.keyCode == 27) {
show_dialog = false;
}
}
"
>
<q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 35vw">
<q-form @submit="onSubmit">
<q-card-section class="q-ma-none q-pa-sm">
<div class="row">
<div class="col-auto text-h6">
{{ upgrade_type }}{{ $t("upgrade") }}
</div>
<q-space />
<div>
<q-btn
:loading="loading"
flat
round
icon="close"
:disable="loading"
color="red"
v-close-popup
>
<q-tooltip>
{{ $t("close") }}
</q-tooltip>
</q-btn>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-section style="max-height: 50vh; width: 35vw" class="scroll">
<q-list>
<q-item>
<q-item-section>
<q-select
:label="$t('upgrade type')"
:hint="$t('please input ') + $t('upgrade type') + ':'"
:options="select_options"
v-model="upgrade_type"
@update:model-value="file_count = 0"
>
</q-select>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-uploader
v-show="upgrade_type == $t('software')"
class="full-width"
ref="uploader_software"
:url="upload_url_software"
method="post"
:label="$t('select software upgrade file') + ':'"
accept=".zip,.tar,.tar.gz"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
<q-uploader
v-show="upgrade_type == $t('rootfs')"
class="full-width"
ref="uploader_rootfs"
:url="upload_url_rootfs"
method="post"
:label="$t('select rootfs upgrade file') + ':'"
accept=".img"
:hide-upload-btn="true"
@uploaded="onUploaded"
@failed="onFailed"
@added="(files) => files && (file_count += files.length)"
@removed="(files) => files && (file_count -= files.length)"
/>
<!-- :headers="generatorFileUploadHeaders" -->
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-separator />
<q-card-actions>
<q-item-section>V: {{ server_version }}</q-item-section>
<q-space />
<q-btn
:loading="loading"
flat
:label="$t('Cancel')"
no-caps
color="primary"
v-close-popup
/>
<q-btn
ref="accept"
flat
:label="$t('Accept')"
:loading="loading"
no-caps
type="submit"
color="primary"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped></style>
<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { HttpProtocol } from "src/entities/HttpProtocol";
export default defineComponent({
name: "ComponentUpgradeDialog",
setup() {
let $store = useStore();
let $q = useQuasar();
let $t = useI18n();
let show_dialog = ref(false);
let uploader_software: any = ref(null);
let uploader_rootfs: any = ref(null);
let loading = ref(false);
let upload_url_software = ref("");
let upload_url_rootfs = ref("");
let file_count = ref(0);
let select_options = [$t.t("software"), $t.t("rootfs")];
let upgrade_type = ref($t.t("software"));
const server_version = ref("unknow");
return {
show_dialog,
loading,
upload_url_software,
upload_url_rootfs,
uploader_software,
uploader_rootfs,
file_count,
upgrade_type,
select_options,
server_version,
loga(a: any) {
console.log(a);
},
showDialog() {
show_dialog.value = true;
let url = GlobalData.getInstance().createCurrentRequestUrl();
if (url) {
url.pathname = "/upload_soft_file";
upload_url_software.value = url.toString();
url.pathname = "/upload_root_fs_file";
upload_url_rootfs.value = url.toString();
}
try {
let client = GlobalData.getInstance().getCurrentClient();
client?.getBuildInfo()?.then((build_info) => {
if (build_info) {
server_version.value = build_info.version;
}
});
} catch (error) {}
},
resetData() {
loading.value = false;
upload_url_software.value = "";
upload_url_rootfs.value = "";
file_count.value = 0;
},
async onSubmit() {
if (file_count.value <= 0) {
$q.notify({
type: "warning",
message: $t.t("please select file first") + "!",
position: "top",
timeout: 1500,
});
return;
}
loading.value = true;
try {
let upgrader =
upgrade_type.value == $t.t("software")
? uploader_software.value
: uploader_rootfs.value;
$q.dialog({
title: $t.t("Confirm"),
message:
$t.t("Confirm") +
$t.t(" ") +
$t.t("use this file to upgrade") +
"?" +
$t.t(" ") +
$t.t(
"after upgrade, please clear browser cache Or refresh hard (Ctrl/Shift + F5 Or Ctrl + Shift + R)"
),
ok: {
label: $t.t("ok"),
noCaps: true,
flat: true,
},
cancel: {
label: $t.t("cancel"),
noCaps: true,
flat: true,
},
persistent: true,
})
.onOk(() => {
upgrader.upload();
})
.onCancel(() => {
loading.value = false;
loading.value = false;
});
} catch {}
},
onUploaded() {
loading.value = false;
let upgrader =
upgrade_type.value == $t.t("software")
? uploader_software.value
: uploader_rootfs.value;
if (upgrader) {
console.log(upgrader);
upgrader.removeUploadedFiles();
}
$q.notify({
type: "positive",
icon: "done",
message:
$t.t("update file upload") +
$t.t("success") +
"! \n" +
upgrade_type.value +
$t.t("automatically restarts after the upgrade is complete"),
position: "top",
timeout: 1500,
});
$q.notify({
type: "positive",
icon: "done",
message: $t.t(
"after upgrade, please clear browser cache Or refresh hard (Ctrl/Shift + F5 Or Ctrl + Shift + R)"
),
position: "top",
timeout: 3000,
});
setTimeout(() => {
window.location.reload();
}, 2000);
},
onFailed(info: any) {
$q.notify({
type: "warning",
message: $t.t("update file upload") + $t.t("fail") + "!",
position: "top",
timeout: 1500,
});
loading.value = false;
},
};
},
});
</script>

View File

@ -45,6 +45,7 @@
</q-item>
<q-item
clickable
v-if="$store.state.isLedPlayer()"
v-close-popup
:disable="$props.disable"
@click="$emit('edit_rect', $props.window.window_id)"

View File

@ -1,44 +1,49 @@
import { AdvancedIpAddressEntity } from "./AdvancedIpAddressEntity";
export default class ApplicationConfigEntity {
user_name: string = "admin";
password: string = "";
auto_ip_address: string = "";
ip_address: string = "";
gateway: string = "";
mac_address: string = "";
subnet_mask: string = "";
dns1 = "";
dns2 = "";
ip_list: AdvancedIpAddressEntity[] = [];
use_ntp: string = "";
ntp_server: string = "";
ntp_sync_delay: string = "";
time_zone: number = 21;
wall_row: number = 1;
wall_col: number = 1;
tcp_port: string = "";
udp_port: string = "";
websocket_port: string = "";
httpserver_port: string = "";
root_fs_upload_path: string = "";
media_upload_dir: string = "";
power_on_plan: string = "";
graphics_brightness: number = 100;
graphics_contrast: number = 100;
graphics_hue: number = 100;
device_rotate: number = 0;
system_volume: number = 100;
system_muted: number = 0;
output_audio_card: string = "";
application_data_dir: string = "";
runtime_os: string = "";
registered: boolean = false;
hdmi_in_decode_type_1: string | undefined;
hdmi_in_audio_device_1: string | undefined;
hw_version: string | undefined;
device_hdmi_output_count = 1;
video_suffix_filter: string | null = "";
image_suffix_filter: string | null = "";
special_video_layout_rotation: string | undefined = "0";
device_hdmi_rotation: number = 0;
}
import { AdvancedIpAddressEntity } from "./AdvancedIpAddressEntity";
export default class ApplicationConfigEntity {
user_name: string = "admin";
password: string = "";
auto_ip_address: string = "";
ip_address: string = "";
gateway: string = "";
mac_address: string = "";
subnet_mask: string = "";
dns1 = "";
dns2 = "";
ip_list: AdvancedIpAddressEntity[] = [];
use_ntp: string = "";
ntp_server: string = "";
ntp_sync_delay: string = "";
time_zone: number = 21;
wall_row: number = 1;
wall_col: number = 1;
tcp_port: string = "";
udp_port: string = "";
websocket_port: string = "";
httpserver_port: string = "";
root_fs_upload_path: string = "";
media_upload_dir: string = "";
power_on_plan: string = "";
graphics_brightness: number = 100;
graphics_contrast: number = 100;
graphics_hue: number = 100;
device_rotate: number = 0;
system_volume: number = 100;
system_muted: number = 0;
output_audio_card: string = "";
application_data_dir: string = "";
runtime_os: string = "";
registered: boolean = false;
hdmi_in_decode_type_1: string | undefined;
hdmi_in_audio_device_1: string | undefined;
hw_version: string | undefined;
device_hdmi_output_count = 1;
video_suffix_filter: string | null = "";
image_suffix_filter: string | null = "";
special_video_layout_rotation: string | undefined = "0";
device_hdmi_rotation: number = 0;
cloud_server_address = "";
cloud_server_verify_key = "";
cloud_server_use_wss = "0";
cloud_server_enable = "0";
magic_list:any=[]
}

View File

@ -0,0 +1,7 @@
export default class DensityCorrection {
control_point = 0;
x = 0;
y = 0;
def_x = 0;
def_y = 0;
}

View File

@ -0,0 +1,7 @@
export default class DensityCorrectionPoint {
control_point = 0;
x = 0;
y = 0;
def_x = 0;
def_y = 0;
}

View File

@ -1,38 +1,145 @@
export enum EDeviceAttribute {
None_UnKNow = 0x0000,
None = 0x0000000000000001,
OutputBoard = 0x0000000000000002,
CenterControl = 0x0000000000000004,
MirroringOutput = 0x0000000000000008,
CustomISV = 0x0000000000000010,
Reserve5 = 0x0000000000000020,
Reserve6 = 0x0000000000000040,
Reserve7 = 0x0000000000000080,
Reserve8 = 0x0000000000000100,
Reserve9 = 0x0000000000000200,
Reserve10 = 0x0000000000000400,
Reserve11 = 0x0000000000000800,
Reserve12 = 0x0000000000001000,
Reserve13 = 0x0000000000002000,
Reserve14 = 0x0000000000004000,
Reserve15 = 0x0000000000008000,
Reserve16 = 0x0000000000010000,
Reserve17 = 0x0000000000020000,
Reserve18 = 0x0000000000040000,
Reserve19 = 0x0000000000080000,
Reserve20 = 0x0000000000100000,
ProductMagicWall = 0x0000000000200000,
ProductFusion_1 = 0x0000000000400000,
ProductFusion_2 = 0x0000000000800000,
ProductFusion_3 = 0x0000000001000000,
ProductFusion_4 = 0x0000000002000000,
ProductFusion_5 = 0x0000000004000000,
ProductFusion_6 = 0x0000000008000000,
ProductFusion_7 = 0x0000000010000000,
ProductFusion_8 = 0x0000000020000000,
ProductFusion_9 = 0x0000000040000000,
Reserve31 = 0x0000000080000000,
Reserve32 = 0x0000000100000000,
Reserve33 = 0x0000000200000000,
Reserve34 = 0x0000000400000000,
Reserve35 = 0x0000000800000000,
Reserve36 = 0x0000001000000000,
Reserve37 = 0x0000002000000000,
Reserve38 = 0x0000004000000000,
Reserve39 = 0x0000008000000000,
Reserve40 = 0x0000010000000000,
Reserve41 = 0x0000020000000000,
Reserve42 = 0x0000040000000000,
Reserve43 = 0x0000080000000000,
Reserve44 = 0x0000100000000000,
Reserve45 = 0x0000200000000000,
Reserve46 = 0x0000400000000000,
Reserve47 = 0x0000800000000000,
Reserve48 = 0x0001000000000000,
Reserve49 = 0x0002000000000000,
Reserve50 = 0x0004000000000000,
Reserve51 = 0x0008000000000000,
Reserve52 = 0x0010000000000000,
Reserve53 = 0x0020000000000000,
Reserve54 = 0x0040000000000000,
Reserve55 = 0x0080000000000000,
Reserve56 = 0x0100000000000000,
Reserve57 = 0x0200000000000000,
Reserve58 = 0x0400000000000000,
Reserve59 = 0x0800000000000000,
Reserve60 = 0x1000000000000000,
Reserve61 = 0x2000000000000000,
Reserve62 = 0x4000000000000000,
Reserve63 = 0x8000000000000000,
None = 0x00000001,
OutputBoard = 0x00000002,
CenterControl = 0x00000004,
MirroringOutput = 0x00000008,
CustomISV = 0x00000010,
Reserve5 = 0x00000020,
Reserve6 = 0x00000040,
Reserve7 = 0x00000080,
Reserve8 = 0x00000100,
Reserve9 = 0x00000200,
Reserve10 = 0x00000400,
Reserve11 = 0x00000800,
Reserve12 = 0x00001000,
Reserve13 = 0x00002000,
Reserve14 = 0x00004000,
Reserve15 = 0x00008000,
Reserve16 = 0x00010000,
Reserve17 = 0x00020000,
Reserve18 = 0x00040000,
Reserve19 = 0x00080000,
Reserve20 = 0x00100000,
Reserve21 = 0x00200000,
Reserve22 = 0x00400000,
Reserve23 = 0x00800000,
Reserve24 = 0x01000000,
Reserve25 = 0x02000000,
Reserve26 = 0x04000000,
Reserve27 = 0x08000000,
Reserve28 = 0x10000000,
Reserve29 = 0x20000000,
Reserve30 = 0x40000000,
Reserve31 = 0x80000000,
All = 0xffffffff,
StandMediaControl = OutputBoard | CenterControl,
All = 0xffffffffffffffff,
}
export class EDeviceAttributeHelper {
public static isProductFusion(attribute: number) {
return (
(attribute & EDeviceAttribute.ProductFusion_1) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_2) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_3) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_4) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_5) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_6) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_7) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_8) != 0 ||
(attribute & EDeviceAttribute.ProductFusion_9) != 0
);
}
public static getProductFusionOutputCount(attribute: number) {
if (attribute & EDeviceAttribute.ProductFusion_1) {
return 1;
} else if (attribute & EDeviceAttribute.ProductFusion_2) {
return 2;
} else if (attribute & EDeviceAttribute.ProductFusion_3) {
return 3;
} else if (attribute & EDeviceAttribute.ProductFusion_4) {
return 4;
} else if (attribute & EDeviceAttribute.ProductFusion_5) {
return 5;
} else if (attribute & EDeviceAttribute.ProductFusion_6) {
return 6;
} else if (attribute & EDeviceAttribute.ProductFusion_7) {
return 7;
} else if (attribute & EDeviceAttribute.ProductFusion_8) {
return 8;
} else if (attribute & EDeviceAttribute.ProductFusion_9) {
return 9;
} else {
return 0;
}
}
public static getProductFusionOutputCountDefault(
attribute: number,
default_Value: number
) {
const ret = EDeviceAttributeHelper.getProductFusionOutputCount(attribute);
if (ret == 0) {
return default_Value;
}
return ret;
}
public static getProdictFusionAttributeByIndex(index: number) {
switch (index) {
case 1:
return EDeviceAttribute.ProductFusion_1;
case 2:
return EDeviceAttribute.ProductFusion_2;
case 3:
return EDeviceAttribute.ProductFusion_3;
case 4:
return EDeviceAttribute.ProductFusion_4;
case 5:
return EDeviceAttribute.ProductFusion_5;
case 6:
return EDeviceAttribute.ProductFusion_6;
case 7:
return EDeviceAttribute.ProductFusion_7;
case 8:
return EDeviceAttribute.ProductFusion_8;
case 9:
return EDeviceAttribute.ProductFusion_9;
default:
return 0;
}
}
}

View File

@ -1,33 +1,33 @@
export namespace HttpProtocol {
export const DefaultHttpPort = 80;
export const RequestUploadFile = "/upload_file";
export const RequestPathUpdateDBBackupFile = "/common/update_db_backup_file";
export const RequestPathDBBackup = "/db_backup";
export const RequestPathListFile = "/list_file";
export const RequestPathCreateDirectory = "/create_directory";
export const RequestPathCheckFileSupport = "/check_file_support";
export const RequestPathGetWebscoketPort = "/get_websocket_port";
export const RequestPathGetAllPort = "/get_all_port";
export const RequestPathDeleteFile = "/delete_file";
export const RequestPathRenameFile = "/rename_file";
export const RequestCheckModeIndex = "/check_mode_index";
export const HttpUploadTypeNormal = "U_T_Normal";
export const UploadTypeBackgroundImage = "U_T_BACKGROUND_IMAGE";
export const UploadTypeMedia = "U_T_MEDIA";
export const UploadTypeDatabase = "U_T_DATABASE";
export const UploadTypeRootFS = "U_T_ROOT_FS";
export const UploadTypeSoftware = "U_T_SOFTWARE";
export const kHeaderXFileLength = "X-File-Length";
export const kHeaderXFileMD5 = "X-File-MD5";
export const kHeaderXProductName = "X-Product-Name";
const kHeaderDefaultValueXProductName = "LED_PLAYER";
export const getProductName = ($store: any): String => {
if ($store && $store.state && $store.state.product_name) {
return $store.state.product_name;
}
return kHeaderDefaultValueXProductName;
};
}
export namespace HttpProtocol {
export const DefaultHttpPort = 80;
export const RequestUploadFile = "/upload_file";
export const RequestPathUpdateDBBackupFile = "/update_db_backup_file";
export const RequestPathDBBackup = "/download_db_backup_file";
export const RequestPathListFile = "/list_file";
export const RequestPathCreateDirectory = "/create_directory";
export const RequestPathCheckFileSupport = "/check_file_support";
export const RequestPathGetWebscoketPort = "/get_websocket_port";
export const RequestPathGetAllPort = "/get_all_port";
export const RequestPathDeleteFile = "/delete_file";
export const RequestPathRenameFile = "/rename_file";
export const RequestCheckModeIndex = "/check_mode_index";
export const HttpUploadTypeNormal = "U_T_Normal";
export const UploadTypeBackgroundImage = "U_T_BACKGROUND_IMAGE";
export const UploadTypeMedia = "U_T_MEDIA";
export const UploadTypeDatabase = "U_T_DATABASE";
export const UploadTypeRootFS = "U_T_ROOT_FS";
export const UploadTypeSoftware = "U_T_SOFTWARE";
export const kHeaderXFileLength = "X-File-Length";
export const kHeaderXFileMD5 = "X-File-MD5";
export const kHeaderXProductName = "X-Product-Name";
const kHeaderDefaultValueXProductName = "LED_PLAYER";
export const getProductName = ($store: any): String => {
if ($store && $store.state && $store.state.product_name) {
return $store.state.product_name;
}
return kHeaderDefaultValueXProductName;
};
}

View File

@ -1,8 +1,8 @@
import RotatedRectF from "./RectF";
import RotatedRectF, { RotatedRectFWithIndex } from "./RectF";
export default class MagicWallConfig {
magic_wall_enable = false;
row = 0;
col = 0;
windows: RotatedRectF[] = [];
windows: RotatedRectFWithIndex[] = [];
}

View File

@ -32,3 +32,11 @@ export class RotatedRectF extends RectF {
this.angle = angle;
}
}
export class RotatedRectFWithIndex extends RotatedRectF{
index:number=0;
percenter:number=0;
initial_h:number=0;
initial_w:number=0;
background_h:number=0;
background_w:number=0;
}

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,10 @@ export default {
Accept: "Accept",
"move speed": "Move Speed",
"y offset": "Y Offset",
"the number must be greater than 0": "The Number Must Be Greater Than 0",
"the number must be less than 2160":"The Number Must Be Less Than 2160",
"the number must be less than 3840":"The Number Must Be Less Than 3840",
"the number must be greater than 360":"The Number Must Be Less Than 360",
"pos x": "X Position",
"pos y": "Y Position",
width: "Width",
@ -162,13 +166,14 @@ export default {
"timing task": " Timing Task",
other: "Other",
"auto ip": "Auto IP",
"ip address": "Ip Address",
"ip address": "IP Address",
gateway: "Gateway",
netmask: "Netmask",
"mac address": "MAC Address",
advanced: "Advanced",
"revert and exit": "Revert And Exit",
apply: "Apply",
load: "Load",
"current real resolution": "Current Real Resolution",
"output type": "Output Type",
"target resolution": "Target Resolution",
@ -184,7 +189,7 @@ export default {
"task type": "Task Type",
time: "Time",
loop: "Loop",
"timing cycle": "Timing Exexute",
"timing cycle": "Timing Execute",
monday: "Monday",
tuesday: "Turesday",
wednesday: "Wednesday",
@ -293,6 +298,7 @@ export default {
"open left tool bar": "Open Left Tool Bar",
"open right tool bar": "Open Right Tool Bar",
fail: " Fail",
finish: "Finish",
"edit group": "Edit Group",
"open window": "Open Window",
"close all windows": "Close All Windows",
@ -378,7 +384,8 @@ export default {
"please select window rotation": "Please Select Window Rotation",
"hdmi internal": "HDMI Internal",
set: "Set",
"hdmi audio frequency acquisition device":"HDMI Audio Frequency Acquisition Device",
"hdmi audio frequency acquisition device":
"HDMI Audio Frequency Acquisition Device",
"send command": "Send Command",
"please check connection config": "Please Check Connection Config",
"connection setting": "Connection Setting",
@ -404,54 +411,107 @@ export default {
"Please input vaild host. example: 192.168.1.1 or 192.168.1.1:8080":
"Please Input Vaild Host. Example: 192.168.1.1 or 192.168.1.1:8080",
"equipment data": "Equipment Data",
"fusion settings":"Fusion Settings",
"FusionLocale":"Fusion Locale",
"FourPointCalibration":"Four Pint Calibration",
"SurfaceCorrection":"Surface Correction",
"DensityCorrection":"Density Correction",
"GridSettings":"Grid Settings",
"point":"dot",
"reset":"reset",
"upper fusion zone parameters":"Upper Fusion Zone Parameters",
"Left fusion Band Parameters":"Left Fusion Band Parameters",
"Lower fusion Zone Parameters":"Lower Fusion Zone Parameters",
"Right fusion Band Parameters":"Right Fusion Band Parameters",
"Set the fusion band width":"Set the fusion band width",
"Please enter a number":"Please enter a number",
"Please enter 0-100":"Please enter 0-your differentiation rate",
"Set Fusion Band Parameters":"Set Fusion Band Parameters",
"Projector":"Projector",
"resetall":"reset all",
"save config":"Save Config",
"Whether to enable integration":"Whether to enable integration",
"Whether to hide the desktop":"Whether to hide the desktop",
"resetall config":"resetall config",
"disable blending params":"Dsable blending params",
"show blending grids":"Show Grids",
"line color":"Line Color",
"center line color":"center line color",
"center circle color":"center circle color",
"Whether to operate synchronously":"Whether to operate synchronously",
"Select saved configuration":"Select saved Configuration",
"read saved configuration":"read saved configuration",
"please choose":"please choose",
"save":"Save",
"Whether to save the configuration":"Whether to save the configuration",
"New Please enter a name":"New Please enter a name",
"Please select an override":"Please select an override",
"confirm delete":"confirm delete",
"delete or not":"delete or not",
"debugging":"Debugging",
"disable_blending":"disable blending",
"disable_clip":"disable clip",
"show_mask":"hide desktop",
"save_bmp":"save bmp",
"disable_blending_params":"disable blending params",
"Please enter a value within the range":"Please enter a value within the range",
"vertical correction":"vertical correction",
"horizontal correction":"horizontal correction",
"line width":"line width",
"level":"level",
"vertical":"vertical",
"auxiliary lines":"auxiliary lines"
fusion: "Fusion",
"fusion settings": "Fusion Settings",
FusionLocale: "Fusion Locale",
FourPointCalibration: "Four Pint Calibration",
SurfaceCorrection: "Surface Correction",
DensityCorrection: "Density Correction",
GridSettings: "Auxiliary Settings",
point: "dot",
reset: "reset",
"upper fusion zone parameters": "Upper Fusion Zone Parameters",
"Left fusion Band Parameters": "Left Fusion Band Parameters",
"Lower fusion Zone Parameters": "Lower Fusion Zone Parameters",
"Right fusion Band Parameters": "Right Fusion Band Parameters",
"Set the fusion band width": "Set the fusion band width",
"Please enter a number": "Please enter a number",
"Please enter 0-100": "Please enter 0-your differentiation rate",
"Set Fusion Band Parameters": "Set Fusion Band Parameters",
Projector: "Projector",
resetall: "reset all",
"save config": "Save Config",
"Whether to enable integration": "Enable projection mode",
"Whether to hide the desktop": "Whether to hide the desktop",
"resetall config": "resetall config",
"disable blending params": "Dsable blending params",
"show blending grids": "Show Grids",
"line color": "Line Color",
"center line color": "center line color",
"center circle color": "center circle color",
"Whether to operate synchronously": "synchronous operation",
"Select saved configuration": "Configuration list",
"read saved configuration": "Configuration list",
"please choose": "please choose",
save: "Save",
"Whether to save the configuration": "Whether to save the configuration",
"New Please enter a name": "New Please enter a name",
"Please select an override": "Please select an override",
"confirm delete": "confirm delete",
"delete or not": "delete or not",
debugging: "Debugging",
disable_blending: "disable blending",
disable_clip: "disable clip",
show_mask: "hide desktop",
save_bmp: "save bmp",
disable_blending_params: "disable blending params",
"Please enter a value within the range":
"Please enter a value within the range",
"vertical correction": "vertical correction",
"horizontal correction": "horizontal correction",
"line width": "line width",
level: "level",
vertical: "vertical",
"auxiliary lines": "auxiliary lines",
"level point": "level point amount",
"vertical point ": "vertical point amount",
"point amount": "point amount",
"add control points": "add control points",
"reduce control points": "delete control points",
"OK to delete you will lose the data you adjusted now":
"OK to delete you will lose the data you adjusted now",
"Please enter the points you need to add":
"Please enter the points you need to add",
"Whether to add control points": "Whether to add control points",
"Reset all program control points": "Reset all program control points",
"Reset the current program control point":
"Reset the current program control point",
"device verify key": "Device Verify Key",
"use wss": "Use Wss",
"server address": "Server Address",
"cloud server": "Cloud Server",
"verify key length is 6": "Verify Key Length Is 6",
server: "Server",
"set cloud server setting": "Set Cloud Server Setting",
"set magic wall": "Set Magic wall",
"update magic wall": "Update Magic Wall",
"magic wall": "Magic Wall",
angle: "Angle",
"topology diagram": "Topology Diagram",
"physical central location": "Central Location",
"monitors list": "Monitors List",
resize: "Resize",
"export magic": "Export",
"raster graph": "Raster Graph",
"the folder name cannot start with a '.'":
"The Folder Name Cannot Start With a '.'",
"change resolution": "change resolution",
"Loading please wait": "Loading please wait",
product: "Product",
normal: "Normal",
"fusion out": "Out",
"Please enter the square number": "Please enter the square number",
"Change projector layout": "Change projector layout",
"reset all": "reset all",
"Do you confirm the modification": "Do you confirm the modification",
"Whether to modify the resolution to": "Whether to modify the resolution to",
"Whether to change the projector layout to":
"Whether to change the projector layout to",
"after upgrade, please clear browser cache Or refresh hard (Ctrl/Shift + F5 Or Ctrl + Shift + R)":
"After Upgrade, Please Clear Browser Cache Or Refresh Hard (Ctrl/Shift + F5 Or Ctrl + Shift + R)",
"fusion zone":"fusion zone",
"up":"up",
"left":"left",
"right":"right",
"down":"down"
};

View File

@ -5,6 +5,7 @@ export default {
" ": "",
title: "MediaPlayerWebApp",
failed: "失败",
finish: "完成",
fail: "失败",
error: "错误",
Confirm: "确认",
@ -123,6 +124,7 @@ export default {
"local disk": "本地磁盘",
usb: "U盘",
"Please input vaild ip address": "请输入合法的IP地址",
"Please input vaild netmask address": "请输入合法的掩码地址",
"Please input vaild mac address": "请输入合法的MAC地址",
"server ip address": "服务器地址",
"please input server ip address": "请输入服务器地址",
@ -216,6 +218,7 @@ export default {
disable: "禁用",
enable: "启用",
apply: "应用",
load: "加载",
"apply and exit": "应用并退出",
revert: "恢复",
"revert and exit": "不保存退出",
@ -486,7 +489,11 @@ export default {
"full screen window": "全屏",
"restore window size": "恢复",
"the number must be greater than 0": "数字必须大于0",
"the number must be less than 2160":"数字必须小于等于2160",
"the number must be less than 3840":"数字必须小于等于3840",
"the number must be greater than 1": "数字必须大于1",
"the number must be greater than 360":"数字必须小于等于360",
X: "X坐标",
Y: "Y坐标",
"edit window rect": "窗口大小调整",
@ -499,7 +506,7 @@ export default {
Warning: "警告",
function: "功能",
commit: "提交",
"set device function": "设置设备功能成功",
"set device function": "设置设备功能",
operator_play_signal_source: "信号源",
"toolbar edit window rect": "窗口大小",
exit: "退出",
@ -673,54 +680,105 @@ export default {
"Please input vaild host. example: 192.168.1.1 or 192.168.1.1:8080":
"请输入合法地址. 例: 192.168.1.1 或 192.168.1.1:8080",
"equipment data": "联动设备",
"fusion settings":"融合设置",
"FusionLocale":"融合区域设置",
"FourPointCalibration":"四点校正",
"SurfaceCorrection":"曲面校正",
"DensityCorrection":"疏密校正",
"GridSettings":"网格设置",
"point":"点",
"reset":"重置",
"upper fusion zone parameters":"上融合带参数",
"Left fusion Band Parameters":"左融合带参数",
"Lower fusion Zone Parameters":"下融合带参数",
"Right fusion Band Parameters":"右融合带参数",
"Set the fusion band width":"设置融合带宽度",
"Please enter a number":"请输入数字",
"Please enter 0-100":"请输入 0-你的分辨率",
"Set Fusion Band Parameters":"设置融合带参数",
"Projector":"投影机",
"resetall":"重置所有",
"save config":"保存配置",
"Whether to enable integration":"是否启用融合",
"Whether to hide the desktop":"是否隐藏桌面",
"resetall config":"重置所有配置",
"disable blending params":"禁用融合参数",
"show blending grids":"显示网格",
"line color":"线条颜色",
"center line color":"中心线颜色",
"center circle color":"中心圆颜色",
"Whether to operate synchronously":"是否同步操作",
"Select saved configuration":"选择保存的配置",
"read saved configuration":"读取保存的配置",
"please choose":"请选择",
"save":"保存",
"Whether to save the configuration":"是否保存配置",
"New Please enter a name":"新建 请输入名称",
"Please select an override":"请选择覆盖",
"confirm delete":"确定删除",
"Whether to delete":"是否删除",
"debugging":"调试",
"disable_blending":"禁用混合",
"disable_clip":"禁用裁剪",
"show_mask":"隐藏桌面",
"save_bmp":"保存BMP",
"disable_blending_params":"禁用融合参数",
"Please enter a value within the range":"请输入范围内的值",
"vertical correction":"垂直校正",
"horizontal correction":"水平校正",
"line width":"线宽",
"level":"水平",
"vertical":"垂直",
"auxiliary lines":"辅助线"
fusion: "融合",
"fusion settings": "融合设置",
FusionLocale: "融合区域设置",
FourPointCalibration: "四点校正",
SurfaceCorrection: "曲面校正",
DensityCorrection: "疏密校正",
GridSettings: "辅助设置",
point: "点",
reset: "重置",
"upper fusion zone parameters": "上融合带参数",
"Left fusion Band Parameters": "左融合带参数",
"Lower fusion Zone Parameters": "下融合带参数",
"Right fusion Band Parameters": "右融合带参数",
"Set the fusion band width": "设置融合带宽度",
"Please enter a number": "请输入数字",
"Please enter 0-100": "请输入 0-你的分辨率",
"Set Fusion Band Parameters": "设置融合带参数",
Projector: "投影机",
resetall: "重置所有",
"save config": "保存配置",
"Enable projection mode": "启用投影模式",
"Whether to hide the desktop": "是否隐藏桌面",
"resetall config": "重置所有配置",
"disable blending params": "禁用融合参数",
"show blending grids": "显示网格",
"line color": "线条颜色",
"center line color": "中心线颜色",
"center circle color": "中心圆颜色",
"Whether to operate synchronously": "是否同步操作",
"Select saved configuration": "配置列表",
"read saved configuration": "融合配置列表",
"please choose": "请选择",
save: "保存",
"Whether to save the configuration": "是否保存配置",
"New Please enter a name": "新建 请输入名称",
"Please select an override": "请选择覆盖",
"confirm delete": "确定删除",
"Whether to delete": "是否删除",
debugging: "调试",
disable_blending: "禁用混合",
disable_clip: "禁用裁剪",
show_mask: "隐藏桌面",
save_bmp: "保存BMP",
disable_blending_params: "禁用融合参数",
"Please enter a value within the range": "请输入范围内的值",
"vertical correction": "垂直校正",
"horizontal correction": "水平校正",
"line width": "线宽",
level: "水平",
vertical: "垂直",
"auxiliary lines": "辅助线",
"level point": "水平点数量",
"vertical point": "垂直点数量",
"point amount": "点数量",
"add control points": "增加",
"reduce control points": "删除",
"OK to delete you will lose the data you adjusted now":
"确定删除你将失去现在调整的数据",
"Please enter the points you need to add": "请输入你所需要添加的点数",
"Whether to add control points": "是否添加控制点",
"Reset all program control points": "重置全部方案控制点",
"Reset the current program control point": "重置当前方案控制点",
"device verify key": "设备校验码",
"use wss": "使用Wss",
"server address": "服务器地址",
"cloud server": "云服务器",
"verify key length is 6": "校验码长度必须为6",
server: "服务",
"set cloud server setting": "设置云服务器",
"set magic wall": "设置魔墙",
"update magic wall": "更新魔墙",
"magic wall": "魔墙",
angle: "角度",
"topology diagram": "拓扑图",
"physical central location": "物理中心位置",
"monitors list": "显示器",
resize: "缩放",
"export magic": "导出",
"raster graph": "栅格图",
"the folder name cannot start with a '.'": "文件夹名称不能以“.” 开头",
"change resolution": "更改分辨率",
"Loading please wait": "加载中 请稍等",
"Version Mismatch !": "版本不匹配!",
"Version Mismatch ! Please Upgrade The Software Again ! Otherwise, The File Function Cannot Be Used !":
"版本不匹配!请重新升级软件!否则文件功能无法正常使用!",
product: "产品",
normal: "普通",
"fusion out": "出",
"Please enter the square number": "请输入平方数",
"Change projector layout": "更改投影机布局",
"reset all": "重置所有",
"Do you confirm the modification": "是否确认修改",
"Whether to modify the resolution to": "是否将分辨率修改到",
"Whether to change the projector layout to": "是否更改投影机布局为",
"after upgrade, please clear browser cache Or refresh hard (Ctrl/Shift + F5 Or Ctrl + Shift + R)":
"升级完成后请清空浏览器缓存或者进行硬刷新(Ctrl/Shift + F5 或者 CTRL + SHIFT + R)",
"fusion zone":"融合带",
"up":"上",
"left":"左",
"right":"右",
"down":"下"
};

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title><%= productName %></title>
<title></title>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />

View File

@ -68,11 +68,7 @@
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
val == 'localhost' ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
val
) ||
$t('Please input vaild ip address'),
isHost(val) || $t('Please input vaild ip address'),
]"
@keydown="
(evt) => {
@ -363,6 +359,7 @@ import Initializer from "src/common/Initializer";
import { api } from "src/boot/axios";
import { HttpProtocol } from "src/entities/HttpProtocol";
import { Plugins as CapacitorPlugins } from "@capacitor/core";
import ValidationUtil from "src/common/ValidationUtil";
class _Data {
user_name: string | null = null;
@ -699,6 +696,9 @@ export default defineComponent({
}
}
},
isHost(str: string) {
return ValidationUtil.isHost(str);
},
};
},
});

View File

@ -135,6 +135,7 @@
<q-btn
stretch
:disable="!$store.state.power_state"
v-if="$store.state.isLedPlayer()"
flat
stack
no-caps
@ -192,6 +193,24 @@
{{ $t("background image setting") }}
</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="
$refs.fusion_settings_dialog.showDialog();
getconfig();
"
v-if="$store.state.custom_defines.function_fusion"
>
<q-item-section avatar>
<q-icon style="color: #63bab4;" name="open_with" />
</q-item-section>
<q-item-section>
{{ $t("fusion settings") }}
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="switchLanguage">
<q-item-section avatar>
<q-icon name="img:pad/toolbar/cn_en.png" />
@ -234,6 +253,9 @@
<advanced-debug-dialog ref="advanced_debug_dialog" />
<window-rect-edit-dialog ref="window_rect_edit_dialog" />
<system-setting-dialog ref="system_setting_dialog" />
<fusion-settings-dialog ref="fusion_settings_dialog" />
</template>
<script lang="ts">
@ -241,6 +263,9 @@ import { defineComponent, Ref, ref, computed, watch } from "vue";
import { Cookies, SessionStorage, useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import { useStore } from "src/store";
import FusionSettingsDialog from "src/components/FusionSettingsDialog.vue";
import BackgroundImageDialog from "src/components/BackgroundImageDialog.vue";
import FileManageDialog from "src/components/FileManageDialog.vue";
import SubtitleDialog from "src/components/SubtitleDialog.vue";
@ -264,12 +289,13 @@ export default defineComponent({
AdvancedDebugDialog,
WindowRectEditDialog,
SystemSettingDialog,
FusionSettingsDialog
},
setup() {
const $store = useStore();
const $q = useQuasar();
const $t = useI18n();
let set = GlobalData.getInstance().getCurrentClient();
const window_rect_edit_dialog: Ref<any> = ref(null);
const plan_running = computed(
@ -287,7 +313,19 @@ export default defineComponent({
}
}
);
const getconfig = () => {
set?.SetBlendingOption("blending_grids_select_ui", '4')
set?.SetBlendingOption('blending_grids_select_projector',"0-0");
set?.SetBlendingOption("blending_grids_select_point", `4:1`)
set?.SetBlendingOption("blending_grids_show", "1");
try {
set?.GetBlendingConfig("").then((res) => {
let tmp = JSON.parse(res ? res.config : "");
$store.commit("setEnablefusion", tmp.enable);
$store.commit("setfusion_configuration", res?.config);
});
} catch (error) {}
};
return {
plan_running,
window_rect_edit_dialog,

View File

@ -1,5 +1,5 @@
<template>
<q-page class="row items-center justify-evenly">
<q-page class="row items-center justify-evenly" :style-fn="wujie_height">
<wall-page />
<media-control-page />
</q-page>
@ -70,7 +70,11 @@ export default defineComponent({
new Initializer(options).initialize();
});
return {};
return {
wujie_height(offset:any){
return { minHeight: offset ? `calc(100vh - ${offset}px)` : '100vh' }
}
};
},
});
</script>

View File

@ -1,482 +1,482 @@
<template>
<q-layout view="hHh lpR fFf">
<img
v-if="landspace"
src="login/login_background.png"
class="fit"
style="position: fixed"
/>
<q-page-container>
<q-page
class="row items-center"
style="position: ; /*fixed*/"
:class="landspace ? '' : 'justify-evenly'"
:style="landspace ? { left: '50%' } : {}"
>
<q-card :style="{ width: (landspace ? 34 : 70) + 'vw' }">
<q-card-section class="text-center text-h6">
{{ $t("login") }}
</q-card-section>
<q-separator />
<q-card-section class="fit">
<q-form ref="login_form" @submit="onSubmit" @reset="onReset">
<q-list class="fit">
<q-item v-if="$store.state.advanced_debug">
<q-item-section>
<q-input
:autofocus="!data.ip_address"
outlined
:loading="data.loading"
:disable="data.loading"
v-model="data.ip_address"
:label="$t('server ip address')"
:hint="$t('please input server ip address')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
val == 'localhost' ||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
val
) ||
$t('Please input vaild ip address'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.user_name?.focus();
}
}
"
>
<template v-slot:prepend>
<q-icon name="public" class="background" />
</template>
<template v-if="data.ip_address" v-slot:append>
<q-icon
name="cancel"
@click.stop="data.ip_address = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
:autofocus="!data.user_name"
outlined
ref="user_name"
:loading="data.loading"
:disable="data.loading"
v-model="data.user_name"
:label="$t('user name')"
:hint="$t('please input user name')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.password_input?.focus();
}
}
"
>
<template v-slot:prepend >
<q-icon name="account_circle" class="background" />
</template>
<template v-if="data.user_name" v-slot:append>
<q-icon
name="cancel"
@click.stop="data.user_name = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
outlined
ref="password_input"
:loading="data.loading"
:disable="data.loading"
:type="data.show_password ? '' : 'password'"
v-model="data.password"
:label="$t('password')"
:hint="$t('please input password')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.login_button?.click();
}
}
"
>
<template v-slot:prepend >
<q-icon name="key" class="background" />
</template>
<template v-if="data.password" v-slot:append>
<q-icon
:name="
data.show_password ? 'visibility' : 'visibility_off'
"
class="cursor-pointer"
@click="data.show_password = !data.show_password"
/>
<q-icon
name="cancel"
@click.stop="data.password = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item class="q-mt-md">
<q-item-section>
<q-checkbox
:label="$t('remember password')"
v-model="remember_password"
:disable="data.loading"
/>
</q-item-section>
<q-item-section>
<q-checkbox
:label="$t('auto login')"
v-model="auto_login"
@update:model-value="remember_password = true"
:disable="data.loading"
/>
</q-item-section>
</q-item>
</q-list>
</q-form>
</q-card-section>
<q-card-actions class="q-px-lg">
<q-btn
ref="login_button"
class="full-width text-h6"
:loading="data.loading"
:label="$t('login')"
no-caps
style="
background: #273de4;
box-shadow: 0 4px 6px 0px rgb(39 60 228 / 40%);
"
text-color="white"
@click="$refs?.login_form?.submit()"
/>
</q-card-actions>
</q-card>
</q-page>
</q-page-container>
</q-layout>
</template>
<style scoped>
.background{
color: #3f69fd;
}
</style>
<script lang="ts">
import { defineComponent, onMounted, reactive, ref, Ref, computed } from "vue";
import GlobalData from "src/common/GlobalData";
import { Cookies, LocalStorage, SessionStorage, useQuasar } from "quasar";
import ClientConnection from "src/common/ClientConnection";
import PermissionLevel from "src/entities/PermissionLevel";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import { useStore } from "src/store";
import { Md5 } from "ts-md5";
import Initializer from "src/common/Initializer";
import { api } from "src/boot/axios";
import { HttpProtocol } from "src/entities/HttpProtocol";
class _Data {
user_name: string | null = null;
password: string | null = null;
loading = false;
ip_address = window.location.hostname;
show_password = false;
constructor() {
let temp = LocalStorage.getItem("default_ip_address");
if (temp) {
this.ip_address = temp.toString();
} else {
this.ip_address = window.location.hostname;
}
temp = LocalStorage.getItem("default_user_name");
if (temp) {
this.user_name = temp.toString();
}
temp = LocalStorage.getItem("default_password");
if (temp) {
this.password = temp.toString();
}
}
}
export default defineComponent({
name: "PageLogin",
components: {},
setup() {
const $q = useQuasar();
const $t = useI18n();
const $route = useRouter();
const $store = useStore();
const data = reactive(new _Data());
try {
(window as any).setPcTheme();
} catch {}
const login_form: Ref<any> = ref(null);
const remember_password = ref(false);
const auto_login = ref(false);
let cache_password: string | null = null;
let web_socket: ClientConnection | null = null;
let is_pwa = ["fullscreen", "standalone", "minimal-ui"].some(
(displayMode) =>
window.matchMedia("(display-mode: " + displayMode + ")").matches
);
const landspace = computed({
get: () => $store.state.landspace,
set: (val) => null,
});
EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
landspace.value = window.innerHeight < window.innerWidth;
});
onMounted(() => {
console.log((<any>window).user_search);
if ((<any>window).user_search?.user && (<any>window).user_search?.pwd) {
if ((<any>window).user_search?.host) {
data.ip_address = (<any>window).user_search?.host;
}
data.user_name = (<any>window).user_search?.user;
data.password = (<any>window).user_search?.pwd;
login_form.value.submit();
} else {
if (auto_login.value) {
login_form.value.submit();
}
}
});
try {
remember_password.value = JSON.parse(
Cookies.get("remember_password")
) as boolean;
auto_login.value = JSON.parse(Cookies.get("auto_login")) as boolean;
if (
typeof remember_password.value == "undefined" ||
remember_password.value == null
) {
remember_password.value = false;
}
if (typeof auto_login.value == "undefined" || auto_login.value == null) {
auto_login.value = false;
}
if (remember_password.value) {
data.user_name = Cookies.get("user_name") ?? data.user_name;
cache_password = Cookies.get("password");
if (
typeof cache_password != "undefined" &&
cache_password != null &&
cache_password.length == 32
) {
data.password = cache_password;
} else {
cache_password = null;
}
}
} catch {}
return {
login_form,
data,
remember_password,
auto_login,
landspace,
is_pwa,
async onSubmit() {
data.loading = true;
return new Promise((resolve) => {
try {
let global_data = GlobalData.getInstance();
api
.get(HttpProtocol.RequestPathGetWebscoketPort)
.then((response) => {
let final_ws_port = GlobalData.kDefaultWebsocektPort;
if (response && typeof response.data != "undefined") {
if (typeof response.data != "number") {
const temp_port = parseInt(response.data);
if (!isNaN(temp_port) && temp_port != Infinity) {
final_ws_port = temp_port;
}
} else {
final_ws_port = response.data;
}
const url =
"ws://" +
data.ip_address +
":" +
final_ws_port.toString() +
GlobalData.kWebsocketResource;
web_socket = new ClientConnection(
url,
data.user_name,
data.password == cache_password
? data.password
: Md5.hashStr(data.password ?? "admin")
);
let timer = setTimeout(() => {
web_socket?.destory();
web_socket = null;
$q.notify({
color: "negative",
icon: "warning",
message:
$t.t("login fail!") +
$t.t("connect time out!") +
$t.t(
"please check server state, or check server ip address!"
),
position: "center",
timeout: 1500,
});
SessionStorage.set("auth", PermissionLevel.None);
resolve(false);
data.loading = false;
}, 5000);
web_socket.login_callback = (is_login) => {
clearTimeout(timer);
if (is_login && web_socket) {
global_data.addClient(data.ip_address, web_socket);
global_data.setCurrentClientName(data.ip_address);
SessionStorage.set("auth", PermissionLevel.Root);
SessionStorage.set("url", url);
SessionStorage.set("name", data.ip_address);
SessionStorage.set("user_name", data.user_name);
SessionStorage.set(
"password",
data.password == cache_password
? data.password
: Md5.hashStr(data.password ?? "admin")
);
// TODO add self to setConnects
if (remember_password.value) {
Cookies.set("remember_password", JSON.stringify(true), {
expires: 15,
});
Cookies.set(
"auto_login",
JSON.stringify(auto_login.value),
{
expires: 15,
}
);
Cookies.set("user_name", data.user_name ?? "admin", {
expires: 15,
});
Cookies.set(
"password",
data.password == cache_password
? data.password ?? Md5.hashStr("admin")
: Md5.hashStr(data.password ?? "admin"),
{
expires: 15,
}
);
} else {
Cookies.remove("remember_password");
Cookies.remove("auto_login");
Cookies.remove("name");
Cookies.remove("user_name");
Cookies.remove("password");
}
$store.commit("setDeviceIpAddress", data.ip_address);
setTimeout(() => {
new Initializer({
$t,
$store,
$q,
})
.initialize()
.then(() => {
$store.commit("setInitialized");
});
}, 0);
$route.push("/");
} else {
$q.notify({
color: "negative",
icon: "warning",
message:
$t.t("login fail!") + $t.t("user or password error!"),
position: "center",
timeout: 1500,
});
SessionStorage.set("auth", PermissionLevel.None);
}
resolve(true);
data.loading = false;
};
}
})
.catch(() => {
resolve(true);
data.loading = false;
});
} catch {
resolve(true);
data.loading = false;
}
});
},
onReset() {
data.user_name = null;
data.password = null;
remember_password.value = false;
},
};
},
});
</script>
<template>
<q-layout view="hHh lpR fFf">
<img
v-if="landspace"
src="login/login_background.png"
class="fit"
style="position: fixed"
/>
<q-page-container>
<q-page
class="row items-center"
style="position: ; /*fixed*/"
:class="landspace ? '' : 'justify-evenly'"
:style="landspace ? { left: '50%' } : {}"
>
<q-card :style="{ width: (landspace ? 34 : 70) + 'vw' }">
<q-card-section class="text-center text-h6">
{{ $t("login") }}
</q-card-section>
<q-separator />
<q-card-section class="fit">
<q-form ref="login_form" @submit="onSubmit" @reset="onReset">
<q-list class="fit">
<q-item v-if="$store.state.advanced_debug">
<q-item-section>
<q-input
:autofocus="!data.ip_address"
outlined
:loading="data.loading"
:disable="data.loading"
v-model="data.ip_address"
:label="$t('server ip address')"
:hint="$t('please input server ip address')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
(val) =>
isHost(val) || $t('Please input vaild ip address'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.user_name?.focus();
}
}
"
>
<template v-slot:prepend>
<q-icon name="public" class="background" />
</template>
<template v-if="data.ip_address" v-slot:append>
<q-icon
name="cancel"
@click.stop="data.ip_address = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
:autofocus="!data.user_name"
outlined
ref="user_name"
:loading="data.loading"
:disable="data.loading"
v-model="data.user_name"
:label="$t('user name')"
:hint="$t('please input user name')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.password_input?.focus();
}
}
"
>
<template v-slot:prepend>
<q-icon name="account_circle" class="background" />
</template>
<template v-if="data.user_name" v-slot:append>
<q-icon
name="cancel"
@click.stop="data.user_name = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-input
outlined
ref="password_input"
:loading="data.loading"
:disable="data.loading"
:type="data.show_password ? '' : 'password'"
v-model="data.password"
:label="$t('password')"
:hint="$t('please input password')"
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
$t('Please type something'),
]"
@keydown="
(evt) => {
if (evt.keyCode == 13) {
$refs?.login_button?.click();
}
}
"
>
<template v-slot:prepend>
<q-icon name="key" class="background" />
</template>
<template v-if="data.password" v-slot:append>
<q-icon
:name="
data.show_password ? 'visibility' : 'visibility_off'
"
class="cursor-pointer"
@click="data.show_password = !data.show_password"
/>
<q-icon
name="cancel"
@click.stop="data.password = null"
class="cursor-pointer"
/>
</template>
</q-input>
</q-item-section>
</q-item>
<q-item class="q-mt-md">
<q-item-section>
<q-checkbox
:label="$t('remember password')"
v-model="remember_password"
:disable="data.loading"
/>
</q-item-section>
<q-item-section>
<q-checkbox
:label="$t('auto login')"
v-model="auto_login"
@update:model-value="remember_password = true"
:disable="data.loading"
/>
</q-item-section>
</q-item>
</q-list>
</q-form>
</q-card-section>
<q-card-actions class="q-px-lg">
<q-btn
ref="login_button"
class="full-width text-h6"
:loading="data.loading"
:label="$t('login')"
no-caps
style="
background: #273de4;
box-shadow: 0 4px 6px 0px rgb(39 60 228 / 40%);
"
text-color="white"
@click="$refs?.login_form?.submit()"
/>
</q-card-actions>
</q-card>
</q-page>
</q-page-container>
</q-layout>
</template>
<style scoped>
.background {
color: #3f69fd;
}
</style>
<script lang="ts">
import { defineComponent, onMounted, reactive, ref, Ref, computed } from "vue";
import GlobalData from "src/common/GlobalData";
import { Cookies, LocalStorage, SessionStorage, useQuasar } from "quasar";
import ClientConnection from "src/common/ClientConnection";
import PermissionLevel from "src/entities/PermissionLevel";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import { useStore } from "src/store";
import { Md5 } from "ts-md5";
import Initializer from "src/common/Initializer";
import { api } from "src/boot/axios";
import { HttpProtocol } from "src/entities/HttpProtocol";
import ValidationUtil from "src/common/ValidationUtil";
class _Data {
user_name: string | null = null;
password: string | null = null;
loading = false;
ip_address = window.location.hostname;
show_password = false;
constructor() {
let temp = LocalStorage.getItem("default_ip_address");
if (temp) {
this.ip_address = temp.toString();
} else {
this.ip_address = window.location.hostname;
}
temp = LocalStorage.getItem("default_user_name");
if (temp) {
this.user_name = temp.toString();
}
temp = LocalStorage.getItem("default_password");
if (temp) {
this.password = temp.toString();
}
}
}
export default defineComponent({
name: "PageLogin",
components: {},
setup() {
const $q = useQuasar();
const $t = useI18n();
const $route = useRouter();
const $store = useStore();
const data = reactive(new _Data());
try {
(window as any).setPcTheme();
} catch {}
const login_form: Ref<any> = ref(null);
const remember_password = ref(false);
const auto_login = ref(false);
let cache_password: string | null = null;
let web_socket: ClientConnection | null = null;
let is_pwa = ["fullscreen", "standalone", "minimal-ui"].some(
(displayMode) =>
window.matchMedia("(display-mode: " + displayMode + ")").matches
);
const landspace = computed({
get: () => $store.state.landspace,
set: (val) => null,
});
EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
landspace.value = window.innerHeight < window.innerWidth;
});
onMounted(() => {
console.log((<any>window).user_search);
if ((<any>window).user_search?.user && (<any>window).user_search?.pwd) {
if ((<any>window).user_search?.host) {
data.ip_address = (<any>window).user_search?.host;
}
data.user_name = (<any>window).user_search?.user;
data.password = (<any>window).user_search?.pwd;
login_form.value.submit();
} else {
if (auto_login.value) {
login_form.value.submit();
}
}
});
try {
remember_password.value = JSON.parse(
Cookies.get("remember_password")
) as boolean;
auto_login.value = JSON.parse(Cookies.get("auto_login")) as boolean;
if (
typeof remember_password.value == "undefined" ||
remember_password.value == null
) {
remember_password.value = false;
}
if (typeof auto_login.value == "undefined" || auto_login.value == null) {
auto_login.value = false;
}
if (remember_password.value) {
data.user_name = Cookies.get("user_name") ?? data.user_name;
cache_password = Cookies.get("password");
if (
typeof cache_password != "undefined" &&
cache_password != null &&
cache_password.length == 32
) {
data.password = cache_password;
} else {
cache_password = null;
}
}
} catch {}
return {
login_form,
data,
remember_password,
auto_login,
landspace,
is_pwa,
async onSubmit() {
data.loading = true;
return new Promise((resolve) => {
try {
let global_data = GlobalData.getInstance();
api
.get(HttpProtocol.RequestPathGetWebscoketPort)
.then((response) => {
let final_ws_port = GlobalData.kDefaultWebsocektPort;
if (response && typeof response.data != "undefined") {
if (typeof response.data != "number") {
const temp_port = parseInt(response.data);
if (!isNaN(temp_port) && temp_port != Infinity) {
final_ws_port = temp_port;
}
} else {
final_ws_port = response.data;
}
const url =
"ws://" +
data.ip_address +
":" +
final_ws_port.toString() +
GlobalData.kWebsocketResource;
web_socket = new ClientConnection(
url,
data.user_name,
data.password == cache_password
? data.password
: Md5.hashStr(data.password ?? "admin")
);
let timer = setTimeout(() => {
web_socket?.destory();
web_socket = null;
$q.notify({
color: "negative",
icon: "warning",
message:
$t.t("login fail!") +
$t.t("connect time out!") +
$t.t(
"please check server state, or check server ip address!"
),
position: "center",
timeout: 1500,
});
SessionStorage.set("auth", PermissionLevel.None);
resolve(false);
data.loading = false;
}, 5000);
web_socket.login_callback = (is_login) => {
clearTimeout(timer);
if (is_login && web_socket) {
global_data.addClient(data.ip_address, web_socket);
global_data.setCurrentClientName(data.ip_address);
SessionStorage.set("auth", PermissionLevel.Root);
SessionStorage.set("url", url);
SessionStorage.set("name", data.ip_address);
SessionStorage.set("user_name", data.user_name);
SessionStorage.set(
"password",
data.password == cache_password
? data.password
: Md5.hashStr(data.password ?? "admin")
);
// TODO add self to setConnects
if (remember_password.value) {
Cookies.set("remember_password", JSON.stringify(true), {
expires: 15,
});
Cookies.set(
"auto_login",
JSON.stringify(auto_login.value),
{
expires: 15,
}
);
Cookies.set("user_name", data.user_name ?? "admin", {
expires: 15,
});
Cookies.set(
"password",
data.password == cache_password
? data.password ?? Md5.hashStr("admin")
: Md5.hashStr(data.password ?? "admin"),
{
expires: 15,
}
);
} else {
Cookies.remove("remember_password");
Cookies.remove("auto_login");
Cookies.remove("name");
Cookies.remove("user_name");
Cookies.remove("password");
}
$store.commit("setDeviceIpAddress", data.ip_address);
setTimeout(() => {
new Initializer({
$t,
$store,
$q,
})
.initialize()
.then(() => {
$store.commit("setInitialized");
});
}, 0);
$route.push("/");
} else {
$q.notify({
color: "negative",
icon: "warning",
message:
$t.t("login fail!") + $t.t("user or password error!"),
position: "center",
timeout: 1500,
});
SessionStorage.set("auth", PermissionLevel.None);
}
resolve(true);
data.loading = false;
};
}
})
.catch(() => {
resolve(true);
data.loading = false;
});
} catch {
resolve(true);
data.loading = false;
}
});
},
onReset() {
data.user_name = null;
data.password = null;
remember_password.value = false;
},
isHost(str: string) {
return ValidationUtil.isHost(str);
},
};
},
});
</script>

View File

@ -33,7 +33,7 @@
</q-btn-dropdown>
<q-btn-dropdown
v-if="show_device_list"
v-if="show_device_list && !$store.state.$wujie"
stretch
no-caps
flat
@ -76,7 +76,11 @@
</q-list>
</q-btn-dropdown>
<q-separator vertical inset />
<q-separator
vertical
inset
v-if="show_device_list && !$store.state.$wujie"
/>
<q-btn
stretch
@ -191,6 +195,7 @@
:disable="plan_running || !$store.state.power_state"
:icon="/*vertical_align_bottom*/ 'img:new_icon/edit_window_rect.png'"
:label="$t('toolbar edit window rect')"
v-if="$store.state.isLedPlayer()"
class="q-mr-sm"
@click="editRect"
/>
@ -297,10 +302,29 @@
class="shadow-2 text-white"
@dragstart.prevent
>
<q-item
clickable
v-close-popup
@click="
$refs.fusion_settings_dialog.showDialog();
getconfig();
"
v-if="$store.state.custom_defines.function_fusion"
>
<q-item-section avatar>
<q-icon name="open_with" />
</q-item-section>
<q-item-section>
{{ $t("fusion settings") }}
</q-item-section>
</q-item>
<q-item
clickable
:disable="!$store.state.power_state"
v-if="$store.state.isLedPlayer()"
v-if="
$store.state.isLedPlayer() &&
!$store.state.custom_defines.function_magic_wall
"
v-close-popup
@click="
($store.state.isSpecialVideo()
@ -317,6 +341,21 @@
{{ $t("grid setting") }}
</q-item-section>
</q-item>
<q-item
clickable
:disable="!$store.state.power_state"
v-close-popup
@click="$refs.control_panel_dialog.showDialog()"
v-if="$store.state.custom_defines.function_magic_wall"
>
<q-item-section avatar>
<!-- <q-icon name="image" /> -->
<q-icon name="web" />
</q-item-section>
<q-item-section>
{{ $t("magic wall") }}
</q-item-section>
</q-item>
<q-item
clickable
@ -334,6 +373,7 @@
</q-item-section>
</q-item>
<q-item
v-if="!iswujie"
clickable
v-close-popup
@click="$refs.background_image_dialog.showDialog()"
@ -347,6 +387,7 @@
</q-item-section>
</q-item>
<q-item
v-if="!iswujie"
clickable
v-close-popup
@click="$refs.recovery_database_dialog.showDialog()"
@ -382,6 +423,7 @@
</q-item-section>
</q-item>
<q-item
v-if="!iswujie"
clickable
v-close-popup
@click="$refs.upgrade_dialog.showDialog()"
@ -417,22 +459,7 @@
</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="
$refs.fusion_settings_dialog.showDialog();
getconfig();
"
>
<q-item-section avatar>
<!-- <q-icon name="devices" /> -->
<q-icon name="open_with" />
</q-item-section>
<q-item-section>
{{ $t("fusion settings") }}
</q-item-section>
</q-item>
<q-item
clickable
@ -464,7 +491,7 @@
<q-separator vertical inset />
<q-item>
<q-item v-if="!iswujie">
<q-item-section avatar style="margin-right: 0px; padding-right: 0px">
<!-- <q-icon class="text-white rotate" name="img:svgs/fan.svg" /> -->
<!-- <q-icon class="text-white rotate" name="img:new_icon/fan.png" /> -->
@ -478,6 +505,15 @@
{{ $store.state.fan_temp.toFixed(1) }}
</q-item-section>
</q-item>
<q-item v-else>
<q-item-section avatar style="margin-right: 0px; padding-right: 0px">
<q-btn
flat
@click="isfullbtn()"
:icon="isfull ? 'fullscreen_exit' : 'fullscreen'"
/>
</q-item-section>
</q-item>
</q-toolbar>
</div>
<grid-setting-dialog
@ -488,6 +524,7 @@
v-if="$store.state.isSpecialVideo()"
ref="special_video_grid_setting_dialog"
/>
<control-panel-dialog ref="control_panel_dialog" />
<background-image-dialog ref="background_image_dialog" />
<subtitle-dialog ref="subtitle_dialog" />
<recovery-database-dialog ref="recovery_database_dialog" />
@ -524,11 +561,14 @@
<script lang="ts">
import { defineComponent, ref, Ref, computed, watch, onMounted } from "vue";
import { useStore } from "src/store";
import { IWuJieInterface, useStore } from "src/store";
import FusionSettingsDialog from "src/components/FusionSettingsDialog.vue";
import GridSettingDialog from "src/components/GridSettingDialog.vue";
import SpecialVideoGridSettingDialog from "src/components/SpecialVideoGridSettingDialog.vue";
import ControlPanelDialog from "src/components/ControlPanelDialog.vue";
import BackgroundImageDialog from "src/components/BackgroundImageDialog.vue";
import RecoveryDatabaseDialog from "src/components/RecoveryDatabaseDialog.vue";
import UpgradeDialog from "src/components/UpgradeDialog.vue";
@ -560,6 +600,9 @@ export default defineComponent({
components: {
GridSettingDialog,
SpecialVideoGridSettingDialog,
ControlPanelDialog,
BackgroundImageDialog,
RecoveryDatabaseDialog,
UpgradeDialog,
@ -588,7 +631,7 @@ export default defineComponent({
const register_dialog: Ref<any> = ref(null);
const window_rect_edit_dialog: Ref<any> = ref(null);
let isfull = ref(false);
const power_flag = ref(false);
watch(
() => power_flag.value,
@ -610,6 +653,10 @@ export default defineComponent({
return "rotate " + sulv + "s linear infinite";
});
const getconfig = () => {
set?.SetBlendingOption("blending_grids_select_ui", '4')
set?.SetBlendingOption('blending_grids_select_projector',"0-0");
set?.SetBlendingOption("blending_grids_select_point", `4:1`)
set?.SetBlendingOption("blending_grids_show", "1");
try {
set?.GetBlendingConfig("").then((res) => {});
set?.GetBlendingConfig("").then((res) => {
@ -683,7 +730,10 @@ export default defineComponent({
show_device_list.value =
typeof (<any>window).user_search?.hide_device_list == "undefined";
});
let iswujie = ref(false);
if ((window as any).$wujie) {
iswujie.value = true;
}
return {
getconfig,
show_advanced_menu,
@ -694,6 +744,8 @@ export default defineComponent({
show_device_list,
power_flag,
fan,
isfull,
iswujie,
async backupDB() {
let client = GlobalData.getInstance().getCurrentClient();
if (client) {
@ -706,8 +758,11 @@ export default defineComponent({
console.log(url.toString());
let response = await api.get(url.toString());
if (response.status == 200 && response && response.data) {
url.pathname =
HttpProtocol.RequestPathDBBackup + "/" + response.data;
console.log(response.data);
url.pathname = HttpProtocol.RequestPathDBBackup;
url.searchParams.append("name", response.data);
console.log(url);
openURL(url.toString());
} else {
$q.notify({
@ -783,9 +838,12 @@ export default defineComponent({
},
logout() {
const w = window as any;
console.log(w);
if (w.controlLogout && typeof w.controlLogout == "function") {
console.log(1);
w.controlLogout();
} else {
console.log(2);
Cookies.remove("auto_login");
SessionStorage.clear();
try {
@ -956,6 +1014,13 @@ export default defineComponent({
?.windowFullScreen(window.window_id, false);
}
},
isfullbtn() {
isfull.value = !isfull.value;
if ((window as any).$wujie) {
const $wujie = (window as any).$wujie as IWuJieInterface;
$wujie?.bus.$emit("isfull", isfull.value);
}
},
};
},
});

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,7 @@
:disable="plan_running || !$store.state.power_state"
:icon="/*vertical_align_bottom*/ 'img:new_icon/edit_window_rect.png'"
:label="$t('toolbar edit window rect')"
v-if="$store.state.isLedPlayer()"
class="q-mr-sm"
@click="editRect"
/>

View File

@ -38,6 +38,14 @@ export default route<StateInterface>(function (/* { store, ssrContext } */) {
});
Router.beforeEach((to, from, next) => {
if ((<any>window).$wujie) {
if (to.path.endsWith("login")) {
next("/");
} else {
next();
}
return;
}
if (
to.meta &&
(to.meta.permission_level != null ||
@ -47,10 +55,10 @@ export default route<StateInterface>(function (/* { store, ssrContext } */) {
if (auth_obj) {
const auth = parseInt(auth_obj);
const target_auth = parseInt(<string>to.meta.permission_level);
if (target_auth == NaN) {
if (isNaN(target_auth)) {
next();
return;
} else if (auth != NaN) {
} else {
if (auth > target_auth) {
next();
return;

View File

@ -2,26 +2,37 @@ import { RouteRecordRaw } from "vue-router";
import PermissionLevel from "src/entities/PermissionLevel";
import RedirectPage from "src/RedirectPage.vue";
import Login from "pages/Login.vue";
import MainLayout from "layouts/MainLayout.vue";
import Index from "pages/Index.vue";
import PadLogin from "src/pad/Login.vue";
import PadMainLayout from "src/pad/MainLayout.vue";
import PadIndex from "src/pad/Index.vue";
import Error404 from "pages/Error404.vue";
const routes: RouteRecordRaw[] = [
{
path: "/",
meta: {},
component: () => import("src/RedirectPage.vue"),
component: RedirectPage,
},
{
path: "/pc/login",
component: () => import("pages/Login.vue"),
component: Login,
},
{
path: "/pc",
meta: {
permission_level: PermissionLevel.User,
},
component: () => import("layouts/MainLayout.vue"),
component: MainLayout,
children: [
{
path: "",
component: () => import("pages/Index.vue"),
component: Index,
meta: {
permission_level: PermissionLevel.User,
},
@ -30,18 +41,18 @@ const routes: RouteRecordRaw[] = [
},
{
path: "/pad/login",
component: () => import("src/pad/Login.vue"),
component: PadLogin,
},
{
path: "/pad",
meta: {
permission_level: PermissionLevel.User,
},
component: () => import("src/pad/MainLayout.vue"),
component: PadMainLayout,
children: [
{
path: "",
component: () => import("src/pad/Index.vue"),
component: PadIndex,
meta: {
permission_level: PermissionLevel.User,
},
@ -53,7 +64,7 @@ const routes: RouteRecordRaw[] = [
// but you can also remove it
{
path: "/:catchAll(.*)*",
component: () => import("pages/Error404.vue"),
component: Error404,
},
];

View File

@ -1,3 +1,4 @@
import { EDeviceAttributeHelper } from "./../entities/EDeviceAttribute";
import { ConnectTableEntity } from "src/entities/ConnectTableEntity";
import {
PollingEntity,
@ -37,8 +38,44 @@ export class CustomDefines {
function_output_board = false;
function_center_control = false;
function_mirroring_output = false;
function_magic_wall = false;
function_fusion = false;
}
export interface IWuJieEventBus {
$on(event: string, fn: Function): IWuJieEventBus;
/** 任何$emit都会导致监听函数触发第一个参数为事件名后续的参数为$emit的参数 */
$onAll(fn: (event: string, ...args: Array<any>) => any): IWuJieEventBus;
$once(event: string, fn: Function): void;
$off(event: string, fn: Function): IWuJieEventBus;
$offAll(fn: Function): IWuJieEventBus;
$emit(event: string, ...args: Array<any>): IWuJieEventBus;
$clear(): IWuJieEventBus;
}
export interface IWuJieInterface {
props: any;
bus: IWuJieEventBus;
}
class test_monitor {
w = 0.0;
h = 0.0;
currentx = 0.0;
currenty = 0.0;
centerx = 0.0;
centery = 0.0;
angle = 0;
id = 0;
constructor(id: number, w: number, h: number) {
this.currentx = 0.0;
this.currenty = 0.0;
this.angle = 0;
this.centerx = 0;
this.centery = 0;
this.id = id;
this.w = w;
this.h = h;
}
}
export interface StateInterface {
// Define your own store structure, using submodules if needed
// example: ExampleStateInterface;
@ -76,12 +113,16 @@ export interface StateInterface {
device_attribute: number;
power_state: boolean;
product_name: string;
show_monitor_list: test_monitor[];
custom_defines: CustomDefines;
fusion_configuration:string;
fusion_configuration: string;
isLedPlayer: () => boolean;
isSpecialVideo: () => boolean;
$wujie: IWuJieInterface | null;
//
selected_projector: string;
enablefusion:boolean
enablefusion: boolean;
}
// provide typings for `this.$store`
@ -339,12 +380,12 @@ export default store(function (/* { ssrContext } */) {
landspace: window.innerWidth > window.innerHeight,
device_attribute: 0,
power_state: false,
fusion_configuration:"",
fusion_configuration: "",
product_name: EProductNames.LED_PLAYER,
show_monitor_list: [],
custom_defines: new CustomDefines(),
selected_projector: "0/0",
enablefusion:false,
enablefusion: false,
isLedPlayer: () => {
return (
Store.state.product_name == EProductNames.LED_PLAYER ||
@ -354,12 +395,17 @@ export default store(function (/* { ssrContext } */) {
isSpecialVideo: () => {
return Store.state.product_name == EProductNames.SPECIAL_VIDEO;
},
$wujie: null,
},
mutations: {
setInitialized(state: StateInterface, playload?: any) {
state.initialized = true;
},
setShowMonitorList(state: StateInterface, playload?: any) {
state.show_monitor_list = playload;
},
updateLandspace(state: StateInterface, playload?: any) {
if (typeof playload == "boolean") {
state.landspace = playload;
@ -392,6 +438,10 @@ export default store(function (/* { ssrContext } */) {
(state.device_attribute & EDeviceAttribute.CenterControl) != 0;
state.custom_defines.function_mirroring_output =
(state.device_attribute & EDeviceAttribute.MirroringOutput) != 0;
state.custom_defines.function_magic_wall =
(state.device_attribute & EDeviceAttribute.ProductMagicWall) != 0;
state.custom_defines.function_fusion =
EDeviceAttributeHelper.isProductFusion(state.device_attribute);
}
},
setAvancedDebug(state: StateInterface, playload?: any) {
@ -561,31 +611,31 @@ export default store(function (/* { ssrContext } */) {
},
setWallCol(state: StateInterface, playload?: any) {
const num = parseInt(playload);
if (num != NaN && num > 0) {
if (!isNaN(num) && num > 0) {
state.wall_col = num;
}
},
setWallRow(state: StateInterface, playload?: any) {
const num = parseInt(playload);
if (num != NaN && num > 0) {
if (!isNaN(num) && num > 0) {
state.wall_row = num;
}
},
setDeviceScreenWidth(state: StateInterface, playload?: any) {
const num = parseInt(playload);
if (num != NaN && num > 0) {
if (!isNaN(num) && num > 0) {
state.device_screen_width = num;
}
},
setDeviceScreenHeight(state: StateInterface, playload?: any) {
const num = parseInt(playload);
if (num != NaN && num > 0) {
if (!isNaN(num) && num > 0) {
state.device_screen_height = num;
}
},
setDeviceScreenRefreshRate(state: StateInterface, playload?: any) {
const num = parseInt(playload);
if (num != NaN && num > 0) {
if (!isNaN(num) && num > 0) {
state.device_screen_refresh_rate = num;
}
},
@ -603,10 +653,10 @@ export default store(function (/* { ssrContext } */) {
state.signal_source_tree = playload;
}
},
setSelectedProjector(state: StateInterface, playload?: any){
setSelectedProjector(state: StateInterface, playload?: any) {
state.selected_projector = playload;
},
setEnablefusion(state: StateInterface, playload?: any){
setEnablefusion(state: StateInterface, playload?: any) {
state.enablefusion = playload;
},
clearSignalSourceTree(state: StateInterface, playload?: any) {
@ -998,15 +1048,18 @@ export default store(function (/* { ssrContext } */) {
state.connect_list.slice(index, 1);
}
},
setfusion_configuration(state: StateInterface, playload?: any){
state.fusion_configuration=playload
}
setWuJie(state: StateInterface, playload?: any) {
state.$wujie = playload;
},
setfusion_configuration(state: StateInterface, playload?: any) {
state.fusion_configuration = playload;
},
},
getters:{
GetTheCurrentlySelectedCamera(state){
let arr = state.selected_projector.split('/');
return [Number(arr[0]),Number(arr[1])];
}
getters: {
GetTheCurrentlySelectedCamera(state) {
let arr = state.selected_projector.split("/");
return [Number(arr[0]), Number(arr[1])];
},
},
// enable strict mode (adds overhead!)
// for dev mode and --debug builds only

View File

@ -1,5 +1,5 @@
{
"extends": "@quasar/app/tsconfig-preset",
"extends": "@quasar/app-webpack/tsconfig-preset",
"compilerOptions": {
"baseUrl": "."
}