@wendongfly/myhi 1.3.165 → 1.3.167
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/dist/chat.html +32 -20
- package/dist/index.html +88 -10
- package/dist/index.js +1 -1
- package/dist/index.min.js +116 -116
- package/package.json +1 -1
package/dist/chat.html
CHANGED
|
@@ -3205,16 +3205,12 @@
|
|
|
3205
3205
|
if (workState !== 'idle') {
|
|
3206
3206
|
(async () => {
|
|
3207
3207
|
try {
|
|
3208
|
-
const
|
|
3209
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
3210
|
-
body: JSON.stringify({ text: prompt, sessionId: SESSION_ID, source: 'busy' }),
|
|
3211
|
-
});
|
|
3212
|
-
const d = await r.json();
|
|
3208
|
+
const d = await postDraft({ text: prompt, sessionId: SESSION_ID, source: 'busy' });
|
|
3213
3209
|
if (d.error) { addStatusMessage('存草稿失败: ' + d.error); return; }
|
|
3214
3210
|
_draftTipDismissed = false;
|
|
3215
3211
|
await refreshInbox();
|
|
3216
3212
|
addStatusMessage('📥 AI 正在跑,已把「重读 ' + p + '」存进草稿,干完自动接上');
|
|
3217
|
-
} catch (e) { addStatusMessage('存草稿失败: ' + e
|
|
3213
|
+
} catch (e) { addStatusMessage('存草稿失败: ' + draftErrMsg(e)); }
|
|
3218
3214
|
})();
|
|
3219
3215
|
return;
|
|
3220
3216
|
}
|
|
@@ -4034,6 +4030,29 @@
|
|
|
4034
4030
|
let _inboxCache = { drafts: [], counts: {} };
|
|
4035
4031
|
let _draftTipDismissed = false;
|
|
4036
4032
|
|
|
4033
|
+
// 存草稿统一走这里:网络层失败(Failed to fetch,多为连接被复用竞争/瞬时断连)
|
|
4034
|
+
// 自动重试一次;clientKey 让服务端去重,重试不会记两条。
|
|
4035
|
+
async function postDraft(body) {
|
|
4036
|
+
body.clientKey = (crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`);
|
|
4037
|
+
let lastErr;
|
|
4038
|
+
for (let i = 0; i < 2; i++) {
|
|
4039
|
+
try {
|
|
4040
|
+
const r = await fetch('/api/inbox', {
|
|
4041
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
4042
|
+
body: JSON.stringify(body),
|
|
4043
|
+
});
|
|
4044
|
+
return await r.json();
|
|
4045
|
+
} catch (e) {
|
|
4046
|
+
lastErr = e;
|
|
4047
|
+
if (!i) await new Promise((res) => setTimeout(res, 400));
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
throw lastErr;
|
|
4051
|
+
}
|
|
4052
|
+
function draftErrMsg(e) {
|
|
4053
|
+
return e.message === 'Failed to fetch' ? '网络连接中断(重试仍失败)' : e.message;
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4037
4056
|
async function refreshInbox(silent = true) {
|
|
4038
4057
|
try {
|
|
4039
4058
|
const r = await fetch('/api/inbox');
|
|
@@ -4187,15 +4206,11 @@
|
|
|
4187
4206
|
const text = ta.value.trim();
|
|
4188
4207
|
if (!text && !_inboxNewImage) { addStatusMessage('写点什么或加张图再记'); return; }
|
|
4189
4208
|
try {
|
|
4190
|
-
const
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
autoSend: document.getElementById('inbox-new-autosend').checked,
|
|
4195
|
-
images: _inboxNewImage ? [_inboxNewImage] : [],
|
|
4196
|
-
}),
|
|
4209
|
+
const d = await postDraft({
|
|
4210
|
+
text, sessionId: SESSION_ID, source: 'manual',
|
|
4211
|
+
autoSend: document.getElementById('inbox-new-autosend').checked,
|
|
4212
|
+
images: _inboxNewImage ? [_inboxNewImage] : [],
|
|
4197
4213
|
});
|
|
4198
|
-
const d = await r.json();
|
|
4199
4214
|
if (d.error) { addStatusMessage('存草稿失败: ' + d.error); return; }
|
|
4200
4215
|
ta.value = '';
|
|
4201
4216
|
clearInboxNewImage();
|
|
@@ -4203,7 +4218,7 @@
|
|
|
4203
4218
|
await refreshInbox();
|
|
4204
4219
|
renderInbox();
|
|
4205
4220
|
} catch (e) {
|
|
4206
|
-
addStatusMessage('存草稿失败: ' + e
|
|
4221
|
+
addStatusMessage('存草稿失败: ' + draftErrMsg(e));
|
|
4207
4222
|
}
|
|
4208
4223
|
};
|
|
4209
4224
|
|
|
@@ -4219,10 +4234,7 @@
|
|
|
4219
4234
|
files: _pendingFile ? [{ path: _pendingFile.path, name: _pendingFile.name }] : [],
|
|
4220
4235
|
};
|
|
4221
4236
|
try {
|
|
4222
|
-
const
|
|
4223
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
|
|
4224
|
-
});
|
|
4225
|
-
const d = await r.json();
|
|
4237
|
+
const d = await postDraft(body);
|
|
4226
4238
|
if (d.error) { addStatusMessage('存草稿失败: ' + d.error); return false; }
|
|
4227
4239
|
cmdInput.value = '';
|
|
4228
4240
|
cmdInput.style.height = 'auto';
|
|
@@ -4236,7 +4248,7 @@
|
|
|
4236
4248
|
: '📥 已存进草稿');
|
|
4237
4249
|
return true;
|
|
4238
4250
|
} catch (e) {
|
|
4239
|
-
addStatusMessage('存草稿失败: ' + e
|
|
4251
|
+
addStatusMessage('存草稿失败: ' + draftErrMsg(e));
|
|
4240
4252
|
return false;
|
|
4241
4253
|
}
|
|
4242
4254
|
};
|
package/dist/index.html
CHANGED
|
@@ -462,6 +462,7 @@
|
|
|
462
462
|
<button id="appearance-btn" onclick="openAppearance()" title="外观" style="background:none;border:1px solid var(--border);color:var(--muted);font-size:0.75rem;padding:0.3rem 0.55rem;border-radius:6px;cursor:pointer;width:auto">🎨</button>
|
|
463
463
|
<button id="doctor-btn" onclick="openDoctor()" style="background:none;border:1px solid var(--border);color:var(--muted);font-size:0.75rem;padding:0.3rem 0.6rem;border-radius:6px;cursor:pointer;width:auto">🩺 体检</button>
|
|
464
464
|
<button id="usage-btn" onclick="showUsage()" style="background:none;border:1px solid var(--border);color:var(--muted);font-size:0.75rem;padding:0.3rem 0.6rem;border-radius:6px;cursor:pointer;width:auto">用量</button>
|
|
465
|
+
<button id="passwd-btn" onclick="openPasswdSheet()" title="修改我的密码" style="display:none;background:none;border:1px solid var(--border);color:var(--muted);font-size:0.75rem;padding:0.3rem 0.6rem;border-radius:6px;cursor:pointer;width:auto">🔑 改密码</button>
|
|
465
466
|
<button id="logout-btn" onclick="doLogout()" style="display:none;background:none;border:1px solid var(--border);color:var(--muted);font-size:0.75rem;padding:0.3rem 0.6rem;border-radius:6px;cursor:pointer;width:auto">退出</button>
|
|
466
467
|
<div id="conn-dot"></div>
|
|
467
468
|
</div>
|
|
@@ -530,6 +531,31 @@
|
|
|
530
531
|
<button onclick="closeNoteSheet()" style="width:100%;background:var(--bg,var(--bg));color:var(--muted,var(--muted));border:1px solid var(--border,var(--border));border-radius:10px;padding:0.65rem;font-size:0.85rem;cursor:pointer;margin-top:0.5rem">取消</button>
|
|
531
532
|
</div>
|
|
532
533
|
|
|
534
|
+
<!-- 修改密码 sheet(成员用户自助改密;管理员改密码在 /admin) -->
|
|
535
|
+
<div id="passwd-backdrop" onclick="closePasswdSheet()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.55);z-index:30"></div>
|
|
536
|
+
<div id="passwd-sheet" style="display:none;position:fixed;left:0;right:0;bottom:0;z-index:31;background:var(--surface);border-radius:16px 16px 0 0;padding:1rem 1rem calc(1rem + env(safe-area-inset-bottom));max-height:88vh;overflow-y:auto">
|
|
537
|
+
<div class="sheet-handle"></div>
|
|
538
|
+
<div class="sheet-title">🔑 修改我的密码</div>
|
|
539
|
+
<div style="font-size:0.7rem;color:var(--muted);line-height:1.55;margin-bottom:0.6rem">
|
|
540
|
+
需要验证原密码才能修改;新密码不能与其他用户的密码重复,至少 4 位。改完当前登录保持有效,下次登录用新密码。
|
|
541
|
+
</div>
|
|
542
|
+
<div class="field">
|
|
543
|
+
<label>原密码</label>
|
|
544
|
+
<input type="password" id="pw-old" autocomplete="current-password" style="width:100%;box-sizing:border-box;background:var(--bg);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:0.6rem;font-size:0.85rem">
|
|
545
|
+
</div>
|
|
546
|
+
<div class="field">
|
|
547
|
+
<label>新密码</label>
|
|
548
|
+
<input type="password" id="pw-new" autocomplete="new-password" style="width:100%;box-sizing:border-box;background:var(--bg);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:0.6rem;font-size:0.85rem">
|
|
549
|
+
</div>
|
|
550
|
+
<div class="field">
|
|
551
|
+
<label>确认新密码</label>
|
|
552
|
+
<input type="password" id="pw-new2" autocomplete="new-password" style="width:100%;box-sizing:border-box;background:var(--bg);border:1px solid var(--border);border-radius:8px;color:var(--text);padding:0.6rem;font-size:0.85rem">
|
|
553
|
+
</div>
|
|
554
|
+
<div id="pw-msg" style="font-size:0.75rem;color:var(--red);margin:0 0 0.4rem;min-height:1rem"></div>
|
|
555
|
+
<button onclick="submitPasswd()" style="width:100%;background:#d29922;color:#1a1a1a;border:none;border-radius:10px;padding:0.75rem;font-size:0.9rem;font-weight:700;cursor:pointer">确认修改</button>
|
|
556
|
+
<button onclick="closePasswdSheet()" style="width:100%;background:var(--bg);color:var(--muted);border:1px solid var(--border);border-radius:10px;padding:0.65rem;font-size:0.85rem;cursor:pointer;margin-top:0.5rem">取消</button>
|
|
557
|
+
</div>
|
|
558
|
+
|
|
533
559
|
<!-- Create sheet -->
|
|
534
560
|
<div id="sheet-backdrop" onclick="closeSheet()"></div>
|
|
535
561
|
<div id="sheet">
|
|
@@ -633,6 +659,10 @@
|
|
|
633
659
|
document.getElementById('user-name').textContent = data.name;
|
|
634
660
|
document.getElementById('logout-btn').style.display = '';
|
|
635
661
|
}
|
|
662
|
+
// 成员用户(users.json 登录)才显示自助改密入口;管理员改密码在 /admin
|
|
663
|
+
if (data.hasUsers && data.role === 'operator') {
|
|
664
|
+
document.getElementById('passwd-btn').style.display = '';
|
|
665
|
+
}
|
|
636
666
|
if (data.dir) {
|
|
637
667
|
_userDir = data.dir;
|
|
638
668
|
// 默认填入绑定目录,隐藏盘符栏,保留最近目录
|
|
@@ -699,6 +729,43 @@
|
|
|
699
729
|
}
|
|
700
730
|
}
|
|
701
731
|
|
|
732
|
+
// ── 修改密码(成员用户自助)────────────────────────────
|
|
733
|
+
window.openPasswdSheet = function() {
|
|
734
|
+
document.getElementById('pw-old').value = '';
|
|
735
|
+
document.getElementById('pw-new').value = '';
|
|
736
|
+
document.getElementById('pw-new2').value = '';
|
|
737
|
+
document.getElementById('pw-msg').textContent = '';
|
|
738
|
+
document.getElementById('passwd-backdrop').style.display = 'block';
|
|
739
|
+
document.getElementById('passwd-sheet').style.display = 'block';
|
|
740
|
+
document.getElementById('pw-old').focus();
|
|
741
|
+
};
|
|
742
|
+
window.closePasswdSheet = function() {
|
|
743
|
+
document.getElementById('passwd-backdrop').style.display = 'none';
|
|
744
|
+
document.getElementById('passwd-sheet').style.display = 'none';
|
|
745
|
+
};
|
|
746
|
+
window.submitPasswd = async function() {
|
|
747
|
+
const msg = document.getElementById('pw-msg');
|
|
748
|
+
const oldPw = document.getElementById('pw-old').value;
|
|
749
|
+
const newPw = document.getElementById('pw-new').value;
|
|
750
|
+
const newPw2 = document.getElementById('pw-new2').value;
|
|
751
|
+
msg.style.color = 'var(--red)';
|
|
752
|
+
if (!oldPw) { msg.textContent = '请输入原密码'; return; }
|
|
753
|
+
if (newPw.length < 4) { msg.textContent = '新密码至少 4 位'; return; }
|
|
754
|
+
if (newPw !== newPw2) { msg.textContent = '两次输入的新密码不一致'; return; }
|
|
755
|
+
if (newPw === oldPw) { msg.textContent = '新密码不能与原密码相同'; return; }
|
|
756
|
+
try {
|
|
757
|
+
const r = await fetch('/api/user/password', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ oldPassword: oldPw, newPassword: newPw }) });
|
|
758
|
+
const d = await r.json();
|
|
759
|
+
if (d.ok) {
|
|
760
|
+
msg.style.color = 'var(--green, #3fb950)';
|
|
761
|
+
msg.textContent = '✓ 密码已修改,下次登录请用新密码';
|
|
762
|
+
setTimeout(closePasswdSheet, 1500);
|
|
763
|
+
} else {
|
|
764
|
+
msg.textContent = d.error || '修改失败';
|
|
765
|
+
}
|
|
766
|
+
} catch { msg.textContent = '连接失败'; }
|
|
767
|
+
};
|
|
768
|
+
|
|
702
769
|
function doLogout() {
|
|
703
770
|
if (!confirm('确定退出登录?')) return;
|
|
704
771
|
fetch('/logout', { method: 'POST' }).finally(() => {
|
|
@@ -1091,20 +1158,31 @@
|
|
|
1091
1158
|
if (!sid) { alert('请选择归属任务'); return; }
|
|
1092
1159
|
if (!text && !_notePendingImage) { alert('写点什么或传张图'); return; }
|
|
1093
1160
|
try {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1161
|
+
// 网络层失败自动重试一次;clientKey 让服务端去重,重试不会记两条
|
|
1162
|
+
const clientKey = (crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`);
|
|
1163
|
+
let d;
|
|
1164
|
+
for (let i = 0; i < 2; i++) {
|
|
1165
|
+
try {
|
|
1166
|
+
const r = await fetch('/api/inbox', {
|
|
1167
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
1168
|
+
body: JSON.stringify({
|
|
1169
|
+
text, sessionId: sid, source: 'home', clientKey,
|
|
1170
|
+
autoSend: document.getElementById('note-autosend').checked,
|
|
1171
|
+
images: _notePendingImage ? [{ path: _notePendingImage.path, name: '图片' }] : [],
|
|
1172
|
+
}),
|
|
1173
|
+
});
|
|
1174
|
+
d = await r.json();
|
|
1175
|
+
break;
|
|
1176
|
+
} catch (e) {
|
|
1177
|
+
if (i) throw e;
|
|
1178
|
+
await new Promise((res) => setTimeout(res, 400));
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1103
1181
|
if (d.error) { alert('存草稿失败:' + d.error); return; }
|
|
1104
1182
|
closeNoteSheet();
|
|
1105
1183
|
refreshDraftCounts();
|
|
1106
1184
|
} catch (e) {
|
|
1107
|
-
alert('存草稿失败:' + e.message);
|
|
1185
|
+
alert('存草稿失败:' + (e.message === 'Failed to fetch' ? '网络连接中断(重试仍失败)' : e.message));
|
|
1108
1186
|
}
|
|
1109
1187
|
};
|
|
1110
1188
|
|