Compare commits

...

185 Commits

Author SHA1 Message Date
kuaifan
ee6eddf308 build 2024-06-04 22:12:51 +08:00
kuaifan
da84f15e9f no message 2024-06-04 21:08:10 +08:00
kuaifan
62f4d43bd9 perf: 通讯录菜单添加会议 2024-06-04 20:19:14 +08:00
kuaifan
376120b6d0 perf: 优化文件里预览图片 2024-06-04 20:11:48 +08:00
kuaifan
ff872c7dce perf: 优化消息描述 2024-06-04 19:50:12 +08:00
kuaifan
a834481d32 fix: 切换对话之后无法通过右键@ 2024-06-04 19:33:38 +08:00
kuaifan
4c5d3bd43e build 2024-06-03 19:39:37 +08:00
weifs
b737b841f5 Merge branch 'kuaifan-pro' into pro 2024-06-03 19:30:25 +08:00
weifs
990a40e4e4 feat: 操作人员离职对okr的移交处理 2024-06-03 15:14:19 +08:00
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
753 changed files with 16486 additions and 50446 deletions

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')

View File

@@ -7,6 +7,7 @@ on:
jobs:
Build:
name: Build Windows
runs-on: windows-latest
environment: build

1
.gitignore vendored
View File

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

View File

@@ -20,3 +20,8 @@ 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,268 @@
All notable changes to this project will be documented in this file.
## [0.37.71]
### Bug Fixes
- 切换对话之后无法通过右键@
### Performance
- 通讯录菜单添加会议
- 优化文件里预览图片
- 优化消息描述
## [0.37.65]
### Bug Fixes
- 如果项目没有流程,无法选择移动后的状态,也没办法确定移动
### Features
- 操作人员离职对okr的移交处理
### 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

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);
}
}
@@ -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.hide', '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.hide', '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.hide', '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.hide', '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);
}
@@ -333,7 +343,7 @@ class DialogController extends AbstractController
/**
* @api {get} api/dialog/hide 08. 会话隐藏
* @api {get} api/dialog/hide 09. 会话隐藏
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -366,7 +376,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/tel 09. 获取对方联系电话
* @api {get} api/dialog/tel 10. 获取对方联系电话
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -416,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
@@ -447,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
@@ -494,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
@@ -581,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
@@ -611,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
@@ -646,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
@@ -681,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
@@ -710,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
@@ -781,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
@@ -824,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
@@ -863,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
@@ -964,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
@@ -1012,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
@@ -1044,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
@@ -1100,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
@@ -1170,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
@@ -1223,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
@@ -1252,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
@@ -1300,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
@@ -1341,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
@@ -1367,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
@@ -1431,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
@@ -1494,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
@@ -1535,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
@@ -1570,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
@@ -1599,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
@@ -1610,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 返回信息(错误描述)
@@ -1618,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
@@ -1672,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
@@ -1710,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,
]);
}
}
//
@@ -1719,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
@@ -1760,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
@@ -1822,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
@@ -1884,7 +2053,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/adduser 39. 添加群成员
* @api {get} api/dialog/group/adduser 43. 添加群成员
*
* @apiDescription 需要token身份
* - 有群主时:只有群主可以邀请
@@ -1920,7 +2089,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/deluser 40. 移出(退出)群成员
* @api {get} api/dialog/group/deluser 44. 移出(退出)群成员
*
* @apiDescription 需要token身份
* - 只有群主、邀请人可以踢人
@@ -1964,7 +2133,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/transfer 41. 转让群组
* @api {get} api/dialog/group/transfer 45. 转让群组
*
* @apiDescription 需要token身份
* - 只有群主且是个人类型群可以解散
@@ -2013,7 +2182,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/group/disband 42. 解散群组
* @api {get} api/dialog/group/disband 46. 解散群组
*
* @apiDescription 需要token身份
* - 只有群主且是个人类型群可以解散
@@ -2041,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
@@ -2070,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
@@ -2109,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
@@ -2145,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
@@ -2168,12 +2337,12 @@ 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) {
@@ -2188,17 +2357,31 @@ class DialogController extends AbstractController
->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;
//
$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;
}
// 编辑更新
$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']];
}
return $result;
}, []);
$list = array_reverse(array_values($list));
}
$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) {
@@ -2209,6 +2392,7 @@ class DialogController extends AbstractController
'text' => $text,
'list' => $list,
'userid' => $user->userid,
'createid' => $createId,
'uuid' => $uuid,
];
return WebSocketDialogMsg::sendMsg(null, $dialog_id, 'word-chain', $msgData, $user->userid);
@@ -2216,7 +2400,7 @@ class DialogController extends AbstractController
}
/**
* @api {post} api/dialog/msg/vote 47. 发起投票
* @api {post} api/dialog/msg/vote 51. 发起投票
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2332,7 +2516,7 @@ class DialogController extends AbstractController
}
/**
* @api {get} api/dialog/msg/top 48. 置顶/取消置顶
* @api {get} api/dialog/msg/top 52. 置顶/取消置顶
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@@ -2392,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

@@ -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;
@@ -202,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 返回数据
@@ -222,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 {
@@ -238,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('{}'));
@@ -278,6 +289,8 @@ class SystemController extends AbstractController
'gemini_key',
'gemini_model',
'gemini_agency',
'zhipu_key',
'zhipu_model',
];
if ($type == 'save') {
@@ -323,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) {
@@ -1322,21 +1342,35 @@ class SystemController extends AbstractController
*/
public function prefetch()
{
$file = base_path('.prefetch');
if (!file_exists($file)) {
return [];
$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);
}
}
}
$version = Base::getVersion();
$content = file_get_contents($file);
$array = explode("\n", $content);
$array = array_values(array_filter($array));
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);
}, 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;
@@ -165,6 +166,8 @@ class IndexController extends InvokeController
Task::deliver(new JokeSoupTask());
// 未领取任务通知
Task::deliver(new UnclaimedTaskRemindTask());
// 关闭会议室
Task::deliver(new CloseMeetingRoomTask());
return "success";
}
@@ -192,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
]);
@@ -236,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]);
}
// 下载

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)

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)

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)
@@ -346,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
@@ -368,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)
@@ -401,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)) {
@@ -502,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)
],
@@ -718,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')) {
@@ -732,6 +759,9 @@ class ProjectTask extends AbstractModel
])->save();
}
}
if (!Arr::exists($data, 'visibility')) {
ProjectTaskObserver::visibilityUpdate($this);
}
}
}
// 计划时间(原则:子任务时间在主任务时间内)
@@ -888,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;
}
// 优先级
@@ -1373,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 = [
@@ -1389,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;
@@ -1630,7 +1673,9 @@ class ProjectTask extends AbstractModel
if (empty($receivers)) {
return;
}
//
$userid = User::userid();
//
$botUser = User::botGetOrCreate('task-alert');
if (empty($botUser)) {
return;
@@ -1662,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);
}
}
}
@@ -1676,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

