Commit 03b382a9 authored by KesaubeEire's avatar KesaubeEire

feat: 配置面板.

parent 254372ce
...@@ -61,12 +61,12 @@ npm run build:prod ...@@ -61,12 +61,12 @@ npm run build:prod
- [ ] 历史玩过的游戏 - [ ] 历史玩过的游戏
- [ ] 收藏的游戏 - [ ] 收藏的游戏
- [ ] 允许玩家给游戏写(本地可见的)备注,显示在标签上方,日文名下方 - [ ] 允许玩家给游戏写(本地可见的)备注,显示在标签上方,日文名下方
- [ ] TODO: 配置面板 - [x] 配置面板
- [ ] 卡片相关 - [x] 卡片相关
- [ ] page 相关 (num & size) - [x] page 相关 (num & size)
- [ ] TODO: 更新数据 (TAG Category 游戏) - [x] 更新数据 (TAG Category 游戏)
- [ ] 主动更新按钮 - [x] 主动更新按钮
- [ ] 定时更新 - [x] 定时更新
- [ ] TODO: 重构云存档系统 - [ ] TODO: 重构云存档系统
- [ ] 统一界面风格 - [ ] 统一界面风格
- [ ] 既有功能的继承 - [ ] 既有功能的继承
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
<!-- NOTE: 配置 --> <!-- NOTE: 配置 -->
<MenuWrapNav title="配置" tailwind="w-72 max-h-[70vh]" tip="自定义适合的配置"> <MenuWrapNav title="配置" tailwind="w-72 max-h-[70vh]" tip="自定义适合的配置">
<MenuConfig /> <MenuConfig {contentDom} />
</MenuWrapNav> </MenuWrapNav>
</ul> </ul>
</div> </div>
...@@ -308,7 +308,7 @@ ...@@ -308,7 +308,7 @@
<!-- NOTE: 配置 --> <!-- NOTE: 配置 -->
<MenuWrapSide title="配置"> <MenuWrapSide title="配置">
<MenuConfig /> <MenuConfig {contentDom} />
</MenuWrapSide> </MenuWrapSide>
</ul> </ul>
</div> </div>
......
<script> <script>
import Card from './components/card.svelte'; import Card from './components/card.svelte';
import { SvelteToast, toast } from '@zerodevx/svelte-toast'; import { SvelteToast, toast } from '@zerodevx/svelte-toast';
import { _category, _detailWindow, _env, _tagTrans, _detailPics } from './stores'; import { _category, _detailWindow, _env, _tagTrans, _detailPics, _config, _timer } from './stores';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { debounceImmediate } from './utils'; import { debounceImmediate } from './utils';
...@@ -12,13 +12,17 @@ ...@@ -12,13 +12,17 @@
if (process.env.APP_ENV === 'dev') console.log(...str); if (process.env.APP_ENV === 'dev') console.log(...str);
} }
// -----------------------------
/**渲染数据列表*/
let List = [];
// ----------------------------- // -----------------------------
// page & 搜索相关 // page & 搜索相关
/**NextPage 指示瀑布流下次应请求的页码数*/ /**NextPage 指示瀑布流下次应请求的页码数*/
let nextPage = 1; let nextPage = 1;
/**NextPage 指示瀑布流下次应请求的limit数*/ /**NextPage 指示瀑布流下次应请求的limit数*/
let globalPageLimit = 20; let globalPageLimit = $_config.page_singleNum;
/**瀑布流是否请求中, 为 true 时不能重复请求*/ /**瀑布流是否请求中, 为 true 时不能重复请求*/
let isSearching = false; let isSearching = false;
/**若isEnd(已经没有新的结果了)则暂停瀑布流请求*/ /**若isEnd(已经没有新的结果了)则暂停瀑布流请求*/
...@@ -35,7 +39,16 @@ ...@@ -35,7 +39,16 @@
const distance = 10; const distance = 10;
// ----------------------------- // -----------------------------
// 各种请求封装头 & 请求函数 // 本地配置变量响应式变化
$: {
if (globalPageLimit != $_config.page_singleNum) {
globalPageLimit = $_config.page_singleNum;
toast.push('单页显示(单次瀑布流加载)数量 变化, 请刷新页面.');
}
}
// -----------------------------
// 各种请求封装头
/**请求封装头 -> 获取语言类别*/ /**请求封装头 -> 获取语言类别*/
const getLanguageCategory = { const getLanguageCategory = {
...@@ -90,7 +103,10 @@ ...@@ -90,7 +103,10 @@
}; };
}; };
/**创建请求 fetch 函数 // -----------------------------
// 请求函数
/**创建请求底层 fetch 函数
* @param {object} param0 参数对象 * @param {object} param0 参数对象
* @param {function} callback 回调函数 * @param {function} callback 回调函数
*/ */
...@@ -132,38 +148,6 @@ ...@@ -132,38 +148,6 @@
}); });
} }
// -----------------------------
// 组件变量 & 函数工具
/**渲染数据列表*/
let List = [];
/**更新视图 -> 替换元素
* @param data JSON数据
*/
function showList(data) {
// List = [...List, ...data];
List = [];
// <!-- FIXME: 暂时以这种略微丑陋的方式做切换动画, 可能这就是唯一方案了 -->
setTimeout(() => {
List = [...data];
window.scrollTo(0, 0);
}, 400);
}
/**更新视图 -> 增加元素 -> 瀑布流
* @param data JSON数据
*/
function appendList(data) {
List = [...List, ...data];
}
/**瀑布流: 延续参数继续搜索下一页*/
function continueLastSearch() {
performSearch(lastSearchType, lastSearchParam, globalPageLimit, nextPage);
}
/**执行搜索主函数 /**执行搜索主函数
* @param searchType * @param searchType
* @param searchParam * @param searchParam
...@@ -228,6 +212,14 @@ ...@@ -228,6 +212,14 @@
}); });
} }
/**瀑布流: 延续参数继续搜索下一页*/
function continueLastSearch() {
performSearch(lastSearchType, lastSearchParam, globalPageLimit, nextPage);
}
// -----------------------------
// 对外请求函数
/**根据 TAG 搜索游戏 /**根据 TAG 搜索游戏
* @param {string} tag TAG * @param {string} tag TAG
*/ */
...@@ -251,34 +243,15 @@ ...@@ -251,34 +243,15 @@
} }
window.searchTitle = searchTitle; window.searchTitle = searchTitle;
/** /**默认搜索 -> 暂时是全部搜索
* 默认搜索 -> 暂时是全部搜索
* TODO: 全局内容 30分钟 一次缓存在 localstorage 里 * TODO: 全局内容 30分钟 一次缓存在 localstorage 里
*/ */
export function searchDefault(limit = globalPageLimit, page = 1) { export function searchDefault(limit = globalPageLimit, page = 1) {
performSearch('', '', limit, page); performSearch('', '', limit, page);
} }
/**获取封面图 /**拉取静态资源: Category */
* @param folder 文件夹路径 export function fetchStaticCategory() {
*/
function getCover(folder) {
// FIXME: 隐患 -> 可能是 1.png 1.webpage 之类的...
return $_env + '/' + folder.substring(2) + '/rpg_info/1.jpg';
}
/**获取 info.json
* @param folder 文件夹路径
*/
function getFolder(folder) {
return $_env + '/' + folder.substring(2);
}
// -----------------------------
// NOTE: 初始化执行 -> 考虑用 onMount
// 初始化请求 -> 拉取所有分类
// TODO: 搞个记时, 每天一刷 & 做一个主动更新的按钮
if (!$_category.length) {
createFetch(getLanguageCategory, data => { createFetch(getLanguageCategory, data => {
if (process.env.APP_ENV === 'dev') console.log(data); if (process.env.APP_ENV === 'dev') console.log(data);
$_category = data; $_category = data;
...@@ -291,9 +264,8 @@ ...@@ -291,9 +264,8 @@
}); });
} }
// 初始化请求 -> 拉取tag翻译 /**拉取静态资源: Tag */
// TODO: 搞个记时, 每天一刷 & 做一个主动更新的按钮 export function fetchStaticTag() {
if (!$_tagTrans.length) {
createFetch(getTranslatedTag, data => { createFetch(getTranslatedTag, data => {
if (process.env.APP_ENV === 'dev') console.log(data); if (process.env.APP_ENV === 'dev') console.log(data);
$_tagTrans = data; $_tagTrans = data;
...@@ -306,6 +278,89 @@ ...@@ -306,6 +278,89 @@
}); });
} }
// -----------------------------
// 组件变量 & 函数工具
/**更新视图 -> 替换元素
* @param data JSON数据
*/
function showList(data) {
// List = [...List, ...data];
List = [];
// <!-- FIXME: 暂时以这种略微丑陋的方式做切换动画, 可能这就是唯一方案了 -->
setTimeout(() => {
List = [...data];
window.scrollTo(0, 0);
}, 400);
}
/**更新视图 -> 增加元素 -> 瀑布流
* @param data JSON数据
*/
function appendList(data) {
List = [...List, ...data];
}
/**获取封面图
* @param folder 文件夹路径
*/
function getCover(folder) {
// FIXME: 隐患 -> 可能是 1.png 1.webpage 之类的...
return $_env + '/' + folder.substring(2) + '/rpg_info/1.jpg';
}
/**获取 info.json
* @param folder 文件夹路径
*/
function getFolder(folder) {
return $_env + '/' + folder.substring(2);
}
/**计算定时时间戳举例现在的时长(单位为小时)*/
export function calcTimerExpiredHours() {
const now = new Date().getTime();
const period = now - $_timer;
const expiredHours = Math.floor(period / (3600 * 1000));
return expiredHours;
}
/**计算定时时间戳是否超时, 默认为 24 小时 -> 1 天
* @param {number} hour 单位小时
*/
export function calcTimerExpired(hour = 24) {
if (!$_timer) {
$_timer = new Date().getTime();
toast.push('初始化时间戳.');
return true;
}
const _hours = calcTimerExpiredHours();
const res = _hours >= hour;
const expiredDay = Math.floor(_hours / 24);
if (process.env.APP_ENV === 'dev' && res) {
toast.push('未更新天数:\t' + expiredDay);
if (process.env.APP_ENV === 'dev') {
console.log('未更新天数:\t', expiredDay);
}
}
return res;
}
// -----------------------------
// NOTE: 初始化执行 -> 考虑用 onMount
// 初始化请求 -> 拉取所有分类
const isTimeExpired = calcTimerExpired();
if (!$_category.length || isTimeExpired) {
fetchStaticCategory();
}
// 初始化请求 -> 拉取tag翻译
if (!$_tagTrans.length || isTimeExpired) {
fetchStaticTag();
}
// 更新时间戳
isTimeExpired ? ($_timer = new Date().getTime()) : '';
/**对加载下一页进行防抖*/ /**对加载下一页进行防抖*/
let debouncedContinue = debounceImmediate(continueLastSearch, 1000); let debouncedContinue = debounceImmediate(continueLastSearch, 1000);
......
<script> <script>
let lastUpdatedTimeCategory; import { onMount } from 'svelte';
let lastUpdatedTimeTag; import { _config, _timer } from '../stores';
function expiredTimeCategory() { export let contentDom;
return new Date().getHours();
} /**显示距离上次时间戳的时长*/
function expiredTimeTag() { let ExpiredHours = '??';
return new Date().getHours();
/**显示距离上次时间戳的时长*/
function calcTimerExpiredHours() {
const now = new Date().getTime();
const period = now - $_timer;
const expiredHours = Math.floor(period / (3600 * 1000));
return expiredHours;
} }
onMount(() => {
ExpiredHours = calcTimerExpiredHours();
console.log(contentDom);
});
</script> </script>
<li> <li>
...@@ -17,15 +28,19 @@ ...@@ -17,15 +28,19 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="form-control w-60"> <div class="form-control w-60">
<label class="label cursor-pointer w-full inline-flex justify-between"> <label class="label cursor-pointer w-full inline-flex justify-between">
<span class="label-text">分类: 距离上次 {expiredTimeCategory()} 小时</span> <span class="label-text">分类&标签: {ExpiredHours} 小时前</span>
<button class="btn btn-xs btn-neutral">更新</button> <button
</label> class="btn btn-xs btn-neutral"
</div> on:click={() => {
// 拉取数据
<div class="form-control w-60"> contentDom.fetchStaticCategory();
<label class="label cursor-pointer flex justify-between"> contentDom.fetchStaticTag();
<span class="label-text">标签: 距离上次 {expiredTimeTag()} 小时</span> // 更新时间戳
<button class="btn btn-xs btn-neutral">更新</button> $_timer = new Date().getTime();
// 更新显示
ExpiredHours = calcTimerExpiredHours();
}}>更新</button
>
</label> </label>
</div> </div>
</div> </div>
...@@ -38,16 +53,25 @@ ...@@ -38,16 +53,25 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="form-control w-60"> <div class="form-control w-60">
<label class="label cursor-pointer w-full inline-flex justify-between"> <label class="label cursor-pointer w-full inline-flex justify-between">
<span class="label-text">显示副标题</span> <span class="label-text">显示语言分类</span>
<input type="checkbox" class="toggle" checked /> <input type="checkbox" bind:checked={$_config.card_showCateGory} class="toggle" />
</label> </label>
</div> </div>
<div class="form-control w-60"> <div class="flex flex-col">
<label class="label cursor-pointer flex justify-between"> <div class="form-control w-60">
<span class="label-text">显示标签</span> <label class="label cursor-pointer w-full inline-flex justify-between">
<input type="checkbox" class="toggle" checked /> <span class="label-text">显示副标题</span>
</label> <input type="checkbox" bind:checked={$_config.card_showSubTitle} class="toggle" />
</label>
</div>
<div class="form-control w-60">
<label class="label cursor-pointer flex justify-between">
<span class="label-text">显示标签</span>
<input type="checkbox" bind:checked={$_config.card_showTag} class="toggle" />
</label>
</div>
</div> </div>
</div> </div>
</ul> </ul>
...@@ -59,15 +83,15 @@ ...@@ -59,15 +83,15 @@
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div>每页数量</div> <div>每页数量</div>
<div> <div>
<input class="w-44 range" type="range" min="0" max="100" value="25" step="25" /> <input class="w-44 range" type="range" min="10" max="50" bind:value={$_config.page_singleNum} step="10" />
<div class="w-44 flex justify-between text-xs px-2"> <div class="w-44 flex justify-between text-xs px-2">
<!-- <span>|</span> --> <!-- <span>|</span> -->
<!-- <span>|</span> --> <!-- <span>|</span> -->
<!-- <span>|</span> --> <!-- <span>|</span> -->
<!-- <span>|</span> --> <!-- <span>|</span> -->
<!-- <span>|</span> --> <!-- <span>|</span> -->
{#each [1, 2, 3, 4, 5] as num} {#each [10, 20, 30, 40, 50] as num}
<span>{num * 10}</span> <span>{num}</span>
{/each} {/each}
</div> </div>
</div> </div>
......
<script> <script>
import { toast } from '@zerodevx/svelte-toast'; import { toast } from '@zerodevx/svelte-toast';
import { _detailPics, _detailWindow, _tagTrans } from '../stores'; import { _detailPics, _detailWindow, _tagTrans, _config } from '../stores';
/**父属性: 主标题*/ /**父属性: 主标题*/
export let title; export let title;
...@@ -110,14 +110,16 @@ ...@@ -110,14 +110,16 @@
<div class="card-body justify-between"> <div class="card-body justify-between">
<h2 class="card-title block text-lg"> <h2 class="card-title block text-lg">
<!-- NOTE: 游戏类别 --> <!-- NOTE: 游戏类别 -->
<div {#if $_config.card_showCateGory}
class="badge badge-secondary m-auto cursor-pointer hover:badge-neutral" <div
style="height: inherit;line-height: inherit;" class="badge badge-secondary m-auto cursor-pointer hover:badge-neutral"
on:click={p_searchCategory(category)} style="height: inherit;line-height: inherit;"
on:keypress={() => {}} on:click={p_searchCategory(category)}
> on:keypress={() => {}}
{language ?? '示例'} >
</div> {language ?? '示例'}
</div>
{/if}
<!-- NOTE: 游戏名称 --> <!-- NOTE: 游戏名称 -->
<a class="hover:link" href={folder} target="_blank"> <a class="hover:link" href={folder} target="_blank">
{#if title} {#if title}
...@@ -127,31 +129,31 @@ ...@@ -127,31 +129,31 @@
{/if} {/if}
</a> </a>
</h2> </h2>
<p>{sub_title ?? '无日文名称'}</p> <!-- NOTE: 游戏副标题 -> (日文)原名 -->
{#if $_config.card_showSubTitle}
<p>{sub_title ?? '无日文名称'}</p>
{/if}
<!-- NOTE: tags --> <!-- NOTE: tags -->
<!-- {#if raw_tags} {#if $_config.card_showTag}
<p>{raw_tags}</p> <div class="card-actions justify-end">
<p>{tags}</p> {#if !raw_tags || tags.length == 0}
{/if} --> <!-- <div class="badge badge-outline">Tag 示例</div> -->
<div class="card-actions justify-end"> {:else}
{#if !raw_tags || tags.length == 0} {#each tags as tag}
<!-- <div class="badge badge-outline">tag1</div> --> <div class="tooltip" data-tip={tag}>
<!-- <div class="badge badge-outline">tag2</div> --> <div
{:else} class="badge badge-outline cursor-pointer hover:bg-neutral hover:text-neutral-content"
{#each tags as tag} on:click={p_searchTag(tag)}
<div class="tooltip" data-tip={tag}> on:keypress={() => {}}
<div >
class="badge badge-outline cursor-pointer hover:bg-neutral hover:text-neutral-content" {getTransTag(tag) ?? tag}
on:click={p_searchTag(tag)} </div>
on:keypress={() => {}}
>
{getTransTag(tag) ?? tag}
</div> </div>
</div> {/each}
{/each} {/if}
{/if} </div>
</div> {/if}
</div> </div>
</div> </div>
......
...@@ -39,6 +39,22 @@ export const _theme = persistStore('_theme', "light"); ...@@ -39,6 +39,22 @@ export const _theme = persistStore('_theme', "light");
/** 永久持久化: 环境变量 */ /** 永久持久化: 环境变量 */
export const _env = persistStore('_env', ""); export const _env = persistStore('_env', "");
/** 永久持久化: 配置 */
export const _config = persistStore('_config', {
// 卡片配置 显示副标题
card_showSubTitle: true,
// 卡片配置 显示标签
card_showTag: true,
// 卡片配置 显示语言分类
card_showCateGory: true,
// 分页配置 单页显示(单次瀑布流加载)数量
page_singleNum: 20,
});
/** 定时持久化: 计时 */
export const _timer = persistStore('_timer', "");
/** 定时持久化: 分类 */ /** 定时持久化: 分类 */
export const _category = persistStore('_category', {}); export const _category = persistStore('_category', {});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment