napgram-plugin-slave-market 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/README.md +248 -0
- package/dist/commands/admin.commands.d.ts +11 -0
- package/dist/commands/admin.commands.d.ts.map +1 -0
- package/dist/commands/admin.commands.js +268 -0
- package/dist/commands/bank.commands.d.ts +13 -0
- package/dist/commands/bank.commands.d.ts.map +1 -0
- package/dist/commands/bank.commands.js +211 -0
- package/dist/commands/base.commands.d.ts +12 -0
- package/dist/commands/base.commands.d.ts.map +1 -0
- package/dist/commands/base.commands.js +149 -0
- package/dist/commands/economy.commands.d.ts +13 -0
- package/dist/commands/economy.commands.d.ts.map +1 -0
- package/dist/commands/economy.commands.js +221 -0
- package/dist/commands/gameplay.commands.d.ts +15 -0
- package/dist/commands/gameplay.commands.d.ts.map +1 -0
- package/dist/commands/gameplay.commands.js +461 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +47 -0
- package/dist/commands/social.commands.d.ts +13 -0
- package/dist/commands/social.commands.d.ts.map +1 -0
- package/dist/commands/social.commands.js +305 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.mjs +57 -0
- package/dist/models/index.d.ts +10 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +40 -0
- package/dist/services/admin.service.d.ts +59 -0
- package/dist/services/admin.service.d.ts.map +1 -0
- package/dist/services/admin.service.js +164 -0
- package/dist/services/bank.service.d.ts +74 -0
- package/dist/services/bank.service.d.ts.map +1 -0
- package/dist/services/bank.service.js +354 -0
- package/dist/services/bodyguard.service.d.ts +36 -0
- package/dist/services/bodyguard.service.d.ts.map +1 -0
- package/dist/services/bodyguard.service.js +102 -0
- package/dist/services/cooldown.service.d.ts +33 -0
- package/dist/services/cooldown.service.d.ts.map +1 -0
- package/dist/services/cooldown.service.js +104 -0
- package/dist/services/farm.service.d.ts +61 -0
- package/dist/services/farm.service.d.ts.map +1 -0
- package/dist/services/farm.service.js +255 -0
- package/dist/services/index.d.ts +16 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +15 -0
- package/dist/services/market.service.d.ts +58 -0
- package/dist/services/market.service.d.ts.map +1 -0
- package/dist/services/market.service.js +286 -0
- package/dist/services/player.service.d.ts +56 -0
- package/dist/services/player.service.d.ts.map +1 -0
- package/dist/services/player.service.js +201 -0
- package/dist/services/ranking.service.d.ts +28 -0
- package/dist/services/ranking.service.d.ts.map +1 -0
- package/dist/services/ranking.service.js +71 -0
- package/dist/services/redpacket.service.d.ts +63 -0
- package/dist/services/redpacket.service.d.ts.map +1 -0
- package/dist/services/redpacket.service.js +207 -0
- package/dist/services/transaction.service.d.ts +48 -0
- package/dist/services/transaction.service.d.ts.map +1 -0
- package/dist/services/transaction.service.js +102 -0
- package/dist/services/vip.service.d.ts +41 -0
- package/dist/services/vip.service.d.ts.map +1 -0
- package/dist/services/vip.service.js +167 -0
- package/dist/services/work.service.d.ts +49 -0
- package/dist/services/work.service.d.ts.map +1 -0
- package/dist/services/work.service.js +258 -0
- package/dist/types/index.d.ts +62 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/helpers.d.ts +40 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +88 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/napgram-plugin.json +15 -0
- package/package.json +56 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工作服务 - 打工、抢劫等收入相关功能
|
|
3
|
+
*/
|
|
4
|
+
import { getDatabase } from '../models';
|
|
5
|
+
export class WorkService {
|
|
6
|
+
ctx;
|
|
7
|
+
config;
|
|
8
|
+
transactionService;
|
|
9
|
+
playerService;
|
|
10
|
+
constructor(ctx, config, transactionService, playerService) {
|
|
11
|
+
this.ctx = ctx;
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.transactionService = transactionService;
|
|
14
|
+
this.playerService = playerService;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 打工
|
|
18
|
+
*/
|
|
19
|
+
async work(userId) {
|
|
20
|
+
const db = getDatabase();
|
|
21
|
+
const player = await db.slaveMarketPlayer.findUnique({
|
|
22
|
+
where: { userId },
|
|
23
|
+
include: { owner: true },
|
|
24
|
+
});
|
|
25
|
+
if (!player) {
|
|
26
|
+
throw new Error('玩家不存在');
|
|
27
|
+
}
|
|
28
|
+
// 基础收入 = 身价 * 收益比例
|
|
29
|
+
const baseIncome = Math.floor(player.worth * this.config.打工收益比例);
|
|
30
|
+
let income = baseIncome;
|
|
31
|
+
let ownerShare = 0;
|
|
32
|
+
let ownerName;
|
|
33
|
+
// 如果有主人,分成给主人
|
|
34
|
+
if (player.owner) {
|
|
35
|
+
ownerShare = Math.floor(income * 0.3); // 主人抽成30%
|
|
36
|
+
income -= ownerShare;
|
|
37
|
+
ownerName = player.owner.nickname;
|
|
38
|
+
// 给主人加钱
|
|
39
|
+
await db.slaveMarketPlayer.update({
|
|
40
|
+
where: { userId: player.owner.userId },
|
|
41
|
+
data: {
|
|
42
|
+
balance: {
|
|
43
|
+
increment: ownerShare,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
// 记录主人收益
|
|
48
|
+
await this.transactionService.createTransaction({
|
|
49
|
+
userId: player.owner.userId,
|
|
50
|
+
type: 'work',
|
|
51
|
+
amount: ownerShare,
|
|
52
|
+
balance: player.owner.balance + ownerShare,
|
|
53
|
+
targetId: userId,
|
|
54
|
+
description: `牛马打工分成(${player.nickname})`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// 更新玩家余额
|
|
58
|
+
const result = await db.slaveMarketPlayer.update({
|
|
59
|
+
where: { userId },
|
|
60
|
+
data: {
|
|
61
|
+
balance: player.balance + income,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
// 记录交易
|
|
65
|
+
await this.transactionService.createTransaction({
|
|
66
|
+
userId,
|
|
67
|
+
type: 'work',
|
|
68
|
+
amount: income,
|
|
69
|
+
balance: result.balance,
|
|
70
|
+
description: ownerName ? `打工(主人: ${ownerName})` : '打工',
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
income,
|
|
74
|
+
ownerShare,
|
|
75
|
+
newBalance: result.balance,
|
|
76
|
+
ownerName,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 抢劫
|
|
81
|
+
*/
|
|
82
|
+
async rob(robberId, targetId, strategy = '平衡') {
|
|
83
|
+
const db = getDatabase();
|
|
84
|
+
if (robberId === targetId) {
|
|
85
|
+
throw new Error('不能抢劫自己');
|
|
86
|
+
}
|
|
87
|
+
const [robber, target] = await Promise.all([
|
|
88
|
+
db.slaveMarketPlayer.findUnique({ where: { userId: robberId } }),
|
|
89
|
+
db.slaveMarketPlayer.findUnique({ where: { userId: targetId } }),
|
|
90
|
+
]);
|
|
91
|
+
if (!robber || !target) {
|
|
92
|
+
throw new Error('玩家不存在');
|
|
93
|
+
}
|
|
94
|
+
// 检查目标是否有保镖
|
|
95
|
+
const hasGuard = target.bodyguardEndTime && Number(target.bodyguardEndTime) > Date.now();
|
|
96
|
+
if (hasGuard) {
|
|
97
|
+
throw new Error(`目标有保镖保护,无法抢劫`);
|
|
98
|
+
}
|
|
99
|
+
// 根据策略计算成功率和收益率
|
|
100
|
+
const strategyConfig = this.getStrategyConfig(strategy);
|
|
101
|
+
const successRate = strategyConfig.successRate;
|
|
102
|
+
const yieldRate = strategyConfig.yieldRate;
|
|
103
|
+
// 判断是否成功
|
|
104
|
+
const success = Math.random() < successRate;
|
|
105
|
+
if (success) {
|
|
106
|
+
// 抢劫成功
|
|
107
|
+
const maxAmount = Math.floor(target.balance * yieldRate);
|
|
108
|
+
const amount = Math.min(maxAmount, target.balance);
|
|
109
|
+
if (amount <= 0) {
|
|
110
|
+
throw new Error('目标余额不足,无法抢劫');
|
|
111
|
+
}
|
|
112
|
+
await db.$transaction([
|
|
113
|
+
// 增加抢劫者余额
|
|
114
|
+
db.slaveMarketPlayer.update({
|
|
115
|
+
where: { userId: robberId },
|
|
116
|
+
data: { balance: robber.balance + amount },
|
|
117
|
+
}),
|
|
118
|
+
// 扣除目标余额
|
|
119
|
+
db.slaveMarketPlayer.update({
|
|
120
|
+
where: { userId: targetId },
|
|
121
|
+
data: { balance: target.balance - amount },
|
|
122
|
+
}),
|
|
123
|
+
]);
|
|
124
|
+
// 记录交易
|
|
125
|
+
await Promise.all([
|
|
126
|
+
this.transactionService.createTransaction({
|
|
127
|
+
userId: robberId,
|
|
128
|
+
type: 'rob',
|
|
129
|
+
amount,
|
|
130
|
+
balance: robber.balance + amount,
|
|
131
|
+
targetId,
|
|
132
|
+
description: `抢劫成功(${target.nickname})`,
|
|
133
|
+
}),
|
|
134
|
+
this.transactionService.createTransaction({
|
|
135
|
+
userId: targetId,
|
|
136
|
+
type: 'rob',
|
|
137
|
+
amount: -amount,
|
|
138
|
+
balance: target.balance - amount,
|
|
139
|
+
targetId: robberId,
|
|
140
|
+
description: `被抢劫(${robber.nickname})`,
|
|
141
|
+
}),
|
|
142
|
+
]);
|
|
143
|
+
return {
|
|
144
|
+
success: true,
|
|
145
|
+
amount,
|
|
146
|
+
newBalance: robber.balance + amount,
|
|
147
|
+
targetBalance: target.balance - amount,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// 抢劫失败,罚款和入狱
|
|
152
|
+
const penalty = Math.floor(robber.balance * 0.1); // 罚款10%
|
|
153
|
+
const jailTime = 10 * 60 * 1000; // 入狱10分钟
|
|
154
|
+
await db.slaveMarketPlayer.update({
|
|
155
|
+
where: { userId: robberId },
|
|
156
|
+
data: {
|
|
157
|
+
balance: Math.max(0, robber.balance - penalty),
|
|
158
|
+
jailEndTime: BigInt(Date.now() + jailTime),
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
// 记录交易
|
|
162
|
+
if (penalty > 0) {
|
|
163
|
+
await this.transactionService.createTransaction({
|
|
164
|
+
userId: robberId,
|
|
165
|
+
type: 'rob',
|
|
166
|
+
amount: -penalty,
|
|
167
|
+
balance: Math.max(0, robber.balance - penalty),
|
|
168
|
+
targetId,
|
|
169
|
+
description: `抢劫失败罚款`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
amount: 0,
|
|
175
|
+
newBalance: Math.max(0, robber.balance - penalty),
|
|
176
|
+
targetBalance: target.balance,
|
|
177
|
+
penalty,
|
|
178
|
+
jailTime: jailTime / 60000, // 转换为分钟
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* 转账
|
|
184
|
+
*/
|
|
185
|
+
async transfer(senderId, receiverId, amount, isAdmin = false) {
|
|
186
|
+
const db = getDatabase();
|
|
187
|
+
if (senderId === receiverId) {
|
|
188
|
+
throw new Error('不能给自己转账');
|
|
189
|
+
}
|
|
190
|
+
if (amount <= 0) {
|
|
191
|
+
throw new Error('转账金额必须大于0');
|
|
192
|
+
}
|
|
193
|
+
const [sender, receiver] = await Promise.all([
|
|
194
|
+
db.slaveMarketPlayer.findUnique({ where: { userId: senderId } }),
|
|
195
|
+
db.slaveMarketPlayer.findUnique({ where: { userId: receiverId } }),
|
|
196
|
+
]);
|
|
197
|
+
if (!sender || !receiver) {
|
|
198
|
+
throw new Error('玩家不存在');
|
|
199
|
+
}
|
|
200
|
+
// 计算手续费(管理员免费)
|
|
201
|
+
const fee = isAdmin ? 0 : Math.ceil(amount * this.config.转账手续费);
|
|
202
|
+
const total = amount + fee;
|
|
203
|
+
if (sender.balance < total) {
|
|
204
|
+
throw new Error(`余额不足,需要 ${total} (含手续费 ${fee})`);
|
|
205
|
+
}
|
|
206
|
+
await db.$transaction([
|
|
207
|
+
// 扣除发送者余额
|
|
208
|
+
db.slaveMarketPlayer.update({
|
|
209
|
+
where: { userId: senderId },
|
|
210
|
+
data: { balance: sender.balance - total },
|
|
211
|
+
}),
|
|
212
|
+
// 增加接收者余额
|
|
213
|
+
db.slaveMarketPlayer.update({
|
|
214
|
+
where: { userId: receiverId },
|
|
215
|
+
data: { balance: receiver.balance + amount },
|
|
216
|
+
}),
|
|
217
|
+
]);
|
|
218
|
+
// 记录交易
|
|
219
|
+
await Promise.all([
|
|
220
|
+
this.transactionService.createTransaction({
|
|
221
|
+
userId: senderId,
|
|
222
|
+
type: 'transfer',
|
|
223
|
+
amount: -total,
|
|
224
|
+
balance: sender.balance - total,
|
|
225
|
+
targetId: receiverId,
|
|
226
|
+
description: `转账给 ${receiver.nickname}`,
|
|
227
|
+
}),
|
|
228
|
+
this.transactionService.createTransaction({
|
|
229
|
+
userId: receiverId,
|
|
230
|
+
type: 'transfer',
|
|
231
|
+
amount,
|
|
232
|
+
balance: receiver.balance + amount,
|
|
233
|
+
targetId: senderId,
|
|
234
|
+
description: `收到转账(${sender.nickname})`,
|
|
235
|
+
}),
|
|
236
|
+
]);
|
|
237
|
+
return {
|
|
238
|
+
fee,
|
|
239
|
+
actualAmount: amount,
|
|
240
|
+
newBalance: sender.balance - total,
|
|
241
|
+
receiverBalance: receiver.balance + amount,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* 获取抢劫策略配置
|
|
246
|
+
*/
|
|
247
|
+
getStrategyConfig(strategy) {
|
|
248
|
+
switch (strategy) {
|
|
249
|
+
case '稳健':
|
|
250
|
+
return { successRate: 0.8, yieldRate: 0.2 }; // 80%成功率,抢20%
|
|
251
|
+
case '激进':
|
|
252
|
+
return { successRate: 0.3, yieldRate: 0.5 }; // 30%成功率,抢50%
|
|
253
|
+
case '平衡':
|
|
254
|
+
default:
|
|
255
|
+
return { successRate: 0.5, yieldRate: 0.3 }; // 50%成功率,抢30%
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript 类型定义
|
|
3
|
+
*/
|
|
4
|
+
export interface Player {
|
|
5
|
+
id: number;
|
|
6
|
+
userId: string;
|
|
7
|
+
plainUserId?: string;
|
|
8
|
+
nickname: string;
|
|
9
|
+
balance: number;
|
|
10
|
+
deposit: number;
|
|
11
|
+
worth: number;
|
|
12
|
+
creditLevel: number;
|
|
13
|
+
loanBalance: number;
|
|
14
|
+
ownerId?: string;
|
|
15
|
+
ownedTime?: number;
|
|
16
|
+
vipEndTime?: number;
|
|
17
|
+
registerTime: number;
|
|
18
|
+
lastWorkTime?: number;
|
|
19
|
+
lastRobTime?: number;
|
|
20
|
+
lastTransferTime?: number;
|
|
21
|
+
lastBuyTime?: number;
|
|
22
|
+
isAdmin: boolean;
|
|
23
|
+
commandBanned: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface Transaction {
|
|
26
|
+
id: number;
|
|
27
|
+
userId: string;
|
|
28
|
+
type: TransactionType;
|
|
29
|
+
amount: number;
|
|
30
|
+
balance: number;
|
|
31
|
+
description?: string;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
}
|
|
34
|
+
export type TransactionType = 'work' | 'rob' | 'transfer' | 'buy_player' | 'release' | 'ransom' | 'deposit' | 'withdraw' | 'interest' | 'loan' | 'repay' | 'plant' | 'harvest' | 'buy_land' | 'hire_guard' | 'red_packet' | 'system';
|
|
35
|
+
export interface FarmLand {
|
|
36
|
+
id: number;
|
|
37
|
+
userId: string;
|
|
38
|
+
plotIndex: number;
|
|
39
|
+
cropType?: string;
|
|
40
|
+
plantTime?: number;
|
|
41
|
+
harvestTime?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface Crop {
|
|
44
|
+
name: string;
|
|
45
|
+
emoji: string;
|
|
46
|
+
price: number;
|
|
47
|
+
growTime: number;
|
|
48
|
+
baseYield: number;
|
|
49
|
+
yieldRange: [number, number];
|
|
50
|
+
}
|
|
51
|
+
export interface Bodyguard {
|
|
52
|
+
name: string;
|
|
53
|
+
price: number;
|
|
54
|
+
duration: number;
|
|
55
|
+
defense: number;
|
|
56
|
+
}
|
|
57
|
+
export interface CooldownRecord {
|
|
58
|
+
userId: string;
|
|
59
|
+
action: string;
|
|
60
|
+
expireTime: number;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,MAAM;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GACrB,MAAM,GACN,KAAK,GACL,UAAU,GACV,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,SAAS,GACT,UAAU,GACV,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,SAAS,GACT,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,QAAQ,CAAC;AAEf,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,IAAI;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具函数
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 格式化数字(添加千分位)
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatNumber(num: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* 格式化时间差
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatDuration(ms: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* 格式化日期
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatDate(timestamp: number | bigint): string;
|
|
16
|
+
/**
|
|
17
|
+
* 生成随机字符串
|
|
18
|
+
*/
|
|
19
|
+
export declare function randomString(length: number, charset?: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* 计算百分比
|
|
22
|
+
*/
|
|
23
|
+
export declare function percentage(value: number, total: number, decimals?: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* 随机整数(包含min和max)
|
|
26
|
+
*/
|
|
27
|
+
export declare function randomInt(min: number, max: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* 检查是否在时间范围内
|
|
30
|
+
*/
|
|
31
|
+
export declare function isWithinTimeRange(timestamp: number | bigint, rangeMs: number): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 安全的除法(避免除零)
|
|
34
|
+
*/
|
|
35
|
+
export declare function safeDivide(numerator: number, denominator: number, defaultValue?: number): number;
|
|
36
|
+
/**
|
|
37
|
+
* 限制数值范围
|
|
38
|
+
*/
|
|
39
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
40
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAsBjD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAS7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAA2C,GAAG,MAAM,CAMzG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,MAAM,CAGrF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAItF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,MAAM,CAEnG;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具函数
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 格式化数字(添加千分位)
|
|
6
|
+
*/
|
|
7
|
+
export function formatNumber(num) {
|
|
8
|
+
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 格式化时间差
|
|
12
|
+
*/
|
|
13
|
+
export function formatDuration(ms) {
|
|
14
|
+
const seconds = Math.floor(ms / 1000);
|
|
15
|
+
const minutes = Math.floor(seconds / 60);
|
|
16
|
+
const hours = Math.floor(minutes / 60);
|
|
17
|
+
const days = Math.floor(hours / 24);
|
|
18
|
+
if (days > 0) {
|
|
19
|
+
const remainingHours = hours % 24;
|
|
20
|
+
return remainingHours > 0 ? `${days}天${remainingHours}小时` : `${days}天`;
|
|
21
|
+
}
|
|
22
|
+
if (hours > 0) {
|
|
23
|
+
const remainingMinutes = minutes % 60;
|
|
24
|
+
return remainingMinutes > 0 ? `${hours}小时${remainingMinutes}分钟` : `${hours}小时`;
|
|
25
|
+
}
|
|
26
|
+
if (minutes > 0) {
|
|
27
|
+
const remainingSeconds = seconds % 60;
|
|
28
|
+
return remainingSeconds > 0 ? `${minutes}分${remainingSeconds}秒` : `${minutes}分钟`;
|
|
29
|
+
}
|
|
30
|
+
return `${seconds}秒`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 格式化日期
|
|
34
|
+
*/
|
|
35
|
+
export function formatDate(timestamp) {
|
|
36
|
+
const date = new Date(Number(timestamp));
|
|
37
|
+
return date.toLocaleString('zh-CN', {
|
|
38
|
+
year: 'numeric',
|
|
39
|
+
month: '2-digit',
|
|
40
|
+
day: '2-digit',
|
|
41
|
+
hour: '2-digit',
|
|
42
|
+
minute: '2-digit',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 生成随机字符串
|
|
47
|
+
*/
|
|
48
|
+
export function randomString(length, charset = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789') {
|
|
49
|
+
let result = '';
|
|
50
|
+
for (let i = 0; i < length; i++) {
|
|
51
|
+
result += charset.charAt(Math.floor(Math.random() * charset.length));
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 计算百分比
|
|
57
|
+
*/
|
|
58
|
+
export function percentage(value, total, decimals = 1) {
|
|
59
|
+
if (total === 0)
|
|
60
|
+
return '0%';
|
|
61
|
+
return ((value / total) * 100).toFixed(decimals) + '%';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 随机整数(包含min和max)
|
|
65
|
+
*/
|
|
66
|
+
export function randomInt(min, max) {
|
|
67
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 检查是否在时间范围内
|
|
71
|
+
*/
|
|
72
|
+
export function isWithinTimeRange(timestamp, rangeMs) {
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
const time = Number(timestamp);
|
|
75
|
+
return now - time <= rangeMs;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 安全的除法(避免除零)
|
|
79
|
+
*/
|
|
80
|
+
export function safeDivide(numerator, denominator, defaultValue = 0) {
|
|
81
|
+
return denominator === 0 ? defaultValue : numerator / denominator;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 限制数值范围
|
|
85
|
+
*/
|
|
86
|
+
export function clamp(value, min, max) {
|
|
87
|
+
return Math.min(Math.max(value, min), max);
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,WAAW,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "napgram-plugin-slave-market",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "大牛马时代 - NapGram 群聊经济养成游戏插件",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"napgram",
|
|
10
|
+
"plugin",
|
|
11
|
+
"game",
|
|
12
|
+
"economy",
|
|
13
|
+
"slave-market"
|
|
14
|
+
],
|
|
15
|
+
"author": "NapGram Team",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/magisk317/napgram-plugin-slave-market.git"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"napgram-plugin.json"
|
|
26
|
+
],
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^25.0.3",
|
|
29
|
+
"@types/pg": "^8.15.5",
|
|
30
|
+
"typescript": "^5.9.3",
|
|
31
|
+
"vitest": "^4.0.16",
|
|
32
|
+
"eslint": "^9.39.2",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
|
34
|
+
"@typescript-eslint/parser": "^8.50.0",
|
|
35
|
+
"prisma": "^7.2.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@prisma/adapter-pg": "^7.2.0",
|
|
39
|
+
"@prisma/client": "^7.2.0",
|
|
40
|
+
"pg": "^8.16.3",
|
|
41
|
+
"@napgram/sdk": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"clean": "rm -rf dist release .cache",
|
|
48
|
+
"build": "pnpm clean && tsc -p tsconfig.build.json",
|
|
49
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
50
|
+
"pack:zip": "pnpm build && node scripts/pack.mjs zip",
|
|
51
|
+
"pack:tgz": "pnpm build && node scripts/pack.mjs tgz",
|
|
52
|
+
"marketplace:snippet": "node scripts/marketplace-snippet.mjs",
|
|
53
|
+
"test": "vitest",
|
|
54
|
+
"lint": "eslint src --ext .ts"
|
|
55
|
+
}
|
|
56
|
+
}
|