@@ -21,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)
@@ -59,6 +65,7 @@ class UserBot extends AbstractModel
'ai-wenxin' => '文心一言',
'ai-qianwen' => '通义千问',
'ai-gemini' => 'Gemini',
'ai-zhipu' => '智谱清言',
'bot-manager' => '机器人管理',
'meeting-alert' => '会议通知',
'okr-alert' => 'OKR提醒',
@@ -120,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',

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)
@@ -47,6 +53,7 @@ class UserTransfer extends AbstractModel
WebSocketDialog::select(['web_socket_dialogs.*'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.type', 'group')
->where('web_socket_dialogs.group_type', '!=', 'okr')
->where('u.userid', $this->original_userid)
->orderByDesc('web_socket_dialogs.id')
->chunk(100, function($list) {

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.hide', '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.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.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;
}
@@ -149,6 +194,7 @@ 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();
//
@@ -552,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
@@ -622,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) {
@@ -630,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
],
]
@@ -528,31 +554,53 @@ class WebSocketDialogMsg extends AbstractModel
}
switch ($data['type']) {
case 'text':
case 'word-chain':
case 'vote':
return $this->previewTextMsg($data['msg']['text'], $preserveHtml);
case 'vote':
$action = Doo::translate("投票");
return "[{$action}] {$this->previewTextMsg($data['msg']['text'], $preserveHtml)}";
case 'word-chain':
$action = Doo::translate("接龙");
return "[{$action}] {$this->previewTextMsg($data['msg']['text'], $preserveHtml)}";
case 'record':
return "[语音]";
$action = Doo::translate("语音");
return "[{$action}]";
case 'meeting':
return "[会议] ${$data['msg']['name']}";
$action = Doo::translate("会议");
return "[{$action}] ${$data['msg']['name']}";
case 'file':
if ($data['msg']['type'] == 'img') {
return "[图片]";
$action = Doo::translate("图片");
return "[{$action}]";
} elseif ($data['msg']['ext'] == 'mp4') {
$action = Doo::translate("视频");
return "[{$action}]";
}
return "[文件] {$data['msg']['name']}";
$action = Doo::translate("文件");
return "[{$action}] {$data['msg']['name']}";
case 'tag':
$action = $data['msg']['action'] === 'remove' ? '取消标注' : '标注';
$action = Doo::translate($data['msg']['action'] === 'remove' ? '取消标注' : '标注');
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
case 'top':
$action = $data['msg']['action'] === 'remove' ? '取消置顶' : '置顶';
$action = Doo::translate($data['msg']['action'] === 'remove' ? '取消置顶' : '置顶');
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
case 'todo':
$action = $data['msg']['action'] === 'remove' ? '取消待办' : ($data['msg']['action'] === 'done' ? '完成' : '设待办');
$action = Doo::translate($data['msg']['action'] === 'remove' ? '取消待办' : ($data['msg']['action'] === 'done' ? '完成' : '设待办'));
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
case 'notice':
return $data['msg']['notice'];
default:
return "[未知的消息]";
$action = Doo::translate("未知的消息");
return "[{$action}]";
}
}
@@ -752,6 +800,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 +843,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 +916,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,17 +941,26 @@ 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);
@@ -902,36 +981,51 @@ 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([
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'),
]);
});

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,7 +127,7 @@ 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 . ')。');
}
}
@@ -359,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, "...");
}
/**
*
* 截取字符串
@@ -2229,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'];
@@ -2244,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'];
@@ -2252,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 = []; // 不限制上传文件类型
@@ -2331,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']);
@@ -2430,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');
}
@@ -2441,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';
@@ -2457,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');

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.hide', '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

@@ -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(),
]),

97
bin/version.js vendored

File diff suppressed because one or more lines are too long

7
cmd
View File

@@ -475,6 +475,13 @@ if [ $# -gt 0 ]; 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"

302
composer.lock generated
View File

@@ -2606,28 +2606,28 @@
},
{
"name": "madnest/madzipper",
"version": "v1.2.1",
"version": "v1.2.2",
"source": {
"type": "git",
"url": "https://github.com/madnest/madzipper.git",
"reference": "40d42f13ecbcb3a9bd8847864cdd2ad3afa4bb5e"
"reference": "cb3cc4c98d4f8434dc32f295876220311d4d4217"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/madnest/madzipper/zipball/40d42f13ecbcb3a9bd8847864cdd2ad3afa4bb5e",
"reference": "40d42f13ecbcb3a9bd8847864cdd2ad3afa4bb5e",
"url": "https://api.github.com/repos/madnest/madzipper/zipball/cb3cc4c98d4f8434dc32f295876220311d4d4217",
"reference": "cb3cc4c98d4f8434dc32f295876220311d4d4217",
"shasum": ""
},
"require": {
"ext-zip": "*",
"illuminate/filesystem": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
"php": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^6.0",
"orchestra/testbench": "^7.0",
"nunomaduro/collision": "^5.0",
"orchestra/testbench": "^6.0",
"phpunit/phpunit": "^9.5"
},
"type": "library",
@@ -2661,9 +2661,9 @@
"description": "Wannabe successor of Chumper/Zipper package for Laravel",
"support": {
"issues": "https://github.com/madnest/madzipper/issues",
"source": "https://github.com/madnest/madzipper/tree/v1.2.1"
"source": "https://github.com/madnest/madzipper/tree/v1.2.2"
},
"time": "2022-05-16T01:31:07+00:00"
"time": "2024-04-05T15:43:20+00:00"
},
{
"name": "maennchen/zipstream-php",
@@ -2975,16 +2975,16 @@
},
{
"name": "monolog/monolog",
"version": "2.9.2",
"version": "2.9.3",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f"
"reference": "a30bfe2e142720dfa990d0a7e573997f5d884215"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
"reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/a30bfe2e142720dfa990d0a7e573997f5d884215",
"reference": "a30bfe2e142720dfa990d0a7e573997f5d884215",
"shasum": ""
},
"require": {
@@ -3005,8 +3005,8 @@
"mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3",
"phpspec/prophecy": "^1.15",
"phpstan/phpstan": "^0.12.91",
"phpunit/phpunit": "^8.5.14",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.5.38 || ^9.6.19",
"predis/predis": "^1.1 || ^2.0",
"rollbar/rollbar": "^1.3 || ^2 || ^3",
"ruflin/elastica": "^7",
@@ -3061,7 +3061,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/2.9.2"
"source": "https://github.com/Seldaek/monolog/tree/2.9.3"
},
"funding": [
{
@@ -3073,7 +3073,7 @@
"type": "tidelift"
}
],
"time": "2023-10-27T15:25:26+00:00"
"time": "2024-04-12T20:52:51+00:00"
},
{
"name": "myclabs/php-enum",
@@ -3518,25 +3518,25 @@
},
{
"name": "orangehill/iseed",
"version": "v3.0.3",
"version": "v3.0.4",
"source": {
"type": "git",
"url": "https://github.com/orangehill/iseed.git",
"reference": "92b98c8bda6280afa0fac016b1b49caf6f57f18d"
"reference": "403ea734f16da238bda7fcc10b8dc549751fa035"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/orangehill/iseed/zipball/92b98c8bda6280afa0fac016b1b49caf6f57f18d",
"reference": "92b98c8bda6280afa0fac016b1b49caf6f57f18d",
"url": "https://api.github.com/repos/orangehill/iseed/zipball/403ea734f16da238bda7fcc10b8dc549751fa035",
"reference": "403ea734f16da238bda7fcc10b8dc549751fa035",
"shasum": ""
},
"require": {
"illuminate/support": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/support": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"php": "^7.2|^8.0.2"
},
"require-dev": {
"illuminate/filesystem": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0",
"laravel/framework": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/filesystem": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"laravel/framework": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"mockery/mockery": "^1.0.0",
"phpunit/phpunit": "^8.0"
},
@@ -3575,9 +3575,9 @@
],
"support": {
"issues": "https://github.com/orangehill/iseed/issues",
"source": "https://github.com/orangehill/iseed/tree/v3.0.3"
"source": "https://github.com/orangehill/iseed/tree/v3.0.4"
},
"time": "2023-03-27T06:14:43+00:00"
"time": "2024-03-27T08:01:21+00:00"
},
{
"name": "overtrue/http",
@@ -4365,16 +4365,16 @@
},
{
"name": "psy/psysh",
"version": "v0.12.0",
"version": "v0.12.3",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
"reference": "750bf031a48fd07c673dbe3f11f72362ea306d0d"
"reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/750bf031a48fd07c673dbe3f11f72362ea306d0d",
"reference": "750bf031a48fd07c673dbe3f11f72362ea306d0d",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73",
"reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73",
"shasum": ""
},
"require": {
@@ -4438,9 +4438,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.12.0"
"source": "https://github.com/bobthecow/psysh/tree/v0.12.3"
},
"time": "2023-12-20T15:28:09+00:00"
"time": "2024-04-02T15:57:53+00:00"
},
{
"name": "ralouphie/getallheaders",
@@ -4578,20 +4578,20 @@
},
{
"name": "ramsey/uuid",
"version": "4.7.5",
"version": "4.7.6",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
"reference": "91039bc1faa45ba123c4328958e620d382ec7088"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
"reference": "91039bc1faa45ba123c4328958e620d382ec7088",
"shasum": ""
},
"require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
@@ -4654,7 +4654,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.7.5"
"source": "https://github.com/ramsey/uuid/tree/4.7.6"
},
"funding": [
{
@@ -4666,7 +4666,7 @@
"type": "tidelift"
}
],
"time": "2023-11-08T05:53:05+00:00"
"time": "2024-04-27T21:32:50+00:00"
},
{
"name": "swiftmailer/swiftmailer",
@@ -4746,16 +4746,16 @@
},
{
"name": "symfony/console",
"version": "v5.4.36",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e"
"reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
"url": "https://api.github.com/repos/symfony/console/zipball/f3e591c48688a0cfa1a3296205926c05e84b22b1",
"reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1",
"shasum": ""
},
"require": {
@@ -4825,7 +4825,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.36"
"source": "https://github.com/symfony/console/tree/v5.4.39"
},
"funding": [
{
@@ -4841,7 +4841,7 @@
"type": "tidelift"
}
],
"time": "2024-02-20T16:33:57+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/css-selector",
@@ -4977,16 +4977,16 @@
},
{
"name": "symfony/error-handler",
"version": "v5.4.36",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
"reference": "90b1d7799bfc1b3ed5f902e8b334eeb7dba537a1"
"reference": "9e02a6e831d6c2dbc5f96c8ff5314d453ecd53cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/90b1d7799bfc1b3ed5f902e8b334eeb7dba537a1",
"reference": "90b1d7799bfc1b3ed5f902e8b334eeb7dba537a1",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/9e02a6e831d6c2dbc5f96c8ff5314d453ecd53cd",
"reference": "9e02a6e831d6c2dbc5f96c8ff5314d453ecd53cd",
"shasum": ""
},
"require": {
@@ -5028,7 +5028,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/error-handler/tree/v5.4.36"
"source": "https://github.com/symfony/error-handler/tree/v5.4.39"
},
"funding": [
{
@@ -5044,7 +5044,7 @@
"type": "tidelift"
}
],
"time": "2024-02-22T11:40:53+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/event-dispatcher",
@@ -5210,16 +5210,16 @@
},
{
"name": "symfony/finder",
"version": "v5.4.35",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435"
"reference": "f6a96e4fcd468a25fede16ee665f50ced856bd0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/abe6d6f77d9465fed3cd2d029b29d03b56b56435",
"reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435",
"url": "https://api.github.com/repos/symfony/finder/zipball/f6a96e4fcd468a25fede16ee665f50ced856bd0a",
"reference": "f6a96e4fcd468a25fede16ee665f50ced856bd0a",
"shasum": ""
},
"require": {
@@ -5253,7 +5253,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v5.4.35"
"source": "https://github.com/symfony/finder/tree/v5.4.39"
},
"funding": [
{
@@ -5269,20 +5269,20 @@
"type": "tidelift"
}
],
"time": "2024-01-23T13:51:25+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v5.4.35",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "f2ab692a22aef1cd54beb893aa0068bdfb093928"
"reference": "3356c93efc30b0c85a37606bdfef16b813faec0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f2ab692a22aef1cd54beb893aa0068bdfb093928",
"reference": "f2ab692a22aef1cd54beb893aa0068bdfb093928",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/3356c93efc30b0c85a37606bdfef16b813faec0e",
"reference": "3356c93efc30b0c85a37606bdfef16b813faec0e",
"shasum": ""
},
"require": {
@@ -5329,7 +5329,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.4.35"
"source": "https://github.com/symfony/http-foundation/tree/v5.4.39"
},
"funding": [
{
@@ -5345,20 +5345,20 @@
"type": "tidelift"
}
],
"time": "2024-01-23T13:51:25+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v5.4.37",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "4ef7ed872564852b3c6c15fecf492975a52cbff3"
"reference": "1d812dc3a2863cc4246aaa636b0d71e0bf68e6b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/4ef7ed872564852b3c6c15fecf492975a52cbff3",
"reference": "4ef7ed872564852b3c6c15fecf492975a52cbff3",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/1d812dc3a2863cc4246aaa636b0d71e0bf68e6b0",
"reference": "1d812dc3a2863cc4246aaa636b0d71e0bf68e6b0",
"shasum": ""
},
"require": {
@@ -5407,6 +5407,7 @@
"symfony/stopwatch": "^4.4|^5.0|^6.0",
"symfony/translation": "^4.4|^5.0|^6.0",
"symfony/translation-contracts": "^1.1|^2|^3",
"symfony/var-dumper": "^4.4.31|^5.4",
"twig/twig": "^2.13|^3.0.4"
},
"suggest": {
@@ -5441,7 +5442,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-kernel/tree/v5.4.37"
"source": "https://github.com/symfony/http-kernel/tree/v5.4.39"
},
"funding": [
{
@@ -5457,7 +5458,7 @@
"type": "tidelift"
}
],
"time": "2024-03-04T20:55:44+00:00"
"time": "2024-04-29T11:17:46+00:00"
},
{
"name": "symfony/mailer",
@@ -5535,16 +5536,16 @@
},
{
"name": "symfony/mime",
"version": "v5.4.35",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "ee94d9b538f93abbbc1ee4ccff374593117b04a9"
"reference": "a5364f016fd9e090f7b4f250a97ea6925a5ca985"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/ee94d9b538f93abbbc1ee4ccff374593117b04a9",
"reference": "ee94d9b538f93abbbc1ee4ccff374593117b04a9",
"url": "https://api.github.com/repos/symfony/mime/zipball/a5364f016fd9e090f7b4f250a97ea6925a5ca985",
"reference": "a5364f016fd9e090f7b4f250a97ea6925a5ca985",
"shasum": ""
},
"require": {
@@ -5565,6 +5566,7 @@
"egulias/email-validator": "^2.1.10|^3.1|^4",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/process": "^5.4|^6.4",
"symfony/property-access": "^4.4|^5.1|^6.0",
"symfony/property-info": "^4.4|^5.1|^6.0",
"symfony/serializer": "^5.4.35|~6.3.12|^6.4.3"
@@ -5599,7 +5601,7 @@
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v5.4.35"
"source": "https://github.com/symfony/mime/tree/v5.4.39"
},
"funding": [
{
@@ -5615,7 +5617,7 @@
"type": "tidelift"
}
],
"time": "2024-01-30T08:00:51+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/options-resolver",
@@ -6473,16 +6475,16 @@
},
{
"name": "symfony/process",
"version": "v5.4.36",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "4fdf34004f149cc20b2f51d7d119aa500caad975"
"reference": "85a554acd7c28522241faf2e97b9541247a0d3d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/4fdf34004f149cc20b2f51d7d119aa500caad975",
"reference": "4fdf34004f149cc20b2f51d7d119aa500caad975",
"url": "https://api.github.com/repos/symfony/process/zipball/85a554acd7c28522241faf2e97b9541247a0d3d5",
"reference": "85a554acd7c28522241faf2e97b9541247a0d3d5",
"shasum": ""
},
"require": {
@@ -6515,7 +6517,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.36"
"source": "https://github.com/symfony/process/tree/v5.4.39"
},
"funding": [
{
@@ -6531,20 +6533,20 @@
"type": "tidelift"
}
],
"time": "2024-02-12T15:49:53+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/routing",
"version": "v5.4.37",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "48ae43e443693ddb4e574f7c12f0d17ce287694e"
"reference": "5485974ef20de1150dd195a81e9da4915d45263f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/48ae43e443693ddb4e574f7c12f0d17ce287694e",
"reference": "48ae43e443693ddb4e574f7c12f0d17ce287694e",
"url": "https://api.github.com/repos/symfony/routing/zipball/5485974ef20de1150dd195a81e9da4915d45263f",
"reference": "5485974ef20de1150dd195a81e9da4915d45263f",
"shasum": ""
},
"require": {
@@ -6605,7 +6607,7 @@
"url"
],
"support": {
"source": "https://github.com/symfony/routing/tree/v5.4.37"
"source": "https://github.com/symfony/routing/tree/v5.4.39"
},
"funding": [
{
@@ -6621,20 +6623,20 @@
"type": "tidelift"
}
],
"time": "2024-02-27T09:52:32+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
"version": "v2.5.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
"reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3",
"reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3",
"shasum": ""
},
"require": {
@@ -6688,7 +6690,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
"source": "https://github.com/symfony/service-contracts/tree/v2.5.3"
},
"funding": [
{
@@ -6704,7 +6706,7 @@
"type": "tidelift"
}
],
"time": "2022-05-30T19:17:29+00:00"
"time": "2023-04-21T15:04:16+00:00"
},
{
"name": "symfony/string",
@@ -6966,16 +6968,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v5.4.36",
"version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "2e9c2b11267119d9c90d6b3fdce5e4e9f15e2e90"
"reference": "1987f86ad7f339fe3d3e8e6cf3b7ce4d4b8e547e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/2e9c2b11267119d9c90d6b3fdce5e4e9f15e2e90",
"reference": "2e9c2b11267119d9c90d6b3fdce5e4e9f15e2e90",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/1987f86ad7f339fe3d3e8e6cf3b7ce4d4b8e547e",
"reference": "1987f86ad7f339fe3d3e8e6cf3b7ce4d4b8e547e",
"shasum": ""
},
"require": {
@@ -7035,7 +7037,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v5.4.36"
"source": "https://github.com/symfony/var-dumper/tree/v5.4.39"
},
"funding": [
{
@@ -7051,7 +7053,7 @@
"type": "tidelift"
}
],
"time": "2024-02-15T11:19:14+00:00"
"time": "2024-04-18T08:26:06+00:00"
},
{
"name": "tightenco/collect",
@@ -7105,6 +7107,7 @@
"issues": "https://github.com/tighten/collect/issues",
"source": "https://github.com/tighten/collect/tree/v9.52.7"
},
"abandoned": "illuminate/collections",
"time": "2023-04-14T21:51:36+00:00"
},
{
@@ -7526,16 +7529,16 @@
},
{
"name": "composer/class-map-generator",
"version": "1.1.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/composer/class-map-generator.git",
"reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9"
"reference": "8286a62d243312ed99b3eee20d5005c961adb311"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/class-map-generator/zipball/953cc4ea32e0c31f2185549c7d216d7921f03da9",
"reference": "953cc4ea32e0c31f2185549c7d216d7921f03da9",
"url": "https://api.github.com/repos/composer/class-map-generator/zipball/8286a62d243312ed99b3eee20d5005c961adb311",
"reference": "8286a62d243312ed99b3eee20d5005c961adb311",
"shasum": ""
},
"require": {
@@ -7579,7 +7582,7 @@
],
"support": {
"issues": "https://github.com/composer/class-map-generator/issues",
"source": "https://github.com/composer/class-map-generator/tree/1.1.0"
"source": "https://github.com/composer/class-map-generator/tree/1.1.1"
},
"funding": [
{
@@ -7595,20 +7598,20 @@
"type": "tidelift"
}
],
"time": "2023-06-30T13:58:57+00:00"
"time": "2024-03-15T12:53:41+00:00"
},
{
"name": "composer/pcre",
"version": "3.1.1",
"version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": ""
},
"require": {
@@ -7650,7 +7653,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.1"
"source": "https://github.com/composer/pcre/tree/3.1.3"
},
"funding": [
{
@@ -7666,7 +7669,7 @@
"type": "tidelift"
}
],
"time": "2023-10-11T07:11:09+00:00"
"time": "2024-03-19T10:26:25+00:00"
},
{
"name": "doctrine/cache",
@@ -7763,16 +7766,16 @@
},
{
"name": "doctrine/dbal",
"version": "3.8.3",
"version": "3.8.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c"
"reference": "b05e48a745f722801f55408d0dbd8003b403dbbd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c",
"reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd",
"reference": "b05e48a745f722801f55408d0dbd8003b403dbbd",
"shasum": ""
},
"require": {
@@ -7856,7 +7859,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.8.3"
"source": "https://github.com/doctrine/dbal/tree/3.8.4"
},
"funding": [
{
@@ -7872,7 +7875,7 @@
"type": "tidelift"
}
],
"time": "2024-03-03T15:55:06+00:00"
"time": "2024-04-25T07:04:44+00:00"
},
{
"name": "doctrine/deprecations",
@@ -8466,16 +8469,16 @@
},
{
"name": "hhxsv5/laravel-s",
"version": "v3.7.37",
"version": "v3.7.38",
"source": {
"type": "git",
"url": "https://github.com/hhxsv5/laravel-s.git",
"reference": "4855c431000a2f904c91c8533cefa8b36a691830"
"reference": "f5123cc80ee98f34bebcf3e50c5d939b4cd64a39"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hhxsv5/laravel-s/zipball/4855c431000a2f904c91c8533cefa8b36a691830",
"reference": "4855c431000a2f904c91c8533cefa8b36a691830",
"url": "https://api.github.com/repos/hhxsv5/laravel-s/zipball/f5123cc80ee98f34bebcf3e50c5d939b4cd64a39",
"reference": "f5123cc80ee98f34bebcf3e50c5d939b4cd64a39",
"shasum": ""
},
"require": {
@@ -8519,7 +8522,7 @@
"email": "hhxsv5@sina.com"
}
],
"description": "🚀 LaravelS is an out-of-the-box adapter between Swoole and Laravel/Lumen.",
"description": "🚀 LaravelS is an out-of-the-box adapter between Laravel/Lumen and Swoole.",
"homepage": "https://github.com/hhxsv5/laravel-s",
"keywords": [
"LaravelS",
@@ -8558,7 +8561,7 @@
"type": "custom"
}
],
"time": "2023-06-06T07:17:34+00:00"
"time": "2024-03-20T10:40:21+00:00"
},
{
"name": "kitloong/laravel-migrations-generator",
@@ -8698,16 +8701,16 @@
},
{
"name": "mockery/mockery",
"version": "1.6.7",
"version": "1.6.11",
"source": {
"type": "git",
"url": "https://github.com/mockery/mockery.git",
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06"
"reference": "81a161d0b135df89951abd52296adf97deb0723d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06",
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06",
"url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d",
"reference": "81a161d0b135df89951abd52296adf97deb0723d",
"shasum": ""
},
"require": {
@@ -8719,8 +8722,8 @@
"phpunit/phpunit": "<8.0"
},
"require-dev": {
"phpunit/phpunit": "^8.5 || ^9.6.10",
"symplify/easy-coding-standard": "^12.0.8"
"phpunit/phpunit": "^8.5 || ^9.6.17",
"symplify/easy-coding-standard": "^12.1.14"
},
"type": "library",
"autoload": {
@@ -8777,7 +8780,7 @@
"security": "https://github.com/mockery/mockery/security/advisories",
"source": "https://github.com/mockery/mockery"
},
"time": "2023-12-10T02:24:34+00:00"
"time": "2024-03-21T18:34:15+00:00"
},
{
"name": "myclabs/deep-copy",
@@ -9156,16 +9159,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.26.0",
"version": "1.29.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "231e3186624c03d7e7c890ec662b81e6b0405227"
"reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227",
"reference": "231e3186624c03d7e7c890ec662b81e6b0405227",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/536889f2b340489d328f5ffb7b02bb6b183ddedc",
"reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc",
"shasum": ""
},
"require": {
@@ -9197,9 +9200,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0"
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.0"
},
"time": "2024-02-23T16:05:55+00:00"
"time": "2024-05-06T12:04:23+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -9522,16 +9525,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.6.17",
"version": "9.6.19",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "1a156980d78a6666721b7e8e8502fe210b587fcd"
"reference": "a1a54a473501ef4cdeaae4e06891674114d79db8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd",
"reference": "1a156980d78a6666721b7e8e8502fe210b587fcd",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8",
"reference": "a1a54a473501ef4cdeaae4e06891674114d79db8",
"shasum": ""
},
"require": {
@@ -9605,7 +9608,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19"
},
"funding": [
{
@@ -9621,7 +9624,7 @@
"type": "tidelift"
}
],
"time": "2024-02-23T13:14:51+00:00"
"time": "2024-04-05T04:35:58+00:00"
},
{
"name": "psr/cache",
@@ -10474,16 +10477,16 @@
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
"reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
"reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
"shasum": ""
},
"require": {
@@ -10495,7 +10498,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
"dev-main": "3.0-dev"
}
},
"autoload": {
@@ -10516,8 +10519,7 @@
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4"
},
"funding": [
{
@@ -10525,7 +10527,7 @@
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
"time": "2024-03-14T16:00:52+00:00"
},
{
"name": "sebastian/type",

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,10 +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,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,59 @@
<?php
use App\Models\ProjectLog;
use App\Models\ProjectTaskUser;
use App\Models\User;
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) {
if (User::whereUserid($item->original_userid)->where("identity", "like", "%,disable,%")->exists()) {
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'),
),

View File

@@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Models\User;
use App\Models\WebSocketDialog;
use App\Models\WebSocketDialogUser;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
@@ -30,7 +31,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'user',
'group_type' => '',
'name' => '',
'last_at' => seeders_at('2021-07-01 17:12:52'),
'created_at' => seeders_at('2021-07-01 10:46:37'),
'updated_at' => seeders_at('2021-07-01 17:12:52'),
'deleted_at' => NULL,
@@ -41,7 +41,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 10:46:47'),
'updated_at' => seeders_at('2021-07-01 17:31:03'),
'deleted_at' => seeders_at('2021-07-01 17:31:03'),
@@ -52,7 +51,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 10:46:47'),
'updated_at' => seeders_at('2021-07-01 10:46:55'),
'deleted_at' => seeders_at('2021-07-01 10:46:55'),
@@ -63,7 +61,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 10:47:45'),
'updated_at' => seeders_at('2021-07-01 17:30:05'),
'deleted_at' => seeders_at('2021-07-01 17:30:05'),
@@ -74,7 +71,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:31:58'),
'created_at' => seeders_at('2021-07-01 10:47:45'),
'updated_at' => seeders_at('2021-07-01 16:31:58'),
'deleted_at' => NULL,
@@ -85,7 +81,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 11:02:57'),
'updated_at' => seeders_at('2021-07-01 17:31:28'),
'deleted_at' => seeders_at('2021-07-01 17:31:28'),
@@ -96,7 +91,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:32:50'),
'created_at' => seeders_at('2021-07-01 11:02:57'),
'updated_at' => seeders_at('2021-07-01 16:32:50'),
'deleted_at' => NULL,
@@ -107,7 +101,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 11:43:01'),
'updated_at' => seeders_at('2021-07-01 17:31:28'),
'deleted_at' => seeders_at('2021-07-01 17:31:28'),
@@ -118,7 +111,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 14:02:57'),
'created_at' => seeders_at('2021-07-01 11:43:01'),
'updated_at' => seeders_at('2021-07-01 14:02:57'),
'deleted_at' => NULL,
@@ -129,7 +121,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 15:33:23'),
'updated_at' => seeders_at('2021-07-01 17:31:28'),
'deleted_at' => seeders_at('2021-07-01 17:31:28'),
@@ -140,7 +131,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:31:40'),
'created_at' => seeders_at('2021-07-01 15:33:23'),
'updated_at' => seeders_at('2021-07-01 16:31:40'),
'deleted_at' => NULL,
@@ -151,7 +141,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 15:37:06'),
'updated_at' => seeders_at('2021-07-01 17:31:28'),
'deleted_at' => seeders_at('2021-07-01 17:31:28'),
@@ -162,7 +151,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 15:44:09'),
'created_at' => seeders_at('2021-07-01 15:37:06'),
'updated_at' => seeders_at('2021-07-01 15:44:09'),
'deleted_at' => NULL,
@@ -173,7 +161,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => NULL,
'created_at' => seeders_at('2021-07-01 16:15:28'),
'updated_at' => seeders_at('2021-07-01 17:31:28'),
'deleted_at' => seeders_at('2021-07-01 17:31:28'),
@@ -184,7 +171,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'project',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:37:59'),
'created_at' => seeders_at('2021-07-01 16:15:28'),
'updated_at' => seeders_at('2021-07-01 16:37:59'),
'deleted_at' => NULL,
@@ -195,7 +181,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'task',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:58:02'),
'created_at' => seeders_at('2021-07-01 16:56:05'),
'updated_at' => seeders_at('2021-07-01 16:58:02'),
'deleted_at' => NULL,
@@ -206,7 +191,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'task',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:57:58'),
'created_at' => seeders_at('2021-07-01 16:56:35'),
'updated_at' => seeders_at('2021-07-01 16:57:58'),
'deleted_at' => NULL,
@@ -217,7 +201,6 @@ class WebSocketDialogsTableSeeder extends Seeder
'type' => 'group',
'group_type' => 'task',
'name' => '',
'last_at' => seeders_at('2021-07-01 16:57:52'),
'created_at' => seeders_at('2021-07-01 16:56:57'),
'updated_at' => seeders_at('2021-07-01 16:57:52'),
'deleted_at' => NULL,
@@ -228,8 +211,7 @@ class WebSocketDialogsTableSeeder extends Seeder
if ($botUser) {
$dialog = WebSocketDialog::checkUserDialog($botUser, 1);
if ($dialog) {
$dialog->last_at = Carbon::now();
$dialog->save();
WebSocketDialogUser::whereDialogId($dialog->id)->change(['last_at' => Carbon::now()->subSecond()]);
}
}
User::botGetOrCreate('ai-openai');

View File

@@ -1,9 +1,7 @@
version: '3'
services:
php:
container_name: "dootask-php-${APP_ID}"
image: "kuaifan/php:swoole-8.0.rc14"
image: "kuaifan/php:swoole-8.0.rc15"
shm_size: "2gb"
ulimits:
core:
@@ -151,7 +149,7 @@ services:
approve:
container_name: "dootask-approve-${APP_ID}"
image: "kuaifan/dooapprove:0.0.10"
image: "kuaifan/dooapprove:0.0.11"
environment:
TZ: "${TIMEZONE:-PRC}"
MYSQL_HOST: "${DB_HOST}"
@@ -171,7 +169,7 @@ services:
ai:
container_name: "dootask-ai-${APP_ID}"
image: "kuaifan/dooai:0.1.8"
image: "kuaifan/dooai:0.2.0"
networks:
extnetwork:
ipv4_address: "${APP_IPPR}.12"
@@ -179,7 +177,7 @@ services:
okr:
container_name: "dootask-okr-${APP_ID}"
image: "kuaifan/doookr:0.4.2"
image: "kuaifan/doookr:0.4.3"
environment:
TZ: "${TIMEZONE:-PRC}"
DOO_TASK_URL: "http://${APP_IPPR}.3"

View File

@@ -12,7 +12,7 @@ default_storage_engine = InnoDB
performance_schema_max_table_instances = 400
table_definition_cache = 400
key_buffer_size = 1024M
max_allowed_packet = 10G
max_allowed_packet = 8192M
table_open_cache = 2048
sort_buffer_size = 4096K
net_buffer_length = 4K
@@ -47,7 +47,7 @@ innodb_write_io_threads = 2
[mysqldump]
quick
max_allowed_packet = 500M
max_allowed_packet = 2048M
[mysql]
no-auto-rehash

131
electron/build.js vendored
View File

@@ -1,4 +1,3 @@
const os = require('os')
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path')
@@ -19,14 +18,13 @@ const devloadCachePath = path.resolve(__dirname, ".devload");
const packageFile = path.resolve(__dirname, "package.json");
const packageBakFile = path.resolve(__dirname, "package-bak.json");
const platforms = ["build-mac", "build-win"];
const comSuffix = os.type() == 'Windows_NT' ? '.cmd' : '';
/**
* 克隆 Drawio
* @param systemInfo
*/
function cloneDrawio(systemInfo) {
child_process.spawnSync("git", ["submodule", "update", "--quiet", "--init", "--depth=1"], {stdio: "inherit"});
child_process.execSync("git submodule update --quiet --init --depth=1", {stdio: "inherit"});
const drawioSrcDir = path.resolve(__dirname, "../resources/drawio/src/main/webapp");
const drawioCoverDir = path.resolve(__dirname, "../docker/drawio/webapp");
const drawioDestDir = path.resolve(electronDir, "drawio/webapp");
@@ -109,6 +107,78 @@ function axiosAutoTry(data) {
})
}
/**
* 上传app应用
* @param url
*/
function androidUpload(url) {
if (!DP_KEY) {
console.error("Missing Deploy Key or GitHub Token and Repository!");
process.exit()
}
const releaseDir = path.resolve(__dirname, "../resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release");
if (!fs.existsSync(releaseDir)) {
console.error("Release not found");
process.exit()
}
fs.readdir(releaseDir, async (err, files) => {
if (err) {
console.warn(err)
} else {
const uploadOras = {}
for (const filename of files) {
const localFile = path.join(releaseDir, filename)
if (/\.apk$/.test(filename) && fs.existsSync(localFile)) {
const fileStat = fs.statSync(localFile)
if (fileStat.isFile()) {
uploadOras[filename] = ora(`Upload [0%] ${filename}`).start()
const formData = new FormData()
formData.append("file", fs.createReadStream(localFile));
formData.append("file_num", 1);
await axiosAutoTry({
axios: {
method: 'post',
url: url,
data: formData,
headers: {
'Publish-Version': config.version,
'Publish-Key': DP_KEY,
'Content-Type': 'multipart/form-data;boundary=' + formData.getBoundary(),
},
onUploadProgress: progress => {
const complete = Math.min(99, Math.round(progress.loaded / progress.total * 100 | 0)) + '%'
uploadOras[filename].text = `Upload [${complete}] ${filename}`
},
},
onRetry: _ => {
uploadOras[filename].warn(`Upload [retry] ${filename}`)
uploadOras[filename] = ora(`Upload [0%] ${filename}`).start()
},
retryNumber: 3
}).then(({status, data}) => {
if (status !== 200) {
uploadOras[filename].fail(`Upload [fail:${status}] ${filename}`)
return
}
if (!utils.isJson(data)) {
uploadOras[filename].fail(`Upload [fail:not json] ${filename}`)
return
}
if (data.ret !== 1) {
uploadOras[filename].fail(`Upload [fail:ret ${data.ret}] ${filename}`)
return
}
uploadOras[filename].succeed(`Upload [100%] ${filename}`)
}).catch(_ => {
uploadOras[filename].fail(`Upload [fail] ${filename}`)
})
}
}
}
}
});
}
/**
* 通用发布
* @param url
@@ -122,6 +192,10 @@ function genericPublish({url, key, version, output}) {
return
}
const filePath = path.resolve(__dirname, output)
if (!fs.existsSync(filePath)) {
console.warn("Publish output not found: " + filePath)
return
}
fs.readdir(filePath, async (err, files) => {
if (err) {
console.warn(err)
@@ -166,7 +240,19 @@ function genericPublish({url, key, version, output}) {
uploadOras[filename] = ora(`Upload [0%] ${filename}`).start()
},
retryNumber: 3
}).then(_ => {
}).then(({status, data}) => {
if (status !== 200) {
uploadOras[filename].fail(`Upload [fail:${status}] ${filename}`)
return
}
if (!utils.isJson(data)) {
uploadOras[filename].fail(`Upload [fail:not json] ${filename}`)
return
}
if (data.ret !== 1) {
uploadOras[filename].fail(`Upload [fail:ret ${data.ret}] ${filename}`)
return
}
uploadOras[filename].succeed(`Upload [100%] ${filename}`)
}).catch(_ => {
uploadOras[filename].fail(`Upload [fail] ${filename}`)
@@ -230,15 +316,34 @@ function startBuild(data) {
//
if (data.id === 'app') {
const eeuiDir = path.resolve(__dirname, "../resources/mobile");
const eeuiCli = "kuaifan/eeui-cli:0.0.1"
const eeuiRun = `--rm -v ${eeuiDir}:/work -w /work kuaifan/eeui-cli:0.0.1`
const publicDir = path.resolve(__dirname, "../resources/mobile/src/public");
fse.removeSync(publicDir)
fse.copySync(electronDir, publicDir)
if (argv[3] === "setting") {
child_process.spawnSync("docker", `run -it --rm -v ${eeuiDir}:/work -w /work ${eeuiCli} eeui setting`.split(" "), {stdio: "inherit", cwd: "resources/mobile"});
child_process.execSync(`docker run -it ${eeuiRun} eeui setting`, {stdio: "inherit", cwd: "resources/mobile"});
}
if (['setting', 'build'].includes(argv[3])) {
child_process.spawnSync("docker", `run -it --rm -v ${eeuiDir}:/work -w /work ${eeuiCli} eeui build --simple`.split(" "), {stdio: "inherit", cwd: "resources/mobile"});
if (argv[3] === "publish") {
const gradleFile = path.resolve(eeuiDir, "platforms/android/eeuiApp/build.gradle")
if (fs.existsSync(gradleFile)) {
let gradleResult = fs.readFileSync(gradleFile, 'utf8')
gradleResult = gradleResult.replace(/versionCode\s*=\s*(.+?)(\n|$)/, `versionCode = ${config.codeVerson}\n`)
gradleResult = gradleResult.replace(/versionName\s*=\s*(.+?)(\n|$)/, `versionName = "${config.version}"\n`)
fs.writeFileSync(gradleFile, gradleResult, 'utf8')
}
const xcconfigFile = path.resolve(eeuiDir, "platforms/ios/eeuiApp/Config/IdentityConfig.xcconfig")
if (fs.existsSync(xcconfigFile)) {
let xcconfigResult = fs.readFileSync(xcconfigFile, 'utf8')
xcconfigResult = xcconfigResult.replace(/BASE_CODE_VERSON\s*=\s*(.+?)(\n|$)/, `BASE_CODE_VERSON = ${config.codeVerson}\n`)
xcconfigResult = xcconfigResult.replace(/BASE_SHORT_VERSON\s*=\s*(.+?)(\n|$)/, `BASE_SHORT_VERSON = ${config.version}\n`)
fs.writeFileSync(xcconfigFile, xcconfigResult, 'utf8')
}
}
if (['setting', 'build', 'publish'].includes(argv[3])) {
if (!fs.existsSync(path.resolve(eeuiDir, "node_modules"))) {
child_process.execSync(`docker run ${eeuiRun} npm install`, {stdio: "inherit", cwd: "resources/mobile"});
}
child_process.execSync(`docker run ${eeuiRun} eeui build --simple`, {stdio: "inherit", cwd: "resources/mobile"});
} else {
[
path.resolve(publicDir, "../../platforms/ios/eeuiApp/bundlejs/eeui/public"),
@@ -291,13 +396,13 @@ function startBuild(data) {
}
econfig.build.directories.output = `${output}-github`;
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 2), 'utf8');
child_process.spawnSync("npm" + comSuffix, ["run", `${platform}-publish`], {stdio: "inherit", cwd: "electron"});
child_process.execSync(`npm run ${platform}-publish`, {stdio: "inherit", cwd: "electron"});
}
// generic (build || publish)
econfig.build.publish = data.publish
econfig.build.directories.output = `${output}-generic`;
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 2), 'utf8');
child_process.spawnSync("npm" + comSuffix, ["run", platform], {stdio: "inherit", cwd: "electron"});
child_process.execSync(`npm run ${platform}`, {stdio: "inherit", cwd: "electron"});
if (publish === true && DP_KEY) {
genericPublish({
url: econfig.build.publish.url,
@@ -338,6 +443,12 @@ if (["dev"].includes(argv[2])) {
notarize: false,
}
}, false, false)
} else if (["android-upload"].includes(argv[2])) {
config.app.forEach(({publish}) => {
if (publish.provider === 'generic') {
androidUpload(publish.url)
}
})
} else if (["all", "win", "mac"].includes(argv[2])) {
// 自动编译
platforms.filter(p => {

58
electron/electron.js vendored
View File

@@ -96,6 +96,14 @@ function createMainWindow() {
}
})
mainWindow.on('focus', () => {
mainWindow.webContents.send("browserWindowFocus", {})
})
mainWindow.on('blur', () => {
mainWindow.webContents.send("browserWindowBlur", {})
})
mainWindow.on('close', event => {
if (!willQuitApp) {
utils.onBeforeUnload(event, mainWindow).then(() => {
@@ -159,6 +167,14 @@ function createChildWindow(args) {
}
})
browser.on('focus', () => {
browser.webContents.send("browserWindowFocus", {})
})
browser.on('blur', () => {
browser.webContents.send("browserWindowBlur", {})
})
browser.on('close', event => {
if (!willQuitApp) {
utils.onBeforeUnload(event, browser).then(() => {
@@ -294,6 +310,12 @@ function createWebTabWindow(args) {
}, webPreferences),
}, config))
if (nativeTheme.shouldUseDarkColors) {
webTabWindow.setBackgroundColor('#3B3B3D')
} else {
webTabWindow.setBackgroundColor('#EFF0F4')
}
webTabWindow.on('resize', () => {
resizeWebTab(0)
})
@@ -343,6 +365,8 @@ function createWebTabWindow(args) {
if (utils.isMetaOrControl(input) && input.key.toLowerCase() === 'r') {
reloadWebTab(0)
event.preventDefault()
} else if (utils.isMetaOrControl(input) && input.shift && input.key.toLowerCase() === 'i') {
devToolsWebTab(0)
}
})
@@ -350,7 +374,11 @@ function createWebTabWindow(args) {
})
}
if (webTabWindow.isMinimized()) {
webTabWindow.restore()
}
webTabWindow.focus();
webTabWindow.show();
// 创建子窗口
const browserView = new BrowserView({
@@ -419,12 +447,16 @@ function createWebTabWindow(args) {
event: 'stop-loading',
id: browserView.webContents.id,
}).then(_ => { })
// 加载完成暗黑模式下把窗口背景色改成白色,避免透明网站背景色穿透
if (nativeTheme.shouldUseDarkColors) {
browserView.setBackgroundColor('#FFFFFF')
}
})
browserView.webContents.on('before-input-event', (event, input) => {
if (utils.isMetaOrControl(input) && input.key.toLowerCase() === 'r') {
browserView.webContents.reload()
event.preventDefault()
} else if (input.meta && input.shift && input.key.toLowerCase() === 'i') {
} else if (utils.isMetaOrControl(input) && input.shift && input.key.toLowerCase() === 'i') {
browserView.webContents.toggleDevTools()
}
})
@@ -469,6 +501,18 @@ function reloadWebTab(id) {
item.view.webContents.reload()
}
/**
* 内置浏览器标签打开开发者工具
* @param id
*/
function devToolsWebTab(id) {
const item = id === 0 ? currentWebTab() : webTabView.find(item => item.id == id)
if (!item) {
return
}
item.view.webContents.toggleDevTools()
}
/**
* 调整内置浏览器标签尺寸
* @param id
@@ -614,18 +658,6 @@ app.on("will-quit",function(){
globalShortcut.unregisterAll();
})
app.on('browser-window-blur', () => {
if (mainWindow) {
mainWindow.webContents.send("browserWindowBlur", {})
}
})
app.on('browser-window-focus', () => {
if (mainWindow) {
mainWindow.webContents.send("browserWindowFocus", {})
}
})
/**
* 设置菜单语言包
* @param args {path}

View File

@@ -26,14 +26,14 @@
"url": "https://github.com/kuaifan/dootask.git"
},
"devDependencies": {
"@electron-forge/cli": "^7.3.0",
"@electron-forge/maker-deb": "^7.3.0",
"@electron-forge/maker-rpm": "^7.3.0",
"@electron-forge/maker-squirrel": "^7.3.0",
"@electron-forge/maker-zip": "^7.3.0",
"@electron-forge/cli": "^7.3.1",
"@electron-forge/maker-deb": "^7.3.1",
"@electron-forge/maker-rpm": "^7.3.1",
"@electron-forge/maker-squirrel": "^7.3.1",
"@electron-forge/maker-zip": "^7.3.1",
"dotenv": "^16.3.1",
"electron": "^29.1.0",
"electron-builder": "^24.12.0",
"electron": "^29.2.0",
"electron-builder": "^24.13.3",
"electron-notarize": "^1.2.2",
"form-data": "^4.0.0",
"ora": "^4.1.1"

View File

@@ -79,6 +79,12 @@
const faviconItem = this.tabs.find(item => item.id === id)
if (faviconItem) {
faviconItem.icon = detail.favicons[detail.favicons.length - 1]
//
const img = new Image();
img.onerror = () => {
faviconItem.icon = ''
};
img.src = faviconItem.icon
}
break

View File

@@ -268,7 +268,7 @@ LDAP 用户禁止修改邮箱
此消息不支持此操作
仅支持修改自己的消息
回复的消息不存在
当前版本 (*) 过低,最低版本要求 (*)。
当前客户端版本 (*) 过低,最低版本要求 (*)。
语音格式错误
语音保存失败
图片格式错误
@@ -441,7 +441,7 @@ Api接口文档
开心笑话
心灵鸡汤
请填写完整的参数
请填写基本配置
终端SN与License不匹配
终端MAC与License不匹配
@@ -491,3 +491,18 @@ Api接口文档
点击下载
置顶会话无法隐藏
注册失败
会议已结束
请选择举报类型
请填写举报原因
开启语音转文字功能需要在应用中开启 ChatGPT AI 机器人。
语音转文字功能未开启
语音文件不存在
语音转文字失败
仅支持语音消息
视频

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