Commit c9770aed authored by KesaubeEire's avatar KesaubeEire

edit & Merge commit '0e55277f'

parents ab4fe607 0e55277f
...@@ -15,8 +15,12 @@ dist-ssr ...@@ -15,8 +15,12 @@ dist-ssr
# 自定义文件夹 # 自定义文件夹
# -- 后端示例文件 # -- 后端示例文件
backEndExample backEndExample
#生成&推送脚本
# 自定义文件
# 生成 & 推送脚本
build-prod.bat build-prod.bat
# 开发服务器代理配置
devServer.config.js
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
......
...@@ -19,15 +19,21 @@ Svelte + daysiUI ...@@ -19,15 +19,21 @@ Svelte + daysiUI
## 开发 ## 开发
```JavaScript
// 在 dev 模式下开发要在根目录(vite.config.js 同级目录)中
// 新建 devServer.config.js
// 改进下面的代码并复制粘贴到这个文件里
// 这个文件子在 .gitignore 中被忽略
// 可以在这里复制名称再新建文件, 不要忘记这步, 非常关键
// 单独提出来的目的是不让开发受这个代理服务器路径变更的影响
export const proxy = "http://192.168.31.103:25702";
```
```bash ```bash
# 安装 # 安装
npm install npm install
# 在 dev 模式下开发要在 vite.config.js 中
# 把 server -> proxy -> /api/ 中的 target
# 改为你能在本地浏览器访问到的 rrpg.duels.link 的网址
# 毕竟我是开了 NGINX 转发开发的, 比较迂回
# 这是 dev 模式开发 # 这是 dev 模式开发
npm run dev:dev npm run dev:dev
...@@ -58,6 +64,7 @@ npm run build:prod ...@@ -58,6 +64,7 @@ npm run build:prod
- [ ] 定时更新 - [ ] 定时更新
- [ ] 卡片展示 - [ ] 卡片展示
- [x] 请求 php - [x] 请求 php
- [x] 瀑布流
- [x] 展示基础卡片 - [x] 展示基础卡片
- [x] 图片 - [x] 图片
- [x] 点击 Cover 预览所有图片 - [x] 点击 Cover 预览所有图片
......
...@@ -3,6 +3,33 @@ ...@@ -3,6 +3,33 @@
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 } from './stores';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { debounceImmediate } from './utils';
/**开发模式下 console.log debug 函数
* @param str
*/
function debugMessage() {
if (process.env.APP_ENV === 'dev') console.log(...str);
}
// -----------------------------
// page & 搜索相关
/**NextPage 指示瀑布流下次应请求的页码数*/
let nextPage = 1;
/**NextPage 指示瀑布流下次应请求的limit数*/
let globalPageLimit = 20;
/**瀑布流是否请求中, 为 true 时不能重复请求*/
let isSearching = false;
/**若isEnd(已经没有新的结果了)则暂停瀑布流请求*/
let isEnd = false;
/**上次搜索完整参数*/
let lastSearchURL;
/**上次搜索类型*/
let lastSearchType = '';
/**上次搜索请求头封装对象*/
let lastSearchParam = null;
// ----------------------------- // -----------------------------
// 各种请求封装头 & 请求函数 // 各种请求封装头 & 请求函数
...@@ -20,10 +47,12 @@ ...@@ -20,10 +47,12 @@
}; };
/**请求封装头 -> 获取所有资料*/ /**请求封装头 -> 获取所有资料*/
const getContentsRequest = { const getContentsRequest = () => {
url: `${$_env}/query.php?action=get`, return {
url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}`,
params: { method: 'GET' } params: { method: 'GET' }
}; };
};
/**请求封装头 -> 搜索对应 Tag (函数形式) /**请求封装头 -> 搜索对应 Tag (函数形式)
* @param {string} tag TAG * @param {string} tag TAG
...@@ -31,7 +60,7 @@ ...@@ -31,7 +60,7 @@
*/ */
const searchTagRequest = tag => { const searchTagRequest = tag => {
return { return {
url: `${$_env}/query.php?action=get&tag=${encodeURIComponent(tag)}`, url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}&tag=${encodeURIComponent(tag)}`,
params: { method: 'GET' } params: { method: 'GET' }
}; };
}; };
...@@ -42,7 +71,7 @@ ...@@ -42,7 +71,7 @@
*/ */
const searchCategoryRequest = category => { const searchCategoryRequest = category => {
return { return {
url: `${$_env}/query.php?action=get&category=${category}`, url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}&category=${category}`,
params: { method: 'GET' } params: { method: 'GET' }
}; };
}; };
...@@ -53,12 +82,11 @@ ...@@ -53,12 +82,11 @@
*/ */
const searchTextRequest = text => { const searchTextRequest = text => {
return { return {
url: `${$_env}/query.php?action=get&search=${encodeURIComponent(text)}`, url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}&search=${encodeURIComponent(text)}`,
params: { method: 'GET' } params: { method: 'GET' }
}; };
}; };
let lastSearchURL;
/**创建请求 fetch 函数 /**创建请求 fetch 函数
* @param {object} param0 参数对象 * @param {object} param0 参数对象
* @param {function} callback 回调函数 * @param {function} callback 回调函数
...@@ -76,7 +104,9 @@ ...@@ -76,7 +104,9 @@
if (params.headers) msg.headers = params.headers; if (params.headers) msg.headers = params.headers;
if (lastSearchURL == url) { if (lastSearchURL == url) {
toast.push('搜索参数重复捏~'); isSearching = false;
if (!isEnd) toast.push('搜索参数重复捏~');
if (process.env.APP_ENV === 'dev') console.log(lastSearchURL, url);
return; return;
} }
lastSearchURL = url; lastSearchURL = url;
...@@ -85,10 +115,6 @@ ...@@ -85,10 +115,6 @@
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
// console.log(data); // console.log(data);
if (!data.length) {
toast.push('没有搜索到东西捏~');
return;
}
// 处理数据 // 处理数据
callback(data); callback(data);
...@@ -97,6 +123,9 @@ ...@@ -97,6 +123,9 @@
// 处理错误 // 处理错误
console.error('网络请求错误:', error); console.error('网络请求错误:', error);
toast.push('网络请求错误'); toast.push('网络请求错误');
})
.finally(() => {
isSearching = false;
}); });
} }
...@@ -106,7 +135,7 @@ ...@@ -106,7 +135,7 @@
/**渲染数据列表*/ /**渲染数据列表*/
let List = []; let List = [];
/**渲染 & 更新视图 /**更新视图 -> 替换元素
* @param data JSON数据 * @param data JSON数据
*/ */
function showList(data) { function showList(data) {
...@@ -116,47 +145,94 @@ ...@@ -116,47 +145,94 @@
// <!-- FIXME: 暂时以这种略微丑陋的方式做切换动画, 可能这就是唯一方案了 --> // <!-- FIXME: 暂时以这种略微丑陋的方式做切换动画, 可能这就是唯一方案了 -->
setTimeout(() => { setTimeout(() => {
List = [...data]; List = [...data];
window.scrollTo(0, 0);
}, 400); }, 400);
} }
/**根据 TAG 搜索游戏 /**更新视图 -> 增加元素 -> 瀑布流
* @param {string} tag TAG * @param data JSON数据
*/ */
export function searchTag(tag) { function appendList(data) {
if (process.env.APP_ENV === 'dev') console.log(tag, encodeURIComponent(tag)); List = [...List, ...data];
createFetch(searchTagRequest(tag), data => { }
/**瀑布流: 延续参数继续搜索下一页*/
function continueLastSearch() {
performSearch(lastSearchType, lastSearchParam, globalPageLimit, nextPage);
}
/**执行搜索主函数
* @param searchType
* @param searchParam
* @param limit
* @param page
*/
function performSearch(searchType, searchParam, limit = 20, page = 1) {
// 瀑布流请求中不能重复请求
if (isSearching) {
return;
}
isSearching = true;
globalPageLimit = limit;
nextPage = page;
lastSearchType = searchType;
lastSearchParam = searchParam;
let requestType;
switch (searchType) {
case 'category':
requestType = searchCategoryRequest;
break;
case 'tag':
requestType = searchTagRequest;
break;
case 'title':
requestType = searchTextRequest;
break;
default:
requestType = getContentsRequest;
break;
}
if (process.env.APP_ENV === 'dev') console.log(requestType(searchParam));
createFetch(requestType(searchParam), data => {
if (process.env.APP_ENV === 'dev') console.log(data); if (process.env.APP_ENV === 'dev') console.log(data);
showList(data); page == 1 ? showList(data) : appendList(data);
if (data.length < globalPageLimit) {
console.log(data.length);
isEnd = true;
toast.push('没有更多数据了捏~');
return;
}
nextPage++;
// console.log(nextPage);
}); });
} }
/**根据 TAG 搜索游戏
* @param {string} tag TAG
*/
export function searchTag(tag, limit = globalPageLimit, page = 1) {
console.log(tag);
performSearch('tag', tag, limit, page);
}
/**根据 category 搜索游戏 /**根据 category 搜索游戏
* @param {string} category category * @param {string} category category
*/ */
export function searchCategory(category) { export function searchCategory(category, limit = globalPageLimit, page = 1) {
if (process.env.APP_ENV === 'dev') console.log(category); performSearch('category', category, limit, page);
createFetch(searchCategoryRequest(category), data => {
if (process.env.APP_ENV === 'dev') console.log(data);
showList(data);
});
} }
/**@var {string} 上次搜索内容*/
let lastSearch;
/**根据 title 搜索游戏 /**根据 title 搜索游戏
* @param {string} title 名称 * @param {string} title 名称
*/ */
export function searchTitle(title) { export function searchTitle(title, limit = globalPageLimit, page = 1) {
if (title === lastSearch) { performSearch('title', title, limit, page);
toast.push('搜索名称重复捏~');
return;
}
lastSearch = title;
if (process.env.APP_ENV === 'dev') console.log('执行搜索:\t', title);
createFetch(searchTextRequest(title), data => {
if (process.env.APP_ENV === 'dev') console.log(data);
showList(data);
});
} }
window.searchTitle = searchTitle; window.searchTitle = searchTitle;
...@@ -164,11 +240,8 @@ ...@@ -164,11 +240,8 @@
* 默认搜索 -> 暂时是全部搜索 * 默认搜索 -> 暂时是全部搜索
* TODO: 全局内容 30分钟 一次缓存在 localstorage 里 * TODO: 全局内容 30分钟 一次缓存在 localstorage 里
*/ */
export function searchDefault() { export function searchDefault(limit = globalPageLimit, page = 1) {
createFetch(getContentsRequest, data => { performSearch('', '', limit, page);
if (process.env.APP_ENV === 'dev') console.log(data);
showList(data);
});
} }
/**获取封面图 /**获取封面图
...@@ -186,17 +259,6 @@ ...@@ -186,17 +259,6 @@
return $_env + '/' + folder.substring(2); return $_env + '/' + folder.substring(2);
} }
// -----------------------------
/**关闭详情*/
function key_closePanels(event) {
if (event.key === 'Escape') {
console.log(event);
// $_iframe_switch = 0;
// $_show_configPanel = false;
$_detailWindow = false;
}
}
// ----------------------------- // -----------------------------
// NOTE: 初始化执行 -> 考虑用 onMount // NOTE: 初始化执行 -> 考虑用 onMount
// 初始化请求 -> 拉取所有分类 // 初始化请求 -> 拉取所有分类
...@@ -205,6 +267,12 @@ ...@@ -205,6 +267,12 @@
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;
if (!data.length) {
toast.push('分类拉取失败了捏~');
} else {
toast.push('分类拉取成功~');
}
}); });
} }
...@@ -214,26 +282,50 @@ ...@@ -214,26 +282,50 @@
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;
if (!data.length) {
toast.push('标签拉取失败了捏~');
} else {
toast.push('标签拉取成功~');
}
}); });
} }
/**对加载下一页进行防抖*/
let debouncedContinue = debounceImmediate(continueLastSearch, 1000);
//拉动到页面底部则更新数据
window.addEventListener('scroll', () => {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
let clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
let scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (clientHeight > 0 && scrollTop > 0 && scrollTop + clientHeight > scrollHeight - 10.0) {
// 加载下一页: page + 1 重复上次搜
// continueLastSearch();
debouncedContinue();
}
});
// 初始化请求 -> 拉取全部条目 // 初始化请求 -> 拉取全部条目
searchDefault(); searchDefault();
</script> </script>
<!-- ----------------------------------------------- DOM ----------------------------------------------- --> <!-- ----------------------------------------------- DOM ----------------------------------------------- -->
<!-- NOTE: svelte 绑定 window -> 关闭详情面板 -->
<svelte:window on:keydown|capture={key_closePanels} />
<!-- Open the modal using ID.showModal() method --> <!-- Open the modal using ID.showModal() method -->
<!-- <button class="btn" onclick="globalModal.showModal()">open modal</button> --> <!-- <button class="btn" onclick="globalModal.showModal()">open modal</button> -->
{#if $_detailWindow} <dialog id="globalModal" class="modal focus:outline-none">
<dialog id="globalModal" class="modal"> {#if $_detailWindow}
<div class="globalModal max-[1024px]:w-[98vw] max-[1024px]:max-w-[98vw]" transition:fade={{ delay: 200, duration: 1000 }}> <div class="globalModal max-[1024px]:w-[98vw] max-[1024px]:max-w-[98vw]" transition:fade={{ delay: 0, duration: 500 }}>
<!-- NOTE: 按钮退出详情 -->
<form method="dialog"> <form method="dialog">
<button class="btn btn-sm round-box btn-ghost absolute right-2 top-2">✕</button> <button
on:click={() => {
$_detailWindow = false;
}}
class="btn btn-sm round-box btn-ghost absolute right-2 top-2">✕</button
>
</form> </form>
<!-- NOTE: Transition --> <!-- NOTE: Transition -->
{#if $_detailPics.length} {#if $_detailPics.length}
...@@ -259,11 +351,16 @@ ...@@ -259,11 +351,16 @@
</div> </div>
{/if} {/if}
</div> </div>
<!-- NOTE: 边框退出详情 -->
<form method="dialog" class="modal-backdrop"> <form method="dialog" class="modal-backdrop">
<button>close</button> <button
on:click={() => {
$_detailWindow = false;
}}
/>
</form> </form>
</dialog> {/if}
{/if} </dialog>
{#if List.length} {#if List.length}
<div class="cardContainer flex flex-wrap justify-evenly gap-4 my-3" transition:fade={{ delay: 0, duration: 300 }}> <div class="cardContainer flex flex-wrap justify-evenly gap-4 my-3" transition:fade={{ delay: 0, duration: 300 }}>
......
/** 防抖函数 -> 立即执行
* @param {function} func 操作函数
* @param {number} delay 延迟
* @returns
*/
export function debounceImmediate(func, delay) {
let timeout;
return function () {
const immediate = !timeout;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
// func.apply(this, arguments);
timeout = null;
}, delay);
if (immediate) {
func.apply(this, arguments);
}
};
}
\ No newline at end of file
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte'; import { svelte } from '@sveltejs/vite-plugin-svelte';
import { proxy } from './devServer.config'
import SetEnvByCommandArg, { getCommandArgv } from 'vite-plugin-env-command'; import SetEnvByCommandArg, { getCommandArgv } from 'vite-plugin-env-command';
...@@ -16,7 +17,8 @@ export default defineConfig({ ...@@ -16,7 +17,8 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
"/api/": { "/api/": {
target: "http://192.168.31.103:25702", // NOTE: 在 ./devServer.config.js 文件把 proxy 后的 ip 改为你的浏览器内能访问到 rrpg.duels.link 的链接
target: proxy,
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""), rewrite: (path) => path.replace(/^\/api/, ""),
}, },
......
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