Compare commits

...

242 Commits

Author SHA1 Message Date
kuaifan
5eb2124b06 build 2024-06-03 14:07:14 +08:00
kuaifan
20d8180347 Merge commit '008040d96c73051fca6db388b35077a0ca7b5b5b' into pro 2024-06-03 14:00:10 +08:00
kuaifan
49203c15a7 perf: 优化视频播放 2024-06-03 11:32:12 +08:00
weifs
008040d96c fix: 如果项目没有流程,无法选择移动后的状态,也没办法确定移动 2024-06-03 11:13:01 +08:00
kuaifan
1a36044de2 no message 2024-06-02 10:56:18 +08:00
kuaifan
4886edc684 perf: 新增通讯录菜单 2024-06-02 10:52:59 +08:00
kuaifan
617fe902a4 perf: 优化快捷创建群组 2024-06-02 10:41:33 +08:00
kuaifan
78ad3468ae build 2024-06-01 17:34:55 +08:00
kuaifan
b58de926b2 no message 2024-06-01 17:24:07 +08:00
kuaifan
7c4c7eea9c perf: 优化回复消息自动@逻辑 2024-06-01 14:43:59 +08:00
kuaifan
eb7d93af87 perf: 甘特图兼容移动端 2024-06-01 10:19:35 +08:00
kuaifan
956b68a545 no message 2024-06-01 08:35:42 +08:00
kuaifan
79065a7675 build 2024-05-31 20:14:06 +08:00
kuaifan
d3514a0334 no message 2024-05-31 18:14:51 +08:00
kuaifan
bb163605af perf: 团队管理选择离职时根据离职时间排序 2024-05-31 13:44:51 +08:00
kuaifan
afcbd6af92 perf: 移动端支持快速编辑描述选择 2024-05-31 13:24:43 +08:00
kuaifan
13edea3449 perf: 优化离职数据移交 2024-05-31 12:38:37 +08:00
kuaifan
6cdcd4e0dc no message 2024-05-30 23:10:02 +08:00
kuaifan
efce884494 perf: 优化举报功能 2024-05-30 22:56:51 +08:00
kuaifan
dcffeded9a fix: 更新可见性后仍存在对话会话列表 2024-05-30 22:10:52 +08:00
kuaifan
e24b6806da perf: 优化网络重连后会话数据逻辑 2024-05-30 19:02:58 +08:00
kuaifan
bc7874a3a0 perf: 优化甘特图移动端交互 2024-05-30 18:27:54 +08:00
kuaifan
d348871b0c perf: 优化md编辑器 2024-05-30 14:50:13 +08:00
kuaifan
f9ee740a8c Merge commit '58ca285edf93b744a6eb358610b73f7e385aa5cf' into pro 2024-05-29 16:02:24 +08:00
kuaifan
c0a90ae89d fix: 消息输入框回复冲突 2024-05-21 15:13:25 +08:00
weifs
58ca285edf feat: 更新approve容器 2024-05-21 11:58:46 +08:00
weifs
325f8c0f7e Merge branch 'kuaifan-pro' into pro 2024-05-21 11:24:52 +08:00
zzw
829fe7e4ba fix:调整智谱清言描述信息 2024-05-15 14:54:54 +08:00
zzw
a6a18a0ee4 feat:添加智谱清言机器人 2024-05-15 14:22:17 +08:00
kuaifan
eda9eb08d5 no message 2024-05-12 13:16:39 +09:00
kuaifan
4625ae7548 build 2024-05-12 00:18:34 +09:00
kuaifan
186d3b0d79 perf: 优化查看任务附件菜单 2024-05-11 23:50:28 +09:00
kuaifan
7bf5805714 perf: 独立窗口未激活阅读逻辑 2024-05-11 23:09:33 +09:00
kuaifan
19604c46f0 no message 2024-05-11 22:49:47 +09:00
kuaifan
a77a32d64e perf: 新消息在会话列表时间与消息里不一致 2024-05-11 22:13:37 +09:00
kuaifan
53145f0ca2 no message 2024-05-11 12:35:52 +09:00
kuaifan
6880baa6a4 perf: 优化Android点击发送按钮效果 2024-05-11 12:34:27 +09:00
kuaifan
2bda6bf668 perf: 支持修改消息待办 2024-05-11 10:53:32 +09:00
kuaifan
80fe978454 no message 2024-05-11 09:13:26 +09:00
kuaifan
94a30ea940 perf: 延期任务时间支持按天 2024-05-11 00:40:59 +09:00
kuaifan
f9d1aa93c4 perf: 优化待办消息样式 2024-05-10 23:52:41 +09:00
kuaifan
d3bda0d869 perf: 优化移动端子任务列表显示 2024-05-10 23:26:12 +09:00
kuaifan
426fa63288 perf: 语音消息转文字 2024-05-10 22:23:45 +09:00
kuaifan
bf46a00937 perf: 更新语音消息插件 2024-05-10 11:53:14 +09:00
kuaifan
0fce0c2386 perf: 优化设置样式 2024-05-09 16:08:44 +09:00
kuaifan
77843ccdee build 2024-05-02 00:55:18 +08:00
kuaifan
b86edcfa96 build 2024-05-01 23:22:56 +08:00
kuaifan
5fb242024a Merge commit 'd7d8ee481e720624225511e102773d1f2fc68e41' into pro 2024-05-01 15:55:13 +08:00
kuaifan
abbfbb85e6 no message 2024-05-01 15:20:15 +08:00
kuaifan
37407cdbac perf: 优化转发消息数据显示 2024-05-01 15:17:58 +08:00
kuaifan
f1f96bda4e build 2024-05-01 14:18:57 +08:00
kuaifan
6f38c4efdd feat: 语音消息未阅读红点提示 2024-05-01 12:02:12 +08:00
kuaifan
e325698899 perf: ipad 发送消息后出现页面跳动的情况 2024-05-01 10:52:52 +08:00
kuaifan
ed36d622ec perf: 仪表盘隐藏未到开始时间的任务 2024-04-30 16:46:04 +08:00
kuaifan
dabe1376c3 perf: 优化查看任务修改历史 2024-04-30 16:39:45 +08:00
kuaifan
199fd4462e perf: 优化聊天工具栏样式 2024-04-30 14:50:57 +08:00
kuaifan
85a7776159 perf: 优化更新聊天中的待办 2024-04-30 13:37:47 +08:00
weifs
d7d8ee481e feat: 修复移动任务中选完成进行移动没有设置完成时间的bug 2024-04-29 20:59:24 +08:00
Pang
875da9fbe5 perf: 优化图标功能提示 2024-04-28 23:02:40 +08:00
spylecym
2bd8199d88 fix: 修复官网帮助中心英文页面头部导航缺失问题 2024-04-28 18:19:21 +08:00
spylecym
ca490f3e96 feat: 新增右侧底部导航 2024-04-28 18:14:35 +08:00
Pang
b81f2f0675 fix: 安装系统部分情况没有数据 2024-04-26 19:46:27 +08:00
weifs
aef23dda13 fix: 修复举报样式错乱 2024-04-26 09:59:18 +08:00
weifs
693fa46688 perf: 审批和任务通知优化 2024-04-25 11:24:30 +08:00
weifs
30676fb761 feat: 添加举报功能 2024-04-24 19:22:36 +08:00
weifs
ac6bdc07ec perf: 优化按钮没有对应类型,控制台报错 2024-04-24 11:34:31 +08:00
kuaifan
f6afdd6604 build 2024-04-23 16:28:14 +08:00
kuaifan
856037c3c9 fix: 任务描述保存图片失败 2024-04-23 16:21:01 +08:00
kuaifan
3203da411d 优化android自动编译 2024-04-23 15:57:44 +08:00
kuaifan
a6708a26a6 perf: 转发消息至群聊时支持@留言 2024-04-23 11:04:43 +08:00
kuaifan
053daa621b perf: 自动发布Android 2024-04-22 18:30:08 +08:00
Pang
a16f5fca07 build 2024-04-22 10:23:43 +08:00
Pang
cfdb6e2a93 fix: 上一版本导致的无法@ 2024-04-22 10:16:37 +08:00
Pang
73261da19b perf: 优化代码 2024-04-22 10:00:26 +08:00
Pang
71f48a4f7c perf: 优化查看文件历史 2024-04-22 09:39:19 +08:00
Pang
dbdb805269 perf: 支持查看任务描述修改历史 2024-04-22 09:38:39 +08:00
Pang
bd61b8c948 perf: 任务描述支持清单 2024-04-22 05:05:07 +08:00
kuaifan
5e6a21ddc5 docs 2024-04-20 21:04:08 +08:00
kuaifan
ccc8170ec7 build 2024-04-20 21:02:10 +08:00
kuaifan
d4bfbb81d8 fix: 修复关闭侧边回复窗口导致会话不正常的情况 2024-04-20 19:38:18 +08:00
kuaifan
a46ffa1089 perf: 消息内容支持待办列表 2024-04-20 19:13:38 +08:00
kuaifan
182e5a6974 perf: 优化自动识别发送消息类型 2024-04-20 16:04:51 +08:00
kuaifan
8ca021df6a perf: 聊天输入框粘贴格式优化 2024-04-20 16:04:22 +08:00
kuaifan
106c011f6b perf: 优化网络错误提示 2024-04-19 15:39:04 +08:00
kuaifan
76664c61c4 build 2024-04-18 12:21:32 +08:00
kuaifan
24839f960f fix: 解决 Unable to preventDefault inside passive event listener 报错 2024-04-18 12:16:42 +08:00
kuaifan
ce7d3f8475 fix: 截图粘贴出现两张图的情况 2024-04-18 12:15:50 +08:00
kuaifan
5e8a6af74c fix: 聊天输入中文过程跟placeholder内容叠加的问题 2024-04-18 12:15:23 +08:00
kuaifan
23a363aeea build 2024-04-17 23:59:29 +08:00
kuaifan
6cbf2bbada perf: 下载pdf使用自带浏览器 2024-04-17 10:21:35 +08:00
kuaifan
ee9cf0a6b6 perf: 优化消息加载中效果 2024-04-17 09:32:53 +08:00
Pang
8d39b4aa0d perf: 审批内容禁止转发 2024-04-17 08:10:08 +08:00
Pang
3c93ad18b2 perf: 滑动快捷表情选择 2024-04-17 07:46:43 +08:00
kuaifan
cc125cc292 perf: 优化聊天输入框 2024-04-17 00:34:12 +08:00
kuaifan
6823d87198 build 2024-04-11 11:52:36 +08:00
kuaifan
288e857321 perf: update chat editor 2024-04-11 11:51:10 +08:00
kuaifan
73d1950d97 fix: added non-passive event listener to a scroll-blocking 'touchstart' event 2024-04-11 11:50:07 +08:00
kuaifan
ee2b047e5d no message 2024-04-11 10:16:00 +08:00
kuaifan
ae83fce524 perf: 优化机器人回复 2024-04-11 10:12:50 +08:00
kuaifan
985c5ff54b perf: 优化android体验 2024-04-11 08:48:55 +08:00
Pang
fe5f56e98b build 2024-04-09 23:35:22 +08:00
Pang
40ef700e5a perf: 优化使用默认浏览器打开规则 2024-04-09 20:46:56 +08:00
Pang
8661c28d10 build 2024-04-09 19:34:19 +08:00
Pang
9edddc461d perf: 优化聊天图片上传 2024-04-09 09:05:36 +08:00
kuaifan
2fbb640bc8 build 2024-04-08 17:00:39 +08:00
kuaifan
a03050bc7b perf: 临时帐号别名 2024-04-08 16:53:24 +08:00
kuaifan
654a90626e perf: tab icon load error 2024-04-08 14:06:45 +08:00
Pang
9acafed459 perf: 优化会议 2024-04-08 09:37:46 +08:00
Pang
b7dcb543f6 perf: 创建会议不需要加入机器人 2024-04-08 08:58:16 +08:00
Pang
e2768f7f20 perf: 暗黑模式下窗口背景色兼容问题 2024-04-08 08:31:51 +08:00
Pang
cda2d0da27 perf: 优化网络检查 2024-04-08 08:13:30 +08:00
Pang
c61815db3a perf: 客户端会议优化 2024-04-08 07:51:57 +08:00
Pang
9390965a0c no message 2024-04-06 11:58:45 +08:00
Pang
0688feefb1 build 2024-04-04 10:33:51 +08:00
Pang
93c8d86caf perf: 优化会议室 2024-04-04 10:31:12 +08:00
Pang
540bff89cf no message 2024-04-04 08:42:41 +08:00
Pang
41c09b3838 perf: 优化会议室 2024-04-04 07:40:57 +08:00
Pang
0a26361724 no message 2024-04-04 07:40:38 +08:00
kuaifan
ee9ad65e18 build 2024-04-03 10:32:00 +08:00
kuaifan
db6b571cfb fix: 部分情况出现注册失败 2024-04-03 10:14:41 +08:00
Pang
bfe359c440 perf: 优化数据读取机制 2024-04-03 07:53:44 +08:00
Pang
ee8f67793a fix: 最小化阅读窗口新建窗口不自动激活 2024-04-03 07:13:35 +08:00
Pang
629fe79c61 fix: 独立窗口不更新消息 2024-04-03 07:13:35 +08:00
Pang
9ae278d622 perf: 优化缓存规则 2024-04-03 07:13:35 +08:00
Pang
3417d68609 perf: 优化完成待办数据推送 2024-04-03 07:13:35 +08:00
weifs
f757749282 perf: 评论审批图片和投票深色按钮 2024-03-26 17:43:08 +08:00
kuaifan
ea40e95cae build 2024-03-26 14:19:02 +08:00
kuaifan
eb066f52fe perf: 优化任务日志内容 2024-03-26 13:52:24 +08:00
kuaifan
b7007135cb perf: 查看版本免请求接口 2024-03-26 13:28:00 +08:00
kuaifan
a7bd403b2c perf: 添加任务时选择任务位置内容溢出 2024-03-26 13:22:25 +08:00
Pang
59c7b148dd perf: 消息支持style 2024-03-26 10:17:49 +08:00
Pang
c67f52e960 perf: 回复消息列表隐藏顶部loading 2024-03-26 08:56:20 +08:00
Pang
f311625060 fix: 修改回复、转发消息后引用的部分消失 2024-03-26 08:51:40 +08:00
kuaifan
d3c08f8d90 perf: 支持FCM推送 2024-03-21 00:37:38 +09:00
kuaifan
2bc655d7ef perf: 设置华为推送自分类 2024-03-20 15:52:48 +09:00
kuaifan
d2b8d0372e perf(client): 优化添加任务可见性点击效果 2024-03-20 13:44:22 +09:00
kuaifan
40b637b16e build 2024-03-20 02:53:37 +09:00
kuaifan
6e68f399b4 perf: 优化数据结构 2024-03-20 02:49:44 +09:00
kuaifan
0be6c70e92 Merge commit '6c2d8fc16313234bbacb4ad4d7f8637b71025a26' into pro 2024-03-20 02:03:26 +09:00
weifs
6c2d8fc163 perf: 接龙优化为清空内容默认删除 2024-03-19 18:41:41 +08:00
kuaifan
a8193b8feb build 2024-03-19 16:32:39 +09:00
kuaifan
34159caf22 Merge commit 'd12c0c42072452de4c99ef55c5915edb108dd2ef' into pro 2024-03-19 16:04:26 +09:00
kuaifan
c75f406459 no message 2024-03-19 15:57:24 +09:00
kuaifan
99dca06d44 perf: 支持取消发送中的消息 2024-03-19 15:57:07 +09:00
weifs
d12c0c4207 perf: 1. 强化接龙接口本地时间戳问题 2. 接龙消息点展开按钮后做缓存处理 2024-03-19 14:38:15 +08:00
kuaifan
915a5ed7d5 fix: 关闭文件后无法再次打开 2024-03-19 12:07:54 +09:00
kuaifan
7bfc43c85f no message 2024-03-19 04:06:45 +09:00
kuaifan
77ea022ddf build 2024-03-19 03:23:09 +09:00
kuaifan
93578f93f4 Merge commit 'cbbd50a2e320ca0427474fb2921f2b93a5ad2c14' into pro 2024-03-19 03:17:19 +09:00
kuaifan
f129615ebe no message 2024-03-19 03:15:38 +09:00
kuaifan
0e5b44baad perf: 自动识别md格式发送 2024-03-19 03:15:19 +09:00
kuaifan
3596475790 fix: 消息太长导致菜单无法正常显示 2024-03-19 03:14:09 +09:00
kuaifan
6218521dea fix: 项目数量不正确的情况 2024-03-19 02:29:06 +09:00
kuaifan
65db8b5703 fix: 部分未读和待办信息不显示的情况 2024-03-19 02:21:48 +09:00
kuaifan
f5ff9a3648 perf: 优化回复、转发消息数据结构 2024-03-18 19:44:20 +09:00
weifs
cbbd50a2e3 fix: 审批中心修复loadIng效果 2024-03-18 14:12:19 +08:00
kuaifan
b04647e65a build 2024-03-17 17:50:27 +09:00
kuaifan
d34d94faa6 perf: 优化iOS端数据读取失败的情况 2024-03-17 17:21:29 +09:00
kuaifan
4038d9560f perf: 回复消息时自动@提及 2024-03-17 17:00:05 +09:00
kuaifan
006fc43498 perf: 优化会话数据结构 2024-03-17 16:23:57 +09:00
kuaifan
47c9b2e1b0 build 2024-03-15 12:51:10 +09:00
kuaifan
dc3e5f0a59 perf: 聊天文件发送进度 2024-03-15 12:48:33 +09:00
kuaifan
01bda83fcd build 2024-03-15 11:24:46 +09:00
kuaifan
9ecb9c68fb perf: 拨打电话确认提示 2024-03-15 11:16:20 +09:00
kuaifan
4612d5180a no message 2024-03-15 11:15:58 +09:00
kuaifan
cfb653796c perf: 优化预加载文件 2024-03-15 10:58:19 +09:00
kuaifan
d00cd5cb26 fix: 子窗口出现重新登录的情况 2024-03-15 10:19:24 +09:00
kuaifan
285a62c87e no message 2024-03-15 02:15:03 +09:00
kuaifan
bcb0c6bc77 build 2024-03-14 13:48:38 +09:00
kuaifan
d1ab2d98eb no message 2024-03-14 13:45:01 +09:00
kuaifan
c3d5328154 perf: 优化接口时间 2024-03-14 13:44:46 +09:00
kuaifan
fc30588014 build 2024-03-14 08:15:46 +09:00
kuaifan
65b02001b2 no message 2024-03-14 08:01:28 +09:00
kuaifan
cd011a172f perf: 优化审批对话按钮配色 2024-03-14 08:01:17 +09:00
kuaifan
bf913d9eff fix: 回复消息点击到原文无效 2024-03-14 07:26:19 +09:00
kuaifan
c2dd15fca1 no message 2024-03-14 02:55:42 +09:00
kuaifan
b267863b58 build 2024-03-13 14:46:32 +09:00
kuaifan
d189fb100a Merge commit 'c6568969c7b2d538d27cb4ca0ee412d4dbdceb56' into pro 2024-03-13 14:39:39 +09:00
kuaifan
dc6c5bef26 no message 2024-03-13 14:38:49 +09:00
kuaifan
7208d51644 perf: 优化文件功能按钮 2024-03-13 14:38:38 +09:00
kuaifan
16359a968d perf: 文件上传支持覆盖上传 2024-03-13 14:25:15 +09:00
kuaifan
d553f77533 perf: 优化app等比显示 2024-03-13 11:34:27 +09:00
kuaifan
bc25f5dfdf perf: 优化发送文件预览 2024-03-13 10:58:46 +09:00
kuaifan
d40028340c perf: 消息发送中禁止右键菜单 2024-03-13 08:03:58 +09:00
kuaifan
4194d1cddd perf: 部分搜索框图标抖动 2024-03-13 07:57:41 +09:00
kuaifan
1fdd532133 perf: 优化复制功能 2024-03-13 07:49:12 +09:00
kuaifan
71c62a3772 fix: 客户端无法打开excel文件 2024-03-13 07:32:16 +09:00
kuaifan
9be6cd5148 perf: 优化pdf文件预览 2024-03-13 07:14:27 +09:00
wfs
c6568969c7 style: 调整代码格式 2024-03-13 00:26:13 +08:00
wfs
f5b1a6ab05 fix: 修复投票实名逻辑 2024-03-13 00:25:10 +08:00
wfs
5efe659cf5 perf: 优化投票接口,加上事务锁 2024-03-13 00:17:23 +08:00
wfs
b254fd5ce2 perf: 优化接龙接口,加上事务锁 2024-03-12 23:49:05 +08:00
kuaifan
631a0ffff4 no message 2024-03-13 00:42:15 +09:00
kuaifan
8b11e9a19e perf: 优化转发消息样式 2024-03-13 00:42:06 +09:00
weifs
f6b006b000 feat: 升级okr 2024-03-11 18:07:37 +08:00
weifs
3a26f420b8 perf: 接龙接口-强化排序 2024-03-11 17:25:40 +08:00
weifs
0919e415ec perf: 审批按钮色微调 2024-03-11 16:57:45 +08:00
weifs
030a07698d perf: 统一审批中心的按钮色 2024-03-11 16:36:12 +08:00
weifs
a7f2582df7 perf: 转发会议亮色皮肤问题,转发文件宽度铺满 2024-03-11 10:39:53 +08:00
Pang
5f0a0e0371 no message 2024-03-10 22:13:21 +08:00
Pang
28717fd0c7 perf: 优化app数据交互 2024-03-10 14:44:55 +08:00
Pang
7014ea176a build 2024-03-10 12:12:30 +08:00
Pang
b4f2da66be fix: 修复搜索偶尔无效的情况 2024-03-10 11:03:34 +08:00
Pang
b53462cf6e build 2024-03-10 00:39:01 +08:00
Pang
8b40364722 no message 2024-03-10 00:36:07 +08:00
Pang
6ee1824410 perf: 优化文件预览 2024-03-09 17:38:33 +08:00
Pang
f63c2da37a no message 2024-03-09 10:44:36 +08:00
Pang
9be0642ba5 perf: 滑动列表自动隐藏键盘 2024-03-09 10:35:44 +08:00
Pang
55a922c7b3 perf: 优化时间格式 2024-03-09 10:16:09 +08:00
kuaifan
50893929d6 perf: 适配nodejs 20 2024-03-08 17:04:56 +08:00
weifs
03c94e791a feat: 升级okr 2024-03-08 11:03:16 +08:00
weifs
96bb554813 feat: 升级okr 2024-03-08 10:48:33 +08:00
Pang
1bc77de144 build 2024-03-07 23:13:44 +08:00
Pang
aa07c78fc8 perf: 修改消息换行优化 2024-03-07 23:13:24 +08:00
kuaifan
52dda88d40 build 2024-03-07 22:47:04 +08:00
kuaifan
c555b309bd feat: 新增不显示会话功能 2024-03-07 21:05:46 +08:00
kuaifan
0a51225762 Merge commit '3d725ddeef1f86eb02ff2b33435c23bc5e6da8de' into pro 2024-03-07 19:26:49 +08:00
kuaifan
fab49b1dda no message 2024-03-07 19:22:41 +08:00
kuaifan
57e422f2d3 perf: 优化预加载资源 2024-03-07 15:54:55 +08:00
kuaifan
50a1a3147e perf: 优化pdf文件预览 2024-03-07 15:54:26 +08:00
kuaifan
277115a30f perf: 优化签到消息 2024-03-07 15:53:31 +08:00
kuaifan
7464de3adc fix: 部分手机出现非正常滚动到底部的情况 2024-03-07 15:52:47 +08:00
HEXIANG
3d725ddeef fix:dootask官网标题 2024-03-07 15:17:25 +08:00
Pang
38d8f289e4 no message 2024-03-07 08:27:47 +08:00
Pang
edfd6e6de2 perf: 优化登录 2024-03-07 07:17:24 +08:00
Pang
a68ab6512e Merge commit '8383b88a448501cfdb32b79b6e2ccafedadf5e97' into pro 2024-03-06 22:03:34 +08:00
HEXIANG
8383b88a44 fix:dootask官网调整 2024-03-06 18:01:50 +08:00
kuaifan
27ff24f44e perf: 优化安装脚本 2024-03-06 17:18:12 +08:00
weifs
b111ecb227 fix: 修复导出任务统计没有按创建时间来的bug 2024-03-06 14:00:13 +08:00
kuaifan
ac17952cd3 perf: 优化消息时间格式 2024-03-06 12:01:18 +08:00
kuaifan
e24978fdd7 perf: 优化app功能 2024-03-06 11:47:05 +08:00
weifs
a4d7579e3f feat: 升级okr 2024-03-06 10:23:47 +08:00
Pang
52171b794a build 2024-03-06 02:44:16 +08:00
Pang
3c33f02e9d Merge commit '0968c43f61e0183aaf47e38a482d037bc33fc434' into pro 2024-03-06 01:08:59 +08:00
Pang
0a8823c40b no message 2024-03-06 01:05:30 +08:00
Pang
a3f7e71638 translate 2024-03-06 01:01:29 +08:00
Pang
7ebf4fb9ce perf: 默认映射443端口 2024-03-06 01:01:12 +08:00
kuaifan
c96bad3cdf perf: 优化子窗口 2024-03-06 00:30:30 +08:00
weifs
0968c43f61 feat: 发起投票功能添加缓存记录选中效果 2024-03-05 17:50:13 +08:00
weifs
ae147c76ff perf: 优化发布接口 删除目录的逻辑 2024-03-05 15:22:40 +08:00
weifs
0e916a2804 feat: 导出的签到数据和审批数据换成xlsx,因老版本的xls会出现兼容性问题 2024-03-05 15:19:12 +08:00
weifs
494565e131 perf: 优化发布接口 删除目录的逻辑 2024-03-04 09:51:35 +08:00
789 changed files with 19018 additions and 51844 deletions

View File

@@ -10,6 +10,7 @@ APP_URL=http://localhost
APP_ID=
APP_IPPR=
APP_PORT=2222
APP_SSL_PORT=
APP_DEV_PORT=
LOG_CHANNEL=stack

