/* v23: 场景真数据接入(定时任务/视频管理/我的)——桌面同源 8001/网关端点
坏主块里的 loadScheduledTasks/loadVideoList/loadUserProfile 从未执行,
此文件以 window 全局实现同名函数,v18 切场景时自动调用渲染真实数据。 */
(function () {
'use strict';
if (window.__mobV23) return;
window.__mobV23 = true;
var API = 'https://api-gateway.duoweiying.cn';
function $(id) { return document.getElementById(id); }
function uid() {
var u = null;
try { u = JSON.parse(localStorage.getItem('user_info') || '{}'); } catch (e) {}
return (u && (u.id || u.username)) || localStorage.getItem('user_id') || 'anonymous';
}
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }
function jget(url) { var u = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_t=' + Date.now(); return fetch(u, { headers: { 'Content-Type': 'application/json' } }).then(function (r) { return r.json().catch(function () { return {}; }); }); }
function toast(t) { try { var o = document.getElementById('v23Tip'); if (o) o.remove(); var d = document.createElement('div'); d.id = 'v23Tip'; d.style.cssText = 'position:fixed;left:50%;bottom:96px;transform:translateX(-50%);z-index:42000;background:#0f172a;color:#fff;font-size:13px;padding:9px 16px;border-radius:18px;box-shadow:0 4px 16px rgba(0,0,0,.25);max-width:82%;text-align:center;'; d.textContent = t; document.body.appendChild(d); setTimeout(function () { d.remove(); }, 2600); } catch (e) {} }
function wrapCss() { return 'background:#fff;border-radius:12px;margin:10px;padding:12px;box-shadow:0 1px 4px rgba(15,23,42,.08);'; }
function emptyBox(c, html) { var el = $(c); if (el) el.innerHTML = html; }
/* ============ 定时任务 ============ */
window.loadScheduledTasks = function () {
var box = $('tasks-container');
if (!box) return;
box.innerHTML = '
加载中…
';
jget(API + '/ai-army/tasks/scheduled-list?user_id=' + encodeURIComponent(uid()))
.then(function (d) {
var tasks = (d && (d.data || d.tasks)) || [];
if (!tasks.length) { emptyBox('tasks-container', '暂无定时任务
可以在对话中让 AI 帮你安排定时发布,或在电脑端「定时任务」创建
'); return; }
var rows = tasks.map(function (t) {
var title = esc(t.title || t.task_name || t.task_type || '未命名任务');
var time = esc(t.scheduled_time || t.publish_time || '');
var plats = (t.target_platforms || t.platforms || []);
if (typeof plats === 'string') { try { plats = JSON.parse(plats); } catch (e) { plats = []; } }
var platTxt = (plats || []).join(' / ') || '';
var status = esc(t.status || 'pending');
var id = t.task_id || t.id || '';
return '' +
'
' + title + '
' +
(platTxt ? '
平台:' + platTxt + '
' : '') +
'
⏰ ' + (time || '未定时间') + ' · 状态:' + status + '
' +
(id ? '
' : '') +
'
';
}).join('');
emptyBox('tasks-container', rows);
var listEl = $('tasks-container');
if (listEl) listEl.onclick = function (e) {
var b = e.target && e.target.closest && e.target.closest('[data-v23pub]');
if (b) { doPublishTask(b.getAttribute('data-v23pub')); }
};
})
.catch(function () { emptyBox('tasks-container', '加载失败,请检查网络后重试
'); });
};
window.doPublishTask = function (taskId) {
if (!taskId) return;
toast('⏳ 正在发布 ' + taskId + ' …');
fetch(API + '/ai-army/tasks/' + encodeURIComponent(taskId) + '/publish', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: uid() }) })
.then(function (r) { return r.json().catch(function () { return {}; }); })
.then(function (d) { toast((d && d.success) ? '✅ 发布成功' : ('发布失败:' + ((d && d.message) || '请稍后重试'))); if (typeof loadScheduledTasks === 'function') { try { loadScheduledTasks(); } catch (e) {} } })
.catch(function () { toast('发布网络错误'); });
};
/* ============ 视频管理(已发布列表) ============ */
window.loadVideoList = function () {
var box = $('video-container');
if (!box) return;
box.innerHTML = '加载中…
';
jget(API + '/ai-army/tasks/completed-list?user_id=' + encodeURIComponent(uid()))
.then(function (d) {
var videos = (d && (d.data || d.tasks)) || [];
if (!videos.length) { emptyBox('video-container', '暂无已发布视频
在对话页让 AI 创作并发布视频后,这里会显示记录
'); return; }
var rows = videos.map(function (v) {
var title = esc(v.title || v.video_name || v.task_name || '未命名视频');
var time = esc(v.published_time || v.created_at || v.scheduled_time || '');
var plats = (v.target_platforms || v.platforms || []);
if (typeof plats === 'string') { try { plats = JSON.parse(plats); } catch (e) { plats = []; } }
var meta = [];
if (v.views != null) meta.push('播放 ' + v.views);
if (v.likes != null) meta.push('点赞 ' + v.likes);
return '' +
'
🎬 ' + title + '
' +
((plats || []).length ? '
平台:' + esc((plats || []).join(' / ')) + '
' : '') +
'
' + (time ? '🕒 ' + esc(time) : '') + (meta.length ? ' · ' + meta.join(' · ') : '') + '
' +
'
';
}).join('');
emptyBox('video-container', rows);
})
.catch(function () { emptyBox('video-container', '加载失败,请检查网络后重试
'); });
};
/* ============ 我的(资料+余额+订阅+设置入口) ============ */
window.loadUserProfile = function () {
var box = $('profile-container');
if (!box) return;
box.innerHTML = '加载中…
';
var u = null;
try { u = JSON.parse(localStorage.getItem('user_info') || '{}'); } catch (e) {}
var name = (u && (u.nickname || u.username)) || '未登录';
Promise.all([
jget(API + '/api/user-settings/profile?user_id=' + encodeURIComponent(uid())),
jget(API + '/api/user-settings/status?user_id=' + encodeURIComponent(uid()))
]).then(function (rs) {
var pf = rs[0] && (rs[0].profile || rs[0].data || rs[0]);
var st = rs[1] && (rs[1].status || rs[1].data || rs[1]);
var nickname = (pf && (pf.nickname || pf.username)) || name;
var bio = (pf && pf.bio) || (pf && pf.description) || '这个人很懒,什么都没写';
var bal = st && st.balance_yuan != null ? st.balance_yuan : null;
var subs = (st && st.subscription) || [];
var subTxt = '无订阅';
if (subs && subs.length) { var s0 = subs[0]; subTxt = (s0.plan_name || s0.type || '订阅中') + (s0.status ? ' · ' + s0.status : ''); }
var calls = st && st.usage ? ('今日 ' + (st.usage.today_calls || 0) + ' 次调用') : '';
var avatar = esc((nickname || '?').slice(0, 1));
var html =
'' +
'
' + avatar + '
' +
'
' +
'
' + esc(nickname) + '
' +
'
' + esc(bio) + '
' +
'' +
'
' + (bal == null ? '—' : '¥' + Number(bal).toFixed(2)) + '
余额
' +
'
' +
(calls ? '
' : '') +
'
' +
menuRow('👤 编辑资料', 'mobEditProfile') + menuRow('🔒 账号安全', 'mobSecurity') + menuRow('🎨 偏好设置', 'mobPrefs') +
menuRow('☁️ 云端同步说明', 'mobCloud') + menuRow('📖 用户协议', 'mobAgreement') +
(localStorage.getItem('user_token') ? '' : '');
emptyBox('profile-container', html);
var lg = $('v23Logout');
if (lg) lg.onclick = function () { try { ['user_token', 'user_info', 'user_id', 'authToken', 'smart_center_token', 'currentUser'].forEach(function (k) { localStorage.removeItem(k); }); } catch (e) {} location.reload(); };
bindMenu();
}).catch(function () { emptyBox('profile-container', '加载失败,请检查网络
'); });
};
function menuRow(t, act) { return '' + t + '›
'; }
function bindMenu() {
var box = $('profile-container');
if (!box) return;
box.onclick = function (e) {
var r = e.target && e.target.closest && e.target.closest('[data-v23m]');
if (!r) return;
var act = r.getAttribute('data-v23m');
if (act === 'mobEditProfile') mobEditProfile();
else if (act === 'mobSecurity') mobSecurity();
else if (act === 'mobPrefs') mobPrefs();
else if (act === 'mobCloud') mobCloud();
else if (act === 'mobAgreement') { try { window.open('/mobile/agreement.html', '_blank'); } catch (e) {} }
};
}
function formPanel(title, inner, onSubmit) {
var old = $('v23Form'); if (old) old.remove();
var d = document.createElement('div');
d.id = 'v23Form';
d.style.cssText = 'position:fixed;inset:0;z-index:40000;background:rgba(15,23,42,.55);display:flex;align-items:center;justify-content:center;';
d.innerHTML = '' +
'
' + esc(title) + '×
' +
'
' + inner + '
';
document.body.appendChild(d);
d.querySelector('#v23FX').onclick = function () { d.remove(); };
d.addEventListener('click', function (e) { if (e.target === d) d.remove(); });
var btn = d.querySelector('#v23Save');
if (btn) btn.onclick = function () { var r = onSubmit(); if (r !== false) d.remove(); };
return d;
}
function mobEditProfile() {
var u = null; try { u = JSON.parse(localStorage.getItem('user_info') || '{}'); } catch (e) {}
formPanel('👤 编辑资料',
'' +
'' +
'', function () {
var nick = document.getElementById('v23Nick').value.trim(); var bio = document.getElementById('v23Bio').value.trim();
fetch(API + '/api/user-settings/profile', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: uid(), nickname: nick, bio: bio }) })
.then(function (r) { return r.json().catch(function () { return {}; }); })
.then(function (d) {
toast((d && d.success) ? '✅ 已保存' : '保存失败');
if (nick) { try { var ui = JSON.parse(localStorage.getItem('user_info') || '{}'); ui.nickname = nick; localStorage.setItem('user_info', JSON.stringify(ui)); } catch (e) {} }
if (typeof loadUserProfile === 'function') { try { loadUserProfile(); } catch (e) {} }
});
return true;
});
try { var ui0 = JSON.parse(localStorage.getItem('user_info') || '{}'); if (ui0.nickname || ui0.username) document.getElementById('v23Nick').value = ui0.nickname || ui0.username; } catch (e) {}
}
function mobSecurity() {
formPanel('🔒 账号安全',
'' +
'' +
'微信扫码账号若未设密码,旧密码留空即可(首次设置)。
' +
'', function () {
var oldp = document.getElementById('v23Old').value; var np = document.getElementById('v23New').value;
if (np.length < 6) { toast('新密码至少 6 位'); return false; }
fetch(API + '/api/user-settings/password', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: uid(), old_password: oldp, new_password: np }) })
.then(function (r) { return r.json().catch(function () { return {}; }); })
.then(function (d) { toast((d && d.success) ? '✅ 密码已更新' : ('修改失败:' + ((d && d.message) || '旧密码不正确'))); });
return true;
});
}
function mobPrefs() {
formPanel('🎨 偏好设置',
'主题
' +
'接收通知
' +
'', function () {
var theme = document.getElementById('v23Theme').value; var notif = document.getElementById('v23Notif').value;
fetch(API + '/api/user-settings/preferences', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: uid(), theme: theme, language: 'zh', notify: notif === '1' }) })
.then(function (r) { return r.json().catch(function () { return {}; }); })
.then(function (d) { toast((d && d.success) ? '✅ 偏好已保存(云端同步)' : '保存失败'); });
return true;
});
}
function mobCloud() {
toast('☁️ 资料/余额/订阅/素材与桌面端同一账号自动互通;手机端专属数据的按需同步规划中');
}
console.log('[MobV23] 数据接入就绪(定时任务/视频/我的)');
})();