Commit c9770aed authored by KesaubeEire's avatar KesaubeEire

edit & Merge commit '0e55277f'

parents ab4fe607 0e55277f
......@@ -15,8 +15,12 @@ dist-ssr
# 自定义文件夹
# -- 后端示例文件
backEndExample
#生成&推送脚本
# 自定义文件
# 生成 & 推送脚本
build-prod.bat
# 开发服务器代理配置
devServer.config.js
# Editor directories and files
.vscode/*
......
......@@ -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
# 安装
npm install
# 在 dev 模式下开发要在 vite.config.js 中
# 把 server -> proxy -> /api/ 中的 target
# 改为你能在本地浏览器访问到的 rrpg.duels.link 的网址
# 毕竟我是开了 NGINX 转发开发的, 比较迂回
# 这是 dev 模式开发
npm run dev:dev
......@@ -58,6 +64,7 @@ npm run build:prod
- [ ] 定时更新
- [ ] 卡片展示
- [x] 请求 php
- [x] 瀑布流
- [x] 展示基础卡片
- [x] 图片
- [x] 点击 Cover 预览所有图片
......
......@@ -3,6 +3,33 @@
import { SvelteToast, toast } from '@zerodevx/svelte-toast';
import { _category, _detailWindow, _env, _tagTrans, _detailPics } from './stores';
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,9 +47,11 @@
};
/**请求封装头 -> 获取所有资料*/
const getContentsRequest = {
url: `${$_env}/query.php?action=get`,
params: { method: 'GET' }
const getContentsRequest = () => {
return {
url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}`,
params: { method: 'GET' }
};
};
/**请求封装头 -> 搜索对应 Tag (函数形式)
......@@ -31,7 +60,7 @@
*/
const searchTagRequest = tag => {
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' }
};
};
......@@ -42,7 +71,7 @@
*/
const searchCategoryRequest = category => {
return {
url: `${$_env}/query.php?action=get&category=${category}`,
url: `${$_env}/query.php?action=get&limit=${globalPageLimit}&page=${nextPage}&category=${category}`,
params: { method: 'GET' }
};
};
......@@ -53,12 +82,11 @@
*/
const searchTextRequest = text => {
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' }
};
};
let lastSearchURL;
/**创建请求 fetch 函数
* @param {object} param0 参数对象
* @param {function} callback 回调函数
......@@ -76,7 +104,9 @@
if (params.headers) msg.headers = params.headers;
if (lastSearchURL == url) {
toast.push('搜索参数重复捏~');
isSearching = false;
if (!isEnd) toast.push('搜索参数重复捏~');
if (process.env.APP_ENV === 'dev') console.log(lastSearchURL, url);
return;
}
lastSearchURL = url;
......@@ -85,10 +115,6 @@
.then(response => response.json())
.then(data => {
// console.log(data);
if (!data.length) {
toast.push('没有搜索到东西捏~');
return;
}
// 处理数据
callback(data);
......@@ -97,6 +123,9 @@
// 处理错误
console.error('网络请求错误:', error);
toast.push('网络请求错误');
})
.finally(() => {
isSearching = false;
});
}
......@@ -106,7 +135,7 @@
/**渲染数据列表*/
let List = [];
/**渲染 & 更新视图
/**更新视图 -> 替换元素
* @param data JSON数据
*/
function showList(data) {
......@@ -116,47 +145,94 @@
// <!-- FIXME: 暂时以这种略微丑陋的方式做切换动画, 可能这就是唯一方案了 -->
setTimeout(() => {
List = [...data];
window.scrollTo(0, 0);
}, 400);
}
/**根据 TAG 搜索游戏
* @param {string} tag TAG
/**更新视图 -> 增加元素 -> 瀑布流
* @param data JSON数据
*/
export function searchTag(tag) {
if (process.env.APP_ENV === 'dev') console.log(tag, encodeURIComponent(tag));
createFetch(searchTagRequest(tag), data => {
function appendList(data) {
List = [...List, ...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);
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 搜索游戏
* @param {string} category category
*/
export function searchCategory(category) {
if (process.env.APP_ENV === 'dev') console.log(category);
createFetch(searchCategoryRequest(category), data => {
if (process.env.APP_ENV === 'dev') console.log(data);
showList(data);
});
export function searchCategory(category, limit = globalPageLimit, page = 1) {
performSearch('category', category, limit, page);
}
/**@var {string} 上次搜索内容*/
let lastSearch;
/**根据 title 搜索游戏
* @param {string} title 名称
*/
export function searchTitle(title) {
if (title === lastSearch) {
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);
});
export function searchTitle(title, limit = globalPageLimit, page = 1) {
performSearch('title', title, limit, page);
}
window.searchTitle = searchTitle;
......@@ -164,11 +240,8 @@
* 默认搜索 -> 暂时是全部搜索
* TODO: 全局内容 30分钟 一次缓存在 localstorage 里
*/
export function searchDefault() {
createFetch(getContentsRequest, data => {
if (process.env.APP_ENV === 'dev') console.log(data);
showList(data);
});
export function searchDefault(limit = globalPageLimit, page = 1) {
performSearch('', '', limit, page);
}
/**获取封面图
......@@ -186,17 +259,6 @@
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
// 初始化请求 -> 拉取所有分类
......@@ -205,6 +267,12 @@
createFetch(getLanguageCategory, data => {
if (process.env.APP_ENV === 'dev') console.log(data);
$_category = data;
if (!data.length) {
toast.push('分类拉取失败了捏~');
} else {
toast.push('分类拉取成功~');
}
});
}
......@@ -214,26 +282,50 @@
createFetch(getTranslatedTag, data => {
if (process.env.APP_ENV === 'dev') console.log(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();
</script>
<!-- ----------------------------------------------- DOM ----------------------------------------------- -->
<!-- NOTE: svelte 绑定 window -> 关闭详情面板 -->
<svelte:window on:keydown|capture={key_closePanels} />
<!-- Open the modal using ID.showModal() method -->
<!-- <button class="btn" onclick="globalModal.showModal()">open modal</button> -->
{#if $_detailWindow}
<dialog id="globalModal" class="modal">
<div class="globalModal max-[1024px]:w-[98vw] max-[1024px]:max-w-[98vw]" transition:fade={{ delay: 200, duration: 1000 }}>
<dialog id="globalModal" class="modal focus:outline-none">
{#if $_detailWindow}
<div class="globalModal max-[1024px]:w-[98vw] max-[1024px]:max-w-[98vw]" transition:fade={{ delay: 0, duration: 500 }}>
<!-- NOTE: 按钮退出详情 -->
<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>
<!-- NOTE: Transition -->
{#if $_detailPics.length}
......@@ -259,11 +351,16 @@
</div>
{/if}
</div>
<!-- NOTE: 边框退出详情 -->
<form method="dialog" class="modal-backdrop">
<button>close</button>
<button
on:click={() => {
$_detailWindow = false;
}}
/>
</form>
</dialog>
{/if}
{/if}
</dialog>
{#if List.length}
<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 { svelte } from '@sveltejs/vite-plugin-svelte';
import { proxy } from './devServer.config'
import SetEnvByCommandArg, { getCommandArgv } from 'vite-plugin-env-command';
......@@ -16,7 +17,8 @@ export default defineConfig({
server: {
proxy: {
"/api/": {
target: "http://192.168.31.103:25702",
// NOTE: 在 ./devServer.config.js 文件把 proxy 后的 ip 改为你的浏览器内能访问到 rrpg.duels.link 的链接
target: proxy,
changeOrigin: true,
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