aicq-chat-plugin 2.5.9 → 2.6.1
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 +11 -6
- package/SKILL.md +11 -6
- package/cli.js +29 -19
- package/extension.js +1 -1
- package/index.js +578 -569
- package/lib/chat.js +0 -0
- package/lib/crypto.js +0 -0
- package/lib/database.js +205 -85
- package/lib/file-transfer.js +0 -0
- package/lib/handshake.js +0 -0
- package/lib/identity.js +0 -0
- package/lib/server-client.js +1 -1
- package/openclaw.plugin.json +2 -2
- package/package.json +12 -12
- package/postinstall.js +15 -5
- package/public/favicon.ico +0 -0
- package/public/icon-16.png +0 -0
- package/public/icon-32.png +0 -0
- package/public/index.html +84 -56
- package/public/logo-512.png +0 -0
package/public/index.html
CHANGED
|
@@ -3,131 +3,142 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta name="theme-color" content="#D97757">
|
|
6
7
|
<title>AICQ 加密聊天</title>
|
|
8
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/icon-32.png">
|
|
9
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/icon-16.png">
|
|
10
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
7
11
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
|
8
12
|
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
|
9
13
|
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
|
|
10
14
|
<script src="https://cdn.jsdelivr.net/npm/marked@12.0.0/marked.min.js"></script>
|
|
11
15
|
<style>
|
|
12
16
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
13
|
-
:root{--primary:#
|
|
14
|
-
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans SC",sans-serif;background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden}
|
|
17
|
+
:root{--primary:#D97757;--primary-light:#C4613F;--primary-lighter:rgba(217,119,87,0.1);--accent:#D97757;--accent-hover:#C4613F;--accent-light:rgba(217,119,87,0.1);--bg:#FAF9F6;--bg2:#F5F1EB;--bg-warm:#F5F1EB;--bg3:#FFFFFF;--bg-card:#FFFFFF;--text:#2D2A26;--text2:#6B6560;--text-sec:#6B6560;--text-muted:#9B958E;--border:#E8DFD3;--beige:#E8DFD3;--success:#4CAF7D;--green:#4CAF7D;--danger:#E05555;--red:#E05555;--warning:#E5A54B;--amber:#E5A54B;--brown:#8B6F4E;--brown-light:rgba(139,111,78,0.1);--cream:#F0EAE0;--info:#5B8DEF;--blue:#5B8DEF;--purple:#7B6CB0;--bubble-me:#D97757;--bubble-them:#FFFFFF;--shadow-sm:0 1px 3px rgba(45,42,38,0.06);--shadow-md:0 4px 16px rgba(45,42,38,0.08);--shadow-lg:0 8px 32px rgba(45,42,38,0.1);--radius:12px;--radius-sm:8px;--radius-lg:20px;--transition:all 0.25s cubic-bezier(0.4,0,0.2,1)}
|
|
18
|
+
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans SC",sans-serif;background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden;-webkit-font-smoothing:antialiased}
|
|
15
19
|
/* Layout */
|
|
16
20
|
.app{display:flex;width:100%;height:100%}
|
|
17
|
-
.right-panel{width:280px;background:var(--
|
|
21
|
+
.right-panel{width:280px;background:var(--bg3);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0}
|
|
18
22
|
.main-panel{flex:1;display:flex;flex-direction:column;min-width:0}
|
|
19
23
|
.chat-area{flex:1;overflow:hidden;display:flex;flex-direction:column}
|
|
20
24
|
/* Right Panel */
|
|
21
25
|
.agent-select{padding:12px;border-bottom:1px solid var(--border)}
|
|
22
|
-
.agent-select select{width:100%;padding:8px 12px;background:var(--
|
|
26
|
+
.agent-select select{width:100%;padding:8px 12px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:10px;font-size:14px;cursor:pointer}
|
|
23
27
|
.action-buttons{display:flex;gap:6px;padding:10px 12px;border-bottom:1px solid var(--border)}
|
|
24
|
-
.action-btn{flex:1;padding:7px 4px;background:var(--
|
|
25
|
-
.action-btn:hover{background:var(--primary);color:#fff}
|
|
28
|
+
.action-btn{flex:1;padding:7px 4px;background:var(--cream);color:var(--text2);border:1px solid var(--border);border-radius:10px;cursor:pointer;font-size:12px;display:flex;flex-direction:column;align-items:center;gap:3px;transition:var(--transition)}
|
|
29
|
+
.action-btn:hover{background:var(--primary);color:#fff;border-color:var(--primary)}
|
|
26
30
|
.action-btn .icon{font-size:18px}
|
|
27
31
|
.list-section{flex:1;overflow-y:auto}
|
|
28
|
-
.list-section h4{padding:10px 12px 6px;color:var(--
|
|
29
|
-
.friend-item,.group-item{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;transition:
|
|
30
|
-
.friend-item:hover,.group-item:hover{background:var(--
|
|
31
|
-
.friend-item.active,.group-item.active{background:
|
|
32
|
-
.avatar{width:36px;height:36px;border-radius:
|
|
33
|
-
.avatar img{width:100%;height:100%;object-fit:cover;border-radius:
|
|
32
|
+
.list-section h4{padding:10px 12px 6px;color:var(--text-muted);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px}
|
|
33
|
+
.friend-item,.group-item{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;transition:var(--transition);border-left:3px solid transparent}
|
|
34
|
+
.friend-item:hover,.group-item:hover{background:var(--cream)}
|
|
35
|
+
.friend-item.active,.group-item.active{background:var(--primary-lighter);border-left-color:var(--primary)}
|
|
36
|
+
.avatar{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,var(--primary),var(--brown));display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:600;flex-shrink:0;color:#fff;overflow:hidden}
|
|
37
|
+
.avatar img{width:100%;height:100%;object-fit:cover;border-radius:12px}
|
|
34
38
|
.avatar.online{box-shadow:0 0 0 2px var(--success)}
|
|
35
39
|
.info{flex:1;min-width:0}
|
|
36
40
|
.info .name{font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
37
41
|
.info .status{font-size:11px;color:var(--text2)}
|
|
38
42
|
.badge-online{color:var(--success);font-size:10px}
|
|
39
43
|
.badge-offline{color:var(--text2);font-size:10px}
|
|
40
|
-
.silent-badge{font-size:9px;background:var(--
|
|
44
|
+
.silent-badge{font-size:9px;background:var(--amber);color:#fff;padding:1px 4px;border-radius:4px;margin-left:4px}
|
|
41
45
|
/* Chat Header */
|
|
42
|
-
.chat-header{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px;background:var(--
|
|
46
|
+
.chat-header{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px;background:var(--bg3)}
|
|
43
47
|
.chat-header .avatar{width:40px;height:40px;font-size:16px}
|
|
44
48
|
.chat-header .info .name{font-size:16px}
|
|
45
49
|
.chat-header .actions{margin-left:auto;display:flex;gap:8px}
|
|
46
|
-
.chat-header .actions button{background:none;border:none;color:var(--text2);cursor:pointer;font-size:18px;padding:4px 8px;border-radius:
|
|
47
|
-
.chat-header .actions button:hover{background:var(--
|
|
50
|
+
.chat-header .actions button{background:none;border:none;color:var(--text2);cursor:pointer;font-size:18px;padding:4px 8px;border-radius:var(--radius-sm);transition:var(--transition)}
|
|
51
|
+
.chat-header .actions button:hover{background:var(--cream);color:var(--primary)}
|
|
48
52
|
/* Messages */
|
|
49
|
-
.messages-container{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:4px}
|
|
53
|
+
.messages-container{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:4px;background:var(--bg2)}
|
|
50
54
|
.load-more{text-align:center;padding:8px;color:var(--text2);font-size:12px;cursor:pointer}
|
|
51
55
|
.load-more:hover{color:var(--primary)}
|
|
52
56
|
.msg-row{display:flex;max-width:75%;gap:8px}
|
|
53
57
|
.msg-row.me{margin-left:auto;flex-direction:row-reverse}
|
|
54
58
|
.msg-row.them{margin-right:auto}
|
|
55
|
-
.msg-bubble{padding:10px 14px;border-radius:
|
|
56
|
-
.msg-row.me .msg-bubble{background:var(--bubble-me);color:#fff;border-
|
|
57
|
-
.msg-row.them .msg-bubble{background:var(--bubble-them);color:var(--text);border-
|
|
59
|
+
.msg-bubble{padding:10px 14px;border-radius:14px;font-size:14px;line-height:1.6;word-break:break-word;position:relative;max-width:100%}
|
|
60
|
+
.msg-row.me .msg-bubble{background:var(--bubble-me);color:#fff;border-top-right-radius:4px}
|
|
61
|
+
.msg-row.them .msg-bubble{background:var(--bubble-them);border:1px solid var(--border);color:var(--text);border-top-left-radius:4px}
|
|
58
62
|
.msg-bubble img{max-width:300px;max-height:300px;border-radius:8px;margin-top:6px;cursor:pointer}
|
|
59
63
|
.msg-bubble .file-link{display:flex;align-items:center;gap:6px;padding:6px 10px;background:rgba(255,255,255,.1);border-radius:6px;margin-top:6px;cursor:pointer;color:inherit;text-decoration:none}
|
|
60
64
|
.msg-bubble .file-link:hover{background:rgba(255,255,255,.2)}
|
|
61
65
|
.msg-time{font-size:10px;color:var(--text2);margin-top:4px;text-align:right}
|
|
66
|
+
.msg-row.me .msg-time{color:rgba(255,255,255,0.6)}
|
|
62
67
|
.msg-row.them .msg-time{text-align:left}
|
|
63
68
|
.msg-actions{position:absolute;top:-8px;right:-4px;display:none;gap:2px}
|
|
64
69
|
.msg-row.me .msg-actions{right:auto;left:-4px}
|
|
65
70
|
.msg-row:hover .msg-actions{display:flex}
|
|
66
|
-
.msg-action-btn{width:24px;height:24px;border-radius:
|
|
67
|
-
.msg-action-btn:hover{background:var(--primary);color:#fff}
|
|
68
|
-
.msg-action-btn.danger:hover{background:var(--danger)}
|
|
71
|
+
.msg-action-btn{width:24px;height:24px;border-radius:var(--radius-sm);background:var(--bg3);border:1px solid var(--border);color:var(--text2);cursor:pointer;font-size:11px;display:flex;align-items:center;justify-content:center;transition:var(--transition)}
|
|
72
|
+
.msg-action-btn:hover{background:var(--primary);color:#fff;border-color:var(--primary)}
|
|
73
|
+
.msg-action-btn.danger:hover{background:var(--danger);border-color:var(--danger)}
|
|
69
74
|
/* Mention */
|
|
70
75
|
.mention{color:var(--info);font-weight:600;cursor:pointer}
|
|
71
76
|
.mention:hover{text-decoration:underline}
|
|
72
77
|
/* Input Area */
|
|
73
|
-
.input-area{padding:12px 16px;border-top:1px solid var(--border);background:var(--
|
|
78
|
+
.input-area{padding:12px 16px;border-top:1px solid var(--border);background:var(--bg3);display:flex;flex-direction:column;gap:8px}
|
|
74
79
|
.input-top{display:flex;gap:8px;align-items:center}
|
|
75
|
-
.input-top input{flex:1;padding:10px 14px;background:var(--bg);border:1px solid var(--border);border-radius:
|
|
76
|
-
.input-top input:focus{border-color:var(--primary)}
|
|
77
|
-
.send-btn{padding:10px 20px;background:var(--primary);color:#fff;border:none;border-radius:
|
|
78
|
-
.send-btn:hover{background:var(--primary-light)}
|
|
79
|
-
.send-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
80
|
+
.input-top input{flex:1;padding:10px 14px;background:var(--bg);border:1px solid var(--border);border-radius:12px;color:var(--text);font-size:14px;outline:none;transition:var(--transition)}
|
|
81
|
+
.input-top input:focus{border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-lighter)}
|
|
82
|
+
.send-btn{padding:10px 20px;background:var(--primary);color:#fff;border:none;border-radius:10px;cursor:pointer;font-size:14px;font-weight:500;box-shadow:0 4px 16px rgba(217,119,87,0.3);transition:var(--transition)}
|
|
83
|
+
.send-btn:hover{background:var(--primary-light);transform:scale(1.05)}
|
|
84
|
+
.send-btn:disabled{opacity:.5;cursor:not-allowed;transform:none}
|
|
80
85
|
.input-toolbar{display:flex;gap:4px}
|
|
81
|
-
.tool-btn{background:none;border:none;color:var(--text2);cursor:pointer;font-size:16px;padding:4px 8px;border-radius:
|
|
82
|
-
.tool-btn:hover{background:var(--
|
|
86
|
+
.tool-btn{background:none;border:none;color:var(--text2);cursor:pointer;font-size:16px;padding:4px 8px;border-radius:var(--radius-sm);transition:var(--transition)}
|
|
87
|
+
.tool-btn:hover{background:var(--cream);color:var(--primary)}
|
|
83
88
|
/* Modals */
|
|
84
|
-
.modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(
|
|
89
|
+
.modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(45,42,38,0.4);display:none;align-items:center;justify-content:center;z-index:1000}
|
|
85
90
|
.modal-overlay.show{display:flex}
|
|
86
|
-
.modal{background:var(--
|
|
91
|
+
.modal{background:var(--bg3);border:1px solid var(--border);border-radius:20px;padding:24px;max-width:480px;width:90%;max-height:80vh;overflow-y:auto;box-shadow:var(--shadow-lg)}
|
|
87
92
|
.modal h3{margin-bottom:16px;font-size:18px}
|
|
88
93
|
.modal .form-group{margin-bottom:14px}
|
|
89
94
|
.modal label{display:block;margin-bottom:6px;font-size:13px;color:var(--text2)}
|
|
90
|
-
.modal input,.modal select,.modal textarea{width:100%;padding:8px 12px;background:var(--bg);border:1px solid var(--border);border-radius:
|
|
95
|
+
.modal input,.modal select,.modal textarea{width:100%;padding:8px 12px;background:var(--bg);border:1px solid var(--border);border-radius:10px;color:var(--text);font-size:14px;transition:var(--transition)}
|
|
96
|
+
.modal input:focus,.modal select:focus,.modal textarea:focus{border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-lighter);outline:none}
|
|
91
97
|
.modal textarea{min-height:80px;resize:vertical}
|
|
92
98
|
.modal .btn-row{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}
|
|
93
|
-
.modal .btn{padding:8px 16px;border:none;border-radius:
|
|
99
|
+
.modal .btn{padding:8px 16px;border:none;border-radius:10px;cursor:pointer;font-size:14px;transition:var(--transition)}
|
|
94
100
|
.modal .btn-primary{background:var(--primary);color:#fff}
|
|
95
101
|
.modal .btn-primary:hover{background:var(--primary-light)}
|
|
96
|
-
.modal .btn-secondary{background:var(--
|
|
102
|
+
.modal .btn-secondary{background:var(--cream);color:var(--text);border:1px solid var(--border)}
|
|
103
|
+
.modal .btn-secondary:hover{background:var(--primary-lighter);border-color:var(--primary);color:var(--primary)}
|
|
97
104
|
.modal .btn-danger{background:var(--danger);color:#fff}
|
|
98
105
|
.qr-container{text-align:center;margin:16px 0}
|
|
99
106
|
.qr-container img{max-width:256px;border-radius:8px}
|
|
100
|
-
.key-display{background:var(--bg);padding:10px;border-radius:
|
|
101
|
-
.warning-box{background:rgba(
|
|
107
|
+
.key-display{background:var(--bg);padding:10px;border-radius:var(--radius-sm);font-family:monospace;font-size:12px;word-break:break-all;margin:8px 0;color:var(--text-muted)}
|
|
108
|
+
.warning-box{background:rgba(224,85,85,0.08);border:1px solid var(--danger);border-radius:var(--radius-sm);padding:12px;margin:12px 0;color:var(--danger);font-size:13px}
|
|
102
109
|
/* Empty State */
|
|
103
|
-
.empty-state{flex:1;display:flex;align-items:center;justify-content:center;color:var(--
|
|
110
|
+
.empty-state{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-muted);font-size:16px;flex-direction:column;gap:12px}
|
|
104
111
|
.empty-state .icon{font-size:48px;opacity:.3}
|
|
105
112
|
/* Mention dropdown */
|
|
106
|
-
.mention-dropdown{position:absolute;bottom:100%;left:0;background:var(--
|
|
113
|
+
.mention-dropdown{position:absolute;bottom:100%;left:0;background:var(--bg3);border:1px solid var(--border);border-radius:10px;max-height:200px;overflow-y:auto;z-index:100;display:none;min-width:200px;box-shadow:var(--shadow-md)}
|
|
107
114
|
.mention-dropdown.show{display:block}
|
|
108
115
|
.mention-option{padding:8px 12px;cursor:pointer;font-size:13px;display:flex;align-items:center;gap:8px}
|
|
109
|
-
.mention-option:hover{background:var(--
|
|
116
|
+
.mention-option:hover{background:var(--cream)}
|
|
110
117
|
/* Scrollbar */
|
|
111
118
|
::-webkit-scrollbar{width:6px}
|
|
112
|
-
::-webkit-scrollbar-track{background:
|
|
119
|
+
::-webkit-scrollbar-track{background:transparent}
|
|
113
120
|
::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
|
|
114
|
-
::-webkit-scrollbar-thumb:hover{background:var(--
|
|
121
|
+
::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}
|
|
115
122
|
/* Markdown in bubbles */
|
|
116
123
|
.msg-bubble p{margin:4px 0}
|
|
117
|
-
.msg-bubble code{background:rgba(
|
|
118
|
-
.msg-bubble
|
|
124
|
+
.msg-row.them .msg-bubble code{background:rgba(0,0,0,0.05);padding:1px 4px;border-radius:3px;font-size:13px}
|
|
125
|
+
.msg-row.me .msg-bubble code{background:rgba(255,255,255,0.2);padding:1px 4px;border-radius:3px;font-size:13px}
|
|
126
|
+
.msg-row.them .msg-bubble pre{background:rgba(0,0,0,0.04);padding:8px;border-radius:6px;overflow-x:auto;margin:6px 0}
|
|
127
|
+
.msg-row.me .msg-bubble pre{background:rgba(255,255,255,0.15);padding:8px;border-radius:6px;overflow-x:auto;margin:6px 0}
|
|
119
128
|
.msg-bubble pre code{background:none;padding:0}
|
|
120
129
|
.msg-bubble blockquote{border-left:3px solid var(--primary);padding-left:10px;margin:6px 0;color:var(--text2)}
|
|
121
130
|
.msg-bubble ul,.msg-bubble ol{padding-left:20px;margin:4px 0}
|
|
122
|
-
.msg-bubble a{color:var(--
|
|
131
|
+
.msg-row.them .msg-bubble a{color:var(--primary)}
|
|
132
|
+
.msg-row.me .msg-bubble a{color:#fff;text-decoration:underline}
|
|
123
133
|
.msg-bubble table{border-collapse:collapse;margin:6px 0}
|
|
124
|
-
.msg-bubble th
|
|
134
|
+
.msg-bubble th{background:var(--cream);border:1px solid var(--border);padding:4px 8px;font-size:13px}
|
|
135
|
+
.msg-bubble td{border:1px solid var(--border);padding:4px 8px;font-size:13px}
|
|
125
136
|
/* Toast */
|
|
126
|
-
.toast{position:fixed;top:20px;left:50%;transform:translateX(-50%);background:var(--
|
|
137
|
+
.toast{position:fixed;top:20px;left:50%;transform:translateX(-50%);background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:12px 24px;border-radius:var(--radius);font-size:14px;z-index:9999;box-shadow:var(--shadow-lg);max-width:90%;text-align:center;opacity:0;transition:opacity .3s;pointer-events:none}
|
|
127
138
|
.toast.show{opacity:1}
|
|
128
|
-
.toast.warning{border-color:var(--warning);background:rgba(
|
|
139
|
+
.toast.warning{border-color:var(--warning);background:rgba(229,165,75,0.1);color:var(--warning)}
|
|
129
140
|
/* Backup section */
|
|
130
|
-
.backup-section{background:var(--bg);border:1px solid var(--border);border-radius:
|
|
141
|
+
.backup-section{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:12px;margin-top:8px}
|
|
131
142
|
.backup-section h4{font-size:14px;margin-bottom:8px;color:var(--text)}
|
|
132
143
|
.backup-section p{font-size:12px;color:var(--text2);line-height:1.6;margin:4px 0}
|
|
133
144
|
.backup-section .warning-box{font-size:12px;padding:8px;margin:8px 0}
|
|
@@ -137,7 +148,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
|
|
|
137
148
|
.key-match-row{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--border)}
|
|
138
149
|
.key-match-row:last-child{border-bottom:none}
|
|
139
150
|
.key-match-row label{font-size:13px;color:var(--text2);min-width:120px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
140
|
-
.key-match-row select{flex:1;padding:6px 10px;background:var(--bg);border:1px solid var(--border);border-radius:
|
|
151
|
+
.key-match-row select{flex:1;padding:6px 10px;background:var(--bg);border:1px solid var(--border);border-radius:10px;color:var(--text);font-size:13px}
|
|
141
152
|
</style>
|
|
142
153
|
</head>
|
|
143
154
|
<body>
|
|
@@ -993,20 +1004,37 @@ function showChatInfo() {
|
|
|
993
1004
|
: `好友: ${currentTarget.name}\nID: ${currentTarget.id}\n状态: ${currentTarget.isOnline ? '在线' : '离线'}`);
|
|
994
1005
|
}
|
|
995
1006
|
|
|
1007
|
+
// ─── Image Resize Utility ───────────────────────────────────────────
|
|
1008
|
+
function resizePluginImage(file,maxW,maxH,quality=0.8){
|
|
1009
|
+
return new Promise((resolve,reject)=>{
|
|
1010
|
+
if(!file.type.startsWith('image/')){reject(new Error('Not an image'));return;}
|
|
1011
|
+
const img=new Image();const url=URL.createObjectURL(file);
|
|
1012
|
+
img.onload=()=>{
|
|
1013
|
+
let w=img.width,h=img.height;
|
|
1014
|
+
if(w<=maxW&&h<=maxH&&file.size<=512*1024){URL.revokeObjectURL(url);resolve(file);return;}
|
|
1015
|
+
const ratio=Math.min(maxW/w,maxH/h,1);w=Math.round(w*ratio);h=Math.round(h*ratio);
|
|
1016
|
+
const canvas=document.createElement('canvas');canvas.width=w;canvas.height=h;
|
|
1017
|
+
const ctx=canvas.getContext('2d');ctx.drawImage(img,0,0,w,h);
|
|
1018
|
+
canvas.toBlob(blob=>{URL.revokeObjectURL(url);if(!blob){reject(new Error('Resize failed'));return;}resolve(new File([blob],file.name.replace(/\.\w+$/,'.jpg'),{type:'image/jpeg',lastModified:Date.now()}));},'image/jpeg',quality);
|
|
1019
|
+
};
|
|
1020
|
+
img.onerror=()=>{URL.revokeObjectURL(url);reject(new Error('Image load failed'));};
|
|
1021
|
+
img.src=url;
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
|
|
996
1025
|
// ─── Avatar Upload ──────────────────────────────────────────────────
|
|
997
1026
|
async function handlePluginAvatarUpload(input) {
|
|
998
|
-
const
|
|
999
|
-
if (!
|
|
1000
|
-
if (!
|
|
1001
|
-
if (file.size > 2 * 1024 * 1024) { alert('图片不能超过2MB'); return; }
|
|
1027
|
+
const rawFile = input.files && input.files[0];
|
|
1028
|
+
if (!rawFile || !currentAgentId) return;
|
|
1029
|
+
if (!rawFile.type.startsWith('image/')) { alert('请选择图片文件'); return; }
|
|
1002
1030
|
try {
|
|
1031
|
+
const file = await resizePluginImage(rawFile, 256, 256, 0.85); // resize for avatar
|
|
1003
1032
|
const formData = new FormData();
|
|
1004
1033
|
formData.append('avatar', file);
|
|
1005
1034
|
formData.append('agent_id', currentAgentId);
|
|
1006
1035
|
const resp = await fetch(API + '/api/identity/avatar', { method: 'POST', body: formData });
|
|
1007
1036
|
const data = await resp.json();
|
|
1008
1037
|
if (data.success || data.avatar) {
|
|
1009
|
-
// Update the settings avatar display
|
|
1010
1038
|
const avatarUrl = data.avatar || (data.account && data.account.avatar);
|
|
1011
1039
|
if (avatarUrl) {
|
|
1012
1040
|
document.getElementById('settingsAvatar').innerHTML = `<img src="${avatarUrl}" alt="头像">`;
|
|
Binary file
|