@zhangxm2512/xm2512todoserver 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ **v1.0.0(2026.6.7)**
2
+ 1.`A` 第一版本
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ 本包是轩铭智能待办官方开发的基于Nodejs的团队服务端。
2
+ **一、脚本**
3
+ 安装:[https://www.zhangls2512.cn/xm2512todoserver-install.sh](https://www.zhangls2512.cn/xm2512todoserver-install.sh)
4
+ 启动:[https://www.zhangls2512.cn/xm2512todoserver-start.sh](https://www.zhangls2512.cn/xm2512todoserver-start.sh)
5
+ 停止:[https://www.zhangls2512.cn/xm2512todoserver-stop.sh](https://www.zhangls2512.cn/xm2512todoserver-stop.sh)
6
+ 更新:[https://www.zhangls2512.cn/xm2512todoserver-update.sh](https://www.zhangls2512.cn/xm2512todoserver-update.sh)
7
+ **二、开发者联系方式**
8
+ 微信:gerenyinsi_z07x17m
9
+ QQ:2300990296
10
+ 邮箱:2300990296@qq.com
@@ -0,0 +1,90 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ if (typeof (requestdata.id) != 'string' || requestdata.id.length != 36) {
6
+ return {
7
+ code: 400,
8
+ msg: '请求参数错误'
9
+ }
10
+ }
11
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
12
+ if (res.code != 0) {
13
+ return res
14
+ } else {
15
+ const account = res.account
16
+ const team = res.team
17
+ const todores = await db.collection('todo').where({
18
+ teamId: team.teamId,
19
+ id: requestdata.id
20
+ }).get()
21
+ if (todores.length == 0) {
22
+ return {
23
+ code: 400,
24
+ msg: '待办不存在'
25
+ }
26
+ }
27
+ const todo = todores[0]
28
+ if (!todo.allowCompleteUids.includes(account.userId)) {
29
+ return {
30
+ code: 403,
31
+ msg: '无权限'
32
+ }
33
+ }
34
+ const recentCompleteTime = todo.recentCompleteTime
35
+ const reviewRecentCompleteTime = todo.reviewRecentCompleteTime
36
+ const recentCompleteTimeIndex = recentCompleteTime.findIndex(item => item.uid == account.userId)
37
+ const reviewRecentCompleteTimeIndex = reviewRecentCompleteTime.findIndex(item => item.uid == account.userId)
38
+ if (recentCompleteTimeIndex == -1 && reviewRecentCompleteTimeIndex == -1) {
39
+ if (todo.completeMode == 'single' && recentCompleteTime.length > 0) {
40
+ return {
41
+ code: 400,
42
+ msg: '已完成'
43
+ }
44
+ }
45
+ const completeTime = Date.now()
46
+ if (todo.startTime > completeTime) {
47
+ return {
48
+ code: 400,
49
+ msg: '未到开始时间'
50
+ }
51
+ }
52
+ if (todo.endTime < completeTime && todo.endTime != -1) {
53
+ return {
54
+ code: 400,
55
+ msg: '已过结束时间'
56
+ }
57
+ }
58
+ if (todo.allowReviewUids.length == 0) {
59
+ recentCompleteTime.push({
60
+ uid: account.userId,
61
+ time: completeTime
62
+ })
63
+ }
64
+ if (todo.allowReviewUids.length > 0) {
65
+ reviewRecentCompleteTime.push({
66
+ uid: account.userId,
67
+ time: completeTime
68
+ })
69
+ }
70
+ } else {
71
+ if (recentCompleteTimeIndex != -1) {
72
+ recentCompleteTime.splice(recentCompleteTimeIndex, 1)
73
+ }
74
+ if (reviewRecentCompleteTimeIndex != -1) {
75
+ reviewRecentCompleteTime.splice(reviewRecentCompleteTimeIndex, 1)
76
+ }
77
+ }
78
+ await db.collection('todo').where({
79
+ teamId: team.teamId,
80
+ id: requestdata.id
81
+ }).update({
82
+ recentCompleteTime: recentCompleteTime,
83
+ reviewRecentCompleteTime: reviewRecentCompleteTime
84
+ })
85
+ return {
86
+ code: 0,
87
+ msg: '成功'
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,54 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
5
+ if (res.code != 0) {
6
+ return res
7
+ } else {
8
+ const account = res.account
9
+ const team = res.team
10
+ if (!account.admin) {
11
+ return {
12
+ code: 403,
13
+ msg: '无权限'
14
+ }
15
+ }
16
+ const viplogres = await db.collection('viplog').where({
17
+ product: 'todoteam',
18
+ uid: team.teamId
19
+ }).count()
20
+ if (viplogres.total > 0) {
21
+ return {
22
+ code: 400,
23
+ msg: '存在付费开通记录'
24
+ }
25
+ }
26
+ const accountres = await db.collection('account').where({
27
+ teamId: team.teamId,
28
+ admin: false
29
+ }).count()
30
+ if (accountres.total > 0) {
31
+ return {
32
+ code: 400,
33
+ msg: '用户未清空'
34
+ }
35
+ }
36
+ const todores = await db.collection('todo').where({
37
+ teamId: team.teamId
38
+ }).count()
39
+ if (todores.total > 0) {
40
+ return {
41
+ code: 400,
42
+ msg: '待办未清空'
43
+ }
44
+ }
45
+ await db.collection('account').where({
46
+ teamId: team.teamId,
47
+ admin: true
48
+ }).remove()
49
+ return {
50
+ code: 0,
51
+ msg: '成功'
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ if (typeof (requestdata.id) != 'string' || requestdata.id.length != 36) {
6
+ return {
7
+ code: 400,
8
+ msg: '请求参数错误'
9
+ }
10
+ }
11
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
12
+ if (res.code != 0) {
13
+ return res
14
+ } else {
15
+ const account = res.account
16
+ const team = res.team
17
+ const todores = await db.collection('todo').where({
18
+ teamId: team.teamId,
19
+ id: requestdata.id
20
+ }).get()
21
+ if (todores.length == 0) {
22
+ return {
23
+ code: 400,
24
+ msg: '待办不存在'
25
+ }
26
+ }
27
+ if (!account.admin && todores[0].uid != account.userId) {
28
+ return {
29
+ code: 403,
30
+ msg: '无权限'
31
+ }
32
+ }
33
+ await db.collection('todo').where({
34
+ teamId: team.teamId,
35
+ id: requestdata.id
36
+ }).remove()
37
+ return {
38
+ code: 0,
39
+ msg: '成功'
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ if (typeof (requestdata.id) != 'string' || requestdata.id.length != 8) {
6
+ return {
7
+ code: 400,
8
+ msg: '请求参数错误'
9
+ }
10
+ }
11
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
12
+ if (res.code != 0) {
13
+ return res
14
+ } else {
15
+ const account = res.account
16
+ const team = res.team
17
+ if (!account.admin) {
18
+ return {
19
+ code: 403,
20
+ msg: '无权限'
21
+ }
22
+ }
23
+ const todores = await db.collection('todo').where({
24
+ teamId: team.teamId,
25
+ uid: requestdata.id
26
+ }).count()
27
+ if (todores.total > 0) {
28
+ return {
29
+ code: 400,
30
+ msg: '其管理的待办未清空'
31
+ }
32
+ }
33
+ const accountres = await db.collection('account').where({
34
+ teamId: team.teamId,
35
+ userId: requestdata.id,
36
+ admin: false
37
+ }).remove()
38
+ if (accountres.deleted == 0) {
39
+ return {
40
+ code: 400,
41
+ msg: '用户不存在'
42
+ }
43
+ }
44
+ return {
45
+ code: 0,
46
+ msg: '成功'
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,34 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
5
+ if (res.code != 0) {
6
+ return res
7
+ } else {
8
+ const account = res.account
9
+ const team = res.team
10
+ if (!account.admin) {
11
+ return {
12
+ code: 403,
13
+ msg: '无权限'
14
+ }
15
+ }
16
+ const accountres = await db.collection('account').where({
17
+ teamId: team.teamId
18
+ }).count()
19
+ const todores = await db.collection('todo').where({
20
+ teamId: team.teamId
21
+ }).count()
22
+ return {
23
+ code: 0,
24
+ msg: '成功',
25
+ data: {
26
+ teamId: team.teamId,
27
+ teamName: team.teamName,
28
+ userCount: accountres.total,
29
+ todoCount: todores.total,
30
+ teamSetting: team.teamSetting
31
+ }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,144 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ const validtypes = ['complete', 'get', 'review', 'create']
6
+ if (!validtypes.includes(requestdata.type)) {
7
+ return {
8
+ code: 400,
9
+ msg: '请求参数错误'
10
+ }
11
+ }
12
+ if (!Number.isInteger(requestdata.time) || requestdata.time < -1) {
13
+ return {
14
+ code: 400,
15
+ msg: '请求参数错误'
16
+ }
17
+ }
18
+ let skip = 0
19
+ let limit = 10
20
+ if (Number.isInteger(requestdata.skip) && requestdata.skip >= 0) {
21
+ skip = requestdata.skip
22
+ }
23
+ if (Number.isInteger(requestdata.limit) && requestdata.limit > 0 && requestdata.limit <= 20) {
24
+ limit = requestdata.limit
25
+ }
26
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
27
+ if (res.code != 0) {
28
+ return res
29
+ } else {
30
+ const account = res.account
31
+ const team = res.team
32
+ if (requestdata.type == 'complete') {
33
+ const todores = await db.collection('todo').where({
34
+ teamId: team.teamId,
35
+ startTime: requestdata.time === -1 ? db.command.gte(0) : db.command.lt(requestdata.time + 86400000),
36
+ allowCompleteUids: db.command.in([account.userId])
37
+ }).skip(skip).limit(limit).field({
38
+ _id: false,
39
+ allowGetUids: false,
40
+ allowCompleteUids: false,
41
+ allowReviewUids: false,
42
+ uid: false,
43
+ setting: false
44
+ }).get()
45
+ const data = todores
46
+ data.forEach(item => {
47
+ const recentCompleteTimeIndex = item.recentCompleteTime.findIndex(item => item.uid == account.userId)
48
+ const reviewRecentCompleteTimeIndex = item.reviewRecentCompleteTime.findIndex(item => item.uid == account.userId)
49
+ if (item.completeMode == 'single') {
50
+ if (item.recentCompleteTime.length > 0) {
51
+ item.status = 'finished'
52
+ item.recentCompletedTime = item.recentCompleteTime[0].time
53
+ } else if (reviewRecentCompleteTimeIndex != -1) {
54
+ item.status = 'reviewing'
55
+ item.recentCompletedTime = item.reviewRecentCompleteTime[reviewRecentCompleteTimeIndex].time
56
+ } else {
57
+ item.status = 'pending'
58
+ item.recentCompletedTime = -1
59
+ }
60
+ }
61
+ if (item.completeMode == 'multiple') {
62
+ if (recentCompleteTimeIndex != -1) {
63
+ item.status = 'finished'
64
+ item.recentCompletedTime = item.recentCompleteTime[recentCompleteTimeIndex].time
65
+ } else if (reviewRecentCompleteTimeIndex != -1) {
66
+ item.status = 'reviewing'
67
+ item.recentCompletedTime = item.reviewRecentCompleteTime[reviewRecentCompleteTimeIndex].time
68
+ } else {
69
+ item.status = 'pending'
70
+ item.recentCompletedTime = -1
71
+ }
72
+ }
73
+ delete item.recentCompleteTime
74
+ delete item.reviewRecentCompleteTime
75
+ })
76
+ return {
77
+ code: 0,
78
+ msg: '成功',
79
+ data: data
80
+ }
81
+ }
82
+ if (requestdata.type == 'review') {
83
+ const todores = await db.collection('todo').where({
84
+ teamId: team.teamId,
85
+ startTime: requestdata.time === -1 ? db.command.gte(0) : db.command.lt(requestdata.time + 86400000),
86
+ allowReviewUids: db.command.in([account.userId])
87
+ }).skip(skip).limit(limit).field({
88
+ _id: false,
89
+ allowGetUids: false,
90
+ allowCompleteUids: false,
91
+ allowReviewUids: false,
92
+ uid: false,
93
+ setting: false
94
+ }).get()
95
+ return {
96
+ code: 0,
97
+ msg: '成功',
98
+ data: todores
99
+ }
100
+ }
101
+ if (requestdata.type == 'get') {
102
+ if (!account.admin && !account.permission.includes('getTodo')) {
103
+ const todores = await db.collection('todo').where({
104
+ teamId: team.teamId,
105
+ startTime: requestdata.time === -1 ? db.command.gte(0) : db.command.lt(requestdata.time + 86400000),
106
+ allowGetUids: db.command.in([account.userId])
107
+ }).skip(skip).limit(limit).field({
108
+ _id: false
109
+ }).get()
110
+ return {
111
+ code: 0,
112
+ msg: '成功',
113
+ data: todores
114
+ }
115
+ } else {
116
+ const todores = await db.collection('todo').where({
117
+ teamId: team.teamId,
118
+ startTime: requestdata.time === -1 ? db.command.gte(0) : db.command.lt(requestdata.time + 86400000)
119
+ }).skip(skip).limit(limit).field({
120
+ _id: false
121
+ }).get()
122
+ return {
123
+ code: 0,
124
+ msg: '成功',
125
+ data: todores
126
+ }
127
+ }
128
+ }
129
+ if (requestdata.type == 'create') {
130
+ const todores = await db.collection('todo').where({
131
+ teamId: team.teamId,
132
+ startTime: requestdata.time === -1 ? db.command.gte(0) : db.command.lt(requestdata.time + 86400000),
133
+ uid: account.userId
134
+ }).skip(skip).limit(limit).field({
135
+ _id: false
136
+ }).get()
137
+ return {
138
+ code: 0,
139
+ msg: '成功',
140
+ data: todores
141
+ }
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
4
+ if (res.code != 0) {
5
+ return res
6
+ } else {
7
+ const account = res.account
8
+ const team = res.team
9
+ return {
10
+ code: 0,
11
+ msg: '成功',
12
+ data: {
13
+ teamId: team.teamId,
14
+ teamName: team.teamName,
15
+ userId: account.userId,
16
+ userName: account.userName,
17
+ userEnabled: account.userEnabled,
18
+ admin: account.admin,
19
+ permission: account.permission,
20
+ userSetting: account.userSetting
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,38 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ let skip = 0
6
+ let limit = 10
7
+ if (Number.isInteger(requestdata.skip) && requestdata.skip >= 0) {
8
+ skip = requestdata.skip
9
+ }
10
+ if (Number.isInteger(requestdata.limit) && requestdata.limit > 0 && requestdata.limit <= 20) {
11
+ limit = requestdata.limit
12
+ }
13
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
14
+ if (res.code != 0) {
15
+ return res
16
+ } else {
17
+ const account = res.account
18
+ const team = res.team
19
+ if (!account.admin && !account.permission.includes('newTodo')) {
20
+ return {
21
+ code: 403,
22
+ msg: '无权限'
23
+ }
24
+ }
25
+ const accountres = await db.collection('account').where({
26
+ teamId: team.teamId
27
+ }).skip(skip).limit(limit).field({
28
+ _id: false,
29
+ password: false,
30
+ userSetting: false
31
+ }).get()
32
+ return {
33
+ code: 0,
34
+ msg: '成功',
35
+ data: accountres
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const db = await (require('../util/db').database(configfilepath))
4
+ const requestdata = JSON.parse(event.body)
5
+ if (typeof (requestdata.id) != 'string' || requestdata.id.length != 8) {
6
+ return {
7
+ code: 400,
8
+ msg: '请求参数错误'
9
+ }
10
+ }
11
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
12
+ if (res.code != 0) {
13
+ return res
14
+ } else {
15
+ const team = res.team
16
+ const accountres = await db.collection('account').where({
17
+ teamId: team.teamId,
18
+ userId: requestdata.id
19
+ }).get()
20
+ if (accountres.length == 0) {
21
+ return {
22
+ code: 400,
23
+ msg: '用户不存在'
24
+ }
25
+ }
26
+ return {
27
+ code: 0,
28
+ msg: '成功',
29
+ name: accountres[0].userName
30
+ }
31
+ }
32
+ }
package/api/newTodo.js ADDED
@@ -0,0 +1,107 @@
1
+ 'use strict'
2
+ exports.main = async (event, configfilepath) => {
3
+ const crypto = require('crypto')
4
+ const db = await (require('../util/db').database(configfilepath))
5
+ const requestdata = JSON.parse(event.body)
6
+ let success = true
7
+ if (typeof (requestdata.content) != 'string' || !requestdata.content) {
8
+ success = false
9
+ }
10
+ if (!Number.isInteger(requestdata.priority) || requestdata.priority < 0 || requestdata.priority > 9) {
11
+ success = false
12
+ }
13
+ if (!Number.isInteger(requestdata.startTime) || requestdata.startTime < 0) {
14
+ success = false
15
+ }
16
+ if (!Number.isInteger(requestdata.endTime) || (requestdata.endTime < requestdata.startTime && requestdata.endTime != -1)) {
17
+ success = false
18
+ }
19
+ if (!Number.isInteger(requestdata.duration) || requestdata.duration < 0) {
20
+ success = false
21
+ }
22
+ if (!Array.isArray(requestdata.tag) || !requestdata.tag.every(item => typeof (item) == 'string' && item)) {
23
+ success = false
24
+ }
25
+ if (!requestdata.location) {
26
+ success = false
27
+ }
28
+ if (typeof (requestdata.location.latitude) != 'number' || requestdata.location.latitude < -90 || requestdata.location.latitude > 90) {
29
+ success = false
30
+ }
31
+ if (typeof (requestdata.location.longitude) != 'number' || requestdata.location.longitude < -180 || requestdata.location.longitude > 180) {
32
+ success = false
33
+ }
34
+ if (typeof (requestdata.location.location) != 'string') {
35
+ success = false
36
+ }
37
+ if (!Array.isArray(requestdata.action)) {
38
+ success = false
39
+ }
40
+ if (typeof (requestdata.bz) != 'string') {
41
+ success = false
42
+ }
43
+ if (!Array.isArray(requestdata.allowGetUids) || !requestdata.allowGetUids.every(item => typeof (item) == 'string' && item.length == 8)) {
44
+ success = false
45
+ }
46
+ if (!Array.isArray(requestdata.allowCompleteUids) || !requestdata.allowCompleteUids.every(item => typeof (item) == 'string' && item.length == 8)) {
47
+ success = false
48
+ }
49
+ if (!Array.isArray(requestdata.allowReviewUids) || !requestdata.allowReviewUids.every(item => typeof (item) == 'string' && item.length == 8)) {
50
+ success = false
51
+ }
52
+ const validcompletemodes = ['single', 'multiple']
53
+ if (!validcompletemodes.includes(requestdata.completeMode)) {
54
+ success = false
55
+ }
56
+ if (!success) {
57
+ return {
58
+ code: 400,
59
+ msg: '请求参数错误'
60
+ }
61
+ }
62
+ const res = await require('../util/authcheck').main(event.headers, configfilepath)
63
+ if (res.code != 0) {
64
+ return res
65
+ } else {
66
+ const account = res.account
67
+ const team = res.team
68
+ if (!account.admin && !account.permission.includes('newTodo')) {
69
+ return {
70
+ code: 403,
71
+ msg: '无权限'
72
+ }
73
+ }
74
+ await db.collection('todo').add({
75
+ id: crypto.randomUUID(),
76
+ teamId: team.teamId,
77
+ content: requestdata.content,
78
+ priority: requestdata.priority,
79
+ startTime: requestdata.startTime,
80
+ endTime: requestdata.endTime,
81
+ duration: requestdata.duration,
82
+ recurrenceRule: '',
83
+ excludeTime: [],
84
+ tag: [...new Set(requestdata.tag)],
85
+ dependency: [],
86
+ location: {
87
+ latitude: requestdata.location.latitude,
88
+ longitude: requestdata.location.longitude,
89
+ location: requestdata.location.location
90
+ },
91
+ action: requestdata.action,
92
+ bz: requestdata.bz,
93
+ allowGetUids: [...new Set(requestdata.allowGetUids)],
94
+ allowCompleteUids: [...new Set(requestdata.allowCompleteUids)],
95
+ allowReviewUids: [...new Set(requestdata.allowReviewUids)],
96
+ recentCompleteTime: [],
97
+ reviewRecentCompleteTime: [],
98
+ uid: account.userId,
99
+ completeMode: requestdata.completeMode,
100
+ updateTime: Date.now()
101
+ })
102
+ return {
103
+ code: 0,
104
+ msg: '成功'
105
+ }
106
+ }
107
+ }