55
.github/workflows/publish-android.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Publish Android
on:
push:
tags:
- 'v*'
jobs:
Build:
name: Build Android
runs-on: ubuntu-latest
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 20.x
- name: Build Js
run: |
git submodule init
git submodule update --remote "resources/mobile"
./cmd appbuild publish
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: Build Android
run: |
cd resources/mobile/platforms/android/eeuiApp
chmod +x ./gradlew
./gradlew assembleRelease --quiet
- name: Upload File
env:
DP_KEY: ${{ secrets.DP_KEY }}
run: |
node ./electron/build.js android-upload
- name: Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
with:
files: |
resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release/*.apk

View File

@@ -7,7 +7,8 @@ on:
jobs:
Build:
runs-on: macos-latest
name: Build Mac
runs-on: macos-12
environment: build
if: startsWith(github.event.ref, 'refs/tags/v')
@@ -15,10 +16,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 16.x
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 16.x
node-version: 20.x
- name: Build
env:

View File

@@ -7,6 +7,7 @@ on:
jobs:
Build:
name: Build Windows
runs-on: windows-latest
environment: build
@@ -15,10 +16,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js 16.x
- name: Use Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 16.x
node-version: 20.x
- name: Build
env:

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ laravels-timer-process.pid
vars.yaml
laravels.conf
laravels.pid
README_LOCAL.md

27
.prefetch Normal file
View File

@@ -0,0 +1,27 @@
office/web-apps/apps/api/documents/api.js?hash={version}
office/7.5.1-23/sdkjs/cell/css/main.css
office/7.5.1-23/web-apps/apps/spreadsheeteditor/main/resources/css/app.css
office/7.5.1-23/web-apps/vendor/requirejs/require.js
office/7.5.1-23/web-apps/apps/spreadsheeteditor/main/app.js
office/7.5.1-23/sdkjs/common/AllFonts.js
office/7.5.1-23/web-apps/vendor/xregexp/xregexp-all-min.js
office/7.5.1-23/web-apps/vendor/socketio/socket.io.min.js
office/7.5.1-23/sdkjs/cell/sdk-all-min.js
office/7.5.1-23/sdkjs/cell/sdk-all.js
office/7.5.1-23/sdkjs/common/libfont/engine/fonts.js
office/7.5.1-23/sdkjs/common/Charts/ChartStyles.js
office/7.5.1-23/sdkjs/common/libfont/engine/fonts.wasm
office/7.5.1-23/web-apps/apps/presentationeditor/main/resources/css/app.css
office/7.5.1-23/web-apps/apps/presentationeditor/main/app.js
office/7.5.1-23/sdkjs/slide/sdk-all-min.js
office/7.5.1-23/sdkjs/slide/sdk-all.js
office/7.5.1-23/sdkjs/slide/themes//themes.js
office/7.5.1-23/web-apps/apps/documenteditor/main/resources/css/app.css
office/7.5.1-23/web-apps/apps/documenteditor/main/app.js
office/7.5.1-23/sdkjs/word/sdk-all-min.js
office/7.5.1-23/sdkjs/word/sdk-all.js
drawio/webapp/js/app.min.js
drawio/webapp/js/stencils.min.js
drawio/webapp/js/extensions.min.js
drawio/webapp/js/shapes-14-6-5.min.js
drawio/webapp/math/es5/output/svg/fonts/tex.js

View File

@@ -2,6 +2,341 @@
All notable changes to this project will be documented in this file.
## [0.37.62]
### Bug Fixes
- 如果项目没有流程,无法选择移动后的状态,也没办法确定移动
### Performance
- 优化视频播放
- 新增通讯录菜单
- 优化快捷创建群组
- 优化回复消息自动@逻辑
- 甘特图兼容移动端
## [0.37.50]
### Bug Fixes
- 更新可见性后仍存在对话会话列表
- 消息输入框回复冲突
### Features
- 更新approve容器
- 添加智谱清言机器人
### Performance
- 团队管理选择离职时根据离职时间排序
- 移动端支持快速编辑描述选择
- 优化离职数据移交
- 优化举报功能
- 优化网络重连后会话数据逻辑
- 优化甘特图移动端交互
- 优化md编辑器
## [0.37.32]
### Performance
- 优化查看任务附件菜单
- 独立窗口未激活阅读逻辑
- 新消息在会话列表时间与消息里不一致
- 优化Android点击发送按钮效果
- 支持修改消息待办
- 延期任务时间支持按天
- 优化待办消息样式
- 优化移动端子任务列表显示
- 语音消息转文字
- 更新语音消息插件
- 优化设置样式
## [0.37.17]
### Bug Fixes
- 修复官网帮助中心英文页面头部导航缺失问题
- 安装系统部分情况没有数据
- 修复举报样式错乱
### Features
- 语音消息未阅读红点提示
- 修复移动任务中选完成进行移动没有设置完成时间的bug
- 新增右侧底部导航
- 添加举报功能
### Performance
- 优化转发消息数据显示
- Ipad 发送消息后出现页面跳动的情况
- 仪表盘隐藏未到开始时间的任务
- 优化查看任务修改历史
- 优化聊天工具栏样式
- 优化更新聊天中的待办
- 优化图标功能提示
- 审批和任务通知优化
- 优化按钮没有对应类型,控制台报错
## [0.36.97]
### Bug Fixes
- 任务描述保存图片失败
### Performance
- 转发消息至群聊时支持@留言
- 自动发布Android
## [0.36.91]
### Bug Fixes
- 上一版本导致的无法@
### Performance
- 优化代码
- 优化查看文件历史
- 支持查看任务描述修改历史
- 任务描述支持清单
## [0.36.84]
### Bug Fixes
- 修复关闭侧边回复窗口导致会话不正常的情况
### Performance
- 消息内容支持待办列表
- 优化自动识别发送消息类型
- 聊天输入框粘贴格式优化
- 优化网络错误提示
## [0.36.78]
### Bug Fixes
- 解决 Unable to preventDefault inside passive event listener 报错
- 截图粘贴出现两张图的情况
- 聊天输入中文过程跟placeholder内容叠加的问题
## [0.36.75]
### Bug Fixes
- Added non-passive event listener to a scroll-blocking 'touchstart' event
### Performance
- 下载pdf使用自带浏览器
- 优化消息加载中效果
- 审批内容禁止转发
- 滑动快捷表情选择
- 优化聊天输入框
- Update chat editor
- 优化机器人回复
- 优化android体验
## [0.36.60]
### Performance
- 优化使用默认浏览器打开规则
- 优化聊天图片上传
- 临时帐号别名
- Tab icon load error
- 优化会议
- 创建会议不需要加入机器人
- 暗黑模式下窗口背景色兼容问题
- 优化网络检查
- 客户端会议优化
## [0.36.49]
### Performance
- 优化会议室
## [0.36.44]
### Bug Fixes
- 部分情况出现注册失败
- 最小化阅读窗口新建窗口不自动激活
- 独立窗口不更新消息
### Performance
- 优化数据读取机制
- 优化缓存规则
- 优化完成待办数据推送
- 评论审批图片和投票深色按钮
## [0.36.36]
### Bug Fixes
- 修改回复、转发消息后引用的部分消失
### Performance
- 优化任务日志内容
- 查看版本免请求接口
- 添加任务时选择任务位置内容溢出
- 消息支持style
- 回复消息列表隐藏顶部loading
- 支持FCM推送
- 设置华为推送自分类
- 优化添加任务可见性点击效果
## [0.36.26]
### Bug Fixes
- 关闭文件后无法再次打开
### Performance
- 优化数据结构
- 接龙优化为清空内容默认删除
- 支持取消发送中的消息
- 1. 强化接龙接口本地时间戳问题 2. 接龙消息点展开按钮后做缓存处理
## [0.36.15]
### Bug Fixes
- 消息太长导致菜单无法正常显示
- 项目数量不正确的情况
- 部分未读和待办信息不显示的情况
- 审批中心修复loadIng效果
### Performance
- 自动识别md格式发送
- 优化回复、转发消息数据结构
- 优化iOS端数据读取失败的情况
- 回复消息时自动@提及
- 优化会话数据结构
## [0.35.90]
### Bug Fixes
- 子窗口出现重新登录的情况
### Performance
- 聊天文件发送进度
- 拨打电话确认提示
- 优化预加载文件
## [0.35.84]
### Bug Fixes
- 回复消息点击到原文无效
### Performance
- 优化接口时间
- 优化审批对话按钮配色
## [0.35.76]
### Bug Fixes
- 客户端无法打开excel文件
- 修复投票实名逻辑
### Features
- 升级okr
### Performance
- 优化文件功能按钮
- 文件上传支持覆盖上传
- 优化app等比显示
- 优化发送文件预览
- 消息发送中禁止右键菜单
- 部分搜索框图标抖动
- 优化复制功能
- 优化pdf文件预览
- 优化投票接口,加上事务锁
- 优化接龙接口,加上事务锁
- 优化转发消息样式
- 接龙接口-强化排序
- 审批按钮色微调
- 统一审批中心的按钮色
- 转发会议亮色皮肤问题,转发文件宽度铺满
- 优化app数据交互
### Styling
- 调整代码格式
## [0.35.48]
### Bug Fixes
- 修复搜索偶尔无效的情况
### Features
- 升级okr
### Performance
- 优化文件预览
- 滑动列表自动隐藏键盘
- 优化时间格式
- 适配nodejs 20
## [0.35.40]
### Bug Fixes
- 部分手机出现非正常滚动到底部的情况
- Dootask官网标题
- Dootask官网调整
- 修复导出任务统计没有按创建时间来的bug
### Features
- 新增不显示会话功能
- 升级okr
### Performance
- 修改消息换行优化
- 优化预加载资源
- 优化pdf文件预览
- 优化签到消息
- 优化登录
- 优化安装脚本
- 优化消息时间格式
- 优化app功能
## [0.35.20]
### Features
- 发起投票功能添加缓存记录选中效果
- 导出的签到数据和审批数据换成xlsx因老版本的xls会出现兼容性问题
### Performance
- 默认映射443端口
- 优化子窗口
- 优化发布接口 删除目录的逻辑
## [0.35.10]
### Bug Fixes

View File

@@ -29,7 +29,7 @@ git clone -b pro --depth=1 https://gitee.com/aipaw/dootask.git
# 2、Enter directory
cd dootask
# 3、InstallationCustom port installation: ./cmd install --port 2222
# 3、InstallationCustom port installation, as: ./cmd install --port 80
./cmd install
```
@@ -43,7 +43,8 @@ cd dootask
### Change port
```bash
./cmd port 2222
# This method only replaces the HTTP port. To replace the HTTPS port, please read the SSL configuration below
./cmd port 80
```
### Change App Url
@@ -67,7 +68,7 @@ cd dootask
### Development compilation
- `NodeJs 18+` must be installed
- `NodeJs 20+` must be installed
```bash
# Development
@@ -87,11 +88,19 @@ cd dootask
./cmd redis "your command" # To run a redis command
./cmd composer "your command" # To run a composer command
./cmd supervisorctl "your command" # To run a supervisorctl command
./cmd test "your command" # To run a phpunit command
./cmd mysql "your command" # To run a mysql command (backup: Backup database, recovery: Restore database)
```
### NGINX PROXY SSL
### SSL configuration
#### Method 1: Automatic configuration
```bash
# Running commands in a project
./cmd https
```
#### Or Method 2: Nginx Agent Configuration
```bash
# 1、Nginx config add
@@ -99,8 +108,8 @@ proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 2、Running commands in a project
./cmd https
# 2、Running commands in a project (If you unconfigure the NGINX agent, run: ./cmd https close)
./cmd https agent
```
## Upgrade

View File

@@ -29,7 +29,7 @@ git clone -b pro --depth=1 https://gitee.com/aipaw/dootask.git
# 2、进入目录
cd dootask
# 3、一键安装项目自定义端口安装 ./cmd install --port 2222
# 3、一键安装项目自定义端口安装,如:./cmd install --port 80
./cmd install
```
@@ -43,7 +43,8 @@ cd dootask
### 更换端口
```bash
./cmd port 2222
# 此方法仅更换http端口更换https端口请阅读下面SSL配置
./cmd port 80
```
### 更换URL
@@ -67,7 +68,7 @@ cd dootask
### 开发编译
- 请确保你已经安装了 `NodeJs 18+`
- 请确保你已经安装了 `NodeJs 20+`
```bash
# 开发模式
@@ -88,11 +89,19 @@ cd dootask
./cmd redis "your command" # 运行 redis 命令
./cmd composer "your command" # 运行 composer 命令
./cmd supervisorctl "your command" # 运行 supervisorctl 命令
./cmd test "your command" # 运行 phpunit 命令
./cmd mysql "your command" # 运行 mysql 命令 (backup: 备份数据库recovery: 还原数据库)
```
### NGINX 代理 SSL
### SSL 配置
#### 方法1自动配置
```bash
# 在项目下运行命令,根据提示执行即可
./cmd https
```
#### 或者方法2Nginx 代理配置
```bash
# 1、Nginx 代理配置添加
@@ -100,8 +109,8 @@ proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 2、在项目下运行命令
./cmd https
# 2、在项目下运行命令(如果取消 Nginx 代理配置请运行:./cmd https close
./cmd https agent
```
## 升级更新

View File

@@ -207,7 +207,7 @@ class ApproveController extends AbstractController
if ($id != $user->userid) {
$dialog = WebSocketDialog::checkUserDialog($botUser, $id);
$processInst['comment_user_id'] = $user->userid;
$processInst['comment_content'] = json_decode($data['content'], true)['content'];
$processInst['comment_contents'] = json_decode($data['content'], true) ?? [];
$this->approveMsg('approve_comment_notifier', $dialog, $botUser, $processInst, $processInst);
}
}
@@ -858,7 +858,7 @@ class ApproveController extends AbstractController
BillExport::create()->setTitle($title)->setHeadings($headings)->setData($datas)->setStyles(["A1:Y1" => ["font" => ["bold" => true]]])
];
//
$fileName = '审批记录_' . Base::time() . '.xls';
$fileName = '审批记录_' . Base::time() . '.xlsx';
$filePath = "temp/approve/export/" . date("Ym", Base::time());
$export = new BillMultipleExport($sheets);
$res = $export->store($filePath . "/" . $fileName);
@@ -866,7 +866,7 @@ class ApproveController extends AbstractController
return Base::retError('导出失败,' . $fileName . '');
}
$xlsPath = storage_path("app/" . $filePath . "/" . $fileName);
$zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xls') . ".zip";
$zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xlsx') . ".zip";
$zipPath = storage_path($zipFile);
if (file_exists($zipPath)) {
Base::deleteDirAndFile($zipPath, true);
@@ -983,7 +983,8 @@ class ApproveController extends AbstractController
'end_day_of_week' => '周' . Base::getTimeWeek(Carbon::parse($process['var']['end_time'])->timestamp),
'description' => $process['var']['description'],
'comment_nickname' => $process['comment_user_id'] ? User::userid2nickname($process['comment_user_id']) : '',
'comment_content' => $process['comment_content'] ?? ''
'comment_content' => $process['comment_contents']['content'] ?? '',
'comment_pictures' => $process['comment_contents']['pictures'] ?? []
];
$text = view('push.bot', ['type' => $type, 'action' => $action, 'is_finished' => $process['is_finished'], 'data' => (object)$data])->render();
$text = preg_replace("/^\x20+/", "", $text);
@@ -992,14 +993,14 @@ class ApproveController extends AbstractController
if ($action == 'withdraw' || $action == 'pass' || $action == 'refuse') {
// 任务完成,给发起人发送消息
if ($type == 'approve_submitter' && $action != 'withdraw') {
return WebSocketDialogMsg::sendMsg($msg_action, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, true);
return WebSocketDialogMsg::sendMsg($msg_action, $dialog->id, 'text', ['text' => $text, 'approve_type' => $type], $botUser->userid, false, false, true);
}
// 查找最后一条消息msg_id
$msg_action = 'change-' . $toUser['msg_id'];
}
//
try {
$msg = WebSocketDialogMsg::sendMsg($msg_action, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, true);
$msg = WebSocketDialogMsg::sendMsg($msg_action, $dialog->id, 'text', ['text' => $text, 'approve_type' => $type], $process['start_user_id'], false, false, true);
// 关联信息
if ($action == 'start') {
$proc_msg = new ApproveProcMsg();

View File

@@ -0,0 +1,158 @@
<?php
namespace App\Http\Controllers\Api;
use Request;
use App\Models\User;
use App\Module\Base;
use App\Models\Complaint;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogMsg;
/**
* @apiDefine dialog
*
* 投诉
*/
class ComplaintController extends AbstractController
{
/**
* @api {get} api/complaint/lists 01. 获取举报投诉列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName lists
*
* @apiParam {Number} [type] 类型
* @apiParam {Number} [status] 状态
*
* @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:50最大:100
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function lists()
{
$user = User::auth();
$user->identity('admin');
//
$type = intval(Request::input('type'));
$status = Request::input('status');
//
$complaints = Complaint::query()
->when($type, function($q) use($type) {
$q->where('type', $type);
})
->when($status != "", function($q) use($status) {
$q->where('status', $status);
})
->orderByDesc('id')
->paginate(Base::getPaginate(100, 50));
//
return Base::retSuccess('success', $complaints);
}
/**
* @api {get} api/complaint/submit 02. 举报投诉
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName submit
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} type 类型
* @apiParam {String} reason 原因
* @apiParam {String} imgs 图片
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function submit()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$type = intval(Request::input('type'));
$reason = trim(Request::input('reason'));
$imgs = Request::input('imgs');
//
WebSocketDialog::checkDialog($dialog_id);
//
if (!$type) {
return Base::retError('请选择举报类型');
}
if (!$reason) {
return Base::retError('请填写举报原因');
}
//
$report_imgs = [];
if (!empty($imgs) && is_array($imgs)) {
foreach ($imgs as $img) {
$report_imgs[] = Base::unFillUrl($img['path']);
}
}
//
Complaint::createInstance([
'dialog_id' => $dialog_id,
'userid' => $user->userid,
'type' => $type,
'reason' => $reason,
'imgs' => $report_imgs,
])->save();
// 通知管理员
$botUser = User::botGetOrCreate('system-msg');
User::where("identity", "like", "%,admin,%")
->orderByDesc('line_at')
->take(10)
->get()
->each(function ($adminUser) use ($reason, $botUser) {
$dialog = WebSocketDialog::checkUserDialog($botUser, $adminUser->userid);
if ($dialog) {
$text = "<p>收到新的举报信息:{$reason} (请前往应用查看详情)</p>";
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid); // todo 未能在任务end事件来发送任务
}
});
//
return Base::retSuccess('success');
}
/**
* @api {get} api/complaint/action 03. 举报投诉 - 操作
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName action
*
* @apiParam {Number} id ID
* @apiParam {Number} type 类型
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function action()
{
$user = User::auth();
$user->identity('admin');
//
$id = intval(Request::input('id'));
$type = trim(Request::input('type'));
//
if ($type == 'handle') {
Complaint::whereId($id)->update([
"status" => 1
]);
}
if ($type == 'delete') {
Complaint::whereId($id)->delete();
}
//
return Base::retSuccess('success');
}
}

View File

@@ -11,6 +11,7 @@ use Carbon\Carbon;
use App\Models\File;
use App\Models\User;
use App\Module\Base;
use App\Module\Extranet;
use App\Module\TimeRange;
use App\Models\FileContent;
use App\Models\AbstractModel;
@@ -58,29 +59,36 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/unread 02. 未读对话列表
* @api {get} api/dialog/beyond 02. 列表外对话
*
* @apiDescription 需要token身份
* @apiDescription 需要token身份,列表外的未读对话 和 列表外的待办对话
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName lists
* @apiName beyond
*
* @apiParam {String} before_at 在这个时间之前未读的数据
* @apiParam {String} unread_at 在这个时间之前未读的数据
* - 格式12021-01-01 00:00:00
* - 格式21612051200
* @apiParam {String} todo_at 在这个时间之前待办的数据
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function unread()
public function beyond()
{
$user = User::auth();
//
$beforeAt = Request::input('before_at');
if (empty($beforeAt)) {
return Base::retError('参数错误');
}
$unreadAt = Request::input('unread_at');
$todoAt = Request::input('todo_at');
//
$data = WebSocketDialog::getDialogUnread($user->userid, Carbon::parse($beforeAt));
$unreadAt = Base::isNumber($unreadAt) ? intval($unreadAt) : trim($unreadAt);
$unreadAt = Carbon::parse($unreadAt)->setTimezone(config('app.timezone'));
//
$todoAt = Base::isNumber($todoAt) ? intval($todoAt) : trim($todoAt);
$todoAt = Carbon::parse($todoAt)->setTimezone(config('app.timezone'));
//
$data = WebSocketDialog::getDialogBeyond($user->userid, $unreadAt, $todoAt);
//
return Base::retSuccess('success', $data);
}
@@ -108,12 +116,12 @@ class DialogController extends AbstractController
return Base::retError('请输入搜索关键词');
}
// 搜索会话
$dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at'])
$dialogs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.name', 'LIKE', "%{$key}%")
->where('u.userid', $user->userid)
->orderByDesc('u.top_at')
->orderByDesc('web_socket_dialogs.last_at')
->orderByDesc('u.last_at')
->take(20)
->get();
$dialogs->transform(function (WebSocketDialog $item) use ($user) {
@@ -145,7 +153,7 @@ class DialogController extends AbstractController
}
// 搜索消息会话
if (count($list) < 20) {
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id'])
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
->where('u.userid', $user->userid)
@@ -178,7 +186,7 @@ class DialogController extends AbstractController
{
$user = User::auth();
// 搜索会话
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id'])
$msgs = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at', 'm.id as search_msg_id'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id')
->where('u.userid', $user->userid)
@@ -213,7 +221,7 @@ class DialogController extends AbstractController
//
$dialog_id = intval(Request::input('dialog_id'));
//
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at'])
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.id', $dialog_id)
->where('u.userid', $user->userid)
@@ -249,8 +257,8 @@ class DialogController extends AbstractController
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
//
$data = $dialog->dialogUser->toArray();
if ($getuser === 1) {
$data = $dialog->dialogUser->toArray();
$array = [];
foreach ($data as $item) {
$res = User::userid2basic($item['userid']);
@@ -258,14 +266,16 @@ class DialogController extends AbstractController
$array[] = array_merge($item, $res->toArray());
}
}
$data = $array;
}
//
$array = [];
foreach ($data as $item) {
if ($item['userid'] > 0) {
$array[] = $item;
}
$array = array_filter($array, function ($item) {
return $item['userid'] > 0;
});
} else {
$data = WebSocketDialogUser::select(['web_socket_dialog_users.*', 'users.bot'])
->join('users', 'web_socket_dialog_users.userid', '=', 'users.userid')
->where('web_socket_dialog_users.dialog_id', $dialog_id)
->orderBy('web_socket_dialog_users.id')
->get();
$array = $data->toArray();
}
return Base::retSuccess('success', $array);
}
@@ -330,8 +340,43 @@ class DialogController extends AbstractController
]);
}
/**
* @api {get} api/dialog/tel 09. 获取对方联系电话
* @api {get} api/dialog/hide 09. 会话隐藏
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName hide
*
* @apiParam {Number} dialog_id 会话ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function hide()
{
$user = User::auth();
$dialogId = intval(Request::input('dialog_id'));
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
if (!$dialogUser) {
return Base::retError("会话不存在");
}
if ($dialogUser->top_at) {
return Base::retError("置顶会话无法隐藏");
}
$dialogUser->hide = 1;
$dialogUser->save();
return Base::retSuccess("success", [
'id' => $dialogUser->dialog_id,
'hide' => 1,
]);
}
/**
* @api {get} api/dialog/tel 10. 获取对方联系电话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -381,7 +426,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/open/user 10. 打开会话
* @api {get} api/dialog/open/user 11. 打开会话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -412,7 +457,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/list 11. 获取消息列表
* @api {get} api/dialog/msg/list 12. 获取消息列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -459,6 +504,7 @@ class DialogController extends AbstractController
$builder = WebSocketDialogMsg::select([
'web_socket_dialog_msgs.*',
'read.mention',
'read.dot',
'read.read_at',
])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) {
$leftJoin
@@ -546,7 +592,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/latest 12. 获取最新消息列表
* @api {get} api/dialog/msg/latest 13. 获取最新消息列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -576,6 +622,7 @@ class DialogController extends AbstractController
$builder = WebSocketDialogMsg::select([
'web_socket_dialog_msgs.*',
'read.mention',
'read.dot',
'read.read_at',
])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) {
$leftJoin
@@ -611,7 +658,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/search 13. 搜索消息位置
* @api {get} api/dialog/msg/search 14. 搜索消息位置
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -646,7 +693,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/one 14. 获取单条消息
* @api {get} api/dialog/msg/one 15. 获取单条消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -675,7 +722,40 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/read 15. 已读聊天消息
* @api {get} api/dialog/msg/dot 16. 聊天消息去除点
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__dot
*
* @apiParam {Number} id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__dot()
{
$user = User::auth();
//
$id = intval(Request::input('id'));
//
$msg = WebSocketDialogMsg::find($id);
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
//
WebSocketDialogMsgRead::whereMsgId($id)->whereUserid($user->userid)->change(['dot' => 0]);
//
return Base::retSuccess('success', [
'id' => $msg->id,
'dot' => 0,
]);
}
/**
* @api {get} api/dialog/msg/read 17. 已读聊天消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -746,7 +826,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/unread 16. 获取未读消息数据
* @api {get} api/dialog/msg/unread 18. 获取未读消息数据
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -789,7 +869,73 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/stream 17. 通知成员监听消息
* @api {get} api/dialog/msg/checked 19. 设置消息checked
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__checked
*
* @apiParam {Number} dialog_id 对话ID
* @apiParam {Number} msg_id 消息ID
* @apiParam {Number} index li 位置
* @apiParam {Number} checked 标记、取消标记
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
* @apiSuccessExample {json} data:
{
"id": 43,
"msg": {
// ....
},
}
*/
public function msg__checked()
{
$user = User::auth();
//
$dialog_id = intval(Request::input('dialog_id'));
$msg_id = intval(Request::input('msg_id'));
$index = intval(Request::input('index'));
$checked = intval(Request::input('checked'));
//
$dialogMsg = WebSocketDialogMsg::whereId($msg_id)->whereDialogId($dialog_id)->first();
if (empty($dialogMsg)) {
return Base::retError('消息不存在');
}
if ($dialogMsg->userid != $user->userid) {
return Base::retError('仅支持修改自己的消息');
}
if ($dialogMsg->type !== 'text') {
return Base::retError('仅支持文本消息');
}
//
$oldMsg = Base::json2array($dialogMsg->getRawOriginal('msg'));
$oldText = $oldMsg['text'] ?? '';
$newText = preg_replace_callback('/<li[^>]*>/i', function ($matches) use ($index, $checked) {
static $i = 0;
if ($i++ == $index) {
$checked = $checked ? 'checked' : 'unchecked';
return '<li data-list="' . $checked . '">';
}
return $matches[0];
}, $oldText);
//
$dialogMsg->updateInstance([
'msg' => array_merge($oldMsg, ['text' => $newText]),
]);
$dialogMsg->save();
//
return Base::retSuccess('success', [
'id' => $dialogMsg->id,
'msg' => $dialogMsg->msg,
]);
}
/**
* @api {post} api/dialog/msg/stream 20. 通知成员监听消息
*
* @apiDescription 通知指定会员EventSource监听流动消息
* @apiVersion 1.0.0
@@ -828,7 +974,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/sendtext 18. 发送消息
* @api {post} api/dialog/msg/sendtext 21. 发送消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -929,7 +1075,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/sendrecord 19. 发送语音
* @api {post} api/dialog/msg/sendrecord 22. 发送语音
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -977,7 +1123,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/sendfile 20. 文件上传
* @api {post} api/dialog/msg/sendfile 23. 文件上传
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1009,7 +1155,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/sendfiles 21. 群发文件上传
* @api {post} api/dialog/msg/sendfiles 24. 群发文件上传
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1065,7 +1211,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/sendfileid 22. 通过文件ID发送文件
* @api {get} api/dialog/msg/sendfileid 25. 通过文件ID发送文件
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1135,7 +1281,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/sendanon 23. 发送匿名消息
* @api {post} api/dialog/msg/sendanon 26. 发送匿名消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1188,7 +1334,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/readlist 24. 获取消息阅读情况
* @api {get} api/dialog/msg/readlist 27. 获取消息阅读情况
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1217,7 +1363,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/detail 25. 消息详情
* @api {get} api/dialog/msg/detail 28. 消息详情
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1265,7 +1411,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/download 26. 文件下载
* @api {get} api/dialog/msg/download 29. 文件下载
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1306,7 +1452,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/withdraw 27. 聊天消息撤回
* @api {get} api/dialog/msg/withdraw 30. 聊天消息撤回
*
* @apiDescription 消息撤回限制24小时内需要token身份
* @apiVersion 1.0.0
@@ -1332,7 +1478,59 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/mark 28. 消息标记操作
* @api {get} api/dialog/msg/voice2text 31. 语音消息转文字
*
* @apiDescription 将语音消息转文字需要token身份
* @apiVersion 1.0.0
* @apiGroup dialog
* @apiName msg__voice2text
*
* @apiParam {Number} msg_id 消息ID
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function msg__voice2text()
{
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
if ($msg->type !== 'record') {
return Base::retError("仅支持语音消息");
}
$msgData = Base::json2array($msg->getRawOriginal('msg'));
if ($msgData['text']) {
$textUserid = is_array($msgData['text_userid']) ? $msgData['text_userid'] : [];
if (!in_array($user->userid, $textUserid)) {
$textUserid[] = $user->userid;
$msg->updateInstance([
'msg' => array_merge($msgData, ['text_userid' => $textUserid]),
]);
$msg->save();
}
return Base::retSuccess("success", $msg);
}
WebSocketDialog::checkDialog($msg->dialog_id);
//
$res = Extranet::openAItranscriptions(public_path($msgData['path']));
if (Base::isError($res)) {
return $res;
}
//
$msg->updateInstance([
'msg' => array_merge($msgData, ['text' => $res['data'], 'text_userid' => [$user->userid]]),
]);
$msg->save();
return Base::retSuccess("success", $msg);
}
/**
* @api {get} api/dialog/msg/mark 32. 消息标记操作
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1396,7 +1594,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/silence 29. 消息免打扰
* @api {get} api/dialog/msg/silence 33. 消息免打扰
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1459,7 +1657,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/forward 30. 转发消息给
* @api {get} api/dialog/msg/forward 34. 转发消息给
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1500,7 +1698,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/emoji 31. emoji回复
* @api {get} api/dialog/msg/emoji 35. emoji回复
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1535,7 +1733,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/tag 32. 标注/取消标注
* @api {get} api/dialog/msg/tag 36. 标注/取消标注
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1564,7 +1762,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/todo 33. 设待办/取消待办
* @api {get} api/dialog/msg/todo 37. 设待办/取消待办
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1575,7 +1773,9 @@ class DialogController extends AbstractController
* @apiParam {String} type 设待办对象
* - all: 会话全部成员(默认)
* - user: 会话指定成员
* @apiParam {Array} userids 会员ID组type=user有效格式: [userid1, userid2, userid3]
* @apiParam {Array} userids 会员ID组
* - type=user 有效,格式: [userid1, userid2, userid3]
* - 可通过 type=user 及 userids:[] 一起使用来清除所有人的待办
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@@ -1583,31 +1783,29 @@ class DialogController extends AbstractController
*/
public function msg__todo()
{
Base::checkClientVersion('0.37.18');
$user = User::auth();
//
$msg_id = intval(Request::input("msg_id"));
$type = trim(Request::input("type", "all"));
$userids = Request::input('userids');
//
if ($type === 'user') {
if (empty($userids)) {
return Base::retError("选择指定成员");
}
} else {
$userids = [];
}
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) {
return Base::retError("消息不存在或已被删除");
}
WebSocketDialog::checkDialog($msg->dialog_id);
$dialog = WebSocketDialog::checkDialog($msg->dialog_id);
//
if ($type === 'all') {
$userids = $dialog->dialogUser->pluck('userid')->toArray();
} else {
$userids = is_array($userids) ? $userids : [];
}
return $msg->toggleTodoMsg($user->userid, $userids);
}
/**
* @api {get} api/dialog/msg/todolist 34. 获取消息待办情况
* @api {get} api/dialog/msg/todolist 38. 获取消息待办情况
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1637,7 +1835,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/done 35. 完成待办
* @api {get} api/dialog/msg/done 39. 完成待办
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1675,6 +1873,12 @@ class DialogController extends AbstractController
if (Base::isSuccess($res)) {
$add = $res['data'];
}
//
$msg->webSocketDialog?->pushMsg('update', [
'id' => $msg->id,
'todo' => $msg->todo,
'dialog_id' => $msg->dialog_id,
]);
}
}
//
@@ -1684,7 +1888,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/color 36. 设置颜色
* @api {get} api/dialog/msg/color 40. 设置颜色
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1725,7 +1929,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/add 37. 新增群组
* @api {get} api/dialog/group/add 41. 新增群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1787,7 +1991,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/edit 38. 修改群组
* @api {get} api/dialog/group/edit 42. 修改群组
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1849,7 +2053,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/adduser 39. 添加群成员
* @api {get} api/dialog/group/adduser 43. 添加群成员
*
* @apiDescription 需要token身份
* - 有群主时:只有群主可以邀请
@@ -1885,7 +2089,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/deluser 40. 移出(退出)群成员
* @api {get} api/dialog/group/deluser 44. 移出(退出)群成员
*
* @apiDescription 需要token身份
* - 只有群主、邀请人可以踢人
@@ -1929,7 +2133,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/transfer 41. 转让群组
* @api {get} api/dialog/group/transfer 45. 转让群组
*
* @apiDescription 需要token身份
* - 只有群主且是个人类型群可以解散
@@ -1978,7 +2182,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/disband 42. 解散群组
* @api {get} api/dialog/group/disband 46. 解散群组
*
* @apiDescription 需要token身份
* - 只有群主且是个人类型群可以解散
@@ -2006,7 +2210,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/searchuser 43. 搜索个人群(仅限管理员)
* @api {get} api/dialog/group/searchuser 47. 搜索个人群(仅限管理员)
*
* @apiDescription 需要token身份用于创建部门搜索个人群组
* @apiVersion 1.0.0
@@ -2035,7 +2239,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/okr/add 44. 创建OKR评论会话
* @api {post} api/dialog/okr/add 48. 创建OKR评论会话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2074,7 +2278,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/okr/push 45. 推送OKR相关信息
* @api {post} api/dialog/okr/push 49. 推送OKR相关信息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2110,7 +2314,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/wordchain 46. 发送接龙消息
* @api {post} api/dialog/msg/wordchain 50. 发送接龙消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2133,47 +2337,70 @@ class DialogController extends AbstractController
$dialog_id = intval(Request::input('dialog_id'));
$uuid = trim(Request::input('uuid'));
$text = trim(Request::input('text'));
$list = Request::input('list');
$list = Request::input('list') ?? [];
//
WebSocketDialog::checkDialog($dialog_id);
$strlen = mb_strlen($text);
$noimglen = mb_strlen(preg_replace("/<img[^>]*?>/i", "", $text));
if ($strlen < 1) {
if ($strlen < 1 || empty($list)) {
return Base::retError('内容不能为空');
}
if ($noimglen > 200000) {
return Base::retError('内容最大不能超过200000字');
}
//
$userid = $user->userid;
if ($uuid) {
$dialogMsg = WebSocketDialogMsg::whereDialogId($dialog_id)
->whereType('word-chain')
->orderByDesc('created_at')
->where('msg', 'like', "%$uuid%")
->value('msg');
$list = array_reverse(array_merge($dialogMsg['list'] ?? [], $list));
$list = array_reduce($list, function ($result, $item) {
$fieldValue = $item['id']; // 指定字段名
if (!isset($result[$fieldValue])) {
$result[$fieldValue] = $item;
return AbstractModel::transaction(function () use ($user, $uuid, $dialog_id, $list, $text) {
if ($uuid) {
$dialogMsg = WebSocketDialogMsg::whereDialogId($dialog_id)
->lockForUpdate()
->whereType('word-chain')
->orderByDesc('created_at')
->where('msg', 'like', "%$uuid%")
->value('msg');
//
$createId = $dialogMsg['createid'] ?? $user->userid;
// 新增
$msgList = $dialogMsg['list'] ?? [];
$addList = array_udiff($list, $msgList, function($a, $b) {
return ($a['id'] ?? 0) - $b['id'];
});
foreach ($addList as $key => $item) {
$item['id'] = intval(round(microtime(true) * 1000)) + $key;
$msgList[] = $item;
}
return $result;
}, []);
$list = array_reverse(array_values($list));
}
//
$msgData = [
'text' => $text,
'list' => $list,
'userid' => $userid,
'uuid' => $uuid ?: Base::generatePassword(36),
];
return WebSocketDialogMsg::sendMsg(null, $dialog_id, 'word-chain', $msgData, $user->userid);
// 编辑更新
$lists = array_column($list,null,'id');
foreach ($msgList as $key => $item) {
if (isset($lists[$item['id']]) && $item['userid'] == $user->userid) {
$msgList[$key] = $lists[$item['id']];
}
}
$list = $msgList;
} else {
$createId = $user->userid;
$uuid = Base::generatePassword(36);
foreach ($list as $key => $item) {
$list[$key]['id'] = intval(round(microtime(true) * 1000)) + $key;
}
}
//
usort($list, function ($a, $b) {
return $a['id'] - $b['id'];
});
//
$msgData = [
'text' => $text,
'list' => $list,
'userid' => $user->userid,
'createid' => $createId,
'uuid' => $uuid,
];
return WebSocketDialogMsg::sendMsg(null, $dialog_id, 'word-chain', $msgData, $user->userid);
});
}
/**
* @api {post} api/dialog/msg/vote 47. 发起投票
* @api {post} api/dialog/msg/vote 51. 发起投票
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2210,8 +2437,6 @@ class DialogController extends AbstractController
WebSocketDialog::checkDialog($dialog_id);
//
$action = null;
$userid = $user->userid;
$result = [];
if ($type != 'create') {
if ($type == 'vote' && empty($votes)) {
return Base::retError('参数错误');
@@ -2219,42 +2444,50 @@ class DialogController extends AbstractController
if (empty($uuid)) {
return Base::retError('参数错误');
}
$dialogMsgs = WebSocketDialogMsg::whereDialogId($dialog_id)
->whereType('vote')
->orderByDesc('created_at')
->where('msg', 'like', "%$uuid%")
->get();
//
if ($type == 'again') {
$res = WebSocketDialogMsg::sendMsg(null, $dialog_id, 'vote', $dialogMsgs[0]->msg, $user->userid);
if (Base::isError($res)) {
return $res;
}
$result[] = $res['data'];
} else {
foreach ($dialogMsgs as $dialogMsg) {
$action = "change-{$dialogMsg->id}";
$msgData = $dialogMsg->msg;
if ($type == 'finish') {
$msgData['state'] = 0;
} else {
$msgDataVotes = $msgData['votes'] ?? [];
if (in_array($userid, array_column($msgDataVotes, 'userid'))) {
return Base::retError('不能重复投票');
}
$msgDataVotes[] = [
'userid' => $userid,
'votes' => $votes,
];
$msgData['votes'] = $msgDataVotes;
}
$res = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'vote', $msgData, $user->userid);
return AbstractModel::transaction(function () use ($user, $uuid, $dialog_id, $type, $votes) {
//
$dialogMsgs = WebSocketDialogMsg::whereDialogId($dialog_id)
->lockForUpdate()
->whereType('vote')
->orderByDesc('created_at')
->where('msg', 'like', "%$uuid%")
->get();
//
$result = [];
if ($type == 'again') {
$res = WebSocketDialogMsg::sendMsg(null, $dialog_id, 'vote', $dialogMsgs[0]->msg, $user->userid);
if (Base::isError($res)) {
return $res;
}
$result[] = $res['data'];
} else {
foreach ($dialogMsgs as $dialogMsg) {
$action = "change-{$dialogMsg->id}";
$msgData = $dialogMsg->msg;
if ($type == 'finish') {
$msgData['state'] = 0;
} else {
$msgDataVotes = $msgData['votes'] ?? [];
if (in_array($user->userid, array_column($msgDataVotes, 'userid'))) {
return Base::retError('不能重复投票');
}
$msgDataVotes[] = [
'userid' => $user->userid,
'votes' => $votes,
];
$msgData['votes'] = $msgDataVotes;
}
//
$res = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'vote', $msgData, $user->userid);
if (Base::isError($res)) {
return $res;
}
$result[] = $res['data'];
}
}
}
//
return Base::retSuccess('发送成功', $result);
});
} else {
$strlen = mb_strlen($text);
$noimglen = mb_strlen(preg_replace("/<img[^>]*?>/i", "", $text));
@@ -2267,7 +2500,7 @@ class DialogController extends AbstractController
$msgData = [
'text' => $text,
'list' => $list,
'userid' => $userid,
'userid' => $user->userid,
'uuid' => $uuid ?: Base::generatePassword(36),
'multiple' => $multiple,
'anonymous' => $anonymous,
@@ -2278,13 +2511,12 @@ class DialogController extends AbstractController
if (Base::isError($res)) {
return $res;
}
$result[] = $res['data'];
return Base::retSuccess('发送成功', [$res['data']]);
}
return Base::retSuccess('发送成功', $result);
}
/**
* @api {get} api/dialog/msg/top 48. 置顶/取消置顶
* @api {get} api/dialog/msg/top 52. 置顶/取消置顶
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2344,7 +2576,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/topinfo 49. 获取置顶消息
* @api {get} api/dialog/msg/topinfo 53. 获取置顶消息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0

View File

@@ -699,6 +699,9 @@ class FileController extends AbstractController
* @apiName content__upload
*
* @apiParam {Number} [pid] 父级ID
* @apiParam {Number} [cover] 覆盖已存在的文件
* - 0不覆盖保留两者默认
* - 1覆盖
* @apiParam {String} [files] 文件名
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
@@ -709,8 +712,9 @@ class FileController extends AbstractController
{
$user = User::auth();
$pid = intval(Request::input('pid'));
$overwrite = intval(Request::input('cover'));
$webkitRelativePath = Request::input('webkitRelativePath');
$data = (new File)->contentUpload($user, $pid, $webkitRelativePath);
$data = (new File)->contentUpload($user, $pid, $webkitRelativePath, $overwrite);
return Base::retSuccess($data['data']['name'] . ' 上传成功', $data['addItem']);
}

View File

@@ -32,6 +32,7 @@ use App\Models\ProjectTaskUser;
use App\Models\WebSocketDialog;
use App\Exceptions\ApiException;
use App\Models\ProjectPermission;
use App\Models\ProjectTaskContent;
use App\Models\WebSocketDialogMsg;
use App\Module\BillMultipleExport;
use Illuminate\Support\Facades\DB;
@@ -1552,12 +1553,12 @@ class ProjectController extends AbstractController
// 项目可见性
$project_userid = ProjectUser::whereProjectId($task->project_id)->whereOwner(1)->value('userid'); // 项目负责人
if ($task->visibility != 1 && $user->userid != $project_userid) {
$taskUserids = ProjectTaskUser::whereTaskId($task_id)->pluck('userid')->toArray(); //任务负责人、协助人
$subTaskUserids = ProjectTaskUser::whereTaskPid($task_id)->pluck('userid')->toArray(); //子任务负责人、协助人
$visibleUserids = ProjectTaskVisibilityUser::whereTaskId($task_id)->pluck('userid')->toArray(); //可见人
$taskUserids = ProjectTaskUser::whereTaskId($task_id)->pluck('userid')->toArray(); //任务负责人、协助人
$subTaskUserids = ProjectTaskUser::whereTaskPid($task_id)->pluck('userid')->toArray(); //子任务负责人、协助人
$visibleUserids = ProjectTaskVisibilityUser::whereTaskId($task_id)->pluck('userid')->toArray(); //可见人
$visibleUserids = array_merge($taskUserids, $subTaskUserids, $visibleUserids);
if (!in_array($user->userid, $visibleUserids)) {
return Base::retError('无任务权限');
return Base::retError('无任务权限', ['task_id' => $task_id, 'force' => 1], -4002);
}
}
//
@@ -1576,7 +1577,8 @@ class ProjectController extends AbstractController
* @apiGroup project
* @apiName task__content
*
* @apiParam {Number} task_id 任务ID
* @apiParam {Number} task_id 任务ID
* @apiParam {Number} [history_id] 历史ID获取历史版本
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@@ -1587,9 +1589,19 @@ class ProjectController extends AbstractController
User::auth();
//
$task_id = intval(Request::input('task_id'));
$history_id = intval(Request::input('history_id'));
//
$task = ProjectTask::userTask($task_id, null);
//
if ($history_id > 0) {
$taskContent = ProjectTaskContent::whereTaskId($task->id)->whereId($history_id)->first();
if (empty($taskContent)) {
return Base::retError('历史版本不存在');
}
return Base::retSuccess('success', array_merge($taskContent->getContentInfo(), [
'name' => $task->name,
]));
}
if (empty($task->content)) {
return Base::retSuccess('success', json_decode('{}'));
}
@@ -1597,7 +1609,39 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/files 26. 获取任务文件列表
* @api {get} api/project/task/content_history 26. 获取任务详细历史描述
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup project
* @apiName task__content_history
*
* @apiParam {Number} task_id 任务ID
*
* @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:20最大:100
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function task__content_history()
{
User::auth();
//
$task_id = intval(Request::input('task_id'));
//
$task = ProjectTask::userTask($task_id, null);
//
$data = ProjectTaskContent::select(['id', 'task_id', 'desc', 'userid', 'created_at'])
->whereTaskId($task->id)
->orderByDesc('id')
->paginate(Base::getPaginate(100, 20));
return Base::retSuccess('success', $data);
}
/**
* @api {get} api/project/task/files 27. 获取任务文件列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1622,7 +1666,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/filedelete 27. 删除任务文件
* @api {get} api/project/task/filedelete 28. 删除任务文件
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -1657,7 +1701,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/filedetail 28. 获取任务文件详情
* @api {get} api/project/task/filedetail 29. 获取任务文件详情
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1701,7 +1745,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/filedown 29. 下载任务文件
* @api {get} api/project/task/filedown 30. 下载任务文件
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1748,7 +1792,7 @@ class ProjectController extends AbstractController
}
/**
* @api {post} api/project/task/add 30. 添加任务
* @api {post} api/project/task/add 31. 添加任务
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -1834,7 +1878,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/addsub 31. 添加子任务
* @api {get} api/project/task/addsub 32. 添加子任务
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -1881,7 +1925,7 @@ class ProjectController extends AbstractController
}
/**
* @api {post} api/project/task/update 32. 修改任务、子任务
* @api {post} api/project/task/update 33. 修改任务、子任务
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -1896,6 +1940,7 @@ class ProjectController extends AbstractController
* @apiParam {String} [content] 任务详情(子任务不支持)
* @apiParam {String} [color] 背景色(子任务不支持)
* @apiParam {Array} [assist] 修改协助人员(子任务不支持)
* @apiParam {Number} [visibility] 修改可见性
* @apiParam {Array} [visibility_appointor] 修改可见性人员
*
* @apiParam {Number} [p_level] 优先级相关(子任务不支持)
@@ -1945,7 +1990,7 @@ class ProjectController extends AbstractController
$task->pushMsgVisibleAdd($data);
}
if ($param['visibility_appointor']) {
$newVisibleUserIds = $param['visibility_appointor'] ?? [];
$newVisibleUserIds = is_array($param['visibility_appointor']) ? $param['visibility_appointor'] : [];
$deleteUserIds = array_diff($visible, $newVisibleUserIds, $subUserids);
$addUserIds = array_diff($newVisibleUserIds, $visible);
$task->pushMsgVisibleUpdate($data, $deleteUserIds, $addUserIds);
@@ -1987,7 +2032,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/dialog 33. 创建/获取聊天室
* @api {get} api/project/task/dialog 34. 创建/获取聊天室
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2036,7 +2081,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/archived 34. 归档任务
* @api {get} api/project/task/archived 35. 归档任务
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -2081,7 +2126,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/remove 35. 删除任务
* @api {get} api/project/task/remove 36. 删除任务
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -2119,7 +2164,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/resetfromlog 36. 根据日志重置任务
* @api {get} api/project/task/resetfromlog 37. 根据日志重置任务
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -2178,7 +2223,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/flow 37. 任务工作流信息
* @api {get} api/project/task/flow 38. 任务工作流信息
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2267,7 +2312,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/task/move 38. 任务移动
* @api {get} api/project/task/move 39. 任务移动
*
* @apiDescription 需要token身份项目、任务负责人
* @apiVersion 1.0.0
@@ -2295,13 +2340,14 @@ class ProjectController extends AbstractController
$flow_item_id = intval(Request::input('flow_item_id'));
$owner = Request::input('owner', []);
$assist = Request::input('assist', []);
$completeAt = trim(Request::input('complete_at', ''));
//
$task = ProjectTask::userTask($task_id);
//
$project = Project::userProject($task->project_id);
ProjectPermission::userTaskPermission($project, ProjectPermission::TASK_MOVE, $task);
//
if( $task->project_id == $project_id && $task->column_id == $column_id){
if ($task->project_id == $project_id && $task->column_id == $column_id) {
return Base::retSuccess('移动成功', ['id' => $task_id]);
}
//
@@ -2310,14 +2356,18 @@ class ProjectController extends AbstractController
if (empty($column)) {
return Base::retError('列表不存在');
}
if($flow_item_id){
if ($flow_item_id) {
$flowItem = projectFlowItem::whereProjectId($project->id)->whereId($flow_item_id)->first();
if (empty($flowItem)) {
return Base::retError('任务状态不存在');
}
} else if (!$flow_item_id && !$completeAt) {
if (projectFlowItem::whereProjectId($project->id)->count() > 0) {
return Base::retError('请选择移动后状态', [], 102);
}
}
//
$task->moveTask($project_id, $column_id, $flow_item_id, $owner, $assist);
$task->moveTask($project_id, $column_id, $flow_item_id, $owner, $assist, $completeAt);
//
$task = ProjectTask::userTask($task_id);
//
@@ -2325,7 +2375,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/flow/list 39. 工作流列表
* @api {get} api/project/flow/list 40. 工作流列表
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2351,7 +2401,7 @@ class ProjectController extends AbstractController
}
/**
* @api {post} api/project/flow/save 40. 保存工作流
* @api {post} api/project/flow/save 41. 保存工作流
*
* @apiDescription 需要token身份项目负责人
* @apiVersion 1.0.0
@@ -2385,7 +2435,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/flow/delete 41. 删除工作流
* @api {get} api/project/flow/delete 42. 删除工作流
*
* @apiDescription 需要token身份项目负责人
* @apiVersion 1.0.0
@@ -2417,7 +2467,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/log/lists 42. 获取项目、任务日志
* @api {get} api/project/log/lists 43. 获取项目、任务日志
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2447,7 +2497,7 @@ class ProjectController extends AbstractController
$builder->whereTaskId($task->id);
} else {
$project = Project::userProject($project_id);
$builder->with(['projectTask:id,parent_id,name'])->whereProjectId($project->id);
$builder->with(['projectTask:id,parent_id,name'])->whereProjectId($project->id)->whereTaskOnly(0);
}
//
$list = $builder->orderByDesc('created_at')->paginate(Base::getPaginate(100, 20));
@@ -2463,6 +2513,21 @@ class ProjectController extends AbstractController
'week' => Doo::translate("" . Base::getTimeWeek($timestamp)),
'segment' => Doo::translate(Base::getTimeDayeSegment($timestamp)),
];
$record = Base::json2array($log->record);
if (is_array($record['change'])) {
foreach ($record['change'] as &$item) {
$item = preg_replace_callback('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', function ($matches) {
$time = strtotime($matches[0]);
$second = date("s", $time);
$second = $second === "00" ? "" : ":$second";
if (date("Y") === date("Y", $time)) {
return date("m-d H:i", $time) . $second;
}
return date("Y-m-d H:i", $time) . $second;
}, $item);
}
$log->record = $record;
}
return $log;
});
//
@@ -2470,7 +2535,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/top 43. 项目置顶
* @api {get} api/project/top 44. 项目置顶
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2500,7 +2565,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/permission 44. 获取项目权限设置
* @api {get} api/project/permission 45. 获取项目权限设置
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2526,7 +2591,7 @@ class ProjectController extends AbstractController
}
/**
* @api {get} api/project/permission/update 45. 项目权限设置
* @api {get} api/project/permission/update 46. 项目权限设置
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0

View File

@@ -40,7 +40,7 @@ class SystemController extends AbstractController
* @apiParam {String} type
* - get: 获取(默认)
* - all: 获取所有(需要管理员权限)
* - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'e2e_message', 'auto_archived', 'archived_day', 'task_visible', 'task_default_time', 'all_group_mute', 'all_group_autoin', 'user_private_chat_mute', 'user_group_chat_mute', 'image_compress', 'image_save_local', 'start_home']
* - save: 保存设置(参数:['reg', 'reg_identity', 'reg_invite', 'temp_account_alias', 'login_code', 'password_policy', 'project_invite', 'chat_information', 'anon_message', 'voice2text', 'e2e_message', 'auto_archived', 'archived_day', 'task_visible', 'task_default_time', 'all_group_mute', 'all_group_autoin', 'user_private_chat_mute', 'user_group_chat_mute', 'image_compress', 'image_save_local', 'start_home']
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
@@ -60,11 +60,13 @@ class SystemController extends AbstractController
'reg',
'reg_identity',
'reg_invite',
'temp_account_alias',
'login_code',
'password_policy',
'project_invite',
'chat_information',
'anon_message',
'voice2text',
'e2e_message',
'auto_archived',
'archived_day',
@@ -92,6 +94,9 @@ class SystemController extends AbstractController
return Base::retError('自动归档时间不可大于100天');
}
}
if ($all['voice2text'] == 'open' && empty(Base::settingFind('aibotSetting', 'openai_key'))) {
return Base::retError('开启语音转文字功能需要在应用中开启 ChatGPT AI 机器人。');
}
$setting = Base::setting('system', Base::newTrim($all));
} else {
$setting = Base::setting('system');
@@ -99,18 +104,20 @@ class SystemController extends AbstractController
//
if ($type == 'all' || $type == 'save') {
User::auth('admin');
$setting['reg_invite'] = $setting['reg_invite'] ?: Base::generatePassword(8);
$setting['reg_invite'] = $setting['reg_invite'] ?: Base::generatePassword();
} else {
if (isset($setting['reg_invite'])) unset($setting['reg_invite']);
}
//
$setting['reg'] = $setting['reg'] ?: 'open';
$setting['reg_identity'] = $setting['reg_identity'] ?: 'normal';
$setting['temp_account_alias'] = $setting['temp_account_alias'] ?: '';
$setting['login_code'] = $setting['login_code'] ?: 'auto';
$setting['password_policy'] = $setting['password_policy'] ?: 'simple';
$setting['project_invite'] = $setting['project_invite'] ?: 'open';
$setting['chat_information'] = $setting['chat_information'] ?: 'optional';
$setting['anon_message'] = $setting['anon_message'] ?: 'open';
$setting['voice2text'] = $setting['voice2text'] ?: 'close';
$setting['e2e_message'] = $setting['e2e_message'] ?: 'close';
$setting['auto_archived'] = $setting['auto_archived'] ?: 'close';
$setting['archived_day'] = floatval($setting['archived_day']) ?: 7;
@@ -126,6 +133,7 @@ class SystemController extends AbstractController
$setting['file_upload_limit'] = $setting['file_upload_limit'] ?: '';
$setting['unclaimed_task_reminder'] = $setting['unclaimed_task_reminder'] ?: 'close';
$setting['unclaimed_task_reminder_time'] = $setting['unclaimed_task_reminder_time'] ?: '';
$setting['server_version'] = Base::getVersion();
//
return Base::retSuccess('success', $setting ?: json_decode('{}'));
}
@@ -201,7 +209,7 @@ class SystemController extends AbstractController
*
* @apiParam {String} type
* - get: 获取(默认)
* - save: 保存设置(参数:['open', 'appid', 'app_certificate']
* - save: 保存设置(参数:['open', 'appid', 'app_certificate', 'api_key', 'api_secret']
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
@@ -221,12 +229,14 @@ class SystemController extends AbstractController
'open',
'appid',
'app_certificate',
'api_key',
'api_secret',
])) {
unset($all[$key]);
}
}
if ($all['open'] === 'open' && (!$all['appid'] || !$all['app_certificate'])) {
return Base::retError('请填写完整的参数');
return Base::retError('请填写基本配置');
}
$setting = Base::setting('meetingSetting', Base::newTrim($all));
} else {
@@ -237,6 +247,8 @@ class SystemController extends AbstractController
if (env("SYSTEM_SETTING") == 'disabled') {
$setting['appid'] = substr($setting['appid'], 0, 4) . str_repeat('*', strlen($setting['appid']) - 8) . substr($setting['appid'], -4);
$setting['app_certificate'] = substr($setting['app_certificate'], 0, 4) . str_repeat('*', strlen($setting['app_certificate']) - 8) . substr($setting['app_certificate'], -4);
$setting['api_key'] = substr($setting['api_key'], 0, 4) . str_repeat('*', strlen($setting['api_key']) - 8) . substr($setting['api_key'], -4);
$setting['api_secret'] = substr($setting['api_secret'], 0, 4) . str_repeat('*', strlen($setting['api_secret']) - 8) . substr($setting['api_secret'], -4);
}
//
return Base::retSuccess('success', $setting ?: json_decode('{}'));
@@ -277,6 +289,8 @@ class SystemController extends AbstractController
'gemini_key',
'gemini_model',
'gemini_agency',
'zhipu_key',
'zhipu_model',
];
if ($type == 'save') {
@@ -322,12 +336,19 @@ class SystemController extends AbstractController
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true);
}
}
if ($backup['zhipu_key'] != $setting['zhipu_key']) {
$botUser = User::botGetOrCreate('ai-zhipu');
if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) {
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true);
}
}
}
//
$setting['openai_model'] = $setting['openai_model'] ?: 'gpt-3.5-turbo';
$setting['wenxin_model'] = $setting['wenxin_model'] ?: 'eb-instant';
$setting['qianwen_model'] = $setting['qianwen_model'] ?: 'qwen-v1';
$setting['gemini_model'] = $setting['gemini_model'] ?: 'gemini-1.0-pro';
$setting['zhipu_model'] = $setting['zhipu_model'] ?: 'glm-4';
if (env("SYSTEM_SETTING") == 'disabled') {
foreach ($keys as $item) {
if (strlen($setting[$item]) > 12) {
@@ -1210,7 +1231,7 @@ class SystemController extends AbstractController
if (count($users) > 1) {
$fileName .= "" . count($userid) . "位成员";
}
$fileName .= '签到记录_' . Base::time() . '.xls';
$fileName .= '签到记录_' . Base::time() . '.xlsx';
$filePath = "temp/checkin/export/" . date("Ym", Base::time());
$export = new BillMultipleExport($sheets);
$res = $export->store($filePath . "/" . $fileName);
@@ -1218,7 +1239,7 @@ class SystemController extends AbstractController
return Base::retError('导出失败,' . $fileName . '');
}
$xlsPath = storage_path("app/" . $filePath . "/" . $fileName);
$zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xls') . ".zip";
$zipFile = "app/" . $filePath . "/" . Base::rightDelete($fileName, '.xlsx') . ".zip";
$zipPath = storage_path($zipFile);
if (file_exists($zipPath)) {
Base::deleteDirAndFile($zipPath, true);
@@ -1275,8 +1296,14 @@ class SystemController extends AbstractController
* @apiGroup system
* @apiName version
*
* @apiSuccess {String} version
* @apiSuccess {String} publish
* @apiSuccessExample {json} Success-Response:
{
"version": "0.0.1",
"publish": {
"provider": "generic",
"url": ""
}
}
*/
public function version()
{
@@ -1298,4 +1325,52 @@ class SystemController extends AbstractController
}
return $array;
}
/**
* @api {get} api/system/prefetch 25. 预加载的资源
*
* @apiVersion 1.0.0
* @apiGroup system
* @apiName prefetch
*
* @apiSuccessExample {array} Success-Response:
[
"https://......",
"https://......",
"......",
]
*/
public function prefetch()
{
$userAgent = strtolower(Request::server('HTTP_USER_AGENT'));
$isMain = str_contains($userAgent, 'maintaskwindow');
$isApp = str_contains($userAgent, 'kuaifan_eeui');
$version = Base::getVersion();
$array = [];
if ($isMain || $isApp) {
$path = 'js/build/';
$list = Base::readDir(public_path($path), false);
foreach ($list as $item) {
if (is_file($item) && filesize($item) > 50 * 1024) {
$array[] = $path . basename($item);
}
}
}
if ($isMain) {
$file = base_path('.prefetch');
if (file_exists($file)) {
$content = file_get_contents($file);
$items = explode("\n", $content);
$array = array_merge($array, $items);
}
}
return array_map(function($item) use ($version) {
$url = trim($item);
$url = str_replace('{version}', $version, $url);
return url($url);
}, array_values(array_filter($array)));
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Http\Controllers\Api;
/**
* 测试
*/
class TestController extends AbstractController
{
}

View File

@@ -28,6 +28,7 @@ use App\Models\WebSocketDialogMsg;
use Illuminate\Support\Facades\DB;
use App\Models\UserEmailVerification;
use App\Module\AgoraIO\AgoraTokenGenerator;
use Swoole\Coroutine;
/**
* @apiDefine users
@@ -582,7 +583,7 @@ class UsersController extends AbstractController
$tags[] = Doo::translate("系统管理员");
}
if ($userInfo->isTemp()) {
$tags[] = Doo::translate("临时帐号");
$tags[] = User::tempAccountAlias(); // 临时帐号
}
if ($userInfo->userid > 3 && Carbon::parse($userInfo->created_at)->isAfter(Carbon::now()->subDays(30))) {
$tags[] = Doo::translate("新帐号");
@@ -615,7 +616,7 @@ class UsersController extends AbstractController
public function basic()
{
$sharekey = Request::header('sharekey');
if(empty($sharekey) || !Meeting::getShareInfo($sharekey)){
if (empty($sharekey) || !Meeting::getShareInfo($sharekey)) {
User::auth();
}
//
@@ -723,6 +724,7 @@ class UsersController extends AbstractController
}
}
if ($keys['disable'] === 'yes') {
$builder->orderByDesc('disable_at');
$builder->whereNotNull('disable_at');
} elseif ($keys['disable'] !== 'all') {
$builder->whereNull('disable_at');
@@ -768,7 +770,7 @@ class UsersController extends AbstractController
//
if ($getCheckinMac) {
$list->transform(function (User $user) use ($getCheckinMac) {
if($getCheckinMac){
if ($getCheckinMac) {
$user->checkin_macs = UserCheckinMac::select(['id', 'mac', 'remark'])->whereUserid($user->userid)->orderBy('id')->get();
}
return $user;
@@ -826,25 +828,30 @@ class UsersController extends AbstractController
}
$userInfo->checkSystem(1);
//
$msg = '修改成功';
$upArray = [];
$upLdap = [];
$transferUser = null;
switch ($type) {
case 'setadmin':
$msg = '设置成功';
$upArray['identity'] = array_diff($userInfo->identity, ['admin']);
$upArray['identity'][] = 'admin';
break;
case 'clearadmin':
$msg = '取消成功';
$upArray['identity'] = array_diff($userInfo->identity, ['admin']);
break;
case 'settemp':
$msg = '设置成功';
$upArray['identity'] = array_diff($userInfo->identity, ['temp']);
$upArray['identity'][] = 'temp';
break;
case 'cleartemp':
$msg = '取消成功';
$upArray['identity'] = array_diff($userInfo->identity, ['temp']);
break;
@@ -878,6 +885,7 @@ class UsersController extends AbstractController
break;
case 'setdisable':
$msg = '操作成功';
if ($userInfo->userid === $user->userid) {
return Base::retError('不能操作自己离职');
}
@@ -898,11 +906,13 @@ class UsersController extends AbstractController
break;
case 'cleardisable':
$msg = '操作成功';
$upArray['identity'] = array_diff($userInfo->identity, ['disable']);
$upArray['disable_at'] = null;
break;
case 'delete':
$msg = '删除成功';
if ($userInfo->userid === $user->userid) {
return Base::retError('不能删除自己');
}
@@ -1004,7 +1014,10 @@ class UsersController extends AbstractController
'new_userid' => $transferUser->userid,
]);
$userTransfer->save();
$userTransfer->start();
go(function () use ($userTransfer) {
Coroutine::sleep(0.1);
$userTransfer->start();
});
} elseif ($type === 'cleardisable') {
// 取消离职重新加入全员群组
if (Base::settingFind('system', 'all_group_autoin', 'yes') === 'yes') {
@@ -1015,7 +1028,7 @@ class UsersController extends AbstractController
});
}
//
return Base::retSuccess('修改成功', $userInfo);
return Base::retSuccess($msg, $userInfo);
}
/**
@@ -1101,10 +1114,17 @@ class UsersController extends AbstractController
];
$row = UmengAlias::where($inArray);
if ($row->exists()) {
$row->update(['updated_at' => Carbon::now()]);
$row->update([
'ua' => $data['userAgent'],
'device' => $data['deviceModel'],
'updated_at' => Carbon::now()
]);
return Base::retSuccess('别名已存在');
}
$row = UmengAlias::createInstance($inArray);
$row = UmengAlias::createInstance(array_merge($inArray, [
'ua' => $data['userAgent'],
'device' => $data['deviceModel'],
]));
if ($row->save()) {
return Base::retSuccess('添加成功');
} else {
@@ -1136,17 +1156,17 @@ class UsersController extends AbstractController
public function meeting__open()
{
$type = trim(Request::input('type'));
$meetingid = trim(Request::input('meetingid'));
$meetingid = str_replace(' ', '', trim(Request::input('meetingid')));
$name = trim(Request::input('name'));
$userids = Request::input('userids');
$sharekey = trim(Request::input('sharekey'));
$username = trim(Request::input('username'));
$user = null;
if(!empty($sharekey) && $type === 'join'){
if(!Meeting::getShareInfo($sharekey)){
if (!empty($sharekey) && $type === 'join') {
if (!Meeting::getShareInfo($sharekey)) {
return Base::retError('分享链接已过期');
}
}else{
} else {
$user = User::auth();
}
$isCreate = false;
@@ -1156,6 +1176,11 @@ class UsersController extends AbstractController
if (empty($meeting)) {
return Base::retError('频道ID不存在');
}
if ($meeting->end_at) {
return Base::retError('会议已结束');
}
$meeting->updated_at = Carbon::now();
$meeting->save();
} elseif ($type === 'create') {
$meetingid = strtoupper(Base::generatePassword(11, 1));
$name = $name ?: "{$user?->nickname} 发起的会议";
@@ -1180,9 +1205,9 @@ class UsersController extends AbstractController
if (empty($meetingSetting['appid']) || empty($meetingSetting['app_certificate'])) {
return Base::retError('会议功能配置错误,请联系管理员');
}
$uid = intval(str_pad(Base::generatePassword(4,1), 9, 8, STR_PAD_LEFT));
if($user){
$uid = intval(str_pad(Base::generatePassword(5,1), 6, 9, STR_PAD_LEFT).$user->userid);
$uid = intval(str_pad(Base::generatePassword(4, 1), 9, 8, STR_PAD_LEFT));
if ($user) {
$uid = intval(str_pad(Base::generatePassword(5, 1), 6, 9, STR_PAD_LEFT) . $user->userid);
}
try {
$service = new AgoraTokenGenerator($meetingSetting['appid'], $meetingSetting['app_certificate'], $meeting->channel, $uid);
@@ -1213,7 +1238,7 @@ class UsersController extends AbstractController
//
$data['appid'] = $meetingSetting['appid'];
$data['uid'] = $uid;
$data['userimg'] = $sharekey ? Base::fillUrl('avatar/'.$username.'.png') : $user?->userimg;
$data['userimg'] = $sharekey ? Base::fillUrl('avatar/' . $username . '.png') : $user?->userimg;
$data['nickname'] = $sharekey ? $username : $user?->nickname;
$data['token'] = $token;
$data['msgs'] = $msgs;
@@ -1242,7 +1267,7 @@ class UsersController extends AbstractController
{
$meetingid = trim(Request::input('meetingid'));
$sharekey = trim(Request::input('sharekey'));
if(empty($sharekey) || !Meeting::getShareInfo($sharekey)){
if (empty($sharekey) || !Meeting::getShareInfo($sharekey)) {
User::auth();
}
$meeting = Meeting::whereMeetingid($meetingid)->first();
@@ -1963,7 +1988,7 @@ class UsersController extends AbstractController
}
}
} else {
if($type == 'file'){
if ($type == 'file') {
$lists[] = [
'type' => 'children',
'url' => Base::fillUrl("api/users/share/list") . "?pid=0",

View File

@@ -10,18 +10,19 @@ use Response;
use App\Module\Doo;
use App\Models\File;
use App\Module\Base;
use App\Tasks\LoopTask;
use App\Module\Extranet;
use App\Tasks\AppPushTask;
use App\Module\RandomColor;
use App\Tasks\LoopTask;
use App\Tasks\AppPushTask;
use App\Tasks\JokeSoupTask;
use App\Tasks\DeleteTmpTask;
use App\Tasks\EmailNoticeTask;
use App\Tasks\AutoArchivedTask;
use App\Tasks\DeleteBotMsgTask;
use App\Tasks\CheckinRemindTask;
use Hhxsv5\LaravelS\Swoole\Task\Task;
use App\Tasks\CloseMeetingRoomTask;
use App\Tasks\UnclaimedTaskRemindTask;
use Hhxsv5\LaravelS\Swoole\Task\Task;
use LasseRafn\InitialAvatarGenerator\InitialAvatar;
@@ -38,14 +39,8 @@ class IndexController extends InvokeController
if ($action) {
$app .= "__" . $action;
}
switch ($app) {
case 'manifest.txt':
$app = 'manifest';
$child = 'txt';
break;
case 'default':
return '';
if ($app == 'default') {
return '';
}
if (!method_exists($this, $app)) {
$app = method_exists($this, $method) ? $method : 'main';
@@ -74,49 +69,7 @@ class IndexController extends InvokeController
'version' => Base::getVersion(),
'style' => $style,
'script' => $script,
])->header('Link', "<" . url('manifest.txt') . ">; rel=\"prefetch\"");
}
/**
* Manifest
* @param $child
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|string
*/
public function manifest($child = '')
{
if (empty($child)) {
$murl = url('manifest.txt');
return response($murl)->header('Link', "<{$murl}>; rel=\"prefetch\"");
}
$array = [
"office/web-apps/apps/api/documents/api.js?hash=" . Base::getVersion(),
"office/7.5.1-23/web-apps/vendor/requirejs/require.js",
"office/7.5.1-23/web-apps/apps/api/documents/api.js",
"office/7.5.1-23/sdkjs/common/AllFonts.js",
"office/7.5.1-23/web-apps/vendor/xregexp/xregexp-all-min.js",
"office/7.5.1-23/web-apps/vendor/sockjs/sockjs.min.js",
"office/7.5.1-23/web-apps/vendor/jszip/jszip.min.js",
"office/7.5.1-23/web-apps/vendor/jszip-utils/jszip-utils.min.js",
"office/7.5.1-23/sdkjs/common/libfont/wasm/fonts.js",
"office/7.5.1-23/sdkjs/common/Charts/ChartStyles.js",
"office/7.5.1-23/sdkjs/slide/themes//themes.js",
"office/7.5.1-23/web-apps/apps/presentationeditor/main/app.js",
"office/7.5.1-23/sdkjs/slide/sdk-all-min.js",
"office/7.5.1-23/sdkjs/slide/sdk-all.js",
"office/7.5.1-23/web-apps/apps/documenteditor/main/app.js",
"office/7.5.1-23/sdkjs/word/sdk-all-min.js",
"office/7.5.1-23/sdkjs/word/sdk-all.js",
"office/7.5.1-23/web-apps/apps/spreadsheeteditor/main/app.js",
"office/7.5.1-23/sdkjs/cell/sdk-all-min.js",
"office/7.5.1-23/sdkjs/cell/sdk-all.js",
];
foreach ($array as &$item) {
$item = url($item);
}
return implode(PHP_EOL, $array);
]);
}
/**
@@ -213,6 +166,8 @@ class IndexController extends InvokeController
Task::deliver(new JokeSoupTask());
// 未领取任务通知
Task::deliver(new UnclaimedTaskRemindTask());
// 关闭会议室
Task::deliver(new CloseMeetingRoomTask());
return "success";
}
@@ -240,7 +195,7 @@ class IndexController extends InvokeController
$publishPath = "uploads/desktop/{$publishVersion}/";
$res = Base::upload([
"file" => Request::file('file'),
"type" => 'desktop',
"type" => 'publish',
"path" => $publishPath,
"fileName" => true
]);
@@ -252,7 +207,7 @@ class IndexController extends InvokeController
if ($uploadSuccessFileNum >= $fileNum){
$directoryPath = public_path("uploads/desktop");
$files = array_filter(scandir($directoryPath), function($file) use($directoryPath) {
return is_dir($directoryPath . '/' . $file) && $file != '.' && $file != '..';
return preg_match("/^\d+\.\d+\.\d+$/", $file) && is_dir($directoryPath . '/' . $file) && $file != '.' && $file != '..';
});
sort($files);
foreach ($files as $key => $file) {
@@ -284,29 +239,6 @@ class IndexController extends InvokeController
];
}
//
$path = "uploads/android";
$dirPath = public_path($path);
$lists = Base::readDir($dirPath);
$apkFile = null;
foreach ($lists as $file) {
if (!str_ends_with($file, '.apk')) {
continue;
}
if ($apkFile && strtotime($apkFile['time']) > filemtime($file)) {
continue;
}
$fileName = Base::leftDelete($file, $dirPath);
$fileSize = filesize($file);
$apkFile = [
'name' => substr($fileName, 1),
'time' => date("Y-m-d H:i:s", filemtime($file)),
'size' => $fileSize > 0 ? Base::readableBytes($fileSize) : 0,
'url' => Base::fillUrl($path . $fileName),
];
}
if ($apkFile) {
$files = array_merge([$apkFile], $files);
}
return view('desktop', ['version' => $name, 'files' => $files]);
}
// 下载
@@ -350,77 +282,85 @@ class IndexController extends InvokeController
abort(404);
}
//
if (file_exists($file)) {
parse_str($data['query'], $query);
$name = Arr::get($query, 'name');
$ext = strtolower(Arr::get($query, 'ext'));
$userAgent = strtolower(Request::server('HTTP_USER_AGENT'));
if ($ext === 'pdf') {
// 文件超过 10m 不支持在线预览,提示下载
if (filesize($file) > 10 * 1024 * 1024) {
return view('download', [
'name' => $name,
'size' => Base::readableBytes(filesize($file)),
'url' => Base::fillUrl($path),
'button' => Doo::translate('点击下载'),
]);
}
// 浏览器类型
$browser = 'none';
if (str_contains($userAgent, 'chrome')) {
$browser = str_contains($userAgent, 'android') || str_contains($userAgent, 'harmonyos') ? 'android-mobile' : 'chrome-desktop';
} elseif (str_contains($userAgent, 'safari')) {
$browser = str_contains($userAgent, 'iphone') || str_contains($userAgent, 'ipad') ? 'safari-mobile' : 'safari-desktop';
}
// electron 直接在线预览查看
if (str_contains($userAgent, 'electron') || str_contains($browser, 'desktop')) {
return Response::download($file, $name, [
'Content-Type' => 'application/pdf'
], 'inline');
}
// EEUI App 直接在线预览查看
if (str_contains($userAgent, 'eeui') && Base::judgeClientVersion("0.34.47")) {
if ($browser === 'safari-mobile') {
$message = Base::array2json([
'type' => 'currentOpen',
'url' => Base::fillUrl($path),
]);
return "<script>window.top.postMessage($message, '*')</script>";
}
}
}
//
if (in_array($ext, File::localExt)) {
$url = Base::fillUrl($path);
} else {
$url = 'http://' . env('APP_IPPR') . '.3/' . $path;
}
if ($ext !== 'pdf') {
$url = Base::urlAddparameter($url, [
'fullfilename' => $name . '.' . $ext
if (!file_exists($file)) {
abort(404);
}
//
parse_str($data['query'], $query);
$name = Arr::get($query, 'name');
$ext = strtolower(Arr::get($query, 'ext'));
$userAgent = strtolower(Request::server('HTTP_USER_AGENT'));
if ($ext === 'pdf') {
// 文件超过 10m 不支持在线预览,提示下载
if (filesize($file) > 10 * 1024 * 1024) {
return view('download', [
'name' => $name,
'size' => Base::readableBytes(filesize($file)),
'url' => Base::fillUrl($path),
'button' => Doo::translate('点击下载'),
]);
}
$toUrl = Base::fillUrl("fileview/onlinePreview?url=" . urlencode(base64_encode($url)));
return Redirect::to($toUrl, 301);
// 浏览器类型
$browser = 'none';
if (str_contains($userAgent, 'chrome') || str_contains($userAgent, 'android_kuaifan_eeui')) {
$browser = str_contains($userAgent, 'android_kuaifan_eeui') ? 'android-mobile' : 'chrome-desktop';
} elseif (str_contains($userAgent, 'safari') || str_contains($userAgent, 'ios_kuaifan_eeui')) {
$browser = str_contains($userAgent, 'ios_kuaifan_eeui') ? 'safari-mobile' : 'safari-desktop';
}
// electron 直接在线预览查看
if (str_contains($userAgent, 'electron') || str_contains($browser, 'desktop')) {
return Response::download($file, $name, [
'Content-Type' => 'application/pdf'
], 'inline');
}
// EEUI App 直接在线预览查看
if (str_contains($userAgent, 'eeui') && Base::judgeClientVersion("0.34.47")) {
if ($browser === 'safari-mobile') {
$redirectUrl = Base::fillUrl($path);
return <<<EOF
<script>
window.top.postMessage({
action: "eeuiAppSendMessage",
data: [
{
action: 'setPageData',
data: {
showProgress: true,
titleFixed: true,
urlFixed: true,
}
},
{
action: 'createTarget',
url: "{$redirectUrl}",
}
]
}, "*")
</script>
EOF;
}
}
}
abort(404);
//
if (in_array($ext, File::localExt)) {
$url = Base::fillUrl($path);
} else {
$url = 'http://' . env('APP_IPPR') . '.3/' . $path;
}
$url = Base::urlAddparameter($url, [
'fullfilename' => Base::rightDelete($name, '.' . $ext) . '_' . filemtime($file) . '.' . $ext
]);
$redirectUrl = Base::fillUrl("fileview/onlinePreview?url=" . urlencode(base64_encode($url)));
return Redirect::to($redirectUrl, 301);
}
/**
* 保存配置
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|string
* 保存配置 (todo 已废弃)
* @return string
*/
public function storage__synch()
{
$key = Request::input('key');
$value = Request::input('value');
if ($key) {
$value = [$key => $value];
}
if (!is_array($value)) {
$value = Base::json2array($value);
}
return view('storage', ['value' => Base::array2json($value)]);
return '<!-- Deprecated -->';
}
/**

View File

@@ -15,9 +15,6 @@ class VerifyCsrfToken extends Middleware
// 接口部分
'api/*',
// 保存配置
'storage/synch/',
// 发布桌面端
'desktop/publish/',
];

View File

@@ -11,9 +11,15 @@ namespace App\Models;
* @property int|null $msg_id 消息ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ApproveProcMsg whereMsgId($value)

41
app/Models/Complaint.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
namespace App\Models;
/**
* App\Models\Complaint
*
* @property int $id
* @property int|null $dialog_id 对话ID
* @property int|null $userid 举报人id
* @property int|null $type 举报类型
* @property string|null $reason 举报原因
* @property string|null $imgs 举报图片
* @property int|null $status 状态 0待处理、1已处理、2已删除
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Complaint newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Complaint newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Complaint query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereImgs($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereReason($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereStatus($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Complaint whereUserid($value)
* @mixin \Eloquent
*/
class Complaint extends AbstractModel
{
}

