koishi-plugin-jrys-plus 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.
@@ -0,0 +1,186 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <style>
6
+ :root {
7
+ --bg-color: #0c0f15;
8
+ --card-bg: #161b22;
9
+ --item-bg: #1f242e;
10
+ --text-primary: #f0f3f5;
11
+ --text-secondary: #8b949e;
12
+ --border-color: #30363d;
13
+ --accent-color: #58a6ff;
14
+ --gold: #fbbf24;
15
+ --gold-bg: rgba(251, 191, 36, 0.12);
16
+ --silver: #94a3b8;
17
+ --silver-bg: rgba(148, 163, 184, 0.1);
18
+ --bronze: #d97706;
19
+ --bronze-bg: rgba(217, 119, 6, 0.1);
20
+ }
21
+ * { margin: 0; padding: 0; box-sizing: border-box; }
22
+ body {
23
+ padding: 48px;
24
+ font-family: "Roboto Mono", "Trebuchet MS", "Inter", -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, sans-serif;
25
+ background-color: var(--bg-color);
26
+ width: 640px;
27
+ color: var(--text-primary);
28
+ display: flex;
29
+ justify-content: center;
30
+ align-items: center;
31
+ }
32
+ .card {
33
+ background-color: var(--card-bg);
34
+ width: 100%;
35
+ padding: 32px 36px;
36
+ border-radius: 16px;
37
+ box-shadow: 0 32px 64px rgba(0,0,0,0.6), 0 0 0 1px var(--border-color);
38
+ position: relative;
39
+ }
40
+ .header { display: flex; align-items: center; gap: 16px; margin-bottom: 28px; padding-bottom: 20px; border-bottom: 1px solid var(--border-color); }
41
+ .header-icon { width: 52px; height: 52px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 26px; box-shadow: 0 8px 16px rgba(88,166,255,0.2); }
42
+ .header-icon.exp { background: linear-gradient(135deg, #58a6ff, #2563eb); }
43
+ .header-icon.sign { background: linear-gradient(135deg, #a78bfa, #7c3aed); }
44
+ .header-info { flex: 1; }
45
+ .header-title { font-size: 24px; font-weight: 700; color: #ffffff; letter-spacing: -0.3px; }
46
+ .header-sub { font-size: 14px; color: var(--text-secondary); font-weight: 500; margin-top: 4px; display: flex; align-items: center; gap: 6px; }
47
+ .header-sub::before { content: ""; display: block; width: 6px; height: 6px; background-color: #22c55e; border-radius: 50%; box-shadow: 0 0 8px #22c55e; }
48
+ .rank-list { display: flex; flex-direction: column; gap: 8px; }
49
+ .rank-item { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: var(--item-bg); border-radius: 12px; border: 1px solid var(--border-color); transition: background 0.2s; }
50
+ .rank-item.top-1 { background: var(--gold-bg); border-color: rgba(255,199,57,0.25); }
51
+ .rank-item.top-2 { background: var(--silver-bg); border-color: rgba(219,232,250,0.3); }
52
+ .rank-item.top-3 { background: var(--bronze-bg); border-color: rgba(125,74,15,0.05); }
53
+ .rank-pos { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 19px; font-weight: 700; flex-shrink: 0; font-family: "Roboto Mono", monospace; }
54
+ .rank-pos.top-1 { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #1a1a1a; box-shadow: 0 4px 12px rgba(251,191,36,0.3); }
55
+ .rank-pos.top-2 { background: linear-gradient(135deg, #dfe9f4, #aec4e2); color: #1a1a1a; box-shadow: 0 4px 12px rgba(148,163,184,0.3); }
56
+ .rank-pos.top-3 { background: linear-gradient(135deg, #dca10b, #9b5302); color: #1a1a1a; box-shadow: 0 4px 12px rgba(217,119,6,0.3); }
57
+ .rank-pos.normal { background: rgba(255,255,255,0.06); color: var(--text-secondary); }
58
+ .rank-user { flex: 1; min-width: 0; }
59
+ .rank-name { font-size: 16px; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
60
+ .rank-sub { font-size: 10px; color: var(--text-secondary); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
61
+ .rank-value { text-align: right; flex-shrink: 0; }
62
+ .rank-value-main { font-size: 21px; font-weight: 700; color: var(--text-primary); font-family: "Roboto Mono", monospace; letter-spacing: -0.5px; }
63
+ .rank-value-label { font-size: 11px; color: var(--text-secondary); margin-top: 2px; text-align: right; }
64
+ .rank-progress { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
65
+ .progress-bar { flex: 1; height: 4px; background: rgba(255,255,255,0.08); border-radius: 2px; overflow: hidden; }
66
+ .progress-fill { height: 100%; border-radius: 2px; transition: width 0.3s; }
67
+ .progress-text { font-size: 11px; color: var(--text-secondary); font-family: "Roboto Mono", monospace; white-space: nowrap; }
68
+ .footer { margin-top: 20px; display: flex; justify-content: space-between; align-items: center; padding-top: 16px; border-top: 1px solid var(--border-color); }
69
+ .footer-stat { font-size: 12px; color: var(--text-secondary); }
70
+ .footer-stat b { color: var(--text-primary); font-family: "Roboto Mono", monospace; }
71
+ .footer-time { font-size: 11px; color: var(--text-secondary); opacity: 0.7; font-family: "Roboto Mono", monospace; }
72
+ </style>
73
+ </head>
74
+ <body>
75
+ <div class="card">
76
+ <div class="header">
77
+ <div class="header-icon" id="header-icon"></div>
78
+ <div class="header-info">
79
+ <div class="header-title" id="header-title"></div>
80
+ <div class="header-sub" id="header-sub"></div>
81
+ </div>
82
+ </div>
83
+ <div class="rank-list" id="rank-list"></div>
84
+ <div class="footer">
85
+ <div class="footer-stat" id="footer-stat"></div>
86
+ <div class="footer-time" id="footer-time"></div>
87
+ </div>
88
+ </div>
89
+ <script type="application/json" id="data-source">{{DATA}}</script>
90
+ <script>
91
+ const DATA = JSON.parse(document.getElementById("data-source").textContent);
92
+ const isExp = DATA.type === "exp";
93
+ const headerIcon = document.getElementById("header-icon");
94
+ headerIcon.className = "header-icon " + (isExp ? "exp" : "sign");
95
+ headerIcon.textContent = isExp ? "&#x1F451;" : "&#x1F4C5;";
96
+ document.getElementById("header-title").textContent = isExp ? "签到经验排行榜 TOP " + DATA.limit : "累计签到排行榜 TOP " + DATA.limit;
97
+ document.getElementById("header-sub").textContent = DATA.channelName || "当前频道";
98
+ const rankList = document.getElementById("rank-list");
99
+ DATA.users.forEach(function(user, i) {
100
+ var rank = i + 1;
101
+ var topClass = rank <= 3 ? "top-" + rank : "";
102
+ var item = document.createElement("div");
103
+ item.className = "rank-item " + topClass;
104
+ var posDiv = document.createElement("div");
105
+ posDiv.className = "rank-pos " + (topClass || "normal");
106
+ posDiv.textContent = rank;
107
+ item.appendChild(posDiv);
108
+ var userDiv = document.createElement("div");
109
+ userDiv.className = "rank-user";
110
+ var nameDiv = document.createElement("div");
111
+ nameDiv.className = "rank-name";
112
+ var nameText = user.displayName;
113
+ if (user.nickname && user.username && user.displayName === user.nickname) {
114
+ nameText += " (" + user.username + ")";
115
+ } else if (user.username && user.displayName !== user.originalId) {
116
+ nameText += " (" + user.originalId + ")";
117
+ }
118
+ nameDiv.textContent = nameText;
119
+ userDiv.appendChild(nameDiv);
120
+ if (user.levelName) {
121
+ var subDiv = document.createElement("div");
122
+ subDiv.className = "rank-sub";
123
+ var color = user.levelColor || "var(--accent-color)";
124
+ if (user.levelProgression) {
125
+ var marker = "「" + user.levelName + "」";
126
+ var parts = user.levelProgression.split(marker);
127
+ if (parts.length === 2) {
128
+ subDiv.appendChild(document.createTextNode(parts[0]));
129
+ var span = document.createElement("span");
130
+ span.textContent = marker;
131
+ span.style.color = color;
132
+ span.style.fontWeight = "700";
133
+ subDiv.appendChild(span);
134
+ subDiv.appendChild(document.createTextNode(parts[1]));
135
+ } else {
136
+ subDiv.textContent = user.levelProgression;
137
+ }
138
+ } else {
139
+ var span2 = document.createElement("span");
140
+ span2.textContent = "「" + user.levelName + "」";
141
+ span2.style.color = color;
142
+ span2.style.fontWeight = "700";
143
+ subDiv.appendChild(span2);
144
+ }
145
+ userDiv.appendChild(subDiv);
146
+ }
147
+ if (isExp && user.nextLevelExp !== null && user.nextLevelExp !== undefined) {
148
+ var progressDiv = document.createElement("div");
149
+ progressDiv.className = "rank-progress";
150
+ var bar = document.createElement("div");
151
+ bar.className = "progress-bar";
152
+ var fill = document.createElement("div");
153
+ fill.className = "progress-fill";
154
+ var currentExp = user.value;
155
+ var baseLevelExp = user.currentLevelExp || 0;
156
+ var nextExp = user.nextLevelExp;
157
+ var progress = nextExp > baseLevelExp ? Math.min(((currentExp - baseLevelExp) / (nextExp - baseLevelExp)) * 100, 100) : 100;
158
+ fill.style.width = progress.toFixed(1) + "%";
159
+ fill.style.background = user.levelColor || "var(--accent-color)";
160
+ bar.appendChild(fill);
161
+ progressDiv.appendChild(bar);
162
+ var pText = document.createElement("div");
163
+ pText.className = "progress-text";
164
+ pText.textContent = progress >= 100 ? "MAX" : currentExp + "/" + nextExp;
165
+ progressDiv.appendChild(pText);
166
+ userDiv.appendChild(progressDiv);
167
+ }
168
+ item.appendChild(userDiv);
169
+ var valueDiv = document.createElement("div");
170
+ valueDiv.className = "rank-value";
171
+ var mainVal = document.createElement("div");
172
+ mainVal.className = "rank-value-main";
173
+ mainVal.textContent = Number(user.value).toLocaleString();
174
+ valueDiv.appendChild(mainVal);
175
+ var labelVal = document.createElement("div");
176
+ labelVal.className = "rank-value-label";
177
+ labelVal.textContent = isExp ? "EXP" : "天";
178
+ valueDiv.appendChild(labelVal);
179
+ item.appendChild(valueDiv);
180
+ rankList.appendChild(item);
181
+ });
182
+ document.getElementById("footer-stat").innerHTML = "共 <b>" + DATA.totalUsers + "</b> 位用户参与";
183
+ document.getElementById("footer-time").textContent = DATA.updateTime;
184
+ </script>
185
+ </body>
186
+ </html>
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "koishi-plugin-jrys-plus",
3
+ "version": "1.0.0",
4
+ "description": "今日运势签到 + 排行榜,精简优化版",
5
+ "main": "lib/index.js",
6
+ "typings": "lib/index.d.ts",
7
+ "files": [
8
+ "lib"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc && node -e \"require('fs').cpSync('src/templates', 'lib/templates', {recursive: true})\"",
12
+ "clean": "rimraf lib",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "koishi": {
16
+ "description": {
17
+ "zh": "今日运势+签到+排行榜(精简版:无金币/经验条,⭐好运值)"
18
+ },
19
+ "service": {
20
+ "required": ["database"],
21
+ "optional": ["puppeteer"]
22
+ }
23
+ },
24
+ "keywords": [
25
+ "koishi",
26
+ "plugin",
27
+ "jrys",
28
+ "fortune",
29
+ "运势",
30
+ "签到",
31
+ "排行榜"
32
+ ],
33
+ "license": "MIT",
34
+ "peerDependencies": {
35
+ "koishi": "^4.18.0",
36
+ "koishi-plugin-puppeteer": "*"
37
+ },
38
+ "devDependencies": {
39
+ "koishi": "^4.18.0",
40
+ "koishi-plugin-puppeteer": "*",
41
+ "typescript": "^5.4.0",
42
+ "rimraf": "^5.0.0"
43
+ }
44
+ }