Commit 03b382a9 authored by KesaubeEire's avatar KesaubeEire

feat: 配置面板.

parent 254372ce
......@@ -61,12 +61,12 @@ npm run build:prod
- [ ] 历史玩过的游戏
- [ ] 收藏的游戏
- [ ] 允许玩家给游戏写(本地可见的)备注,显示在标签上方,日文名下方
- [ ] TODO: 配置面板
- [ ] 卡片相关
- [ ] page 相关 (num & size)
- [ ] TODO: 更新数据 (TAG Category 游戏)
- [ ] 主动更新按钮
- [ ] 定时更新
- [x] 配置面板
- [x] 卡片相关
- [x] page 相关 (num & size)
- [x] 更新数据 (TAG Category 游戏)
- [x] 主动更新按钮
- [x] 定时更新
- [ ] TODO: 重构云存档系统
- [ ] 统一界面风格
- [ ] 既有功能的继承
......
......@@ -244,7 +244,7 @@
<!-- NOTE: 配置 -->
<MenuWrapNav title="配置" tailwind="w-72 max-h-[70vh]" tip="自定义适合的配置">
<MenuConfig />
<MenuConfig {contentDom} />
</MenuWrapNav>
</ul>
</div>
......@@ -308,7 +308,7 @@
<!-- NOTE: 配置 -->
<MenuWrapSide title="配置">
<MenuConfig />
<MenuConfig {contentDom} />
</MenuWrapSide>
</ul>
</div>
......
<script>
import Card from './components/card.svelte';
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 { debounceImmediate } from './utils';
......@@ -12,13 +12,17 @@
if (process.env.APP_ENV === 'dev') console.log(...str);
}
// -----------------------------
/**渲染数据列表*/
let List = [];
// -----------------------------
// page & 搜索相关
/**NextPage 指示瀑布流下次应请求的页码数*/
let nextPage = 1;
/**NextPage 指示瀑布流下次应请求的limit数*/
let globalPageLimit = 20;
let globalPageLimit = $_config.page_singleNum;
/**瀑布流是否请求中, 为 true 时不能重复请求*/
let isSearching = false;
/**若isEnd(已经没有新的结果了)则暂停瀑布流请求*/
......@@ -35,7 +39,16 @@
const distance = 10;
// -----------------------------
// 各种请求封装头 & 请求函数
// 本地配置变量响应式变化
$: {
if (globalPageLimit != $_config.page_singleNum) {
globalPageLimit = $_config.page_singleNum;
toast.push('单页显示(单次瀑布流加载)数量 变化, 请刷新页面.');
}
}
// -----------------------------
// 各种请求封装头
/**请求封装头 -> 获取语言类别*/
const getLanguageCategory = {
......@@ -90,7 +103,10 @@
};
};
/**创建请求 fetch 函数
// -----------------------------
// 请求函数
/**创建请求底层 fetch 函数
* @param {object} param0 参数对象
* @param {function} callback 回调函数
*/
......@@ -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 searchParam
......@@ -228,6 +212,14 @@
});
}
/**瀑布流: 延续参数继续搜索下一页*/
function continueLastSearch() {
performSearch(lastSearchType, lastSearchParam, globalPageLimit, nextPage);
}
// -----------------------------
// 对外请求函数
/**根据 TAG 搜索游戏
* @param {string} tag TAG
*/
......@@ -251,34 +243,15 @@
}
window.searchTitle = searchTitle;
/**
* 默认搜索 -> 暂时是全部搜索
/**默认搜索 -> 暂时是全部搜索
* TODO: 全局内容 30分钟 一次缓存在 localstorage 里
*/
export function searchDefault(limit = globalPageLimit, page = 1) {
performSearch('', '', limit, page);
}
/**获取封面图
* @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);
}
// -----------------------------
// NOTE: 初始化执行 -> 考虑用 onMount
// 初始化请求 -> 拉取所有分类
// TODO: 搞个记时, 每天一刷 & 做一个主动更新的按钮
if (!$_category.length) {
/**拉取静态资源: Category */
export function fetchStaticCategory() {
createFetch(getLanguageCategory, data => {
if (process.env.APP_ENV === 'dev') console.log(data);
$_category = data;
......@@ -291,9 +264,8 @@
});
}
// 初始化请求 -> 拉取tag翻译
// TODO: 搞个记时, 每天一刷 & 做一个主动更新的按钮
if (!$_tagTrans.length) {
/**拉取静态资源: Tag */
export function fetchStaticTag() {
createFetch(getTranslatedTag, data => {
if (process.env.APP_ENV === 'dev') console.log(data);
$_tagTrans = data;
......@@ -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);
......
<script>
let lastUpdatedTimeCategory;
let lastUpdatedTimeTag;
import { onMount } from 'svelte';
import { _config, _timer } from '../stores';
function expiredTimeCategory() {
return new Date().getHours();
}
function expiredTimeTag() {
return new Date().getHours();
export let contentDom;
/**显示距离上次时间戳的时长*/
let ExpiredHours = '??';
/**显示距离上次时间戳的时长*/
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>
<li>
......@@ -17,15 +28,19 @@
<div class="flex flex-col">
<div class="form-control w-60">
<label class="label cursor-pointer w-full inline-flex justify-between">
<span class="label-text">分类: 距离上次 {expiredTimeCategory()} 小时</span>
<button class="btn btn-xs btn-neutral">更新</button>
</label>
</div>
<div class="form-control w-60">
<label class="label cursor-pointer flex justify-between">
<span class="label-text">标签: 距离上次 {expiredTimeTag()} 小时</span>
<button class="btn btn-xs btn-neutral">更新</button>
<span class="label-text">分类&标签: {ExpiredHours} 小时前</span>
<button
class="btn btn-xs btn-neutral"
on:click={() => {
// 拉取数据
contentDom.fetchStaticCategory();
contentDom.fetchStaticTag();
// 更新时间戳
$_timer = new Date().getTime();
// 更新显示
ExpiredHours = calcTimerExpiredHours();
}}>更新</button
>
</label>
</div>
</div>
......@@ -38,16 +53,25 @@
<div class="flex flex-col">
<div class="form-control w-60">
<label class="label cursor-pointer w-full inline-flex justify-between">
<span class="label-text">显示副标题</span>
<input type="checkbox" class="toggle" checked />
<span class="label-text">显示语言分类</span>
<input type="checkbox" bind:checked={$_config.card_showCateGory} 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" class="toggle" checked />
</label>
<div class="flex flex-col">
<div class="form-control w-60">
<label class="label cursor-pointer w-full inline-flex justify-between">
<span class="label-text">显示副标题</span>
<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>
</ul>
......@@ -59,15 +83,15 @@
<div class="flex items-center justify-between">
<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">
<!-- <span>|</span> -->
<!-- <span>|</span> -->
<!-- <span>|</span> -->
<!-- <span>|</span> -->
<!-- <span>|</span> -->
{#each [1, 2, 3, 4, 5] as num}
<span>{num * 10}</span>
{#each [10, 20, 30, 40, 50] as num}
<span>{num}</span>
{/each}
</div>
</div>
......
<script>
import { toast } from '@zerodevx/svelte-toast';
import { _detailPics, _detailWindow, _tagTrans } from '../stores';
import { _detailPics, _detailWindow, _tagTrans, _config } from '../stores';
/**父属性: 主标题*/
export let title;
......@@ -110,14 +110,16 @@
<div class="card-body justify-between">
<h2 class="card-title block text-lg">
<!-- NOTE: 游戏类别 -->
<div
class="badge badge-secondary m-auto cursor-pointer hover:badge-neutral"
style="height: inherit;line-height: inherit;"
on:click={p_searchCategory(category)}
on:keypress={() => {}}
>
{language ?? '示例'}
</div>
{#if $_config.card_showCateGory}
<div
class="badge badge-secondary m-auto cursor-pointer hover:badge-neutral"
style="height: inherit;line-height: inherit;"
on:click={p_searchCategory(category)}
on:keypress={() => {}}
>
{language ?? '示例'}
</div>
{/if}
<!-- NOTE: 游戏名称 -->
<a class="hover:link" href={folder} target="_blank">
{#if title}
......@@ -127,31 +129,31 @@
{/if}
</a>
</h2>
<p>{sub_title ?? '无日文名称'}</p>
<!-- NOTE: 游戏副标题 -> (日文)原名 -->
{#if $_config.card_showSubTitle}
<p>{sub_title ?? '无日文名称'}</p>
{/if}
<!-- NOTE: tags -->
<!-- {#if raw_tags}
<p>{raw_tags}</p>
<p>{tags}</p>
{/if} -->
<div class="card-actions justify-end">
{#if !raw_tags || tags.length == 0}
<!-- <div class="badge badge-outline">tag1</div> -->
<!-- <div class="badge badge-outline">tag2</div> -->
{:else}
{#each tags as tag}
<div class="tooltip" data-tip={tag}>
<div
class="badge badge-outline cursor-pointer hover:bg-neutral hover:text-neutral-content"
on:click={p_searchTag(tag)}
on:keypress={() => {}}
>
{getTransTag(tag) ?? tag}
{#if $_config.card_showTag}
<div class="card-actions justify-end">
{#if !raw_tags || tags.length == 0}
<!-- <div class="badge badge-outline">Tag 示例</div> -->
{:else}
{#each tags as tag}
<div class="tooltip" data-tip={tag}>
<div
class="badge badge-outline cursor-pointer hover:bg-neutral hover:text-neutral-content"
on:click={p_searchTag(tag)}
on:keypress={() => {}}
>
{getTransTag(tag) ?? tag}
</div>
</div>
</div>
{/each}
{/if}
</div>
{/each}
{/if}
</div>
{/if}
</div>
</div>
......
......@@ -39,6 +39,22 @@ export const _theme = persistStore('_theme', "light");
/** 永久持久化: 环境变量 */
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', {});
......
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