View File

@@ -12,9 +12,15 @@ use Carbon\Carbon;
* @property int|null $did 删除的数据ID
* @property int|null $userid 关系会员ID
* @property \Illuminate\Support\Carbon|null $created_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Deleted newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Deleted newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Deleted query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Deleted whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Deleted whereDid($value)
* @method static \Illuminate\Database\Eloquent\Builder|Deleted whereId($value)

View File

@@ -28,10 +28,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|File newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|File newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|File onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|File query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|File whereCid($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereCreatedId($value)
@@ -190,9 +196,10 @@ class File extends AbstractModel
* @param user $user
* @param int $pid
* @param string $webkitRelativePath
* @param bool $overwrite
* @return array
*/
public function contentUpload($user, int $pid, $webkitRelativePath)
public function contentUpload($user, int $pid, $webkitRelativePath, $overwrite = false)
{
$userid = $user->userid;
if ($pid > 0) {
@@ -283,17 +290,25 @@ class File extends AbstractModel
if ($data['ext'] == 'markdown') {
$data['ext'] = 'md';
}
$file = File::createInstance([
$file = null;
$params = [
'pid' => $pid,
'name' => Base::rightDelete($data['name'], '.' . $data['ext']),
'type' => $type,
'ext' => $data['ext'],
'userid' => $userid,
'created_id' => $user->userid,
]);
$file->handleDuplicateName();
];
if ($overwrite) {
$file = self::wherePid($params['pid'])->whereExt($params['ext'])->whereName($params['name'])->first();
}
if (!$file) {
$overwrite = false;
$file = File::createInstance($params);
$file->handleDuplicateName();
}
// 开始创建
return AbstractModel::transaction(function () use ($addItem, $webkitRelativePath, $type, $user, $data, $file) {
return AbstractModel::transaction(function () use ($overwrite, $addItem, $webkitRelativePath, $type, $user, $data, $file) {
$file->size = $data['size'] * 1024;
$file->saveBeforePP();
//
@@ -321,11 +336,12 @@ class File extends AbstractModel
$tmpRow->pushMsg('add', $tmpRow);
//
$data = File::handleImageUrl($tmpRow->toArray());
$data['full_name'] = $webkitRelativePath ?: $data['name'];
$data['full_name'] = $webkitRelativePath ?: ($data['name'] . '.' . $data['ext']);
$data['overwrite'] = $overwrite ? 1 : 0;
//
$addItem[] = $data;
return ['data'=>$data,'addItem'=>$addItem];
return ['data' => $data, 'addItem' => $addItem];
});
}

View File

@@ -18,10 +18,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|FileContent newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileContent newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileContent onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|FileContent query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|FileContent whereContent($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileContent whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileContent whereDeletedAt($value)
@@ -70,7 +76,7 @@ class FileContent extends AbstractModel
'name' => $name,
'ext' => $fileExt
]));
return Base::fillUrl("online/preview/{$name}?key={$key}");
return Base::fillUrl("online/preview/{$name}?key={$key}&version=" . Base::getVersion() . "&__=" . Base::msecTime());
}
/**

View File

@@ -8,16 +8,22 @@ use App\Module\Base;
* App\Models\FileLink
*
* @property int $id
* @property int|null $file_id 项目ID
* @property int|null $file_id 文件ID
* @property int|null $num 累计访问
* @property string|null $code 链接码
* @property int|null $userid 会员ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\File|null $file
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|FileLink newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileLink newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileLink query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|FileLink whereCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileLink whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileLink whereFileId($value)

View File

@@ -12,9 +12,15 @@ namespace App\Models;
* @property int|null $permission 权限0只读1读写
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|FileUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|FileUser query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|FileUser whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileUser whereFileId($value)
* @method static \Illuminate\Database\Eloquent\Builder|FileUser whereId($value)

View File

@@ -18,9 +18,15 @@ use Illuminate\Support\Carbon;
* @property Carbon|null $updated_at
* @property string|null $end_at
* @property Carbon|null $deleted_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Meeting newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Meeting newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Meeting query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Meeting whereChannel($value)
* @method static \Illuminate\Database\Eloquent\Builder|Meeting whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Meeting whereDeletedAt($value)
@@ -44,12 +50,12 @@ class Meeting extends AbstractModel
public function getShareLink()
{
$code = base64_encode("{$this->meetingid}" . Base::generatePassword());
Cache::put(self::CACHE_KEY.'_'.$code, [
Cache::put(self::CACHE_KEY . '_' . $code, [
'id' => $this->id,
'meetingid' => $this->meetingid,
'channel' => $this->channel,
], Carbon::now()->addHours(self::CACHE_EXPIRED_TIME));
return Base::fillUrl("meeting/{$this->meetingid}/".$code);
return Base::fillUrl("meeting/{$this->meetingid}/" . $code);
}
/**
@@ -58,19 +64,19 @@ class Meeting extends AbstractModel
*/
public static function getShareInfo($code)
{
if(Cache::has(self::CACHE_KEY.'_'.$code)){
return Cache::get(self::CACHE_KEY.'_'.$code);
if (Cache::has(self::CACHE_KEY . '_' . $code)) {
return Cache::get(self::CACHE_KEY . '_' . $code);
}
return null;
}
/**
* 保存访客信息
* @return mixed
* @return void
*/
public static function setTouristInfo($data)
{
Cache::put(Meeting::CACHE_KEY.'_'.$data['uid'], [
Cache::put(Meeting::CACHE_KEY . '_' . $data['uid'], [
'uid' => $data['uid'],
'userimg' => $data['userimg'],
'nickname' => $data['nickname'],
@@ -83,8 +89,8 @@ class Meeting extends AbstractModel
*/
public static function getTouristInfo($touristId)
{
if(Cache::has(Meeting::CACHE_KEY.'_'.$touristId)){
return Cache::get(Meeting::CACHE_KEY.'_'.$touristId);
if (Cache::has(Meeting::CACHE_KEY . '_' . $touristId)) {
return Cache::get(Meeting::CACHE_KEY . '_' . $touristId);
}
return null;
}

34
app/Models/MeetingMsg.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace App\Models;
/**
* App\Models\MeetingMsg
*
* @property int $id
* @property string|null $meetingid 会议ID
* @property int|null $dialog_id 对话ID
* @property int|null $msg_id 消息ID
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg whereMeetingid($value)
* @method static \Illuminate\Database\Eloquent\Builder|MeetingMsg whereMsgId($value)
* @mixin \Eloquent
*/
class MeetingMsg extends AbstractModel
{
function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->timestamps = false;
}
}

View File

@@ -36,10 +36,16 @@ use Request;
* @property-read int|null $project_user_count
* @method static \Illuminate\Database\Eloquent\Builder|Project allData($userid = null)
* @method static \Illuminate\Database\Eloquent\Builder|Project authData($userid = null, $owner = null)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Project newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Project newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Project onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|Project query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Project whereArchivedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Project whereArchivedUserid($value)
* @method static \Illuminate\Database\Eloquent\Builder|Project whereCreatedAt($value)

View File

@@ -22,10 +22,16 @@ use Request;
* @property-read \App\Models\Project|null $project
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ProjectTask> $projectTask
* @property-read int|null $project_task_count
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn whereColor($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectColumn whereDeletedAt($value)

View File

@@ -2,8 +2,6 @@
namespace App\Models;
use App\Module\Base;
/**
* App\Models\ProjectFlow
*
@@ -14,9 +12,15 @@ use App\Module\Base;
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ProjectFlowItem> $projectFlowItem
* @property-read int|null $project_flow_item_count
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlow whereName($value)

View File

@@ -13,7 +13,7 @@ use App\Module\Base;
* @property string|null $name 名称
* @property string|null $status 状态
* @property array $turns 可流转
* @property array $userids 自动负责人ID
* @property array $userids 状态负责人ID
* @property string|null $usertype 流转模式
* @property int|null $userlimit 限制负责人
* @property int|null $columnid 对应的项目列表
@@ -21,9 +21,15 @@ use App\Module\Base;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\ProjectFlow|null $projectFlow
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereColumnid($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereFlowId($value)

View File

@@ -13,9 +13,15 @@ namespace App\Models;
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read bool $already
* @property-read \App\Models\Project|null $project
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite whereCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectInvite whereId($value)

View File

@@ -10,7 +10,8 @@ use App\Module\Base;
* @property int $id
* @property int|null $project_id 项目ID
* @property int|null $column_id 列表ID
* @property int|null $task_id 项目ID
* @property int|null $task_id 任务ID
* @property int|null $task_only 仅任务日志0否1是
* @property int|null $userid 会员ID
* @property string|null $detail 详细信息
* @property array $record 记录数据
@@ -18,9 +19,15 @@ use App\Module\Base;
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\ProjectTask|null $projectTask
* @property-read \App\Models\User|null $user
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereColumnId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereDetail($value)
@@ -28,12 +35,16 @@ use App\Module\Base;
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereProjectId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereRecord($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereTaskId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereTaskOnly($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectLog whereUserid($value)
* @mixin \Eloquent
*/
class ProjectLog extends AbstractModel
{
protected $hidden = [
'task_only',
];
/**
* @param $value

View File

@@ -13,9 +13,15 @@ use App\Module\Base;
* @property string $permissions 权限
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectPermission wherePermissions($value)

View File

@@ -9,8 +9,8 @@ use Carbon\Carbon;
use App\Module\Base;
use App\Tasks\PushTask;
use App\Exceptions\ApiException;
use App\Observers\ProjectTaskObserver;
use Hhxsv5\LaravelS\Swoole\Task\Task;
use App\Models\ProjectTaskVisibilityUser;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@@ -63,10 +63,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask allData($userid = null)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask authData($userid = null, $owner = null)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask betweenTime($start, $end, $type = 'taskTime')
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereArchivedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereArchivedFollow($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTask whereArchivedUserid($value)
@@ -329,13 +335,7 @@ class ProjectTask extends AbstractModel
$query->where(function ($q1) use ($start, $end, $type) {
switch ($type) {
case 'createdTime':
$q1->where(function ($q2) use ($start) {
$q2->where('project_tasks.created_at', '>=', $start);
})->orWhere(function ($q2) use ($end) {
$q2->where('project_tasks.created_at', '<=', $end);
})->orWhere(function ($q2) use ($start, $end) {
$q2->where('project_tasks.created_at', '>', $start)->where('project_tasks.created_at', '<', $end);
});
$q1->where('project_tasks.created_at', '>=', $start)->where('project_tasks.created_at', '<=', $end);
break;
default:
@@ -352,6 +352,25 @@ class ProjectTask extends AbstractModel
return $query;
}
/**
* 生成描述
* @param $content
* @return string
*/
public static function generateDesc($content)
{
$content = preg_replace_callback('/<ul class="tox-checklist">(.+?)<\/ul>/is', function ($matches) {
return preg_replace_callback('/<li([^>]*)>(.+?)<\/li>/is', function ($m) {
if (str_contains($m[1], 'tox-checklist--checked')) {
return "<li{$m[1]}>[√]{$m[2]} </li>";
} else {
return "<li{$m[1]}>[ ]{$m[2]} </li>";
}
}, $matches[0]);
}, $content);
return Base::cutStr(strip_tags($content), 100, 0, "...");
}
/**
* 添加任务
* @param $data
@@ -374,7 +393,7 @@ class ProjectTask extends AbstractModel
$p_color = $data['p_color'];
$top = intval($data['top']);
$userid = User::userid();
$visibility = isset($data['visibility_appoint']) ? $data['visibility_appoint'] : $data['visibility'];
$visibility = $data['visibility_appoint'] ?? $data['visibility'];
$visibility_userids = $data['visibility_appointor'] ?: [];
//
if (ProjectTask::whereProjectId($project_id)
@@ -407,7 +426,7 @@ class ProjectTask extends AbstractModel
'visibility' => $visibility ?: 1
]);
if ($content) {
$task->desc = Base::getHtml($content, 100);
$task->desc = self::generateDesc($content);
}
// 标题
if (empty($name)) {
@@ -508,6 +527,8 @@ class ProjectTask extends AbstractModel
ProjectTaskContent::createInstance([
'project_id' => $task->project_id,
'task_id' => $task->id,
'userid' => $task->userid,
'desc' => $task->desc,
'content' => [
'url' => ProjectTaskContent::saveContent($task->id, $content)
],
@@ -724,8 +745,8 @@ class ProjectTask extends AbstractModel
// 可见性
if (Arr::exists($data, 'visibility') || Arr::exists($data, 'visibility_appointor')) {
if (Arr::exists($data, 'visibility')) {
ProjectTask::whereId($data['task_id'])->update(['visibility' => $data["visibility"]]);
ProjectTask::whereParentId($data['task_id'])->update(['visibility' => $data["visibility"]]);
$this->visibility = $data["visibility"];
ProjectTask::whereParentId($data['task_id'])->change(['visibility' => $data["visibility"]]);
}
ProjectTaskVisibilityUser::whereTaskId($data['task_id'])->delete();
if (Arr::exists($data, 'visibility_appointor')) {
@@ -738,6 +759,9 @@ class ProjectTask extends AbstractModel
])->save();
}
}
if (!Arr::exists($data, 'visibility')) {
ProjectTaskObserver::visibilityUpdate($this);
}
}
}
// 计划时间(原则:子任务时间在主任务时间内)
@@ -894,15 +918,25 @@ class ProjectTask extends AbstractModel
}
// 内容
if (Arr::exists($data, 'content')) {
$logRecord = [];
$logContent = ProjectTaskContent::whereTaskId($this->id)->orderByDesc('id')->first();
if ($logContent) {
$logRecord['link'] = [
'title' => '查看历史',
'url' => 'single/task/content/' . $this->id . '?history_id=' . $logContent->id,
];
}
$this->desc = self::generateDesc($data['content']);
ProjectTaskContent::createInstance([
'project_id' => $this->project_id,
'task_id' => $this->id,
'userid' => User::userid(),
'desc' => $this->desc,
'content' => [
'url' => ProjectTaskContent::saveContent($this->id, $data['content'])
],
])->save();
$this->desc = Base::getHtml($data['content'], 100);
$this->addLog("修改{任务}详细描述");
$this->addLog("修改{任务}详细描述", $logRecord);
$updateMarking['is_update_content'] = true;
}
// 优先级
@@ -1379,7 +1413,7 @@ class ProjectTask extends AbstractModel
* @param int $userid
* @return ProjectLog
*/
public function addLog($detail, $record = [], $userid = 0)
public function addLog($detail, $record = [], $userid = 0, $taskOnly = 0)
{
$detail = str_replace("{任务}", $this->parent_id ? "子任务" : "任务", $detail);
$array = [
@@ -1395,6 +1429,9 @@ class ProjectTask extends AbstractModel
if ($record) {
$array['record'] = $record;
}
if ($taskOnly) {
$array['task_only'] = $taskOnly;
}
$log = ProjectLog::createInstance($array);
$log->save();
return $log;
@@ -1636,7 +1673,9 @@ class ProjectTask extends AbstractModel
if (empty($receivers)) {
return;
}
//
$userid = User::userid();
//
$botUser = User::botGetOrCreate('task-alert');
if (empty($botUser)) {
return;
@@ -1668,7 +1707,7 @@ class ProjectTask extends AbstractModel
ProjectTaskPushLog::createInstance($data)->save();
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', [
'text' => str_replace("您的任务", $replace, $text) . $suffix
], $botUser->userid);
], in_array($type, [0, 3]) ? $userid : $botUser->userid);
}
}
}
@@ -1682,46 +1721,58 @@ class ProjectTask extends AbstractModel
* @param array $assist
* @return bool
*/
public function moveTask(int $projectId, int $columnId,int $flowItemId = 0,array $owner = [], array $assist = [])
public function moveTask(int $projectId, int $columnId,int $flowItemId = 0,array $owner = [], array $assist = [], string $completeAt='')
{
AbstractModel::transaction(function () use($projectId, $columnId, $flowItemId, $owner, $assist) {
AbstractModel::transaction(function () use ($projectId, $columnId, $flowItemId, $owner, $assist, $completeAt) {
$newTaskUser = array_merge($owner, $assist);
//
$this->project_id = $projectId;
$this->column_id = $columnId;
$this->flow_item_id = $flowItemId;
// 任务内容
if($this->content){
if ($this->content) {
$this->content->project_id = $projectId;
$this->content->save();
}
// 任务文件
foreach ($this->taskFile as $taskFile){
foreach ($this->taskFile as $taskFile) {
$taskFile->project_id = $projectId;
$taskFile->save();
}
// 任务标签
foreach ($this->taskTag as $taskTag){
foreach ($this->taskTag as $taskTag) {
$taskTag->project_id = $projectId;
$taskTag->save();
}
// 任务用户
$this->updateTask(['owner' => $owner]);
$this->updateTask(['assist' => $assist]);
foreach ($this->taskUser as $taskUser){
if( in_array($taskUser->id, $newTaskUser) ){
$this->updateTask([
'owner' => $owner,
'assist' => $assist
]);
foreach ($this->taskUser as $taskUser) {
if (in_array($taskUser->id, $newTaskUser)) {
$taskUser->project_id = $projectId;
$taskUser->save();
}
}
//
if($flowItemId){
if ($flowItemId) {
$flowItem = projectFlowItem::whereProjectId($projectId)->whereId($flowItemId)->first();
$this->flow_item_id = $flowItemId;
$this->flow_item_name = $flowItem->status . "|" . $flowItem->name;
}else{
if ($flowItem->status == 'end') {
$this->completeTask(Carbon::now(), $flowItem->name);
} else {
$this->completeTask(null);
}
} else {
$this->flow_item_id = 0;
$this->flow_item_name = '';
}
//
if ($completeAt) {
$this->complete_at = $completeAt;
}
//
$this->save();
//
$this->addLog("移动{任务}");

View File

@@ -11,24 +11,33 @@ use App\Exceptions\ApiException;
* @property int $id
* @property int|null $project_id 项目ID
* @property int|null $task_id 任务ID
* @property int|null $userid 用户ID
* @property string|null $desc 内容描述
* @property string|null $content 内容
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereContent($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereDesc($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereProjectId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereTaskId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskContent whereUserid($value)
* @mixin \Eloquent
*/
class ProjectTaskContent extends AbstractModel
{
protected $hidden = [
'created_at',
'updated_at',
];

View File

@@ -22,9 +22,15 @@ use Cache;
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read int $height
* @property-read int $width
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile whereDownload($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFile whereExt($value)

View File

@@ -14,9 +14,15 @@ namespace App\Models;
* @property string|null $after_flow_item_name (变化后)工作流状态名称
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange whereAfterFlowItemId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange whereAfterFlowItemName($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskFlowChange whereBeforeFlowItemId($value)

View File

@@ -17,10 +17,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskPushLog whereId($value)

View File

@@ -12,9 +12,15 @@ namespace App\Models;
* @property string|null $color 颜色
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag whereColor($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskTag whereId($value)

View File

@@ -14,9 +14,15 @@ namespace App\Models;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\ProjectTask|null $projectTask
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskUser whereOwner($value)
@@ -46,7 +52,7 @@ class ProjectTaskUser extends AbstractModel
*/
public static function transfer($originalUserid, $newUserid)
{
self::whereUserid($originalUserid)->chunk(100, function ($list) use ($originalUserid, $newUserid) {
self::whereUserid($originalUserid)->chunkById(100, function ($list) use ($originalUserid, $newUserid) {
$tastIds = [];
/** @var self $item */
foreach ($list as $item) {
@@ -62,7 +68,7 @@ class ProjectTaskUser extends AbstractModel
$item->save();
}
if ($item->projectTask) {
$item->projectTask->addLog("移交{任务}身份", ['userid' => [$originalUserid, ' => ', $newUserid]]);
$item->projectTask->addLog("移交{任务}身份", ['userid' => [$originalUserid, ' => ', $newUserid]], 0, 1);
if (!in_array($item->task_pid, $tastIds)) {
$tastIds[] = $item->task_pid;
$item->projectTask->syncDialogUser();

View File

@@ -12,9 +12,15 @@ namespace App\Models;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\ProjectTask|null $projectTask
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectTaskVisibilityUser whereProjectId($value)

View File

@@ -13,9 +13,15 @@ namespace App\Models;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\Project|null $project
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ProjectUser whereOwner($value)

View File

@@ -29,9 +29,15 @@ use JetBrains\PhpStorm\Pure;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $receivesUser
* @property-read int|null $receives_user_count
* @property-read \App\Models\User|null $sendUser
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static Builder|Report newModelQuery()
* @method static Builder|Report newQuery()
* @method static Builder|Report query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static Builder|Report whereContent($value)
* @method static Builder|Report whereCreatedAt($value)
* @method static Builder|Report whereId($value)

View File

@@ -13,9 +13,15 @@ use Illuminate\Database\Eloquent\Model;
* @property string|null $receive_time 接收时间
* @property int $userid 接收人
* @property int $read 是否已读
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereRead($value)
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereReceiveTime($value)

View File

@@ -13,9 +13,15 @@ use App\Module\Base;
* @property string|null $setting
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Setting newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Setting newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Setting query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereDesc($value)
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereId($value)

View File

@@ -15,10 +15,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker whereArgs($value)
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|TaskWorker whereDeletedAt($value)

View File

@@ -11,9 +11,15 @@ namespace App\Models;
* @property string|null $content
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|Tmp newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Tmp newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Tmp query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|Tmp whereContent($value)
* @method static \Illuminate\Database\Eloquent\Builder|Tmp whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Tmp whereId($value)

View File

@@ -14,15 +14,25 @@ use Hedeqiang\UMeng\IOS;
* @property int|null $userid 会员ID
* @property string|null $alias 别名
* @property string|null $platform 平台类型
* @property string|null $device 设备类型
* @property string|null $ua userAgent
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereAlias($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereDevice($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias wherePlatform($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUa($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUserid($value)
* @mixin \Eloquent
@@ -142,7 +152,13 @@ class UmengAlias extends AbstractModel
'mi_activity' => 'app.eeui.umeng.activity.MfrMessageActivity',
'policy' => [
'expire_time' => Carbon::now()->addSeconds($seconds)->toDateTimeString(),
]
],
'channel_properties' => [
'vivo_category' => 'IM',
'huawei_channel_importance' => 'NORMAL',
'huawei_channel_category' => 'IM',
'channel_fcm' => 1,
],
]);
default:

View File

@@ -37,10 +37,16 @@ use Carbon\Carbon;
* @property int|null $bot 是否机器人
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Database\Factories\UserFactory factory(...$parameters)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|User whereAz($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereBot($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereChangepass($value)
@@ -527,6 +533,16 @@ class User extends AbstractModel
}
}
/**
* 临时帐号别名
* @return mixed|string
*/
public static function tempAccountAlias()
{
$alias = Base::settingFind('system', 'temp_account_alias');
return $alias ?: Doo::translate("临时帐号");
}
/**
* 获取头像
* @param $userid
@@ -561,6 +577,8 @@ class User extends AbstractModel
return url("images/avatar/default_claude.png");
case 'ai-gemini@bot.system':
return url("images/avatar/default_gemini.png");
case 'ai-zhipu@bot.system':
return url("images/avatar/default_zhipu.png");
case 'bot-manager@bot.system':
return url("images/avatar/default_bot.png");
case 'meeting-alert@bot.system':

View File

@@ -5,6 +5,7 @@ namespace App\Models;
use App\Module\Base;
use App\Module\Doo;
use App\Module\Extranet;
use App\Tasks\JokeSoupTask;
use Cache;
use Carbon\Carbon;
@@ -20,9 +21,15 @@ use Carbon\Carbon;
* @property int|null $webhook_num 消息webhook请求次数
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserBot newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserBot newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserBot query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereBotId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereClearAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserBot whereClearDay($value)
@@ -58,6 +65,7 @@ class UserBot extends AbstractModel
'ai-wenxin' => '文心一言',
'ai-qianwen' => '通义千问',
'ai-gemini' => 'Gemini',
'ai-zhipu' => '智谱清言',
'bot-manager' => '机器人管理',
'meeting-alert' => '会议通知',
'okr-alert' => 'OKR提醒',
@@ -119,6 +127,7 @@ class UserBot extends AbstractModel
'ai-claude@bot.system',
'ai-wenxin@bot.system',
'ai-gemini@bot.system',
'ai-zhipu@bot.system',
'ai-qianwen@bot.system' => [
[
'key' => '%3A.clear',
@@ -229,8 +238,8 @@ class UserBot extends AbstractModel
if ($checkins && $botUser = User::botGetOrCreate('check-in')) {
$getJokeSoup = function($type) {
$pre = $type == "up" ? "每日开心:" : "心灵鸡汤:";
$key = $type == "up" ? "JokeSoupTask:jokes" : "JokeSoupTask:soups";
$array = Base::json2array(Cache::get($key));
$key = $type == "up" ? "jokes" : "soups";
$array = Base::json2array(Cache::get(JokeSoupTask::keyName($key)));
if ($array) {
$item = $array[array_rand($array)];
if ($item) {

View File

@@ -15,9 +15,15 @@ use App\Module\Base;
* @property string|null $remark 备注
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinMac whereMac($value)

View File

@@ -16,9 +16,15 @@ use App\Module\Base;
* @property int|null $report_time 上报的时间戳
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord whereDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinRecord whereId($value)

View File

@@ -16,9 +16,15 @@ use App\Module\Base;
* @property string $cache 会员资料缓存
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete whereCache($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserDelete whereEmail($value)

View File

@@ -14,9 +14,15 @@ use App\Exceptions\ApiException;
* @property int|null $owner_userid 部门负责人
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserDepartment whereId($value)

View File

@@ -19,9 +19,15 @@ use Guanguans\Notify\Messages\EmailMessage;
* @property int|null $type 邮件类型1-邮箱认证2-修改邮箱
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification whereCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserEmailVerification whereEmail($value)

View File

@@ -16,9 +16,15 @@ use Guanguans\Notify\Messages\EmailMessage;
* @property int|null $new_userid 交接人
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserTransfer whereNewUserid($value)

View File

@@ -13,9 +13,15 @@ namespace App\Models;
* @property int|null $userid
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereFd($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereId($value)

View File

@@ -20,29 +20,35 @@ use Illuminate\Support\Facades\DB;
* @property string|null $group_type 聊天室类型
* @property string|null $name 对话名称
* @property string $avatar 头像(群)
* @property string|null $last_at 最后消息时间
* @property int|null $owner_id 群主用户ID
* @property int|null $link_id 关联id
* @property int|null $top_userid 置顶的用户ID
* @property int|null $top_msg_id 置顶的消息ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\WebSocketDialogUser> $dialogUser
* @property-read int|null $dialog_user_count
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereAvatar($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereGroupType($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereLastAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereLinkId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereOwnerId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereTopMsgId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereTopUserid($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialog withTrashed()
@@ -81,7 +87,7 @@ class WebSocketDialog extends AbstractModel
*/
public static function getDialogList($userid, $updated = "", $deleted = "")
{
$builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at'])
$builder = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('u.userid', $userid);
if ($updated) {
@@ -89,7 +95,7 @@ class WebSocketDialog extends AbstractModel
}
$list = $builder
->orderByDesc('u.top_at')
->orderByDesc('web_socket_dialogs.last_at')
->orderByDesc('u.last_at')
->paginate(Base::getPaginate(100, 50));
$list->transform(function (WebSocketDialog $item) use ($userid) {
return $item->formatData($userid);
@@ -103,31 +109,70 @@ class WebSocketDialog extends AbstractModel
}
/**
* 获取未读对话列表
* 列表外的未读对话 和 列表外的待办对话
* @param $userid
* @param $beforeAt
* @param $take
* @param $unreadAt
* @param $todoAt
* @return WebSocketDialog[]
*/
public static function getDialogUnread($userid, $beforeAt, $take = 20)
public static function getDialogBeyond($userid, $unreadAt, $todoAt)
{
DB::statement("SET SQL_MODE=''");
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msg_reads as r', 'web_socket_dialogs.id', '=', 'r.dialog_id')
->where('u.userid', $userid)
->where('r.userid', $userid)
->where('r.silence', 0)
->where('r.read_at')
->where('web_socket_dialogs.last_at', '>', $beforeAt)
->groupBy('web_socket_dialogs.id')
->take(min(100, $take))
->get();
$list->transform(function (WebSocketDialog $item) use ($userid) {
return $item->formatData($userid);
});
//
return $list;
$ids = [];
$array = [];
if ($unreadAt) {
// 未读对话
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msg_reads as r', 'web_socket_dialogs.id', '=', 'r.dialog_id')
->where('u.userid', $userid)
->where('r.userid', $userid)
->where('r.read_at')
->where('u.last_at', '<', $unreadAt)
->groupBy('u.dialog_id')
->take(20)
->get();
$list->transform(function (WebSocketDialog $item) use ($userid, &$ids, &$array) {
if (!in_array($item->id, $ids)) {
$ids[] = $item->id;
$array[] = $item->formatData($userid);
}
});
// 标记未读会话
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('u.userid', $userid)
->where('u.mark_unread', 1)
->where('u.last_at', '<', $unreadAt)
->take(20)
->get();
$list->transform(function (WebSocketDialog $item) use ($userid, &$ids, &$array) {
if (!in_array($item->id, $ids)) {
$ids[] = $item->id;
$array[] = $item->formatData($userid);
}
});
}
if ($todoAt) {
// 待办会话
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->join('web_socket_dialog_msg_todos as t', 'web_socket_dialogs.id', '=', 't.dialog_id')
->where('u.userid', $userid)
->where('t.userid', $userid)
->where('t.done_at')
->where('u.last_at', '<', $todoAt)
->groupBy('u.dialog_id')
->take(20)
->get();
$list->transform(function (WebSocketDialog $item) use ($userid, &$ids, &$array) {
if (!in_array($item->id, $ids)) {
$ids[] = $item->id;
$array[] = $item->formatData($userid);
}
});
}
return $array;
}
@@ -147,14 +192,16 @@ class WebSocketDialog extends AbstractModel
};
//
$time = Carbon::parse($this->user_at ?? $dialogUserFun('updated_at'));
$this->hide = $this->hide ?? $dialogUserFun('hide');
$this->top_at = $this->top_at ?? $dialogUserFun('top_at');
$this->last_at = $this->last_at ?? $dialogUserFun('last_at');
$this->user_at = $time->toDateTimeString('millisecond');
$this->user_ms = $time->valueOf();
//
if (isset($this->search_msg_id)) {
// 最后消息 (搜索预览消息)
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id);
$this->last_at = $this->last_msg?->created_at;
$this->last_at = $this->last_msg ? Carbon::parse($this->last_msg->created_at)->format('Y-m-d H:i:s') : null;
} else {
// 未读信息
if (Base::judgeClientVersion("0.34.0")) {
@@ -551,20 +598,6 @@ class WebSocketDialog extends AbstractModel
Task::deliver($task);
}
/**
* 更新对话最后消息时间
* @return WebSocketDialogMsg|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
*/
public function updateMsgLastAt()
{
$lastMsg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
if ($lastMsg) {
$this->last_at = $lastMsg->created_at;
$this->save();
}
return $lastMsg;
}
/**
* 获取对话(同时检验对话身份)
* @param $dialog_id
@@ -621,7 +654,6 @@ class WebSocketDialog extends AbstractModel
'name' => $name ?: '',
'group_type' => $group_type,
'owner_id' => $owner_id,
'last_at' => in_array($group_type, ['user', 'department', 'all']) ? Carbon::now() : null,
]);
$dialog->save();
foreach (is_array($userid) ? $userid : [$userid] as $value) {
@@ -629,7 +661,8 @@ class WebSocketDialog extends AbstractModel
WebSocketDialogUser::createInstance([
'dialog_id' => $dialog->id,
'userid' => $value,
'important' => !in_array($group_type, ['user', 'all'])
'important' => !in_array($group_type, ['user', 'all']),
'last_at' => in_array($group_type, ['user', 'department', 'all']) ? Carbon::now() : null,
])->save();
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Models;
use Carbon\Carbon;
use App\Module\Base;
use App\Module\Doo;
use App\Module\Image;
use App\Tasks\PushTask;
use App\Exceptions\ApiException;
@@ -33,18 +34,21 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property int|null $reply_id 回复ID
* @property int|null $forward_id 转发ID
* @property int|null $forward_num 被转发多少次
* @property int|null $forward_show 是否显示转发的来源
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property-read \App\Models\WebSocketDialogMsg|null $forward_data
* @property-read int|mixed $percentage
* @property-read \App\Models\WebSocketDialogMsg|null $reply_data
* @property-read \App\Models\WebSocketDialog|null $webSocketDialog
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDialogId($value)
@@ -52,7 +56,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereEmoji($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereForwardId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereForwardNum($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereForwardShow($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereKey($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereLink($value)
@@ -78,8 +81,6 @@ class WebSocketDialogMsg extends AbstractModel
protected $appends = [
'percentage',
'reply_data',
'forward_data',
];
protected $hidden = [
@@ -107,36 +108,6 @@ class WebSocketDialogMsg extends AbstractModel
return $this->appendattrs['percentage'];
}
/**
* 回复消息详情
* @return WebSocketDialogMsg|null
*/
public function getReplyDataAttribute()
{
if (!isset($this->appendattrs['reply_data'])) {
$this->appendattrs['reply_data'] = null;
if ($this->reply_id > 0) {
$this->appendattrs['reply_data'] = self::find($this->reply_id, ['id', 'userid', 'type', 'msg'])?->cancelAppend() ?: null;
}
}
return $this->appendattrs['reply_data'];
}
/**
* 转发消息详情
* @return WebSocketDialogMsg|null
*/
public function getForwardDataAttribute()
{
if (!isset($this->appendattrs['forward_data'])) {
$this->appendattrs['forward_data'] = null;
if ($this->forward_id > 0) {
$this->appendattrs['forward_data'] = self::find($this->forward_id, ['id', 'userid', 'type', 'msg'])?->cancelAppend() ?: null;
}
}
return $this->appendattrs['forward_data'];
}
/**
* 消息格式化
* @param $value
@@ -147,13 +118,9 @@ class WebSocketDialogMsg extends AbstractModel
if (is_array($value)) {
return $value;
}
$value = Base::json2array($value);
if ($this->type === 'file') {
$value['type'] = in_array($value['ext'], ['jpg', 'jpeg', 'webp', 'png', 'gif']) ? 'img' : 'file';
$value['path'] = Base::fillUrl($value['path']);
$value['thumb'] = Base::fillUrl($value['thumb'] ?: Base::extIcon($value['ext']));
} else if ($this->type === 'record') {
$value['path'] = Base::fillUrl($value['path']);
$value = $this->formatDataMsg($this->type, $value);
if (isset($value['reply_data'])) {
$value['reply_data']['msg'] = $this->formatDataMsg($value['reply_data']['type'], $value['reply_data']['msg']);
}
return $value;
}
@@ -171,6 +138,34 @@ class WebSocketDialogMsg extends AbstractModel
return Base::json2array($value);
}
/**
* 处理消息数据
* @param $type
* @param $msg
* @return mixed
*/
private function formatDataMsg($type, $msg)
{
if (!is_array($msg)) {
$msg = Base::json2array($msg);
}
if ($type === 'file') {
$msg['type'] = in_array($msg['ext'], ['jpg', 'jpeg', 'webp', 'png', 'gif']) ? 'img' : 'file';
$msg['path'] = Base::fillUrl($msg['path']);
$msg['thumb'] = Base::fillUrl($msg['thumb'] ?: Base::extIcon($msg['ext']));
} else if ($type === 'record') {
$msg['path'] = Base::fillUrl($msg['path']);
$textUserid = is_array($msg['text_userid']) ? $msg['text_userid'] : [];
if (isset($msg['text_userid'])) {
unset($msg['text_userid']);
}
if ($msg['text'] && !in_array(Doo::userId(), $textUserid)) {
$msg['text'] = "";
}
}
return $msg;
}
/**
* 获取占比
* @param bool|int $increment 是否新增阅读数
@@ -333,41 +328,54 @@ class WebSocketDialogMsg extends AbstractModel
if (in_array($this->type, ['tag', 'todo', 'notice'])) {
return Base::retError('此消息不支持设待办');
}
if ($this->todo && $this->todo != $sender) {
return Base::retError('仅支持设此待办人员【' . User::userid2nickname($this->todo) . '】取消');
}
$before = $this->todo;
$this->todo = $before ? 0 : $sender;
$current = WebSocketDialogMsgTodo::whereMsgId($this->id)->pluck('userid')->toArray();
$cancel = array_diff($current, $userids);
$setup = array_diff($userids, $current);
//
$this->todo = $setup || count($current) > count($cancel) ? $sender : 0;
$this->save();
$resData = [
$upData = [
'id' => $this->id,
'todo' => $this->todo,
'dialog_id' => $this->dialog_id,
];
$dialog = WebSocketDialog::find($this->dialog_id);
$dialog->pushMsg('update', $upData);
//
$data = [
'update' => $resData
$retData = [
'add' => [],
'update' => $upData
];
$res = self::sendMsg(null, $this->dialog_id, 'todo', [
'action' => $this->todo ? 'add' : 'remove',
'data' => [
'id' => $this->id,
'type' => $this->type,
'msg' => $this->quoteTextMsg(),
'userids' => implode(",", $userids),
]
], $sender);
if (Base::isSuccess($res)) {
$data['add'] = $res['data'];
$dialog = WebSocketDialog::find($this->dialog_id);
$dialog->pushMsg('update', array_merge($resData, ['dialog_id' => $this->dialog_id]));
//
if ($this->todo) {
if ($cancel) {
$res = self::sendMsg(null, $this->dialog_id, 'todo', [
'action' => 'remove',
'data' => [
'id' => $this->id,
'type' => $this->type,
'msg' => $this->quoteTextMsg(),
'userids' => implode(",", $cancel),
]
], $sender);
if (Base::isSuccess($res)) {
$retData['add'][] = $res['data'];
WebSocketDialogMsgTodo::whereMsgId($this->id)->whereIn('userid', $cancel)->delete();
}
}
if ($setup) {
$res = self::sendMsg(null, $this->dialog_id, 'todo', [
'action' => 'add',
'data' => [
'id' => $this->id,
'type' => $this->type,
'msg' => $this->quoteTextMsg(),
'userids' => implode(",", $setup),
]
], $sender);
if (Base::isSuccess($res)) {
$retData['add'][] = $res['data'];
$useridList = $dialog->dialogUser->pluck('userid')->toArray();
foreach ($useridList as $userid) {
if ($userids && !in_array($userid, $userids)) {
continue;
}
if (empty($userid)) {
foreach ($setup as $userid) {
if (!in_array($userid, $useridList)) {
continue;
}
WebSocketDialogMsgTodo::createInstance([
@@ -376,30 +384,40 @@ class WebSocketDialogMsg extends AbstractModel
'userid' => $userid,
])->saveOrIgnore();
}
} else {
WebSocketDialogMsgTodo::whereMsgId($this->id)->delete();
}
} else {
$this->todo = $before;
$this->save();
}
//
return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $data);
return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $retData);
}
/**
* 转发消息
* @param array|int $dialogids
* @param array|int $userids
* @param User $user 发送的会员
* @param int $showSource 是否显示原发送者信息
* @param string $leaveMessage 转发留言
* @param User $user 发送的会员
* @param int $showSource 是否显示原发送者信息
* @param string $leaveMessage 转发留言
* @return mixed
*/
public function forwardMsg($dialogids, $userids, $user, $showSource = 1, $leaveMessage = '')
{
return AbstractModel::transaction(function() use ($dialogids, $user, $userids, $showSource, $leaveMessage) {
$originalMsg = Base::json2array($this->getRawOriginal('msg'));
return AbstractModel::transaction(function () use ($dialogids, $user, $userids, $showSource, $leaveMessage) {
$msgData = Base::json2array($this->getRawOriginal('msg'));
$forwardData = is_array($msgData['forward_data']) ? $msgData['forward_data'] : [];
$forwardId = $forwardData['id'] ?: $this->id;
$forwardUserid = $forwardData['userid'] ?: $this->userid;
if ($forwardData['show'] === 0) {
// 如果上一条消息不显示原发送者信息,则转发的消息原始数据为当前消息
$forwardId = $this->id;
$forwardUserid = $this->userid;
}
$msgData['forward_data'] = [
'id' => $forwardId, // 转发的消息ID原始
'userid' => $forwardUserid, // 转发的消息会员ID原始
'parent_id' => $this->id, // 转发的消息ID
'parent_userid' => $this->userid, // 转发的消息会员ID
'show' => $showSource, // 是否显示原发送者信息
];
$msgs = [];
$already = [];
if ($dialogids) {
@@ -407,13 +425,16 @@ class WebSocketDialogMsg extends AbstractModel
$dialogids = [$dialogids];
}
foreach ($dialogids as $dialogid) {
$res = self::sendMsg('forward-'.( $showSource ? 1 : 0).'-'.($this->forward_id ?: $this->id), $dialogid, $this->type, $originalMsg, $user->userid);
$res = self::sendMsg('forward-' . $forwardId, $dialogid, $this->type, $msgData, $user->userid);
if (Base::isSuccess($res)) {
$msgs[] = $res['data'];
$already[] = $dialogid;
}
if ($leaveMessage) {
self::sendMsg(null, $dialogid, 'text', ['text' => $leaveMessage], $user->userid);
$res = self::sendMsg(null, $dialogid, 'text', ['text' => $leaveMessage], $user->userid);
if (Base::isSuccess($res)) {
$msgs[] = $res['data'];
}
}
}
}
@@ -427,16 +448,22 @@ class WebSocketDialogMsg extends AbstractModel
}
$dialog = WebSocketDialog::checkUserDialog($user, $userid);
if ($dialog && !in_array($dialog->id, $already)) {
$res = self::sendMsg('forward-'.( $showSource ? 1 : 0).'-'.($this->forward_id ?: $this->id), $dialog->id, $this->type, $originalMsg, $user->userid);
$res = self::sendMsg('forward-' . $forwardId, $dialog->id, $this->type, $msgData, $user->userid);
if (Base::isSuccess($res)) {
$msgs[] = $res['data'];
}
if ($leaveMessage) {
self::sendMsg(null, $dialog->id, 'text', ['text' => $leaveMessage], $user->userid);
$res = self::sendMsg(null, $dialog->id, 'text', ['text' => $leaveMessage], $user->userid);
if (Base::isSuccess($res)) {
$msgs[] = $res['data'];
}
}
}
}
}
if (count($msgs) > 0) {
$this->increment('forward_num', count($msgs));
}
return Base::retSuccess('转发成功', [
'msgs' => $msgs
]);
@@ -458,9 +485,8 @@ class WebSocketDialogMsg extends AbstractModel
WebSocketDialogMsgTodo::whereIn('msg_id', $ids)->delete();
self::whereIn('id', $ids)->delete();
//
$dialogDatas = WebSocketDialog::whereIn('id', $dialogIds)->get();
foreach ($dialogDatas as $dialogData) {
$dialogData->updateMsgLastAt();
foreach ($dialogIds as $dialogId) {
WebSocketDialogUser::updateMsgLastAt($dialogId);
}
foreach ($replyIds as $id) {
self::whereId($id)->update(['reply_num' => self::whereReplyId($id)->count()]);
@@ -501,7 +527,7 @@ class WebSocketDialogMsg extends AbstractModel
'data' => [
'id' => $this->id,
'dialog_id' => $this->dialog_id,
'last_msg' => $dialogData->updateMsgLastAt(),
'last_msg' => WebSocketDialogUser::updateMsgLastAt($this->dialog_id),
'update_read' => $deleteRead ? 1 : 0
],
]
@@ -752,6 +778,15 @@ class WebSocketDialogMsg extends AbstractModel
$text = str_replace($str, "[:QUICK:{$quickKey}:{$quickLabel}:]", $text);
}
}
// 处理 li 标签
preg_match_all("/<li[^>]*?>/i", $text, $matchs);
foreach ($matchs[0] as $str) {
if (preg_match("/data-list=['\"](bullet|ordered|checked|unchecked)['\"]/i", $str, $match)) {
$text = str_replace($str, '<li data-list="' . $match[1] . '">', $text);
} else {
$text = str_replace($str, '<li>', $text);
}
}
// 处理链接标签
preg_match_all("/<a[^>]*?href=([\"'])(.*?)\\1[^>]*?>(.*?)<\/a>/is", $text, $matchs);
foreach ($matchs[0] as $key => $str) {
@@ -786,7 +821,20 @@ class WebSocketDialogMsg extends AbstractModel
}
// 过滤标签
$text = strip_tags($text, '<blockquote> <strong> <pre> <ol> <ul> <li> <em> <p> <s> <u> <a>');
$text = preg_replace("/\<(blockquote|strong|pre|ol|ul|li|em|p|s|u).*?\>/is", "<$1>", $text); // 不用去除a标签,上面已经处理过了
$text = preg_replace_callback("/\<(blockquote|strong|pre|ol|ul|em|p|s|u)(.*?)\>/is", function (array $match) { // 不用去除 li 和 a 标签,上面已经处理过了
preg_match("/<[^>]*?style=([\"'])(.*?)\\1[^>]*?>/is", $match[0], $matchs);
$attach = '';
if ($matchs) {
$styleArray = explode(';', $matchs[2]);
$validStyles = array_filter($styleArray, function ($styleItem) {
return preg_match('/\s*(?:color|font-size|background-color|font-weight|font-family|text-decoration|font-style)\s*:/i', $styleItem); // 只保留指定样式
});
if ($validStyles) {
$attach = ' style="' . implode(';', $validStyles) . '"';
}
}
return "<{$match[1]}{$attach}>";
}, $text);
$text = preg_replace_callback("/\[:LINK:(.*?):(.*?):\]/i", function (array $match) {
return "<a href=\"" . base64_decode($match[1]) . "\" target=\"_blank\">" . base64_decode($match[2]) . "</a>";
}, $text);
@@ -846,10 +894,10 @@ class WebSocketDialogMsg extends AbstractModel
$push_silence = !in_array($type, ["text", "file", "record", "meeting"]);
}
//
$update_id = preg_match("/^update-(\d+)$/", $action, $match) ? $match[1] : 0;
$change_id = preg_match("/^change-(\d+)$/", $action, $match) ? $match[1] : 0;
$reply_id = preg_match("/^reply-(\d+)$/", $action, $match) ? $match[1] : 0;
$forward_id = preg_match("/^forward-(\d+)-(\d+)$/", $action, $match) ? $match[2] : 0;
$update_id = intval(preg_match("/^update-(\d+)$/", $action, $match) ? $match[1] : 0);
$change_id = intval(preg_match("/^change-(\d+)$/", $action, $match) ? $match[1] : 0);
$reply_id = intval(preg_match("/^reply-(\d+)$/", $action, $match) ? $match[1] : 0);
$forward_id = intval(preg_match("/^forward-(\d+)$/", $action, $match) ? $match[1] : 0);
$sender = $sender === null ? User::userid() : $sender;
//
$dialog = WebSocketDialog::find($dialog_id);
@@ -871,23 +919,37 @@ class WebSocketDialogMsg extends AbstractModel
if (empty($dialogMsg)) {
throw new ApiException('消息不存在');
}
if ($dialogMsg->type !== 'text' && $dialogMsg->type !== 'vote') {
throw new ApiException('此消息不支持此操作');
}
if ($dialogMsg->userid != $sender && $dialogMsg->type !== 'vote') {
throw new ApiException('仅支持修改自己的消息');
$oldMsg = Base::json2array($dialogMsg->getRawOriginal('msg'));
if ($dialogMsg->type === 'vote') {
if ($dialogMsg->userid != $sender) {
$msg = [
'votes' => $msg['votes'],
];
}
} else {
if ($dialogMsg->type !== 'text') {
throw new ApiException('此消息不支持此操作');
}
if ($dialogMsg->userid != $sender) {
throw new ApiException('仅支持修改自己的消息');
}
}
//
$updateData = [
'mtype' => $mtype,
'link' => $link,
'msg' => $msg,
'msg' => array_merge($oldMsg, $msg),
'modify' => $modify,
];
$dialogMsg->updateInstance($updateData);
$dialogMsg->key = $dialogMsg->generateMsgKey();
$dialogMsg->save();
//
WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($sender)->whereHide(1)->change([
'hide' => 0, // 修改消息时,显示会话(仅自己)
'updated_at' => Carbon::now()->toDateTimeString('millisecond'),
]);
//
$dialogMsg->msgJoinGroup($dialog);
//
$dialog->pushMsg('update', array_merge($updateData, [
@@ -897,34 +959,53 @@ class WebSocketDialogMsg extends AbstractModel
return Base::retSuccess('修改成功', $dialogMsg);
} else {
// 发送
if ($reply_id && !self::whereId($reply_id)->increment('reply_num')) {
throw new ApiException('回复的消息不存在');
}
// 转发
if ($forward_id && !self::whereId($forward_id)->increment('forward_num')) {
throw new ApiException('转发的消息不存在');
if ($reply_id) {
// 回复
$replyRow = self::whereId($reply_id)->whereDialogId($dialog_id)->first();
if (empty($replyRow)) {
throw new ApiException('回复的消息不存在');
}
$replyMsg = Base::json2array($replyRow->getRawOriginal('msg'));
unset($replyMsg['reply_data']);
$msg['reply_data'] = [
'id' => $replyRow->id,
'userid' => $replyRow->userid,
'type' => $replyRow->type,
'msg' => $replyMsg,
];
$replyRow->increment('reply_num');
}
//
$dialogMsg = self::createInstance([
'dialog_id' => $dialog_id,
'dialog_type' => $dialog->type,
'reply_id' => $reply_id,
'forward_id' => $forward_id,
'userid' => $sender,
'type' => $type,
'mtype' => $mtype,
'link' => $link,
'msg' => $msg,
'read' => 0,
'forward_id' => $forward_id,
'forward_show' => $forward_id ? $match[1] : 1,
]);
AbstractModel::transaction(function () use ($dialog, $dialogMsg) {
$dialog->last_at = Carbon::now();
$dialog->save();
AbstractModel::transaction(function () use ($dialogMsg) {
$dialogMsg->send = 1;
$dialogMsg->key = $dialogMsg->generateMsgKey();
$dialogMsg->save();
WebSocketDialogUser::whereDialogId($dialog->id)->change(['updated_at' => Carbon::now()->toDateTimeString('millisecond')]);
//
if ($dialogMsg->type === 'meeting') {
MeetingMsg::createInstance([
'meetingid' => $dialogMsg->msg['meetingid'],
'dialog_id' => $dialogMsg->dialog_id,
'msg_id' => $dialogMsg->id,
])->save();
}
//
WebSocketDialogUser::whereDialogId($dialogMsg->dialog_id)->change([
'hide' => 0, // 有新消息时,显示会话(会话内所有会员)
'last_at' => Carbon::now(),
'updated_at' => Carbon::now()->toDateTimeString('millisecond'),
]);
});
//
$task = new WebSocketDialogMsgTask($dialogMsg->id);

View File

@@ -15,13 +15,21 @@ use Carbon\Carbon;
* @property int|null $silence 是否免打扰0否1是
* @property int|null $email 是否发了邮件
* @property int|null $after 在阅读之后才添加的记录
* @property int|null $dot 红点标记
* @property string|null $read_at 阅读时间
* @property-read \App\Models\WebSocketDialogMsg|null $webSocketDialogMsg
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereAfter($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereDot($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMention($value)

View File

@@ -11,9 +11,15 @@ namespace App\Models;
* @property int|null $userid 接收会员ID
* @property string|null $done_at 完成时间
* @property-read array|mixed $msg_data
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereDoneAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgTodo whereId($value)

View File

@@ -11,23 +11,33 @@ use Carbon\Carbon;
* @property int|null $dialog_id 对话ID
* @property int|null $userid 会员ID
* @property string|null $top_at 置顶时间
* @property string|null $last_at 最后消息时间
* @property int|null $mark_unread 是否标记为未读0否1是
* @property int|null $silence 是否免打扰0否1是
* @property int|null $hide 不显示会话0否1是
* @property int|null $inviter 邀请人
* @property int|null $important 是否不可移出(项目、任务人员)
* @property int|null $important 是否不可移出(项目、任务、部门人员)
* @property string|null $color 颜色
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\WebSocketDialog|null $webSocketDialog
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereColor($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereHide($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereImportant($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereInviter($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereLastAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereMarkUnread($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereSilence($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value)
@@ -46,4 +56,17 @@ class WebSocketDialogUser extends AbstractModel
{
return $this->hasOne(WebSocketDialog::class, 'id', 'dialog_id');
}
/**
* 更新对话最后消息时间
* @return WebSocketDialogMsg|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
*/
public static function updateMsgLastAt($dialogId)
{
$lastMsg = WebSocketDialogMsg::whereDialogId($dialogId)->orderByDesc('id')->first();
if ($lastMsg) {
WebSocketDialogUser::whereDialogId($dialogId)->change(['last_at' => $lastMsg->created_at]);
}
return $lastMsg;
}
}

View File

@@ -12,9 +12,15 @@ namespace App\Models;
* @property int|null $create_id 所属会员ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg query()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg whereCreateId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketTmpMsg whereId($value)

View File

@@ -127,13 +127,14 @@ class Base
public static function checkClientVersion($min)
{
if (!self::judgeClientVersion($min)) {
throw new ApiException('当前版本 (v' . Base::getClientVersion() . ') 过低,最低版本要求 (v' . $min . ')。');
throw new ApiException('当前客户端版本 (' . Base::getClientVersion() . ') 过低,最低版本要求 (' . $min . ')。');
}
}
/**
* 判断客户端版本
* @param $min
* @param $min // 最小版本满足此版本返回true
* @param null $clientVersion
* @return bool
*/
public static function judgeClientVersion($min, $clientVersion = null)
@@ -358,17 +359,6 @@ class Base
}
}
/**
* 去除html
* @param $text
* @param int $length
* @return string
*/
public static function getHtml($text, $length = 250)
{
return Base::cutStr(strip_tags($text), $length, 0, "...");
}
/**
*
* 截取字符串
@@ -2228,7 +2218,7 @@ class Base
$type = ['jpg', 'jpeg', 'webp', 'gif', 'png'];
break;
case 'video':
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4'];
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'webm'];
break;
case 'audio':
$type = ['mp3', 'wma', 'wav', 'amr'];
@@ -2243,7 +2233,7 @@ class Base
$type = ['zip'];
break;
case 'file':
$type = ['jpg', 'jpeg', 'webp', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz', 'ai', 'avi', 'bmp', 'cdr', 'eps', 'mov', 'mp3', 'mp4', 'pr', 'psd', 'svg', 'tif'];
$type = ['jpg', 'jpeg', 'webp', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz', 'ai', 'avi', 'bmp', 'cdr', 'eps', 'mov', 'mp3', 'mp4', 'webm', 'pr', 'psd', 'svg', 'tif'];
break;
case 'firmware':
$type = ['img', 'tar', 'bin'];
@@ -2251,8 +2241,8 @@ class Base
case 'md':
$type = ['md'];
break;
case 'desktop':
$type = ['yml', 'yaml', 'dmg', 'pkg', 'blockmap', 'zip', 'exe', 'msi'];
case 'publish':
$type = ['yml', 'yaml', 'dmg', 'pkg', 'blockmap', 'zip', 'exe', 'msi', 'apk'];
break;
case 'more':
$type = []; // 不限制上传文件类型
@@ -2330,6 +2320,17 @@ class Base
}
}
//
if (in_array($extension, ['mp4', 'webm'])) {
// 视频尺寸
$thumbFile = $array['file'] . '_thumb.jpg';
shell_exec("ffmpeg -i {$array['file']} -ss 1 -vframes 1 {$thumbFile} 2>&1");
if (file_exists($thumbFile)) {
$paramet = getimagesize($thumbFile);
$array['width'] = $paramet[0];
$array['height'] = $paramet[1];
$array['thumb'] = $array['path'] . '_thumb.jpg';
}
}
if (in_array($extension, ['jpg', 'jpeg', 'webp', 'gif', 'png'])) {
//图片尺寸
$paramet = getimagesize($array['file']);
@@ -2429,7 +2430,8 @@ class Base
*/
public static function isThumb($file): bool
{
return str_ends_with($file, '_thumb.jpg')
return str_ends_with($file, '_thumb.jpeg')
|| str_ends_with($file, '_thumb.jpg')
|| str_ends_with($file, '_thumb.png');
}
@@ -2440,7 +2442,9 @@ class Base
*/
public static function getThumbExt($file): string
{
if (file_exists($file . '_thumb.jpg')) {
if (file_exists($file . '_thumb.jpeg')) {
return 'jpeg';
} elseif (file_exists($file . '_thumb.jpg')) {
return 'jpg';
} elseif (file_exists($file . '_thumb.png')) {
return 'png';
@@ -2456,7 +2460,9 @@ class Base
*/
public static function thumbRestore($file): mixed
{
if (str_ends_with($file, '_thumb.jpg')) {
if (str_ends_with($file, '_thumb.jpeg')) {
return Base::rightDelete($file, '_thumb.jpeg');
} elseif (str_ends_with($file, '_thumb.jpg')) {
return Base::rightDelete($file, '_thumb.jpg');
} elseif (str_ends_with($file, '_thumb.png')) {
return Base::rightDelete($file, '_thumb.png');
@@ -2472,13 +2478,18 @@ class Base
*/
public static function extIcon($ext)
{
return match ($ext) {
"docx" => 'images/ext/doc.png',
"xlsx" => 'images/ext/xls.png',
"pptx" => 'images/ext/ppt.png',
"ai", "avi", "bmp", "cdr", "doc", "eps", "gif", "mov", "mp3", "mp4", "pdf", "ppt", "pr", "psd", "rar", "svg", "tif", "txt", "xls", "zip" => 'images/ext/' . $ext . '.png',
default => 'images/ext/file.png',
};
if ($ext == "docx") {
$ext = 'doc';
} elseif ($ext == "xlsx") {
$ext = 'xls';
} elseif ($ext == "pptx") {
$ext = 'ppt';
}
if (in_array($ext, ["ai", "avi", "bmp", "cdr", "doc", "eps", "gif", "mov", "mp3", "mp4", "pdf", "ppt", "pr", "psd", "rar", "svg", "tif", "txt", "xls", "zip"])) {
return 'images/ext/' . $ext . '.png';
} else {
return 'images/ext/file.png';
}
}
/**

View File

@@ -228,6 +228,14 @@ class Doo
if (Base::isError($data)) {
throw new ApiException($data['msg'] ?: '注册失败');
}
if (\DB::transactionLevel() > 0) {
try {
\DB::commit();
\DB::beginTransaction();
} catch (\Throwable) {
// do nothing
}
}
$user = User::whereEmail($email)->first();
if (empty($user)) {
throw new ApiException('注册失败');

View File

@@ -12,6 +12,49 @@ use Illuminate\Support\Facades\Config;
*/
class Extranet
{
/**
* 通过 openAI 语音转文字
* @param string $filePath
* @return array
*/
public static function openAItranscriptions($filePath)
{
if (!file_exists($filePath)) {
return Base::retError("语音文件不存在");
}
$systemSetting = Base::setting('system');
$aibotSetting = Base::setting('aibotSetting');
if ($systemSetting['voice2text'] !== 'open' || empty($aibotSetting['openai_key'])) {
return Base::retError("语音转文字功能未开启");
}
//
$extra = [
'Content-Type' => 'multipart/form-data',
'Authorization' => 'Bearer ' . $aibotSetting['openai_key'],
];
if ($aibotSetting['openai_agency']) {
$extra['CURLOPT_PROXY'] = $aibotSetting['openai_agency'];
if (str_contains($aibotSetting['openai_agency'], 'socks')) {
$extra['CURLOPT_PROXYTYPE'] = CURLPROXY_SOCKS5;
} else {
$extra['CURLOPT_PROXYTYPE'] = CURLPROXY_HTTP;
}
}
$res = Ihttp::ihttp_request('https://api.openai.com/v1/audio/transcriptions', [
'file' => new \CURLFile($filePath),
'model' => 'whisper-1'
], $extra, 15);
if (Base::isError($res)) {
return Base::retError("语音转文字失败", $res);
}
$resData = Base::json2array($res['data']);
if (empty($resData['text'])) {
return Base::retError("语音转文字失败", $resData);
}
//
return Base::retSuccess("success", $resData['text']);
}
/**
* 获取IP地址经纬度
* @param string $ip

View File

@@ -35,8 +35,12 @@ class Ihttp
if($post) {
if (is_array($post)) {
$filepost = false;
foreach ($post as $name => $value) {
if (is_string($value) && substr($value, 0, 1) == '@') {
foreach ($post as $value) {
if (is_string($value) && str_starts_with($value, '@')) {
$filepost = true;
break;
}
if ($value instanceof \CURLFile) {
$filepost = true;
break;
}

View File

@@ -29,8 +29,9 @@ class TimeRange
$updated = Base::isNumber($range[0]) ? intval($range[0]) : trim($range[0]);
$deleted = Base::isNumber($range[1]) ? intval($range[1]) : trim($range[1]);
//
$this->updated = $updated ? Carbon::parse($updated) : null;
$this->deleted = $deleted ? Carbon::parse($deleted) : null;
$timezone = config('app.timezone');
$this->updated = $updated ? Carbon::parse($updated)->setTimezone($timezone) : null;
$this->deleted = $deleted ? Carbon::parse($deleted)->setTimezone($timezone) : null;
}
/**

View File

@@ -4,6 +4,8 @@ namespace App\Observers;
use App\Models\Deleted;
use App\Models\ProjectTask;
use App\Models\ProjectTaskUser;
use App\Models\ProjectTaskVisibilityUser;
use App\Models\ProjectUser;
class ProjectTaskObserver
@@ -27,11 +29,14 @@ class ProjectTaskObserver
*/
public function updated(ProjectTask $projectTask)
{
if ($projectTask->isDirty('visibility')) {
self::visibilityUpdate($projectTask);
}
if ($projectTask->isDirty('archived_at')) {
if ($projectTask->archived_at) {
Deleted::record('projectTask', $projectTask->id, $this->userids($projectTask));
Deleted::record('projectTask', $projectTask->id, self::userids($projectTask));
} else {
Deleted::forget('projectTask', $projectTask->id, $this->userids($projectTask));
Deleted::forget('projectTask', $projectTask->id, self::userids($projectTask));
}
}
}
@@ -44,7 +49,7 @@ class ProjectTaskObserver
*/
public function deleted(ProjectTask $projectTask)
{
Deleted::record('projectTask', $projectTask->id, $this->userids($projectTask));
Deleted::record('projectTask', $projectTask->id, self::userids($projectTask));
}
/**
@@ -55,7 +60,7 @@ class ProjectTaskObserver
*/
public function restored(ProjectTask $projectTask)
{
Deleted::forget('projectTask', $projectTask->id, $this->userids($projectTask));
Deleted::forget('projectTask', $projectTask->id, self::userids($projectTask));
}
/**
@@ -71,10 +76,46 @@ class ProjectTaskObserver
/**
* @param ProjectTask $projectTask
* @param string[]|string $dataType
* @return array
*/
private function userids(ProjectTask $projectTask)
public static function userids(ProjectTask $projectTask, array|string $dataType = 'project')
{
return ProjectUser::whereProjectId($projectTask->project_id)->pluck('userid')->toArray();
if (!is_array($dataType)) {
$dataType = [$dataType];
}
if (in_array('project', $dataType)) {
return ProjectUser::whereProjectId($projectTask->project_id)->pluck('userid')->toArray();
}
$array = [];
if (in_array('task', $dataType)) {
$array = array_merge($array, ProjectTaskUser::whereTaskId($projectTask->id)->pluck('userid')->toArray());
}
if (in_array('visibility', $dataType)) {
$array = array_merge($array, ProjectTaskVisibilityUser::whereTaskId($projectTask->id)->pluck('userid')->toArray());
}
return array_values(array_filter(array_unique($array)));
}
/**
* 可见性更新
* @param ProjectTask $projectTask
*/
public static function visibilityUpdate(ProjectTask $projectTask)
{
$projectUserids = self::userids($projectTask);
switch ($projectTask->visibility) {
case 1:
Deleted::forget('projectTask', $projectTask->id, $projectUserids);
break;
case 2:
case 3:
$dataType = $projectTask->visibility == 2 ? ['task'] : ['task', 'visibility'];
$forgetUserids = self::userids($projectTask, $dataType);
$recordUserids = array_diff($projectUserids, $forgetUserids);
Deleted::record('projectTask', $projectTask->id, $recordUserids);
Deleted::forget('projectTask', $projectTask->id, $forgetUserids);
break;
}
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Observers;
use App\Models\Deleted;
use App\Models\WebSocketDialogUser;
use Carbon\Carbon;
class WebSocketDialogUserObserver
{
@@ -15,6 +16,18 @@ class WebSocketDialogUserObserver
*/
public function created(WebSocketDialogUser $webSocketDialogUser)
{
if (!$webSocketDialogUser->last_at) {
if (in_array($webSocketDialogUser->webSocketDialog?->group_type, ['user', 'department', 'all'])) {
$webSocketDialogUser->last_at = Carbon::now();
$webSocketDialogUser->save();
} else {
$item = WebSocketDialogUser::whereDialogId($webSocketDialogUser->dialog_id)->orderByDesc('last_at')->first();
if ($item?->last_at) {
$webSocketDialogUser->last_at = $item->last_at;
$webSocketDialogUser->save();
}
}
}
Deleted::forget('dialog', $webSocketDialogUser->dialog_id, $webSocketDialogUser->userid);
}

View File

@@ -62,6 +62,7 @@ class WebSocketService implements WebSocketHandlerInterface
'type' => 'open',
'data' => [
'fd' => $fd,
'ud' => $user->userid,
],
]));
// 通知上线

View File

@@ -316,12 +316,12 @@ class BotReceiveMsgTask extends AbstractTask
$nameKey = $isManager ? $array[2] : $array[1];
$data = $this->botManagerOne($botId, $msg->userid);
if ($data) {
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'u.silence', 'u.color', 'u.updated_at as user_at'])
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.name', 'LIKE', "%{$nameKey}%")
->where('u.userid', $data->userid)
->orderByDesc('u.top_at')
->orderByDesc('web_socket_dialogs.last_at')
->orderByDesc('u.last_at')
->take(20)
->get();
if ($list->isEmpty()) {
@@ -456,6 +456,22 @@ class BotReceiveMsgTask extends AbstractTask
$error = 'The client version is low (required version ≥ v0.29.12).';
}
break;
// 智谱清言 机器人
case 'ai-zhipu@bot.system':
$setting = Base::setting('aibotSetting');
$webhookUrl = "{$serverUrl}/ai/zhipu/send";
$extras = [
'zhipu_key' => $setting['zhipu_key'],
'zhipu_model' => $setting['zhipu_model'],
'server_url' => $serverUrl,
];
if (empty($extras['zhipu_key'])) {
$error = 'Robot disabled.';
} elseif (in_array($this->client['platform'], ['win', 'mac', 'web'])
&& !Base::judgeClientVersion("0.29.11", $this->client['version'])) {
$error = 'The client version is low (required version ≥ v0.29.12).';
}
break;
// 其他机器人
default:
$userBot = UserBot::whereBotId($botUser->userid)->first();

View File

@@ -0,0 +1,132 @@
<?php
namespace App\Tasks;
use App\Models\Meeting;
use App\Models\WebSocketDialog;
use App\Module\Base;
use Carbon\Carbon;
use App\Models\WebSocketDialogMsg;
use Illuminate\Support\Facades\Cache;
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
class CloseMeetingRoomTask extends AbstractTask
{
public function __construct()
{
parent::__construct();
}
public function start()
{
// 10分钟执行一次
$time = intval(Cache::get("CloseMeetingRoomTask:Time"));
if (time() - $time < 600) {
return;
}
Cache::put("CloseMeetingRoomTask:Time", time(), Carbon::now()->addMinutes(10));
// 判断参数
$setting = Base::setting('meetingSetting');
if ($setting['open'] !== 'open') {
return;
}
if (empty($setting['appid']) ||empty($setting['api_key']) || empty($setting['api_secret'])) {
return;
}
$credentials = $setting['api_key'] . ":" . $setting['api_secret'];
$base64Credentials = base64_encode($credentials);
$arrHeader = [
"Accept: application/json",
"Authorization: Basic " . $base64Credentials
];
// 获取10分钟未更新的会议
$meetings = Meeting::whereNull('end_at')
->where('updated_at', '<', Carbon::now()->subMinutes(10))
->take(100)
->get();
$dialogIds = [];
/** @var Meeting $meeting */
foreach ($meetings as $meeting) {
if (!$this->isEmptyChannel($setting['appid'], $meeting->channel, $arrHeader)) {
$meeting->updated_at = Carbon::now();
$meeting->save();
continue;
}
$meeting->end_at = Carbon::now();
$meeting->save();
// 更新消息
$newMsg = $meeting->toArray();
$newMsg['end_at'] = $meeting->end_at->toDateTimeString();
WebSocketDialogMsg::select(['web_socket_dialog_msgs.*', 'm.meetingid'])
->join("meeting_msgs as m", "m.msg_id", "=", "web_socket_dialog_msgs.id")
->where('m.meetingid', $meeting->meetingid)
->chunk(100, function ($msgs) use ($newMsg, &$dialogIds) {
/** @var WebSocketDialogMsg $msg */
foreach ($msgs as $msg) {
$msgData = Base::json2array($msg->getRawOriginal('msg'));
$msg->msg = Base::array2json(array_merge($msgData, $newMsg));
$msg->save();
//
if (!isset($dialogIds[$msg->dialog_id])) {
$dialogIds[$msg->dialog_id] = [];
}
$dialogIds[$msg->dialog_id][] = [
'id' => $msg->id,
'msg' => $msg->msg,
];
}
});
}
// 推送更新
foreach ($dialogIds as $dialogId => $datas) {
$dialog = WebSocketDialog::find($dialogId);
if (empty($dialog)) {
continue;
}
foreach ($datas as $data) {
$dialog->pushMsg('update', $data);
}
}
}
public function end()
{
}
/**
* 是否空频道
* @param $appid
* @param $channel
* @param $arrHeader
* @return bool
*/
private function isEmptyChannel($appid, $channel, $arrHeader)
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sd-rtn.com/dev/v1/channel/user/{$appid}/{$channel}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => $arrHeader,
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
return false; // 错误
}
$data = Base::json2array($response);
if (!$data['success']) {
return false; // 失败
}
if ($data['data']['channel_exist']) {
return false; // 有人
}
return true;
}
}

View File

@@ -17,7 +17,10 @@ use Carbon\Carbon;
*/
class JokeSoupTask extends AbstractTask
{
private $keyPrefix = "JokeSoupTask-v2";
public static function keyName($key)
{
return "JokeSoupTask-v2:{$key}";
}
public function __construct()
{
@@ -27,24 +30,24 @@ class JokeSoupTask extends AbstractTask
public function start()
{
// 判断每分钟执行一次
if (Cache::get("{$this->keyPrefix}:YmdHi") == date("YmdHi")) {
if (Cache::get(self::keyName("YmdHi")) == date("YmdHi")) {
return;
}
Cache::put("{$this->keyPrefix}:YmdHi", date("YmdHi"), Carbon::now()->addDay());
Cache::put(self::keyName("YmdHi"), date("YmdHi"), Carbon::now()->addDay());
//
$array = Base::json2array(Cache::get("{$this->keyPrefix}:jokes"));
$array = Base::json2array(Cache::get(self::keyName("jokes")));
$data = Extranet::randJoke();
if ($data) {
$array[] = $data;
}
Cache::forever("{$this->keyPrefix}:jokes", Base::array2json(array_slice($array, -200)));
Cache::forever(self::keyName("jokes"), Base::array2json(array_slice($array, -200)));
//
$array = Base::json2array(Cache::get("{$this->keyPrefix}:soups"));
$array = Base::json2array(Cache::get(self::keyName("soups")));
$data = Extranet::soups();
if ($data) {
$array[] = $data;
}
Cache::forever("{$this->keyPrefix}:soups", Base::array2json(array_slice($array, -200)));
Cache::forever(self::keyName("soups"), Base::array2json(array_slice($array, -200)));
}
public function end()

View File

@@ -112,24 +112,28 @@ class WebSocketDialogMsgTask extends AbstractTask
if ($userid == $msg->userid) {
$array[$userid] = [
'userid' => $userid,
'mention' => false,
'mention' => 0,
'silence' => $silence,
'dot' => 0,
'updated' => $updated,
];
} else {
$mention = array_intersect([0, $userid], $mentions) ? 1 : 0;
$silence = $mention ? false : $silence;
$dot = $msg->type === 'record' ? 1 : 0;
WebSocketDialogMsgRead::createInstance([
'dialog_id' => $msg->dialog_id,
'msg_id' => $msg->id,
'userid' => $userid,
'mention' => $mention,
'silence' => $silence,
'dot' => $dot,
])->saveOrIgnore();
$array[$userid] = [
'userid' => $userid,
'mention' => $mention,
'silence' => $silence,
'dot' => $dot,
'updated' => $updated,
];
// 机器人收到消处理
@@ -169,6 +173,7 @@ class WebSocketDialogMsgTask extends AbstractTask
'silence' => $item['silence'] ? 1 : 0,
'data' => array_merge($msg->toArray(), [
'mention' => $item['mention'],
'dot' => $item['dot'],
'user_at' => Carbon::parse($item['updated'])->toDateTimeString('millisecond'),
'user_ms' => Carbon::parse($item['updated'])->valueOf(),
]),

169
bin/https Normal file
View File

@@ -0,0 +1,169 @@
#!/bin/sh
#fonts color
Green="\033[32m"
Yellow="\033[33m"
Red="\033[31m"
GreenBG="\033[42;37m"
YellowBG="\033[43;37m"
RedBG="\033[41;37m"
Font="\033[0m"
#notification information
OK="${Green}[OK]${Font}"
Warn="${Yellow}[警告]${Font}"
Error="${Red}[错误]${Font}"
cd "$(
cd "$(dirname "$0")" || exit
pwd
)" || exit
#================================================================
#================================================================
success() {
echo -e "${OK} ${GreenBG}$1${Font}"
}
warning() {
echo -e "${Warn} ${YellowBG}$1${Font}"
}
error() {
echo -e "${Error} ${RedBG}$1${Font}"
}
info() {
echo -e "$1"
}
env_get() {
local key=$1
local value=`cat $(dirname "$PWD")/.env | grep "^$key=" | awk -F '=' '{print $2}'`
echo "$value"
}
env_set() {
local key=$1
local val=$2
local exist=`cat $(dirname "$PWD")/.env | grep "^$key="`
if [ -z "$exist" ]; then
echo "$key=$val" >> $(dirname "$PWD")/.env
else
sed -i "/^${key}=/c\\${key}=${val}" $(dirname "$PWD")/.env
fi
}
#================================================================
#================================================================
check() {
while [ -z "$domain" ]; do
read -rp "请输入你的域名: " domain
# 判断域名是否合法
if [ -z "$domain" ]; then
error "域名不能为空"
elif [ -z "$(echo "$domain" | grep -E '^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$')" ]; then
error "域名格式不正确"
domain=""
fi
done
success "正在域名DNS解析IP..."
local domain_ip=$(ping -c 1 "${domain}" 2>/dev/null | grep PING | cut -d "(" -f2 | cut -d ")" -f1)
local local_ip=$(curl -sk ip.sb)
info "域名DNS解析IP: ${domain_ip}"
info "本机IP: ${local_ip}"
sleep 2
if [[ "$(echo "${local_ip}" | tr '.' '+' | bc)" == "$(echo "${domain_ip}" | tr '.' '+' | bc)" ]]; then
success "域名DNS解析IP 与 本机IP 匹配"
sleep 2
else
warning "域名DNS解析IP 与 本机IP 不匹配,是否继续操作? [Y/n]"
read -r continue_next
[[ -z ${continue_next} ]] && continue_next="Y"
case $continue_next in
[yY][eE][sS] | [yY])
success "继续操作"
sleep 2
;;
*)
error "操作终止"
exit 2
;;
esac
fi
}
install() {
local sitePath="$(dirname "$PWD")/docker/nginx/site"
local sslPath="$sitePath/ssl"
if [[ -f "$sslPath/$domain.key" && -f "$sslPath/$domain.crt" ]]; then
warning "$domain 证书文件已存在,是否删除并继续操作? [Y/n]"
read -r continue_install
[[ -z ${continue_install} ]] && continue_install="Y"
case $continue_install in
[yY][eE][sS] | [yY])
rm -f "$sslPath/$domain.key"
rm -f "$sslPath/$domain.crt"
success "继续操作"
sleep 2
;;
*)
error "操作终止"
exit 2
;;
esac
fi
apk add --no-cache openssl socat
curl https://get.acme.sh | sh
if [[ 0 -ne $? ]]; then
error "安装证书生成脚本失败"
exit 1
fi
if /root/.acme.sh/acme.sh --issue -d "${domain}" -w "$(dirname "$PWD")/public" --standalone -k ec-256 --force --test; then
success "SSL 证书测试签发成功,开始正式签发"
rm -rf "/root/.acme.sh/${domain}_ecc"
sleep 2
else
error "SSL 证书测试签发失败"
rm -rf "root/.acme.sh/${domain}_ecc"
exit 1
fi
if /root/.acme.sh/acme.sh --issue -d "${domain}" -w "$(dirname "$PWD")/public" --server letsencrypt --standalone -k ec-256 --force; then
success "SSL 证书生成成功"
sleep 2
mkdir -p $sslPath
if /root/.acme.sh/acme.sh --installcert -d "${domain}" --fullchainpath "${sslPath}/${domain}.crt" --keypath "${sslPath}/${domain}.key" --ecc --force; then
success "SSL 证书配置成功"
sleep 2
fi
else
error "SSL 证书生成失败"
rm -rf "/root/.acme.sh/${domain}_ecc"
exit 1
fi
env_set "APP_URL" "https://${domain}"
cat >${sitePath}/ssl.conf <<EOF
server_name ${domain};
listen 443 ssl;
ssl_certificate /etc/nginx/conf.d/site/ssl/${domain}.crt;
ssl_certificate_key /etc/nginx/conf.d/site/ssl/${domain}.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
error_page 497 https://\$host\$request_uri;
EOF
}
check
install

File diff suppressed because one or more lines are too long

155
cmd
View File

@@ -2,13 +2,16 @@
#fonts color
Green="\033[32m"
Yellow="\033[33m"
Red="\033[31m"
GreenBG="\033[42;37m"
YellowBG="\033[43;37m"
RedBG="\033[41;37m"
Font="\033[0m"
#notification information
OK="${Green}[OK]${Font}"
Warn="${Yellow}[警告]${Font}"
Error="${Red}[错误]${Font}"
cur_path="$(pwd)"
@@ -17,14 +20,30 @@ COMPOSE="docker-compose"
judge() {
if [[ 0 -eq $? ]]; then
echo -e "${OK} ${GreenBG} $1 完成 ${Font}"
success "$1 完成"
sleep 1
else
echo -e "${Error} ${RedBG} $1 失败${Font}"
error "$1 失败"
exit 1
fi
}
success() {
echo -e "${OK} ${GreenBG}$1${Font}"
}
warning() {
echo -e "${Warn} ${YellowBG}$1${Font}"
}
error() {
echo -e "${Error} ${RedBG}$1${Font}"
}
info() {
echo -e "$1"
}
rand() {
local min=$1
local max=$(($2-$min+1))
@@ -51,7 +70,7 @@ restart_php() {
$COMPOSE stop php
$COMPOSE start php
else
echo -e "$RES"
info "$RES"
fi
}
@@ -69,21 +88,21 @@ switch_debug() {
check_docker() {
docker --version &> /dev/null
if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 未安装 Docker${Font}"
error "未安装 Docker"
exit 1
fi
docker-compose version &> /dev/null
if [ $? -ne 0 ]; then
docker compose version &> /dev/null
if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 未安装 Docker-compose${Font}"
error "未安装 Docker-compose"
exit 1
fi
COMPOSE="docker compose"
fi
if [[ -n `$COMPOSE version | grep -E "\sv*1"` ]]; then
if [[ -n `$COMPOSE version | grep -E "\sv1"` ]]; then
$COMPOSE version
echo -e "${Error} ${RedBG} Docker-compose 版本过低请升级至v2+${Font}"
error "Docker-compose 版本过低请升级至v2+"
exit 1
fi
}
@@ -91,7 +110,17 @@ check_docker() {
check_node() {
npm --version &> /dev/null
if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 未安装nodejs${Font}"
error "未安装 npm"
exit 1
fi
node --version &> /dev/null
if [ $? -ne 0 ]; then
error "未安装 Node.js"
exit 1
fi
if [[ -n `node --version | grep -E "v1"` ]]; then
node --version
error "Node.js 版本过低请升级至v20+"
exit 1
fi
}
@@ -154,7 +183,7 @@ run_exec() {
local cmd=$2
local name=`docker_name $container`
if [ -z "$name" ]; then
echo -e "${Error} ${RedBG} 没有找到 $container 容器! ${Font}"
error "没有找到 $container 容器!"
exit 1
fi
docker exec -it "$name" /bin/sh -c "$cmd"
@@ -170,7 +199,7 @@ run_mysql() {
filename="${cur_path}/docker/mysql/backup/${database}_$(date "+%Y%m%d%H%M%S").sql.gz"
run_exec mariadb "exec mysqldump --databases $database -u$username -p$password" | gzip > $filename
judge "备份数据库"
[ -f "$filename" ] && echo -e "备份文件:$filename"
[ -f "$filename" ] && info "备份文件:$filename"
elif [ "$1" = "recovery" ]; then
database=$(env_get DB_DATABASE)
username=$(env_get DB_USERNAME)
@@ -179,19 +208,19 @@ run_mysql() {
mkdir -p ${cur_path}/docker/mysql/backup
list=`ls -1 "${cur_path}/docker/mysql/backup" | grep ".sql.gz"`
if [ -z "$list" ]; then
echo -e "${Error} ${RedBG} 没有备份文件!${Font}"
error "没有备份文件!"
exit 1
fi
echo "$list"
read -rp "请输入备份文件名称还原:" inputname
filename="${cur_path}/docker/mysql/backup/${inputname}"
if [ ! -f "$filename" ]; then
echo -e "${Error} ${RedBG} 备份文件:${inputname} 不存在! ${Font}"
error "备份文件:${inputname} 不存在!"
exit 1
fi
container_name=`docker_name mariadb`
if [ -z "$container_name" ]; then
echo -e "${Error} ${RedBG} 没有找到 mariadb 容器! ${Font}"
error "没有找到 mariadb 容器!"
exit 1
fi
docker cp $filename $container_name:/
@@ -201,6 +230,49 @@ run_mysql() {
fi
}
https_auto() {
restart_nginx="n"
if [[ "$(env_get APP_PORT)" != "80" ]]; then
warning "HTTP服务端口不是80是否修改并继续操作 [Y/n]"
read -r continue_http
[[ -z ${continue_http} ]] && continue_http="Y"
case $continue_http in
[yY][eE][sS] | [yY])
success "继续操作"
env_set "APP_PORT" "80"
restart_nginx="y"
;;
*)
error "操作终止"
exit 1
;;
esac
fi
if [[ "$(env_get APP_SSL_PORT)" != "443" ]]; then
warning "HTTPS服务端口不是443是否修改并继续操作 [Y/n]"
read -r continue_https
[[ -z ${continue_https} ]] && continue_https="Y"
case $continue_https in
[yY][eE][sS] | [yY])
success "继续操作"
env_set "APP_SSL_PORT" "443"
restart_nginx="y"
;;
*)
error "操作终止"
exit 1
;;
esac
fi
if [[ "$restart_nginx" == "y" ]]; then
$COMPOSE up -d
fi
docker run -it --rm -v $(pwd):/work nginx:alpine sh "/work/bin/https"
if [[ 0 -eq $? ]]; then
run_exec nginx "nginx -s reload"
fi
}
env_get() {
local key=$1
local value=`cat ${cur_path}/.env | grep "^$key=" | awk -F '=' '{print $2}'`
@@ -220,7 +292,7 @@ env_set() {
docker run -it --rm -v ${cur_path}:/www alpine sh -c "sed -i "/^${key}=/c\\${key}=${val}" /www/.env"
fi
if [ $? -ne 0 ]; then
echo -e "${Error} ${RedBG} 设置env参数失败${Font}"
error "设置env参数失败"
exit 1
fi
fi
@@ -293,7 +365,7 @@ if [ $# -gt 0 ]; then
run_exec php "composer config --unset repos.packagist"
fi
if [ ! -f "${cur_path}/vendor/autoload.php" ]; then
echo -e "${Error} ${RedBG}composer install 失败,请重试! ${Font}"
error "composer install 失败,请重试!"
exit 1
fi
[[ -z "$(env_get APP_KEY)" ]] && run_exec php "php artisan key:generate"
@@ -303,7 +375,7 @@ if [ $# -gt 0 ]; then
while [ ! -f "${cur_path}/docker/mysql/data/$(env_get DB_DATABASE)/db.opt" ]; do
((remaining=$remaining-1))
if [ $remaining -lt 0 ]; then
echo -e "${Error} ${RedBG} 数据库初始化失败! ${Font}"
error "数据库初始化失败!"
exit 1
fi
chmod -R 775 "${cur_path}/docker/mysql/data"
@@ -311,19 +383,21 @@ if [ $# -gt 0 ]; then
done
run_exec php "php artisan migrate --seed"
if [ ! -f "${cur_path}/docker/mysql/data/$(env_get DB_DATABASE)/$(env_get DB_PREFIX)migrations.ibd" ]; then
echo -e "${Error} ${RedBG} 数据库安装失败! ${Font}"
error "数据库安装失败!"
exit 1
fi
# 设置初始化密码
res=`run_exec mariadb "sh /etc/mysql/repassword.sh"`
$COMPOSE up -d
restart_php
echo -e "${OK} ${GreenBG} 安装完成 ${Font}"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
echo -e "$res"
success "安装完成"
info "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
info "$res"
elif [[ "$1" == "update" ]]; then
shift 1
run_mysql backup
if [[ "$@" != "nobackup" ]]; then
run_mysql backup
fi
if [[ -z "$(arg_get local)" ]]; then
git fetch --all
git reset --hard origin/$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
@@ -340,10 +414,10 @@ if [ $# -gt 0 ]; then
[[ -z ${uninstall} ]] && uninstall="Y"
case $uninstall in
[yY][eE][sS] | [yY])
echo -e "${RedBG} 开始卸载... ${Font}"
info "${RedBG}开始卸载...${Font}"
;;
*)
echo -e "${GreenBG} 终止卸载。 ${Font}"
info "${GreenBG}终止卸载。${Font}"
exit 2
;;
esac
@@ -352,7 +426,7 @@ if [ $# -gt 0 ]; then
rm -rf "./docker/mysql/data"
rm -rf "./docker/log/supervisor"
find "./storage/logs" -name "*.log" | xargs rm -rf
echo -e "${OK} ${GreenBG} 卸载完成 ${Font}"
success "卸载完成"
elif [[ "$1" == "reinstall" ]]; then
shift 1
./cmd uninstall $@
@@ -362,20 +436,20 @@ if [ $# -gt 0 ]; then
shift 1
env_set APP_PORT "$1"
$COMPOSE up -d
echo -e "${OK} ${GreenBG} 修改成功 ${Font}"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
success "修改成功"
info "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
elif [[ "$1" == "url" ]]; then
shift 1
env_set APP_URL "$1"
restart_php
echo -e "${OK} ${GreenBG} 修改成功 ${Font}"
success "修改成功"
elif [[ "$1" == "env" ]]; then
shift 1
if [ -n "$1" ]; then
env_set $1 "$2"
fi
restart_php
echo -e "${OK} ${GreenBG} 修改成功 ${Font}"
success "修改成功"
elif [[ "$1" == "repassword" ]]; then
shift 1
run_exec mariadb "sh /etc/mysql/repassword.sh \"$@\""
@@ -391,6 +465,23 @@ if [ $# -gt 0 ]; then
elif [[ "$1" == "electron" ]]; then
shift 1
run_electron $@
elif [[ "$1" == "eeui" ]]; then
shift 1
cli="$@"
por=""
if [[ "$cli" == "build" ]]; then
cli="build --simple"
elif [[ "$cli" == "dev" ]]; then
por="-p 8880:8880"
fi
docker run -it --rm -v ${cur_path}/resources/mobile:/work -w /work ${por} kuaifan/eeui-cli:0.0.1 eeui ${cli}
elif [[ "$1" == "npm" ]]; then
shift 1
npm $@
cd electron
npm $@
cd ..
docker run --rm -it -v ${cur_path}/resources/mobile:/work -w /work --entrypoint=/bin/bash node:16 -c "npm $@"
elif [[ "$1" == "doc" ]]; then
shift 1
run_exec php "php app/Http/Controllers/Api/apidoc.php"
@@ -398,13 +489,15 @@ if [ $# -gt 0 ]; then
elif [[ "$1" == "debug" ]]; then
shift 1
switch_debug "$@"
echo "success"
info "success"
elif [[ "$1" == "https" ]]; then
shift 1
if [[ "$@" == "auto" ]]; then
if [[ "$1" == "agent" ]] || [[ "$1" == "true" ]]; then
env_set APP_SCHEME "true"
elif [[ "$1" == "close" ]] || [[ "$1" == "auto" ]]; then
env_set APP_SCHEME "auto"
else
env_set APP_SCHEME "true"
https_auto
fi
restart_php
elif [[ "$1" == "artisan" ]]; then

1084
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@
use App\Models\Project;
use App\Models\ProjectTask;
use Carbon\Carbon;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

View File

@@ -1,8 +1,6 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class InsertSettingColumnTemplate extends Migration
{

View File

@@ -16,7 +16,7 @@ class FilesUpdateExt extends Migration
*/
public function up()
{
File::whereIn('type', ['mind', 'drawio', 'document'])->where('ext', '')->orderBy('id')->chunk(100, function($files) {
File::whereIn('type', ['mind', 'drawio', 'document'])->where('ext', '')->chunkById(100, function($files) {
/** @var File $file */
foreach ($files as $file) {
$fileContent = FileContent::whereFid($file->id)->orderByDesc('id')->first();

View File

@@ -1,9 +1,7 @@
<?php
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
use App\Models\User;
use App\Models\WebSocketDialog;
use App\Module\Base;
use Carbon\Carbon;
use Illuminate\Database\Migrations\Migration;
class AllGroupMuteHandle extends Migration

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogUsersAddHide extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
if (!Schema::hasColumn('web_socket_dialog_users', 'hide')) {
$table->integer('hide')->nullable()->default(0)->after('silence')->comment('不显示会话0否1是');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
$table->dropColumn("hide");
});
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIndexSome20240315 extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
$table->index(['dialog_id', 'userid', 'read_at', 'msg_id'], 'IDEX_dialog_id_userid_read_at_msg_id');
});
}
/**
* Reverse the migrations.
*
* @return voidw
*/
public function down()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
$table->dropIndex('IDEX_dialog_id_userid_read_at_msg_id');
});
}
}

View File

@@ -0,0 +1,50 @@
<?php
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogUser;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogUsersLastAt extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$isAdd = false;
Schema::table('web_socket_dialog_users', function (Blueprint $table) use (&$isAdd) {
if (!Schema::hasColumn('web_socket_dialog_users', 'last_at')) {
$isAdd = true;
$table->timestamp('last_at')->nullable()->after('top_at')->comment('最后消息时间');
}
});
if ($isAdd) {
// 更新数据
WebSocketDialog::chunk(100, function ($dialogs) {
/** @var WebSocketDialog $dialog */
foreach ($dialogs as $dialog) {
WebSocketDialogUser::whereDialogId($dialog->id)->update(['last_at' => $dialog->last_at]);
}
});
// 删除表字段
Schema::table('web_socket_dialogs', function (Blueprint $table) {
$table->dropColumn("last_at");
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// 回滚数据 - 无法回滚
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIndexSome20240317 extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_users', function (Blueprint $table) {
$table->dropIndex(['userid']);
$table->index(['userid', 'dialog_id']);
});
}
/**
* Reverse the migrations.
*
* @return voidw
*/
public function down()
{
// 回滚数据 - 无法回滚
}
}

View File

@@ -0,0 +1,55 @@
<?php
use App\Module\Base;
use App\Models\WebSocketDialogMsg;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeForwardData extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
if (Schema::hasColumn('web_socket_dialog_msgs', 'forward_show')) {
WebSocketDialogMsg::where("forward_id", ">", 0)->chunk(100, function ($items) {
/** @var WebSocketDialogMsg $item */
foreach ($items as $item) {
$msg = Base::json2array($item->getRawOriginal('msg'));
$msg['forward_data'] = [
'id' => $item->forward_id,
'userid' => 0,
'parent_id' => $item->forward_id,
'parent_userid' => 0,
'show' => 0,
];
$original = WebSocketDialogMsg::select(['id', 'userid', 'forward_show'])->whereId($item->forward_id)->withTrashed()->first();
if ($original) {
$msg['forward_data']['userid'] = $original->userid;
$msg['forward_data']['parent_userid'] = $original->userid;
$msg['forward_data']['show'] = $original->forward_show;
}
$item->msg = Base::array2json($msg);
$item->save();
}
});
$table->dropColumn("forward_show");
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// 回滚数据 - 无法回滚
}
}

View File

@@ -0,0 +1,49 @@
<?php
use App\Module\Base;
use App\Models\WebSocketDialogMsg;
use Illuminate\Database\Migrations\Migration;
class ChangeReplyData extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
WebSocketDialogMsg::where("reply_id", ">", 0)->chunk(100, function ($items) {
/** @var WebSocketDialogMsg $item */
foreach ($items as $item) {
$msg = Base::json2array($item->getRawOriginal('msg'));
$msg['reply_data'] = [
'id' => $item->reply_id,
'userid' => 0,
'type' => '',
'msg' => [],
];
$original = WebSocketDialogMsg::whereId($item->reply_id)->withTrashed()->first();
if ($original) {
$replyMsg = Base::json2array($original->getRawOriginal('msg'));
unset($replyMsg['reply_data']);
$msg['reply_data']['userid'] = $original->userid;
$msg['reply_data']['type'] = $original->type;
$msg['reply_data']['msg'] = $replyMsg;
}
$item->msg = Base::array2json($msg);
$item->save();
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// 回滚数据 - 无法回滚
}
}

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUmengAliasDevice extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table('umeng_alias', function (Blueprint $table) {
if (!Schema::hasColumn('umeng_alias', 'device')) {
$table->text('ua')->nullable()->after('platform')->comment('userAgent');
$table->string('device', 100)->nullable()->default('')->after('platform')->comment('设备类型');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::table('umeng_alias', function (Blueprint $table) {
$table->dropColumn("ua");
$table->dropColumn("device");
});
}
}

View File

@@ -2,6 +2,7 @@
use App\Models\User;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogUser;
use Carbon\Carbon;
use Illuminate\Database\Migrations\Migration;
@@ -19,8 +20,7 @@ class GenerateWebSocketDialogsDefaultGroup extends Migration
if ($botUser) {
$dialog = WebSocketDialog::checkUserDialog($botUser, 1);
if ($dialog) {
$dialog->last_at = Carbon::now();
$dialog->save();
WebSocketDialogUser::whereDialogId($dialog->id)->update(['last_at' => Carbon::now()]);
}
}

View File

@@ -0,0 +1,45 @@
<?php
use App\Models\WebSocketDialogMsg;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMeetingMsgsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::dropIfExists('meeting_msgs');
Schema::create('meeting_msgs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('meetingid')->nullable()->default('')->comment('会议ID');
$table->bigInteger('dialog_id')->nullable()->default(0)->comment('对话ID');
$table->bigInteger('msg_id')->nullable()->default(0)->comment('消息ID');
});
\DB::table('meetings')->update(['end_at' => null]);
WebSocketDialogMsg::whereType('meeting')->chunk(100, function ($msgs) {
/** @var WebSocketDialogMsg $msg */
foreach ($msgs as $msg) {
$meetingid = $msg->msg['meetingid'];
$dialog_id = $msg->dialog_id;
$msg_id = $msg->id;
\DB::table('meeting_msgs')->insert(compact('meetingid', 'dialog_id', 'msg_id'));
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('meeting_msgs');
}
}

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddProjectTaskContentsUserid extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table('project_task_contents', function (Blueprint $table) {
if (!Schema::hasColumn('project_task_contents', 'userid')) {
$table->string('desc', 500)->nullable()->default('')->after('task_id')->comment('内容描述');
$table->bigInteger('userid')->nullable()->default(0)->after('task_id')->comment('用户ID');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::table('project_task_contents', function (Blueprint $table) {
$table->dropColumn("desc");
$table->dropColumn("userid");
});
}
}

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateComplaintsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasTable('complaints'))
return;
Schema::create('complaints', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('dialog_id')->nullable()->default(0)->comment('对话ID');
$table->bigInteger('userid')->nullable()->default(0)->comment('举报人id');
$table->bigInteger('type')->nullable()->default(0)->comment('举报类型');
$table->string('reason', 500)->nullable()->default('')->comment('举报原因');
$table->text('imgs')->nullable()->comment('举报图片');
$table->bigInteger('status')->nullable()->default(0)->comment('状态 0待处理、1已处理、2已删除');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('complaints');
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogMsgReadsDot extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
if (!Schema::hasColumn('web_socket_dialog_msg_reads', 'dot')) {
$table->integer('dot')->nullable()->default(0)->after('after')->comment('红点标记');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
$table->dropColumn("dot");
});
}
}

View File

@@ -0,0 +1,56 @@
<?php
use App\Models\ProjectLog;
use App\Models\ProjectTaskUser;
use App\Models\UserTransfer;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Swoole\Coroutine;
class ProjectLogsAddTaskOnly extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$isAdd = false;
Schema::table('project_logs', function (Blueprint $table) use (&$isAdd) {
if (!Schema::hasColumn('project_logs', 'task_only')) {
$isAdd = true;
$table->index('project_id');
$table->index('task_id');
$table->integer('task_only')->index()->nullable()->default(0)->after('task_id')->comment('仅任务日志0否1是');
}
});
if ($isAdd) {
// 更新数据
go(function () {
Coroutine::sleep(0.1);
ProjectLog::whereDetail('移交子任务身份')->update(['task_only' => 1]);
ProjectLog::whereDetail('移交任务身份')->update(['task_only' => 1]);
UserTransfer::chunkById(100, function ($lists) {
/** @var UserTransfer $item */
foreach ($lists as $item) {
ProjectTaskUser::transfer($item->original_userid, $item->new_userid);
}
});
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('project_logs', function (Blueprint $table) {
$table->dropColumn("task_only");
});
}
}

View File

@@ -15,9 +15,13 @@ class SettingsTableSeeder extends Seeder
public function run()
{
if (\DB::table('settings')->where('name', 'system')->count() > 0) {
return;
$system = \DB::table('settings')->where('name', 'system')->first();
if ($system) {
$system = json_decode($system->setting, true);
if (isset($system['reg'])) {
return;
}
\DB::table('settings')->delete();
}
\DB::table('settings')->insert(array (

View File

@@ -26,6 +26,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 1,
'dialog_id' => 1,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 10:46:37'),
'created_at' => seeders_at('2021-07-01 10:46:37'),
'updated_at' => seeders_at('2021-07-01 10:46:37'),
),
@@ -34,6 +35,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 2,
'dialog_id' => 1,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 10:46:37'),
'created_at' => seeders_at('2021-07-01 10:46:37'),
'updated_at' => seeders_at('2021-07-01 10:46:37'),
),
@@ -42,6 +44,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 3,
'dialog_id' => 2,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 10:46:47'),
'created_at' => seeders_at('2021-07-01 10:46:47'),
'updated_at' => seeders_at('2021-07-01 10:46:47'),
),
@@ -50,6 +53,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 4,
'dialog_id' => 3,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 10:46:47'),
'created_at' => seeders_at('2021-07-01 10:46:47'),
'updated_at' => seeders_at('2021-07-01 10:46:47'),
),
@@ -58,6 +62,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 5,
'dialog_id' => 4,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 10:47:45'),
'created_at' => seeders_at('2021-07-01 10:47:45'),
'updated_at' => seeders_at('2021-07-01 10:47:45'),
),
@@ -66,6 +71,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 6,
'dialog_id' => 5,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 10:47:45'),
'created_at' => seeders_at('2021-07-01 10:47:45'),
'updated_at' => seeders_at('2021-07-01 10:47:45'),
),
@@ -74,6 +80,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 7,
'dialog_id' => 6,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 11:02:57'),
'created_at' => seeders_at('2021-07-01 11:02:57'),
'updated_at' => seeders_at('2021-07-01 11:02:57'),
),
@@ -82,6 +89,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 8,
'dialog_id' => 7,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 11:02:57'),
'created_at' => seeders_at('2021-07-01 11:02:57'),
'updated_at' => seeders_at('2021-07-01 11:02:57'),
),
@@ -90,6 +98,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 9,
'dialog_id' => 8,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 11:43:01'),
'created_at' => seeders_at('2021-07-01 11:43:01'),
'updated_at' => seeders_at('2021-07-01 11:43:01'),
),
@@ -98,6 +107,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 10,
'dialog_id' => 9,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 11:43:01'),
'created_at' => seeders_at('2021-07-01 11:43:01'),
'updated_at' => seeders_at('2021-07-01 11:43:01'),
),
@@ -106,6 +116,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 11,
'dialog_id' => 10,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 15:33:23'),
'created_at' => seeders_at('2021-07-01 15:33:23'),
'updated_at' => seeders_at('2021-07-01 15:33:23'),
),
@@ -114,6 +125,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 12,
'dialog_id' => 11,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 15:33:23'),
'created_at' => seeders_at('2021-07-01 15:33:23'),
'updated_at' => seeders_at('2021-07-01 15:33:23'),
),
@@ -122,6 +134,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 13,
'dialog_id' => 12,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 15:37:06'),
'created_at' => seeders_at('2021-07-01 15:37:06'),
'updated_at' => seeders_at('2021-07-01 15:37:06'),
),
@@ -130,6 +143,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 14,
'dialog_id' => 13,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 15:37:06'),
'created_at' => seeders_at('2021-07-01 15:37:06'),
'updated_at' => seeders_at('2021-07-01 15:37:06'),
),
@@ -138,6 +152,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 15,
'dialog_id' => 14,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 16:15:28'),
'created_at' => seeders_at('2021-07-01 16:15:28'),
'updated_at' => seeders_at('2021-07-01 16:15:28'),
),
@@ -146,6 +161,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 16,
'dialog_id' => 15,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 16:15:28'),
'created_at' => seeders_at('2021-07-01 16:15:28'),
'updated_at' => seeders_at('2021-07-01 16:15:28'),
),
@@ -154,6 +170,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 17,
'dialog_id' => 7,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:22:42'),
'created_at' => seeders_at('2021-07-01 16:22:42'),
'updated_at' => seeders_at('2021-07-01 16:22:42'),
),
@@ -162,6 +179,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 18,
'dialog_id' => 5,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:23:15'),
'created_at' => seeders_at('2021-07-01 16:23:15'),
'updated_at' => seeders_at('2021-07-01 16:23:15'),
),
@@ -170,6 +188,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 19,
'dialog_id' => 15,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:23:40'),
'created_at' => seeders_at('2021-07-01 16:23:40'),
'updated_at' => seeders_at('2021-07-01 16:23:40'),
),
@@ -178,6 +197,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 20,
'dialog_id' => 11,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:29:38'),
'created_at' => seeders_at('2021-07-01 16:29:38'),
'updated_at' => seeders_at('2021-07-01 16:29:38'),
),
@@ -186,6 +206,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 21,
'dialog_id' => 16,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:56:05'),
'created_at' => seeders_at('2021-07-01 16:56:05'),
'updated_at' => seeders_at('2021-07-01 16:56:05'),
),
@@ -194,6 +215,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 22,
'dialog_id' => 16,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 16:56:05'),
'created_at' => seeders_at('2021-07-01 16:56:05'),
'updated_at' => seeders_at('2021-07-01 16:56:05'),
),
@@ -202,6 +224,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 23,
'dialog_id' => 17,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:56:35'),
'created_at' => seeders_at('2021-07-01 16:56:35'),
'updated_at' => seeders_at('2021-07-01 16:56:35'),
),
@@ -210,6 +233,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 24,
'dialog_id' => 17,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 16:56:35'),
'created_at' => seeders_at('2021-07-01 16:56:35'),
'updated_at' => seeders_at('2021-07-01 16:56:35'),
),
@@ -218,6 +242,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 25,
'dialog_id' => 18,
'userid' => 2,
'last_at' => seeders_at('2021-07-01 16:56:57'),
'created_at' => seeders_at('2021-07-01 16:56:57'),
'updated_at' => seeders_at('2021-07-01 16:56:57'),
),
@@ -226,6 +251,7 @@ class WebSocketDialogUsersTableSeeder extends Seeder
'id' => 26,
'dialog_id' => 18,
'userid' => 1,
'last_at' => seeders_at('2021-07-01 16:56:57'),
'created_at' => seeders_at('2021-07-01 16:56:57'),
'updated_at' => seeders_at('2021-07-01 16:56:57'),
),

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