- 左侧固定卡片展示照片幻灯片,淡入淡出切换 - 进度条动画显示当前照片剩余时间 - 设置窗口支持选择图片目录和切换间隔(5/10/15/20/30/60秒) - Win32 SHBrowseForFolderW 目录选择对话框 - Go 端管理幻灯片状态,按间隔推送照片 data URI
751 lines
28 KiB
HTML
751 lines
28 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<style>
|
|
:root {
|
|
--bg: #0f0f1a;
|
|
--card-bg: rgba(255,255,255,0.04);
|
|
--card-border: rgba(255,255,255,0.06);
|
|
--card-divider: rgba(255,255,255,0.04);
|
|
--text: #e0e0e0;
|
|
--text-strong: #fff;
|
|
--text-weak: rgba(255,255,255,0.25);
|
|
--text-muted: rgba(255,255,255,0.5);
|
|
--input-bg: rgba(255,255,255,0.08);
|
|
--input-border: rgba(255,255,255,0.1);
|
|
--input-border-focus: #4f8cff;
|
|
--accent: #4f8cff;
|
|
--toggle-track: rgba(255,255,255,0.1);
|
|
--toggle-thumb: rgba(255,255,255,0.5);
|
|
--option-bg: #1a1a2e;
|
|
--footer-color: rgba(255,255,255,0.3);
|
|
}
|
|
.light {
|
|
--bg: #f5f5f5;
|
|
--card-bg: rgba(0,0,0,0.03);
|
|
--card-border: rgba(0,0,0,0.08);
|
|
--card-divider: rgba(0,0,0,0.05);
|
|
--text: #333;
|
|
--text-strong: #111;
|
|
--text-weak: rgba(0,0,0,0.35);
|
|
--text-muted: rgba(0,0,0,0.55);
|
|
--input-bg: rgba(0,0,0,0.04);
|
|
--input-border: rgba(0,0,0,0.12);
|
|
--input-border-focus: #2b6cb0;
|
|
--accent: #2b6cb0;
|
|
--toggle-track: rgba(0,0,0,0.12);
|
|
--toggle-thumb: rgba(0,0,0,0.45);
|
|
--option-bg: #fff;
|
|
--footer-color: rgba(0,0,0,0.35);
|
|
}
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
padding: 16px 18px;
|
|
user-select: none;
|
|
-webkit-font-smoothing: antialiased;
|
|
overflow-y: auto;
|
|
}
|
|
::-webkit-scrollbar { width: 6px; }
|
|
::-webkit-scrollbar-track { background: transparent; }
|
|
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 3px; }
|
|
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }
|
|
.light ::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.12); }
|
|
.light ::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.22); }
|
|
.header { margin-bottom: 14px; }
|
|
.header h1 { font-size: 16px; font-weight: 600; color: var(--text-strong); }
|
|
.header p { font-size: 11px; color: var(--text-weak); margin-top: 2px; }
|
|
.section { margin-bottom: 12px; }
|
|
.section-label {
|
|
font-size: 10px; font-weight: 600; color: var(--text-weak);
|
|
text-transform: uppercase; letter-spacing: 1.5px;
|
|
margin-bottom: 4px; padding-left: 2px;
|
|
}
|
|
.card {
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--card-border);
|
|
border-radius: 8px;
|
|
}
|
|
.item {
|
|
display: flex; justify-content: space-between; align-items: center;
|
|
padding: 8px 14px;
|
|
}
|
|
.item + .item { border-top: 1px solid var(--card-divider); }
|
|
.item-label { font-size: 12px; font-weight: 500; color: var(--text-muted); }
|
|
.item-desc { font-size: 10px; color: var(--text-weak); margin-top: 1px; }
|
|
.item-sub { padding-left: 32px; }
|
|
|
|
/* Toggle */
|
|
.switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; }
|
|
.switch input { display: none; }
|
|
.switch .track {
|
|
position: absolute; inset: 0;
|
|
background: var(--toggle-track);
|
|
border-radius: 10px; cursor: pointer; transition: background 0.2s;
|
|
}
|
|
.switch .thumb {
|
|
position: absolute; width: 14px; height: 14px; top: 3px; left: 3px;
|
|
background: var(--toggle-thumb);
|
|
border-radius: 50%; transition: all 0.2s; pointer-events: none;
|
|
}
|
|
.switch input:checked + .track { background: var(--accent); }
|
|
.switch input:checked + .track .thumb { transform: translateX(16px); background: var(--text-strong); }
|
|
|
|
/* Select */
|
|
select {
|
|
background: var(--input-bg); border: 1px solid var(--input-border);
|
|
border-radius: 6px; color: var(--text); font-size: 11px; padding: 3px 6px;
|
|
font-family: inherit; cursor: pointer; outline: none;
|
|
min-width: 80px; max-width: 160px;
|
|
}
|
|
select:focus { border-color: var(--input-border-focus); }
|
|
select option { background: var(--option-bg); color: var(--text); }
|
|
|
|
/* Button */
|
|
.btn {
|
|
background: var(--input-bg); border: 1px solid var(--input-border);
|
|
border-radius: 6px; color: var(--text); font-size: 11px; padding: 4px 10px;
|
|
font-family: inherit; cursor: pointer; transition: background 0.15s; white-space: nowrap;
|
|
}
|
|
.btn:hover { background: var(--card-border); }
|
|
.btn:active { background: var(--input-bg); }
|
|
.btn.active { background: var(--accent); border-color: var(--accent); color: var(--text-strong); }
|
|
.btn-sm { padding: 3px 8px; font-size: 10px; }
|
|
.btn-group { display: flex; gap: 4px; }
|
|
.radio-tabs { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
.bing-nav { display: flex; gap: 4px; align-items: center; }
|
|
|
|
.wp-type-section { display: none; }
|
|
.wp-type-section.visible { display: block; }
|
|
|
|
input[type="text"] {
|
|
background: var(--input-bg); border: 1px solid var(--input-border);
|
|
border-radius: 6px; color: var(--text); font-size: 11px; padding: 4px 8px;
|
|
font-family: inherit; outline: none; width: 140px;
|
|
}
|
|
input[type="text"]:focus { border-color: var(--input-border-focus); }
|
|
|
|
/* City Picker */
|
|
.city-picker {
|
|
position: relative;
|
|
background: var(--input-bg); border: 1px solid var(--input-border);
|
|
border-radius: 6px; padding: 4px 24px 4px 8px; cursor: pointer;
|
|
font-size: 11px; min-width: 140px; max-width: 180px;
|
|
}
|
|
.city-picker:focus, .city-picker.open { border-color: var(--input-border-focus); }
|
|
.city-picker-text { color: var(--text); }
|
|
.city-picker-arrow {
|
|
position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
|
|
color: var(--text-weak); font-size: 10px; pointer-events: none;
|
|
}
|
|
.city-panel {
|
|
display: none; position: absolute; right: -1px; bottom: calc(100% + 4px);
|
|
background: var(--option-bg); border: 1px solid var(--input-border);
|
|
border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.25);
|
|
z-index: 1000; width: 260px; height: 200px; overflow: hidden;
|
|
}
|
|
.city-picker.open .city-panel { display: flex; }
|
|
.city-col {
|
|
flex: 1; overflow-y: auto; border-right: 1px solid var(--card-divider);
|
|
}
|
|
.city-col:last-child { border-right: none; }
|
|
.city-col div {
|
|
padding: 5px 10px; font-size: 11px; color: var(--text); cursor: pointer;
|
|
white-space: nowrap;
|
|
}
|
|
.city-col div:hover { background: var(--input-bg); }
|
|
.city-col div.active { color: var(--accent); font-weight: 600; }
|
|
|
|
/* Saved colors */
|
|
.color-swatch {
|
|
width: 28px; height: 28px; border-radius: 6px; cursor: pointer;
|
|
border: 2px solid transparent; transition: border-color 0.15s; position: relative;
|
|
}
|
|
.color-swatch:hover { border-color: var(--accent); }
|
|
.color-swatch .del {
|
|
display: none; position: absolute; top: -6px; right: -6px;
|
|
width: 14px; height: 14px; border-radius: 50%;
|
|
background: #e53e3e; color: #fff; font-size: 9px; line-height: 14px;
|
|
text-align: center; cursor: pointer;
|
|
}
|
|
.color-swatch:hover .del { display: block; }
|
|
|
|
.footer {
|
|
text-align: center; font-size: 11px; color: var(--footer-color); margin-top: 12px;
|
|
padding: 6px 0; letter-spacing: 0.5px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>桌面设置</h1>
|
|
<p>壁纸 · 布局 · 信息显示</p>
|
|
</div>
|
|
|
|
<!-- 显示控制 -->
|
|
<div class="section">
|
|
<div class="section-label">显示控制</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div><div class="item-label">显示壁纸</div></div>
|
|
<label class="switch"><input type="checkbox" id="wallpaper" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">时间日期</div></div>
|
|
<label class="switch"><input type="checkbox" id="time" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item item-sub">
|
|
<div><div class="item-label">显示秒</div></div>
|
|
<label class="switch"><input type="checkbox" id="showSeconds" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">天气信息</div></div>
|
|
<label class="switch"><input type="checkbox" id="weather" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">星座运势</div></div>
|
|
<label class="switch"><input type="checkbox" id="zodiacCard" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">知识卡片</div></div>
|
|
<label class="switch"><input type="checkbox" id="knowledgeCard" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">AI 资讯</div></div>
|
|
<label class="switch"><input type="checkbox" id="ainewsCard" checked><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 壁纸类型 -->
|
|
<div class="section">
|
|
<div class="section-label">壁纸类型</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-label">类型选择</div>
|
|
<div class="radio-tabs" id="wpTypeTabs">
|
|
<button class="btn" data-type="theme">主题</button>
|
|
<button class="btn" data-type="image">本地图片</button>
|
|
<button class="btn" data-type="bing">Bing</button>
|
|
<button class="btn" data-type="color">纯色/渐变</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 主题选择 -->
|
|
<div class="section wp-type-section" id="sec-theme">
|
|
<div class="section-label">壁纸主题</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-label">选择主题</div>
|
|
<select id="themeSelect"></select>
|
|
</div>
|
|
<div class="item" id="textInputRow" style="display:none">
|
|
<div class="item-label">自定义文字</div>
|
|
<input type="text" id="wallpaperText" placeholder="输入显示文字">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 本地图片 -->
|
|
<div class="section wp-type-section" id="sec-image">
|
|
<div class="section-label">本地图片</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-desc" id="imagePathDisplay">未选择图片</div>
|
|
<button class="btn" id="btnPickImage">选择图片</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bing -->
|
|
<div class="section wp-type-section" id="sec-bing">
|
|
<div class="section-label">Bing 每日壁纸</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div style="display:flex;align-items:center;gap:8px;flex:1;min-width:0">
|
|
<img id="bingPreview" style="width:64px;height:40px;object-fit:cover;border-radius:4px;flex-shrink:0;display:none">
|
|
<div style="min-width:0;overflow:hidden">
|
|
<div class="item-label" id="bingCopyright" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Bing 每日壁纸</div>
|
|
<div class="item-desc" id="bingIdx"></div>
|
|
</div>
|
|
</div>
|
|
<div class="bing-nav" style="flex-shrink:0">
|
|
<button class="btn btn-sm" id="btnBingPrev">◀</button>
|
|
<button class="btn btn-sm" id="btnBingNext">▶</button>
|
|
<button class="btn btn-sm" id="btnBingFav">☆</button>
|
|
</div>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">定时切换</div><div class="item-desc">每小时自动切换壁纸</div></div>
|
|
<label class="switch"><input type="checkbox" id="bingAutoRefresh"><span class="track"><span class="thumb"></span></span></label>
|
|
</div>
|
|
</div>
|
|
<div id="bingFavSection" style="display:none;margin-top:6px">
|
|
<div class="section-label">收藏列表</div>
|
|
<div class="card" id="bingFavList"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 纯色/渐变 -->
|
|
<div class="section wp-type-section" id="sec-color">
|
|
<div class="section-label">纯色 / 渐变</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-label">选择颜色</div>
|
|
<div class="btn-group">
|
|
<button class="btn" id="btnSolidColor">纯色</button>
|
|
<button class="btn" id="btnGradientColor">渐变</button>
|
|
</div>
|
|
</div>
|
|
<div class="item" id="currentColorRow" style="display:none">
|
|
<div class="item-label">当前颜色</div>
|
|
<div style="display:flex;align-items:center;gap:6px">
|
|
<span id="currentColorPreview" style="display:inline-block;width:24px;height:16px;border-radius:3px;border:1px solid var(--input-border)"></span>
|
|
<button class="btn btn-sm" id="btnSaveColor">收藏</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="savedColorsSection" style="display:none;margin-top:6px">
|
|
<div class="card" id="savedColorsGrid" style="padding:8px 12px;display:flex;flex-wrap:wrap;gap:6px">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 布局 -->
|
|
<div class="section">
|
|
<div class="section-label">布局</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-label">信息布局</div>
|
|
<select id="layout">
|
|
<option value="single">合并卡片</option>
|
|
<option value="multi">独立卡片</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 相册 -->
|
|
<div class="section">
|
|
<div class="section-label">相册</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-desc" id="photoDirDisplay">未选择目录</div>
|
|
<div class="btn-group">
|
|
<button class="btn" id="btnPickPhotoDir">选择目录</button>
|
|
<button class="btn btn-sm" id="btnClearPhotoDir" style="display:none">清除</button>
|
|
</div>
|
|
</div>
|
|
<div class="item">
|
|
<div class="item-label">切换间隔</div>
|
|
<select id="photoInterval">
|
|
<option value="5">5 秒</option>
|
|
<option value="10">10 秒</option>
|
|
<option value="15" selected>15 秒</option>
|
|
<option value="20">20 秒</option>
|
|
<option value="30">30 秒</option>
|
|
<option value="60">60 秒</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 星座 + 城市 -->
|
|
<div class="section">
|
|
<div class="section-label">个性化</div>
|
|
<div class="card">
|
|
<div class="item">
|
|
<div class="item-label">我的星座</div>
|
|
<select id="zodiacSelect">
|
|
<option>白羊座</option><option>金牛座</option><option>双子座</option>
|
|
<option>巨蟹座</option><option>狮子座</option><option>处女座</option>
|
|
<option>天秤座</option><option>天蝎座</option><option>射手座</option>
|
|
<option>摩羯座</option><option>水瓶座</option><option>双鱼座</option>
|
|
</select>
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">知识关键字</div><div class="item-desc">AI 将根据关键字生成知识小卡片</div></div>
|
|
<input type="text" id="knowledgeKeyword" placeholder="如: 历史、科学、冷知识">
|
|
</div>
|
|
<div class="item">
|
|
<div><div class="item-label">知识提示词</div><div class="item-desc">自定义生成风格,不会显示在桌面</div></div>
|
|
<input type="text" id="knowledgePrompt" placeholder="如: 用幽默口吻、面向程序员">
|
|
</div>
|
|
<div class="item" style="position:relative">
|
|
<div class="item-label">天气城市</div>
|
|
<div class="city-picker" id="cityPicker" tabindex="0">
|
|
<span class="city-picker-text" id="cityPickerText">未选择</span>
|
|
<span class="city-picker-arrow">▾</span>
|
|
<div class="city-panel" id="cityPanel">
|
|
<div class="city-col" id="provCol"></div>
|
|
<div class="city-col" id="cityCol"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer">u-desktop v1.0</div>
|
|
|
|
<script>
|
|
var toggleKeys = ['wallpaper', 'time', 'showSeconds', 'weather', 'zodiacCard', 'knowledgeCard', 'ainewsCard'];
|
|
var initDone = false;
|
|
function sendToggle() {
|
|
if (!initDone) return;
|
|
var data = {};
|
|
toggleKeys.forEach(function(k) { data[k] = document.getElementById(k).checked; });
|
|
if (window.saveToggles) window.saveToggles(JSON.stringify(data));
|
|
}
|
|
toggleKeys.forEach(function(k) {
|
|
document.getElementById(k).addEventListener('change', sendToggle);
|
|
});
|
|
document.getElementById('layout').addEventListener('change', function() {
|
|
if (window.saveLayout) window.saveLayout(this.value);
|
|
});
|
|
document.getElementById('zodiacSelect').addEventListener('change', function() {
|
|
if (window.saveZodiac) window.saveZodiac(this.value);
|
|
});
|
|
|
|
var kwTimer = null;
|
|
document.getElementById('knowledgeKeyword').addEventListener('input', function() {
|
|
clearTimeout(kwTimer);
|
|
var val = this.value;
|
|
kwTimer = setTimeout(function() {
|
|
if (window.saveKnowledgeKeyword) window.saveKnowledgeKeyword(val);
|
|
}, 500);
|
|
});
|
|
|
|
var kpTimer = null;
|
|
document.getElementById('knowledgePrompt').addEventListener('input', function() {
|
|
clearTimeout(kpTimer);
|
|
var val = this.value;
|
|
kpTimer = setTimeout(function() {
|
|
if (window.saveKnowledgePrompt) window.saveKnowledgePrompt(val);
|
|
}, 500);
|
|
});
|
|
|
|
// City picker
|
|
var cityMap = {};
|
|
var selectedCityId = '';
|
|
var selectedCityName = '';
|
|
var picker = document.getElementById('cityPicker');
|
|
var pickerText = document.getElementById('cityPickerText');
|
|
var provCol = document.getElementById('provCol');
|
|
var cityCol = document.getElementById('cityCol');
|
|
var activeProv = '';
|
|
|
|
function renderProvinces(provinces) {
|
|
provCol.innerHTML = '';
|
|
provinces.forEach(function(p) {
|
|
var div = document.createElement('div');
|
|
div.textContent = p;
|
|
if (p === activeProv) div.className = 'active';
|
|
div.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
activeProv = p;
|
|
renderProvinces(provinces);
|
|
renderCities(p);
|
|
});
|
|
provCol.appendChild(div);
|
|
});
|
|
}
|
|
function renderCities(prov) {
|
|
cityCol.innerHTML = '';
|
|
var list = cityMap[prov] || [];
|
|
list.forEach(function(c) {
|
|
var div = document.createElement('div');
|
|
div.textContent = c.name;
|
|
if (c.id === selectedCityId) div.className = 'active';
|
|
div.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
selectedCityId = c.id;
|
|
selectedCityName = c.name;
|
|
pickerText.textContent = activeProv + ' · ' + c.name;
|
|
picker.classList.remove('open');
|
|
renderCities(prov);
|
|
if (window.saveCity) window.saveCity(c.id);
|
|
});
|
|
cityCol.appendChild(div);
|
|
});
|
|
}
|
|
picker.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
this.classList.toggle('open');
|
|
this.focus();
|
|
});
|
|
document.addEventListener('click', function(e) {
|
|
if (!picker.contains(e.target)) picker.classList.remove('open');
|
|
});
|
|
|
|
document.getElementById('themeSelect').addEventListener('change', function() {
|
|
if (window.saveWallpaperType) window.saveWallpaperType('theme', this.value);
|
|
document.getElementById('textInputRow').style.display = this.value === 'text' ? 'flex' : 'none';
|
|
});
|
|
|
|
document.getElementById('btnPickPhotoDir').addEventListener('click', function() {
|
|
if (!window.pickPhotoDir) return;
|
|
window.pickPhotoDir().then(function(dir) {
|
|
if (dir) {
|
|
document.getElementById('photoDirDisplay').textContent = dir;
|
|
document.getElementById('btnClearPhotoDir').style.display = '';
|
|
}
|
|
});
|
|
});
|
|
document.getElementById('btnClearPhotoDir').addEventListener('click', function() {
|
|
if (!window.clearPhotoDir) return;
|
|
window.clearPhotoDir().then(function() {
|
|
document.getElementById('photoDirDisplay').textContent = '未选择目录';
|
|
document.getElementById('btnClearPhotoDir').style.display = 'none';
|
|
});
|
|
});
|
|
document.getElementById('photoInterval').addEventListener('change', function() {
|
|
if (window.savePhotoInterval) window.savePhotoInterval(parseInt(this.value));
|
|
});
|
|
|
|
var textTimer = null;
|
|
document.getElementById('wallpaperText').addEventListener('input', function() {
|
|
clearTimeout(textTimer);
|
|
var val = this.value;
|
|
textTimer = setTimeout(function() {
|
|
if (window.saveWallpaperText) window.saveWallpaperText(val);
|
|
}, 500);
|
|
});
|
|
|
|
var wpTypeTabs = document.querySelectorAll('#wpTypeTabs .btn');
|
|
var currentWpType = '';
|
|
function setWpType(type) {
|
|
wpTypeTabs.forEach(function(b) { b.classList.toggle('active', b.dataset.type === type); });
|
|
document.querySelectorAll('.wp-type-section').forEach(function(s) { s.classList.remove('visible'); });
|
|
var sec = document.getElementById('sec-' + type);
|
|
if (sec) sec.classList.add('visible');
|
|
if (type === 'bing' && currentWpType !== 'bing') {
|
|
if (window.enableBing) window.enableBing();
|
|
}
|
|
currentWpType = type;
|
|
}
|
|
wpTypeTabs.forEach(function(b) {
|
|
b.addEventListener('click', function() { setWpType(b.dataset.type); });
|
|
});
|
|
|
|
document.getElementById('btnPickImage').addEventListener('click', function() {
|
|
if (!window.pickLocalImage) return;
|
|
window.pickLocalImage().then(function(path) {
|
|
if (path) document.getElementById('imagePathDisplay').textContent = path;
|
|
});
|
|
});
|
|
function updateBingUI(stateJson) {
|
|
if (!stateJson) return;
|
|
var s = JSON.parse(stateJson);
|
|
document.getElementById('btnBingFav').textContent = s.label;
|
|
document.getElementById('bingCopyright').textContent = s.copyright || 'Bing 每日壁纸';
|
|
document.getElementById('bingIdx').textContent = (s.total > 0) ? ((s.idx + 1) + ' / ' + s.total) : '';
|
|
// load preview thumbnail
|
|
if (s.filename && window.bingThumbDataURI) {
|
|
var preview = document.getElementById('bingPreview');
|
|
window.bingThumbDataURI(s.filename).then(function(uri) {
|
|
if (uri) { preview.src = uri; preview.style.display = 'block'; }
|
|
});
|
|
}
|
|
}
|
|
function loadBingFavorites() {
|
|
if (!window.getBingFavorites) return;
|
|
window.getBingFavorites().then(function(json) {
|
|
var favs = JSON.parse(json);
|
|
var sec = document.getElementById('bingFavSection');
|
|
var list = document.getElementById('bingFavList');
|
|
list.innerHTML = '';
|
|
if (!favs || favs.length === 0) { sec.style.display = 'none'; return; }
|
|
sec.style.display = 'block';
|
|
list.style.cssText = 'padding:8px 12px;display:flex;flex-wrap:wrap;gap:6px';
|
|
favs.forEach(function(f) {
|
|
var img = document.createElement('img');
|
|
img.style.cssText = 'width:64px;height:40px;object-fit:cover;border-radius:4px;cursor:pointer;border:2px solid transparent;transition:border-color 0.15s';
|
|
img.title = f.copyright + ' (' + f.date + ')';
|
|
img.addEventListener('click', function() {
|
|
if (window.bingSetByIdx) window.bingSetByIdx(f.idx).then(function(s) { updateBingUI(s); });
|
|
});
|
|
img.addEventListener('mouseenter', function() { this.style.borderColor = 'var(--accent)'; });
|
|
img.addEventListener('mouseleave', function() { this.style.borderColor = 'transparent'; });
|
|
list.appendChild(img);
|
|
if (window.bingThumbDataURI) {
|
|
window.bingThumbDataURI(f.filename).then(function(uri) {
|
|
if (uri) img.src = uri;
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
document.getElementById('btnBingPrev').addEventListener('click', function() {
|
|
if (window.bingNext) window.bingNext().then(function(s) { updateBingUI(s); });
|
|
});
|
|
document.getElementById('btnBingNext').addEventListener('click', function() {
|
|
if (window.bingPrev) window.bingPrev().then(function(s) { updateBingUI(s); });
|
|
});
|
|
document.getElementById('btnBingFav').addEventListener('click', function() {
|
|
if (window.bingToggleFavorite) {
|
|
window.bingToggleFavorite().then(function(s) { updateBingUI(s); loadBingFavorites(); });
|
|
}
|
|
});
|
|
document.getElementById('bingAutoRefresh').addEventListener('change', function() {
|
|
if (window.saveBingAutoRefresh) window.saveBingAutoRefresh(this.checked);
|
|
});
|
|
document.getElementById('btnSolidColor').addEventListener('click', function() {
|
|
if (window.pickSolidColor) {
|
|
window.pickSolidColor().then(function(c) {
|
|
if (c) { currentColor1 = c; currentColor2 = ''; currentGradient = false; updateColorPreview(); }
|
|
});
|
|
}
|
|
});
|
|
document.getElementById('btnGradientColor').addEventListener('click', function() {
|
|
if (window.pickGradientColor) {
|
|
window.pickGradientColor().then(function(res) {
|
|
if (res) {
|
|
var parts = res.split(',');
|
|
currentColor1 = parts[0]; currentColor2 = parts[1] || ''; currentGradient = true;
|
|
updateColorPreview();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Color favorites
|
|
var currentColor1 = '', currentColor2 = '', currentGradient = false;
|
|
var savedColors = [];
|
|
|
|
function updateColorPreview() {
|
|
var row = document.getElementById('currentColorRow');
|
|
var preview = document.getElementById('currentColorPreview');
|
|
if (!currentColor1) { row.style.display = 'none'; return; }
|
|
row.style.display = 'flex';
|
|
if (currentGradient && currentColor2) {
|
|
preview.style.background = 'linear-gradient(135deg,' + currentColor1 + ',' + currentColor2 + ')';
|
|
} else {
|
|
preview.style.background = currentColor1;
|
|
}
|
|
}
|
|
|
|
function renderSavedColors() {
|
|
var sec = document.getElementById('savedColorsSection');
|
|
var grid = document.getElementById('savedColorsGrid');
|
|
grid.innerHTML = '';
|
|
if (!savedColors || savedColors.length === 0) { sec.style.display = 'none'; return; }
|
|
sec.style.display = 'block';
|
|
savedColors.forEach(function(sc, idx) {
|
|
var swatch = document.createElement('div');
|
|
swatch.className = 'color-swatch';
|
|
if (sc.gradient && sc.color2) {
|
|
swatch.style.background = 'linear-gradient(135deg,' + sc.color1 + ',' + sc.color2 + ')';
|
|
} else {
|
|
swatch.style.background = sc.color1;
|
|
}
|
|
var del = document.createElement('span');
|
|
del.className = 'del'; del.textContent = 'x';
|
|
del.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
if (window.removeSavedColor) window.removeSavedColor(idx).then(function() {
|
|
savedColors.splice(idx, 1);
|
|
renderSavedColors();
|
|
});
|
|
});
|
|
swatch.appendChild(del);
|
|
swatch.addEventListener('click', function() {
|
|
if (window.applySavedColor) window.applySavedColor(idx);
|
|
currentColor1 = sc.color1; currentColor2 = sc.color2; currentGradient = sc.gradient;
|
|
updateColorPreview();
|
|
});
|
|
grid.appendChild(swatch);
|
|
});
|
|
}
|
|
|
|
document.getElementById('btnSaveColor').addEventListener('click', function() {
|
|
if (!currentColor1) return;
|
|
if (window.addSavedColor) window.addSavedColor(currentColor1, currentColor2, currentGradient).then(function() {
|
|
savedColors.push({color1: currentColor1, color2: currentColor2, gradient: currentGradient});
|
|
renderSavedColors();
|
|
});
|
|
});
|
|
|
|
if (window.loadAllSettings) {
|
|
window.loadAllSettings().then(function(raw) {
|
|
var s = JSON.parse(raw);
|
|
|
|
// Apply system theme
|
|
if (s.lightTheme) {
|
|
document.documentElement.className = 'light';
|
|
}
|
|
|
|
// Province-city cascade
|
|
cityMap = s.citiesByProv || {};
|
|
selectedCityId = s.city || '';
|
|
activeProv = '';
|
|
if (s.provinces && s.provinces.length) {
|
|
for (var p in cityMap) {
|
|
for (var ci = 0; ci < cityMap[p].length; ci++) {
|
|
if (cityMap[p][ci].id === selectedCityId) { activeProv = p; selectedCityName = cityMap[p][ci].name; break; }
|
|
}
|
|
if (activeProv) break;
|
|
}
|
|
renderProvinces(s.provinces);
|
|
if (activeProv) renderCities(activeProv);
|
|
if (activeProv && selectedCityName) {
|
|
pickerText.textContent = activeProv + ' · ' + selectedCityName;
|
|
}
|
|
}
|
|
|
|
if (s.themes && s.themes.length) {
|
|
var themeSel = document.getElementById('themeSelect');
|
|
s.themes.forEach(function(t) {
|
|
var opt = document.createElement('option');
|
|
opt.value = t.value;
|
|
opt.textContent = t.label;
|
|
themeSel.appendChild(opt);
|
|
});
|
|
}
|
|
toggleKeys.forEach(function(k) {
|
|
if (s[k] !== undefined) document.getElementById(k).checked = s[k];
|
|
});
|
|
if (s.layout) document.getElementById('layout').value = s.layout;
|
|
if (s.zodiac) document.getElementById('zodiacSelect').value = s.zodiac;
|
|
if (s.theme) document.getElementById('themeSelect').value = s.theme;
|
|
if (s.wallpaperText) document.getElementById('wallpaperText').value = s.wallpaperText;
|
|
if (s.imagePath) document.getElementById('imagePathDisplay').textContent = s.imagePath;
|
|
if (s.knowledgeKeyword) document.getElementById('knowledgeKeyword').value = s.knowledgeKeyword;
|
|
if (s.knowledgePrompt) document.getElementById('knowledgePrompt').value = s.knowledgePrompt;
|
|
if (s.theme === 'text') document.getElementById('textInputRow').style.display = 'flex';
|
|
// Photo state
|
|
if (s.photoDir) {
|
|
document.getElementById('photoDirDisplay').textContent = s.photoDir;
|
|
document.getElementById('btnClearPhotoDir').style.display = '';
|
|
}
|
|
if (s.photoInterval) document.getElementById('photoInterval').value = s.photoInterval;
|
|
// Color state
|
|
if (s.color1) { currentColor1 = s.color1; currentColor2 = s.color2 || ''; currentGradient = s.colorGradient || false; }
|
|
if (s.wallpaperType === 'color') updateColorPreview();
|
|
savedColors = s.savedColors || [];
|
|
renderSavedColors();
|
|
setWpType(s.wallpaperType || 'theme');
|
|
// Bing state
|
|
if (s.wallpaperType === 'bing' && window.getBingInfo) {
|
|
window.getBingInfo().then(function(si) { updateBingUI(si); });
|
|
}
|
|
if (s.wallpaperType === 'bing') loadBingFavorites();
|
|
if (s.bingAutoRefresh !== undefined) document.getElementById('bingAutoRefresh').checked = s.bingAutoRefresh;
|
|
// resize window to fit content
|
|
setTimeout(function() {
|
|
var el = document.documentElement;
|
|
var cw = el.scrollWidth;
|
|
var ch = el.scrollHeight + 8;
|
|
if (window.resizeToFit) window.resizeToFit(cw, ch);
|
|
}, 100);
|
|
initDone = true;
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|