10 Commits afd47e4ff8 ... 490f110ff0

Author SHA1 Message Date
  raod 490f110ff0 info 4 months ago
  Foming c46b92138d !217 fix: 优化日历组件数据解析部分 4 months ago
  Foming 2db26a7d9c 增加日历属性sql 4 months ago
  李帅武 af96edf734 fix: 优化日历组件数据解析部分 4 months ago
  Foming eaa3018140 !216 增加日历组件 4 months ago
  李帅武 183e7f2863 增加日历组件 4 months ago
  Foming 15f02c44c9 !214 丰富了文本组件的样式属性 4 months ago
  李帅武 4c4b2747c2 丰富了文本组件的样式属性 4 months ago
  Devli c131977a5a update quick start 4 months ago
  Devli c57258f95a update quick start 4 months ago

+ 1 - 61
README.en.md

@@ -1,61 +1 @@
-## Online experience
-
-####   Computer online experience: [https://ajreport.beliefteam.cn/](https://ajreport.beliefteam.cn/ "链接")   account:guest  password:guest
-
-#### &emsp; Online documents: [https://ajreport.beliefteam.cn/report-doc/](https://ajreport.beliefteam.cn/report-doc/ "doc")<br>
-
-#### &emsp; issues: [https://gitee.com/anji-plus/report/issues](https://gitee.com/anji-plus/report/issues "issue")
-
-## Function overview
-
-#### &emsp; Component introduction
-
-&emsp;&emsp; (AJ-Report)is a visual drag edit, intuitive, cool, with a sense of science and technology chart tool full
-open source project.
-
-The built-in basic functions include data source, data set, report management, and some screenshots of the project are
-shown below.。<br>
-
-## Packaging directory
-
-```
-├── bin                                           
-│   ├── logs                                     
-│   ├── cache                                    
-│   ├── startup.cmd
-│   ├── shutdown.cmd
-│   ├── startup.sh
-│   └── shutdown.sh
-├── config                                       
-├── lib                                          
-├── target                                       
-```
-
-## System directory
-
-```
-├── doc                                          
-│   ├── docs
-│   ├── package.json
-│   └── README.md
-├── pom.xml                                      
-├── report-core                                  
-│   ├── pom.xml                                  
-│   └── README.md
-├── report-ui                                    
-├── LICENSE
-├── README.md
-```
-
-## Short term plan
-
-#### &emsp; Enrich more chart components
-
-## technical support
-
-If you have any questions, please submit to [Issue](https://gitee.com/anji-plus/report/issues)
-
-#### Open source is not easy, please, star ☺
-
-
-
+# This address has stopped maintenance

+ 1 - 302
README.md

@@ -1,302 +1 @@
-## 简介
-
-&emsp; &emsp; AJ-Report是全开源的一个BI平台,酷炫大屏展示,能随时随地掌控业务动态,让每个决策都有数据支撑。<br>
-&emsp; &emsp;
-多数据源支持,内置mysql、elasticsearch、kudu驱动,支持自定义数据集省去数据接口开发,目前已支持30+种大屏组件/图表,不会开发,照着设计稿也可以制作大屏。<br>
-&emsp; &emsp; 三步轻松完成大屏设计:配置数据源---->写SQL配置数据集---->拖拽配置大屏---->保存发布。欢迎体验。
-
-## 在线体验
-
-#### &emsp; [在线体验](https://ajreport.beliefteam.cn/index.html "链接"): https://ajreport.beliefteam.cn/index.html  &emsp;体验账号:guest 密码:guest
-
-#### 文档位置
-
-#### &emsp; [在线文档](https://ajreport.beliefteam.cn/report-doc/ "doc"): https://ajreport.beliefteam.cn/report-doc/ <br>
-
-源码 doc -> docs -> guide 目录下即所有文档
-
-#### 模板链接
-
-#### &emsp; [模板下载](https://ajreport.beliefteam.cn/download "temp"): https://ajreport.beliefteam.cn/download<br>
-
-通过百度网盘分享的文件:大屏模板
-链接:https://pan.baidu.com/s/1rkjBiiTpA4DBQdep-uAYzQ?pwd=w3rm提取码:w3rm
-
-#### &emsp; [在线提问](https://gitee.com/anji-plus/report/issues "issue"): https://gitee.com/anji-plus/report/issues <br>
-
-## 发行版本
-
-#### &emsp; [下载链接](https://gitee.com/anji-plus/report/releases "下载链接"): https://gitee.com/anji-plus/report/releases <br>
-
-## 功能概述
-
-#### &emsp; 组件介绍
-
-&emsp;&emsp; 大屏设计(AJ-Report)是一个可视化拖拽编辑的,直观,酷炫,具有科技感的图表工具全开源项目。
-内置的基础功能包括数据源,数据集,报表管理,项目部分截图如下。<br>
-
-![操作](https://images.gitee.com/uploads/images/2021/0703/094742_c0243f70_1728982.gif "2021-07-03_09-43-50.gif")
-
-## 数据流程图
-
-![An image](https://images.gitee.com/uploads/images/2021/0630/160451_31bb9052_1728982.png)
-
-## 打包目录build
-
-```
-├── bin                                           启动命令脚本
-│   ├── restart.sh
-│   ├── start.bat
-│   ├── start.sh
-│   └── stop.sh
-├── conf                                       配置文件目录
-│   └── bootstrap.yml
-├── logs                                          启动日志目录
-├── cache                                         本地缓存目录
-├── lib                                           自定义扩展包&report-core核心包
-```
-
-## 系统目录
-
-```
-├── doc                                           文档源码
-│   ├── docs
-│   ├── package.json
-│   └── README.md
-├── pom.xml                                       父pom,jar版本管理
-├── report-core                                   java源码
-│   ├── pom.xml                                   gaea父pom,jar版本管理
-│   └── README.md
-├── report-ui                                     前端vue源码
-├── LICENSE
-├── README.md
-```
-
-## 核心技术
-
-### 依赖
-
-- [Mysql] 5.7
-- [Jdk] 1.8
-
-### 后端
-
-- [aj-gaea](https://gitee.com/anji-plus/gaea) 低代码平台+spring微服务组件.
-- [Spring Boot2.3.5.RELEASE](https://spring.io/projects/spring-boot/): Spring Boot是一款开箱即用框架,让我们的Spring应用变的更轻量化、更快的入门。
-  在主程序执行main函数就可以运行。你也可以打包你的应用为jar并通过使用java -jar来运行你的Web应用;
-- [Mybatis-plus3.3.2](https://mp.baomidou.com/): MyBatis-plus(简称 MP)是一个 MyBatis (opens new window) 的增强工具。
-- [flyway5.2.1](https://flywaydb.org/): 主要用于在你的应用版本不断升级的同时,升级你的数据库结构和里面的数据
-
-### 前端
-
-- [npm](https://www.npmjs.com/):node.js的包管理工具,用于统一管理我们前端项目中需要用到的包、插件、工具、命令等,便于开发和维护。
-- [webpack](https://webpack.docschina.org/):用于现代 JavaScript 应用程序的静态模块打包工具。
-- [ES6](https://es6.ruanyifeng.com/):JavaScript的新版本,ECMAScript6的简称。利用ES6我们可以简化我们的JS代码,同时利用其提供的强大功能来快速实现JS逻辑。
-- [vue-cli](https://cli.vuejs.org/):Vue的脚手架工具,用于自动生成Vue项目的目录及文件。
-- [vue-router](https://router.vuejs.org/): Vue提供的前端路由工具,利用其我们实现页面的路由控制,局部刷新及按需加载,构建单页应用,实现前后端分离。
-- [element-ui](https://element.eleme.cn/#/zh-CN):基于MVVM框架Vue开源出来的一套前端ui组件。
-- [avue](https://www.avuejs.com/): 用该组件包裹后可以变成拖拽组件,采用相对于父类绝对定位,用键盘的上下左右也可以控制移动。
-- [vue-echarts](https://www.npmjs.com/package/vue-echarts/): vue-echarts是封装后的vue插件,基于 ECharts v4.0.1+ 开发。
-- [vue-superslide](https://www.npmjs.com/package/vue-super-slider/): Vue-SuperSlide(Github) 是 SuperSlide 的 Vue 封装版本。
-- [vuedraggable](https://github.com/SortableJS/Vue.Draggable/): 是一款基于Sortable.js实现的vue拖拽插件。
-- [luckysheet](https://gitee.com/mengshukeji/Luckysheet): Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。
-
-## 部署方式
-
-**[运行环境参考文档](https://ajreport.beliefteam.cn/report-doc/guide/quicklyDevelop.html)** <br>
-**注意版本兼容性** <br>
-源码 doc -> docs -> guide 目录下即所有文档。<br>
-启动文档(在线文档图片多,打开很慢可以本地启动文档,方便查看) <br>
-
-```
-cd .\doc\
-npm run docs:dev
-```
-
-### 发行版部署
-
-**[发行版部署详细文档](https://ajreport.beliefteam.cn/report-doc/guide/quicklyDistribution.html)** <br>
-
-简易步骤
-
-```
-下载最新发行版,解压
-cd aj-report-xxxx
-vim conf/bootstrap.yml 修改数据库连接、上传下载地址、jwt令牌等信息
-sh bin/start.sh Linux启动
-bin/start.bat Windows修改第4行的JAVA_HOME后(去掉rem注释),双击启动
-
-启动后访问
-http://serverip:9095
-用户名密码:admin/123456
-
-```
-
-### 源码编译部署
-
-**[源码编译部署详细文档](https://ajreport.beliefteam.cn/report-doc/guide/quicklySource.html)** <br>
-
-在Linux上先准备好maven、node.js、jdk
-
-- [Apache Maven] 3.5 <br>
-- [Node.js]
-    - report1.5以下版本请使用 node <= V14
-    - report1.5及以上版本请使用 node = V16
-- [Jdk] 1.8
-
-简易步骤
-
-```
-git clone https://gitee.com/anji-plus/report.git
-cd report
-sh build.sh
-编译完成放在build文件夹 aj-report-xxxx.zip
-
-unzip aj-report-xxxx.zip
-cd aj-report-xxxx
-vim conf/bootstrap.yml 修改数据库连接、上传下载地址、jwt令牌等信息
-sh bin/start.sh Linux启动
-bin/start.bat Windows修改第4行的JAVA_HOME后(去掉rem注释),双击启动
-
-启动后访问
-http://serverip:9095
-用户名密码:admin/123456
-
-```
-
-### 前后端分离部署
-
-**[前后端分离部署参考文档](https://ajreport.beliefteam.cn/report-doc/guide/quicklySeparate.html)** <br>
-
-## 信息安全
-
-### 修改密钥
-
-```
-启动前,切记配置文件中修改,修改默认的32位密钥,避免被伪造攻击,修改admin默认密码
-spring.gaea.Security.jwtSecret = 修改32位jwt密钥
-```
-
-### 慎重公网
-
-```
-建议内网部署,避免公网攻击
-```
-
-## 快速入门
-
-**[快速入门](https://ajreport.beliefteam.cn/report-doc/guide/quicklyUse.html)** <br>
-
-**[更多社区大屏](https://ajreport.beliefteam.cn/report-doc/guide/bigScreenCase.html)** <br>
-
-**[社区大屏下载链接](https://ajreport.beliefteam.cn/download/)** <br>
-
-## SQL初始化
-
-sql文件的目录在:report-core --> src --> main --> resources -- > db.migration <br>
-系统初始化时flyway会自动的将该目录下的sql文件执行,不需要手动执行sql文件,执行完将会创建
-aj_report(存放系统基础数据)数据库 <br>
-
-**注意:** 如果sql初始化有问题,请将bootstrap.yml中flyway改为false,并手动执行这些sql <br>
-
-示例数据sql目录在:doc/example,有需要的请手动执行 <br>
-
-## 谁在使用
-
-感谢关注并使用AJ-Report的朋友,如果贵公司、组织、学校等正在使用AJ-Report,希望可以按照此[Issue](https://gitee.com/anji-plus/report/issues/I3ZXT4)
-登记并提供贵公司、组织、学校的logo,我们将把贵方的logo放在项目首页进行展示并优先进行技术支持 <br>
-
-<a href='http://www.jtit.com.cn/'><img src="doc/docs/picture/WhoIsUsing/17.png" width = "130" height = "50" /> </a>
-<img src="doc/docs/picture/WhoIsUsing/5.png" width = "130" height = "50" alt="广东南铝建筑机器人科技有限公司"/>
-<a href='http://www.plian.net/'><img src="doc/docs/picture/WhoIsUsing/4.png" width = "130" height = "50" /> </a>
-<a href='http://www.turingoal.com/'><img src="doc/docs/picture/WhoIsUsing/3.png" width = "130" height = "50" /> </a>
-<br>
-
-<a href='http://www.yourongyun.cn/'><img src="doc/docs/picture/WhoIsUsing/12.png" width = "130" height = "50" /> </a>
-<a href='https://www.yunstech.cn'> <img src="doc/docs/picture/WhoIsUsing/1.png" width = "130" height = "50" align=left/> </a>
-<a href='http://www.fgkb.net/'><img src="doc/docs/picture/WhoIsUsing/2.png" width = "130" height = "50" /> </a>
-<a href='https://soft.pusdn.com/'><img src="doc/docs/picture/WhoIsUsing/15.png" width = "130" height = "50" /> </a>
-<br>
-
-<a href='https://www.sandieji.tech/'><img src="doc/docs/picture/WhoIsUsing/9.png" width = "128" height = "130" /></a>
-<img src="doc/docs/picture/WhoIsUsing/11.png" width = "128" height = "130" alt="北京易盛宁洲科技有限公司"/>
-<img src="doc/docs/picture/WhoIsUsing/10.png" width = "128" height = "130" alt="光引科技"/>
-<img src="doc/docs/picture/WhoIsUsing/8.png" width = "128" height = "130" alt="武汉微安信息科技有限公司"/>
-<br>
-
-<a href='https://www.zjjcl.cn/'><img src="doc/docs/picture/WhoIsUsing/16.png" width = "130" height = "50" /> </a>
-<a href='https://www.wenkai.net/'><img src="doc/docs/picture/WhoIsUsing/13.png" width = "130" height = "50" /> </a>
-<img src="doc/docs/picture/WhoIsUsing/7.png" width = "130" height = "50" />
-<img src="doc/docs/picture/WhoIsUsing/6.jpeg" width = "130" height = "50" />
-<img src="doc/docs/picture/WhoIsUsing/14.png" width = "130" height = "50" />
-<br>
-
-## 已知问题
-
-- IE白屏(兼容性问题)
-
-## 版本问题
-
-已知以下版本存在兼容性问题,请不要使用
-
-- Node.js 请根据实际使用的report版本调整
-- openJdk
-- Jdk 1.7及以下/11及以上(jdk11部分版本有问题)
-- Mysql 8.0(8.0.23/26版本没有问题,8.0.21版本存在问题)
-
-**[常见问题](https://ajreport.beliefteam.cn/report-doc/guide/question.html)**
-
-## 商业授权
-
-AJ-Report使用[Apache2.0开源协议](http://www.apache.org/licenses/LICENSE-2.0.html)
-,允许商业使用,但务必保留类作者、Copyright信息。 <br>
-个人和企业,在直接使用、二次开发后商业使用,需要遵守:
-
-- 包含Apache LICENSE文件
-- 如果修改了代码,需要在被修改的文件中说明
-- 在修改和有源代码衍生的代码中,需要带有原来代码中的协议,商标
-- 在二次开发后商业发布的产品中,使用了多个开源软件,则必须包含一个Notice文件,在Notice文件中需要带有Apache
-  LICENSE。你可以在Notice中增加自己的许可,但不可以表现为对Apache
-  LICENSE构成更改。
-
-## 技术支持
-
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
-
-个人微信:个人微信,不闲聊,加群、咨询请备注,备注格式不限但最好是:“项目名 + 问题” ,项目名可以是**AJ-Report**、**Report**、**大屏
-**,只要能一眼分辨就行 <br>
-例1:大屏 加群 <br>
-例2:report 有个问题xxxx <br>
-有问题,不管是技术问题还是使用问题,都尽量在群里问。加个人微信记得**一定要加备注 !!!**<br>
-
-<img src="https://foruda.gitee.com/images/1724817510954363329/305a6044_7492051.jpeg" width = "300" height = "450" align=left/>
-
-## 更多支持
-
-联系方式 <br>
-
-<img src="https://foruda.gitee.com/images/1681893479845506596/859934b5_1950629.png" width = "300" height = "300" align=left/>
-
-## 加入我们
-
-- 提交PR是最快的加入方式:<br>
-  · PR可以包含新功能、现有功能的改进。<br>
-  . PR请提交到dev分支 <br>
-- 提供文档原文或者文档链接:<br>
-  . 文档原文的话,请放在doc/docs/guide/community目录下,也可直接提交pr <br>
-  . 文档链接的话,文档需要完全的公开,不掺杂收费等相关内容,审核通过会放在首页 <br>
-- 提供大屏模板:<br>
-  . 可将自己设计好的大屏进行导出(不包含数据集),将导出产生的压缩包提供给我们 <br>
-  . 提供的大屏将会在AJ-Report在线演示环境进行展示和供其他人下载 <br>
-
-#### 开源不易,劳烦各位star ☺
-
-## 感谢JetBrains 的支持
-
-#### JetBrains:[https://www.jetbrains.com/?from=AJ-Report](https://www.jetbrains.com/?from=AJ-Report"链接")
-
-<br>
-
-## Stargazers over time
-
-[![Stargazers over time](https://starchart.cc/anji-plus/report.svg)](https://starchart.cc/anji-plus/report)
+# 本地址已停止维护了

+ 2 - 2
doc/docs/guide/quicklyDistribution.md

@@ -30,9 +30,9 @@
 
 ```yaml
   datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
+    url: jdbc:mysql://127.0.0.1:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
     username: root
-    password: appuser@anji
+    password: xxxxxxxx
 ```
 
 ## flyway

+ 2 - 2
doc/docs/guide/quicklySeparate.md

@@ -56,9 +56,9 @@ report-core --> src --> main --> resources --> bootstrap.yml <br>
 
 ```yaml
   datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
+    url: jdbc:mysql://127.0.0.1:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
     username: root
-    password: appuser@anji
+    password: xxxxxxxx
 ```
 
 ## flyway

+ 2 - 2
doc/docs/guide/quicklySource.md

@@ -62,9 +62,9 @@ git clone https://gitee.com/anji-plus/report.git <br>
 
 ```yaml
   datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
+    url: jdbc:mysql://127.0.0.1:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
     username: root
-    password: appuser@anji
+    password: xxxxxxxx
 ```
 
 ## flyway

+ 2 - 2
report-core/src/main/resources/bootstrap.yml → report-core/src/main/resources/application.yml

@@ -32,9 +32,9 @@ spring:
   messages:
     basename: i18n/messages
   datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
+    url: jdbc:mysql://127.0.0.1:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
     username: root
-    password: appuser@anji
+    password: xxxxxx
     driver-class-name: com.mysql.cj.jdbc.Driver
     type: com.alibaba.druid.pool.DruidDataSource
   #数据源连接池配置

+ 0 - 17
report-core/src/main/resources/bootstrap-dev.yml

@@ -1,17 +0,0 @@
-# 该文件配置会继承bootstrap.xml,只需要配置数据库等差异配置
-spring:
-  datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
-    username: root
-    password: appuser@anji
-    type: com.alibaba.druid.pool.DruidDataSource
-  gaea:
-    subscribes:
-      oss: #文件存储
-        enabled: true
-        ##允许上传的文件后缀
-        file-type-white-list: .png|.jpg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi|.jpeg|.aaa|.svg
-        # 用于文件上传成功后,生成文件的下载公网完整URL
-        downloadPath: http://127.0.0.1:9095/file/download
-        nfs:
-          path: D:\\aaa\\

+ 0 - 6
report-core/src/main/resources/bootstrap-prod.yml

@@ -1,6 +0,0 @@
-# 该文件配置会继承bootstrap.xml,只需要配置数据库等差异配置
-spring:
-  datasource:
-    url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
-    username: root
-    password: appuser@anji

+ 5 - 0
report-core/src/main/resources/db/migration/V1.7.0__update.sql

@@ -0,0 +1,5 @@
+-- 增加日历解析属性
+INSERT INTO `gaea_dict`(`dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES ('日历属性', 'CALENDAR_PROPERTIES', '日历属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1);
+
+INSERT INTO `gaea_dict_item`(`dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES ('CALENDAR_PROPERTIES', '日期', 'date', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:31:51', 'admin', '2021-08-20 10:31:51', 1);
+INSERT INTO `gaea_dict_item`(`dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES ('CALENDAR_PROPERTIES', '数据', 'data', NULL, 1, 'zh', NULL, 6, 'admin', '2021-08-20 10:32:52', 'admin', '2021-08-20 10:32:52', 1);

+ 18 - 0
report-ui/src/mixins/queryform.js

@@ -173,6 +173,8 @@ export default {
         return this.piechartFn(params.chartProperties, data);
       } else if (chartType == "widget-text") {
         return this.widgettext(params.chartProperties, data)
+      } else if (chartType == "widget-calendar") {
+        return this.widgetcalendar(params.chartProperties, data)
       } else if (chartType == "widget-stackchart") {
         return this.stackChartFn(params.chartProperties, data)
       } else if (chartType == "widget-coord") {
@@ -285,6 +287,22 @@ export default {
       }
       return analysisData;
     },
+    widgetcalendar (chartProperties, data) {
+      const analysisData = [];
+      for (let i = 0; i < data.length; i++) {
+        const obj = {};
+        for (const key in chartProperties) {
+          const value = chartProperties[key];
+          if (value === "date") {
+            obj["date"] = data[i][key];
+          } else {
+            obj["data"] = data[i][key];
+          }
+        }
+        analysisData.push(obj);
+      }
+      return analysisData;
+    },
     // 坐标系数据解析
     coordChartFn(chartProperties, data) {
       const analysisData = {};

+ 223 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/texts/widget-calendar.js

@@ -0,0 +1,223 @@
+/*
+ * @Descripttion: 日历组件json
+ * @version:
+ * @Author: lishuaiwu
+ * @Date: 2025-06-05 13:44:32
+ */
+export const widgetCalendar = {
+  code: 'widget-calendar',
+  type: 'text',
+  tabName: '文本栏',
+  label: '日历',
+  icon: 'iconbiaoge',
+  options: {
+    // 配置
+    setup: [
+      {
+        type: 'el-input-text',
+        label: '图层名称',
+        name: 'layerName',
+        required: false,
+        placeholder: '',
+        value: '日历',
+      },
+      [
+        {
+          name: '日历样式',
+          list: [
+            {
+              type: 'vue-color',
+              label: '边框线颜色',
+              name: 'borderColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(221, 221, 221)'
+            },
+            {
+              type: 'vue-color',
+              label: '头部背景颜色',
+              name: 'headerBackground',
+              required: false,
+              placeholder: '',
+              value: 'rgb(10, 115, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '头部文字颜色',
+              name: 'headerTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(255, 255, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '头部按钮颜色',
+              name: 'headerBtnBackground',
+              required: false,
+              placeholder: '',
+              value: 'rgb(10, 115, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '头部按钮文字',
+              name: 'headerBtnTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(255, 255, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '星期背景色',
+              name: 'weekBackground',
+              required: false,
+              placeholder: '',
+              value: 'rgb(10, 39, 50)'
+            },
+            {
+              type: 'vue-color',
+              label: '星期文字颜色',
+              name: 'weekTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(255, 255, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '日期背景色',
+              name: 'dayBackground',
+              required: false,
+              placeholder: '',
+              value: 'rgb(0, 59, 81)'
+            },
+            {
+              type: 'vue-color',
+              label: '日期文字颜色',
+              name: 'dayTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(255, 255, 255)'
+            },
+            {
+              type: 'vue-color',
+              label: '当日背景色',
+              name: 'todayBackground',
+              required: false,
+              placeholder: '',
+              value: 'rgba(0, 59, 81, .5)'
+            },
+            {
+              type: 'vue-color',
+              label: '当日文字颜色',
+              name: 'todayTextColor',
+              required: false,
+              placeholder: '',
+              value: 'rgb(0, 0, 0)'
+            },
+            {
+              type: 'el-switch',
+              label: '按钮显隐',
+              name: 'isButton',
+              required: false,
+              placeholder: '',
+              value: true,
+            },
+          ]
+        }
+      ]
+    ],
+    data: [
+      {
+        type: 'el-radio-group',
+        label: '数据类型',
+        name: 'dataType',
+        require: false,
+        placeholder: '',
+        selectValue: true,
+        selectOptions: [
+          {
+            code: 'staticData',
+            name: '静态数据',
+          },
+          {
+            code: 'dynamicData',
+            name: '动态数据',
+          },
+        ],
+        value: 'staticData',
+      },
+      {
+        type: 'el-input-number',
+        label: '刷新时间(毫秒)',
+        name: 'refreshTime',
+        relactiveDom: 'dataType',
+        relactiveDomValue: 'dynamicData',
+        value: 600000
+      },
+      {
+        type: 'el-button',
+        label: '静态数据',
+        name: 'staticData',
+        required: false,
+        placeholder: '',
+        relactiveDom: 'dataType',
+        relactiveDomValue: 'staticData',
+        value: [
+          {
+            "date": "2025-06-01",
+            "data": '2单'
+          },
+          {
+            "date": "2025-06-02",
+            "data": '10单'
+          }
+        ],
+      },
+      {
+        type: 'dycustComponents',
+        label: '',
+        name: 'dynamicData',
+        required: false,
+        placeholder: '',
+        relactiveDom: 'dataType',
+        relactiveDomValue: 'dynamicData',
+        chartType: 'widget-calendar',
+        dictKey: 'CALENDAR_PROPERTIES',
+        value: '',
+      }
+    ],
+    position: [
+      {
+        type: 'el-input-number',
+        label: '左边距',
+        name: 'left',
+        required: false,
+        placeholder: '',
+        value: 0,
+      },
+      {
+        type: 'el-input-number',
+        label: '上边距',
+        name: 'top',
+        required: false,
+        placeholder: '',
+        value: 0,
+      },
+      {
+        type: 'el-input-number',
+        label: '宽度',
+        name: 'width',
+        required: false,
+        placeholder: '该容器在1920px大屏中的宽度',
+        value: 600,
+      },
+      {
+        type: 'el-input-number',
+        label: '高度',
+        name: 'height',
+        required: false,
+        placeholder: '该容器在1080px大屏中的高度',
+        value: 400,
+      },
+    ]
+  }
+}

+ 44 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/configure/texts/widget-text.js

@@ -98,6 +98,50 @@ export const widgetText = {
         ],
         value: 'center'
       },
+      {
+        type: 'el-input-number',
+        label: '行高',
+        name: 'lineHeight',
+        required: false,
+        placeholder: '',
+        value: '0',
+      },
+      {
+        type: 'el-input-number',
+        label: '边框宽度',
+        name: 'borderWidth',
+        required: false,
+        placeholder: '',
+        value: '0',
+      },
+      {
+        type: 'vue-color',
+        label: '边框颜色',
+        name: 'borderColor',
+        required: false,
+        placeholder: '',
+        value: 'rgba(255,255,255,0)',
+      },
+      {
+        type: 'el-select',
+        label: '边框类型',
+        name: 'borderStyle',
+        required: false,
+        placeholder: '',
+        selectOptions: [
+          { code: 'solid', name: '实线' },
+          { code: 'dashed', name: '虚线' },
+        ],
+        value: 'solid',
+      },
+      {
+        type: 'el-input-number',
+        label: '边框圆角',
+        name: 'borderRadius',
+        required: false,
+        placeholder: '',
+        value: '0',
+      },
       {
         type: 'el-switch',
         label: '识别换行符',

+ 2 - 0
report-ui/src/views/bigscreenDesigner/designer/tools/main.js

@@ -17,6 +17,7 @@ import {widgetSliders} from "./configure/texts/widget-slider"
 import {widgetVideo} from "./configure/texts/widget-video"
 import {widgetTable} from "./configure/texts/widget-table"
 import {widgetIframe} from "./configure/texts/widget-iframe"
+import {widgetCalendar} from "./configure/texts/widget-calendar"
 import {widgetUniversal} from "./configure/widget-universal"
 import {widgetBarchart} from "./configure/barCharts/widget-barchart"
 import {widgetGradientBarchart} from "./configure/barCharts/widget-gradient-barchart"
@@ -70,6 +71,7 @@ export const widgetTool = [
   widgetVideo,
   widgetTable,
   widgetIframe,
+  widgetCalendar,
   //  widgetUniversal,
   widgetBarchart,
   widgetGradientBarchart,

+ 2 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue

@@ -19,6 +19,7 @@ import widgetImage from "./texts/widgetImage.vue";
 import widgetSlider from "./texts/widgetSlider.vue";
 import widgetVideo from "./texts/widgetVideo.vue";
 import WidgetIframe from "./texts/widgetIframe.vue";
+import widgetCalendar from "./texts/widgetCalendar.vue";
 import widgetBarchart from "./bar/widgetBarchart.vue";
 import widgetLinechart from "./line/widgetLinechart.vue";
 import widgetBarlinechart from "./barline/widgetBarlinechart";
@@ -72,6 +73,7 @@ export default {
     widgetSlider,
     widgetVideo,
     WidgetIframe,
+    widgetCalendar,
     widgetBarchart,
     widgetGradientColorBarchart,
     widgetLinechart,

+ 371 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetCalendar.vue

@@ -0,0 +1,371 @@
+<template>
+  <div class="calendar-container full-box" :style="styleObj">
+    <div class="calendar-header" :style="headerStyle">
+      <button class="nav-button" :style="headerBtnStyle" @click="prevMonth" v-if="showButton">&lt;</button>
+      <div class="current-month-title">{{ currentMonthTitle }}</div>
+      <button class="nav-button" :style="headerBtnStyle" @click="nextMonth" v-if="showButton">&gt;</button>
+    </div>
+    
+    <div class="calendar-month">
+      <div class="weekdays" :style="weekStyle">
+        <div class="weekday" v-for="day in weekdays" :key="day">{{ day }}</div>
+      </div>
+      <div class="days-grid" :style="dayStyle">
+        <div 
+          class="day-cell"
+          v-for="day in currentMonthDays"
+          :key="day.date"
+          :class="{
+            'out-of-range': day.isOutOfRange,
+            'current-month': day.isCurrentMonth,
+            'today': day.isToday
+          }"
+          :style="cellStyle(day.isToday)"
+        >
+          <slot name="day" :day="day">
+            <div class="day-number">{{ day.day }}</div>
+            <div class="day-content" v-html="text[day.date] || ''"></div>
+          </slot>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { targetWidgetLinkageLogic } from "@/views/bigscreenDesigner/designer/linkageLogic";
+
+export default {
+  name: 'widgetCalendar',
+  props: {
+    value: Object,
+    ispreview: Boolean,
+  },
+  data() {
+    return {
+      weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+      currentMonth: moment().startOf('month'),
+      startDate: moment().format('YYYY-MM-DD'),
+      endDate: moment().format('YYYY-MM-DD'),
+      options: {},
+      optionsSetUp: {},
+      optionsPosition: {},
+      optionsData: {},
+
+      text: ''
+    }
+  },
+  computed: {
+    momentStartDate() {
+      return moment(this.startDate, 'YYYY-MM-DD').startOf('day')
+    },
+    momentEndDate() {
+      return moment(this.endDate, 'YYYY-MM-DD').endOf('day')
+    },
+    showButton () {
+      return this.optionsSetUp.isButton;
+    },
+    styleObj() {
+      const allStyle = this.optionsPosition;
+      return {
+        position: this.ispreview ? "absolute" : "static",
+        width: allStyle.width + "px",
+        height: allStyle.height + "px",
+        left: allStyle.left + "px",
+        top: allStyle.top + "px",
+        background: this.optionsSetUp.tableBgColor,
+        borderColor: this.optionsSetUp.borderColor
+      };
+    },
+    headerStyle () {
+      return {
+        background: this.optionsSetUp.headerBackground,
+        color: this.optionsSetUp.headerTextColor,
+        justifyContent: this.optionsSetUp.isButton ? 'space-between' : 'center'
+
+      };
+    },
+    headerBtnStyle () {
+      return {
+        background: this.optionsSetUp.headerBtnBackground,
+        color: this.optionsSetUp.headerBtnTextColor
+      };
+    },
+    weekStyle () {
+      return {
+        background: this.optionsSetUp.weekBackground,
+        color: this.optionsSetUp.weekTextColor
+      };
+    },
+    dayStyle () {
+      return {
+        backgroundColor: this.optionsSetUp.borderColor
+      }
+    },
+    currentMonthTitle() {
+      return `${this.currentMonth.year()}年${this.currentMonth.month() + 1}月`
+    },
+    currentMonthDays() {
+      const daysInMonth = this.currentMonth.daysInMonth()
+      const firstDayOfMonth = moment(this.currentMonth).startOf('month')
+      const startingDayOfWeek = firstDayOfMonth.day()
+      
+      const days = []
+      
+      // 添加上个月的日期
+      const daysFromPrevMonth = startingDayOfWeek
+      const prevMonth = moment(this.currentMonth).subtract(1, 'month')
+      for (let i = 0; i < daysFromPrevMonth; i++) {
+        const day = prevMonth.daysInMonth() - daysFromPrevMonth + i + 1
+        const date = moment(prevMonth).date(day)
+        days.push(this.createDayObject(date, false))
+      }
+      
+      // 添加当前月的日期
+      for (let day = 1; day <= daysInMonth; day++) {
+        const date = moment(this.currentMonth).date(day)
+        days.push(this.createDayObject(date, true))
+      }
+      
+      // 添加下个月的日期
+      const totalCells = daysFromPrevMonth + daysInMonth
+      const remainingCells = totalCells % 7 === 0 ? 0 : 7 - (totalCells % 7)
+      const nextMonth = moment(this.currentMonth).add(1, 'month')
+      for (let i = 1; i <= remainingCells; i++) {
+        const date = moment(nextMonth).date(i)
+        days.push(this.createDayObject(date, false))
+      }
+      
+      return days
+    }
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.options = val;
+        this.optionsSetUp = val.setup;
+        this.optionsPosition = val.position;
+        this.optionsData = val.data;
+        this.setOptionsData();
+      },
+      deep: true
+    }
+  },
+  mounted() {
+    this.options = this.value;
+    this.optionsSetUp = this.value.setup;
+    this.optionsPosition = this.value.position;
+    this.optionsData = this.value.data;
+    targetWidgetLinkageLogic(this);
+    this.setOptionsData();
+  },
+  methods: {
+    // 数据解析
+    setOptionsData(e, paramsConfig) {
+      const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      // 联动接收者逻辑开始
+      optionsData.dynamicData = optionsData.dynamicData || {}; // 兼容 dynamicData undefined
+      const myDynamicData = optionsData.dynamicData;
+      clearInterval(this.flagInter); // 不管咋,先干掉上一次的定时任务,避免多跑
+      if (
+        e &&
+        optionsData.dataType !== "staticData" &&
+        Object.keys(myDynamicData.contextData).length
+      ) {
+        const keyArr = Object.keys(myDynamicData.contextData);
+        paramsConfig.forEach((conf) => {
+          if (keyArr.includes(conf.targetKey)) {
+            myDynamicData.contextData[conf.targetKey] = e[conf.originKey];
+          }
+        });
+      }
+      // 联动接收者逻辑结束
+      if (optionsData.dataType === "dynamicData") {
+        this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
+      } else {
+        const data = this.objToOne(this.options).staticData
+        let obj = {}
+        data.forEach(e => {
+          obj[e.date] = e.data
+        });
+        this.text = obj
+      };
+    },
+    dynamicDataFn(val, refreshTime) {
+      if (!val) return;
+      if (this.ispreview) {
+        this.getEchartData(val);
+        this.flagInter = setInterval(() => {
+          this.getEchartData(val);
+        }, refreshTime);
+      } else {
+        this.getEchartData(val);
+      }
+    },
+    getEchartData(val) {
+      const data = this.queryEchartsData(val);
+      data.then(res => {
+        let obj = {}
+        res.forEach(e => {
+          obj[e.date] = e.data
+        });
+        this.text = obj
+        this.$forceUpdate();
+      });
+    },
+    cellStyle (isToday) {
+      return {
+        backgroundColor: isToday ? this.optionsSetUp.todayBackground : this.optionsSetUp.dayBackground,
+        color: isToday ? this.optionsSetUp.todayTextColor : this.optionsSetUp.dayTextColor,
+      }
+    },
+    prevMonth() {
+      this.currentMonth = moment(this.currentMonth).subtract(1, 'month')
+    },
+    nextMonth() {
+      this.currentMonth = moment(this.currentMonth).add(1, 'month')
+    },
+    createDayObject(date, isCurrentMonth) {
+      const isToday = date.isSame(moment(), 'day')
+      const isBeforeRange = date.isBefore(this.momentStartDate, 'day')
+      const isAfterRange = date.isAfter(this.momentEndDate, 'day')
+      const isDisabled = isBeforeRange || isAfterRange
+      
+      return {
+        date: date.format('YYYY-MM-DD'),
+        year: date.year(),
+        month: date.month(), // 0-11
+        day: date.date(),   // 1-31
+        weekday: date.day(), // 0-6 (0是周日)
+        isCurrentMonth,
+        isOutOfRange: !isCurrentMonth,
+        isToday,
+        isBeforeRange,
+        isAfterRange,
+        isDisabled,
+        fullDate: date.toDate()
+      }
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.calendar-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  border: 1px solid #ddd;
+}
+
+.full-box {
+  height: 100%;
+  .calendar-month {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    .days-grid {
+      flex: 1;
+    }
+  }
+}
+
+.calendar-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px;
+  background-color: rgb(10, 115, 255);
+  color: #ffffff;
+}
+
+.current-month-title {
+  font-size: 18px;
+  font-weight: bold;
+}
+
+.nav-button {
+  background: none;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  padding: 5px 10px;
+  cursor: pointer;
+  font-size: 16px;
+  color: #ffffff;
+  
+  &:hover {
+    opacity: .5;
+  }
+}
+
+.weekdays {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+  background-color: rgb(10, 39, 50);
+  color: #ffffff;
+}
+
+.weekday {
+  text-align: center;
+  padding: 8px 0;
+  font-weight: bold;
+}
+
+.days-grid {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+  grid-gap: 1px;
+  background-color: rgb(221, 221, 221);
+  flex: 1;
+}
+
+.day-cell {
+  min-height: 60px;
+  background-color: rgb(0, 59, 81);
+  padding: 5px;
+  position: relative;
+  width: calc(100% - 0px);
+  display: flex;
+  flex-direction: column;
+}
+
+/* 当前月份的日期 */
+.day-cell.current-month {
+  background-color: rgb(0, 59, 81);
+  color: #ffffff;
+}
+
+/* 非当前月份的日期 */
+.day-cell:not(.current-month) {
+ background-color: rgba(0, 59, 81, .5);
+  color: #ffffff;
+}
+
+/* 今天日期 */
+.day-cell.today {
+  background-color: #e6f7ff;
+  color: #000;
+}
+
+/* 日期范围外的单元格 */
+.day-cell.disabled-day {
+  background-color: #e0e0e0;
+  color: #999;
+  cursor: not-allowed;
+}
+
+.day-number {
+  font-weight: bold;
+  width: 30px;
+}
+.day-content {
+  text-align: left;
+  padding: 0 10px;
+  flex: 1;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+</style>

+ 6 - 1
report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetText.vue

@@ -46,7 +46,12 @@ export default {
         left: this.transStyle.left + "px",
         top: this.transStyle.top + "px",
         right: this.transStyle.right + "px",
-        whiteSpace: this.transStyle.whiteSpace ? "pre-line": "normal"
+        whiteSpace: this.transStyle.whiteSpace ? "pre-line": "normal",
+        lineHeight:  this.transStyle.lineHeight + "px",
+        borderColor: this.transStyle.borderColor,
+        borderWidth: this.transStyle.borderWidth + "px",
+        borderStyle: this.transStyle.borderStyle,
+        borderRadius: this.transStyle.borderRadius + "px",
       };
     },
     computedStyleColor() {

+ 2 - 0
report-ui/src/views/bigscreenDesigner/designer/widget/widget.vue

@@ -26,6 +26,7 @@ import widgetImage from "./texts/widgetImage.vue";
 import widgetSlider from "./texts/widgetSlider.vue";
 import widgetVideo from "./texts/widgetVideo.vue";
 import WidgetIframe from "./texts/widgetIframe.vue";
+import widgetCalendar from "./texts/widgetCalendar.vue";
 import widgetBarchart from "./bar/widgetBarchart.vue";
 import widgetScatter from "./scatter/widgetScatter.vue";
 import widgetGradientColorBarchart from "./bar/widgetGradientColorBarchart.vue";
@@ -79,6 +80,7 @@ export default {
     widgetSlider,
     widgetVideo,
     WidgetIframe,
+    widgetCalendar,
     widgetBarchart,
     widgetGradientColorBarchart,
     widgetLinechart,