mirror of
https://ghproxy.com/https://github.com/StreakingMan/solvable-sheep-game
synced 2025-05-23 05:48:15 +08:00
feat: 接入Bmob储存自定义配置
This commit is contained in:
parent
e35ddfa44e
commit
f6681cabb0
2
.env
Normal file
2
.env
Normal file
|
@ -0,0 +1,2 @@
|
|||
VITE_BMOB_SECRETKEY=yourBmobAppSecretKey
|
||||
VITE_BMOB_SECCODE=youBmobAppSecurityCode
|
35
index.html
35
index.html
|
@ -22,6 +22,10 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
// vite没有global,手动声明
|
||||
var global = global || window;
|
||||
</script>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
<script
|
||||
async
|
||||
|
@ -30,19 +34,26 @@
|
|||
<script async>
|
||||
// 如果您基于此项目二创,可以删除以下代码
|
||||
// 否则请标明原仓库地址
|
||||
setTimeout(()=>{
|
||||
const {hostname} = location
|
||||
if(hostname!=='localhost'&&!hostname.endsWith('streakingman.com')){
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href','https://github.com/StreakingMan/solvable-sheep-game')
|
||||
a.setAttribute('target','_blank')
|
||||
a.innerText='本项目仅供交流,禁止商业用途,点击查看原github仓库'
|
||||
const p = document.createElement('p')
|
||||
p.style.textAlign = 'center'
|
||||
p.append(a)
|
||||
document.body.prepend(p)
|
||||
setTimeout(() => {
|
||||
const { hostname } = location;
|
||||
if (
|
||||
hostname !== 'localhost' &&
|
||||
!hostname.endsWith('streakingman.com')
|
||||
) {
|
||||
const a = document.createElement('a');
|
||||
a.setAttribute(
|
||||
'href',
|
||||
'https://github.com/StreakingMan/solvable-sheep-game'
|
||||
);
|
||||
a.setAttribute('target', '_blank');
|
||||
a.innerText =
|
||||
'本项目仅供交流,禁止商业用途,点击查看原github仓库';
|
||||
const p = document.createElement('p');
|
||||
p.style.textAlign = 'center';
|
||||
p.append(a);
|
||||
document.body.prepend(p);
|
||||
}
|
||||
},5000)
|
||||
}, 5000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.3.2",
|
||||
"hydrogen-js-sdk": "^2.3.10",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
|
|
30
src/App.tsx
30
src/App.tsx
|
@ -9,7 +9,7 @@ import React, {
|
|||
import './App.scss';
|
||||
import { GithubIcon } from './components/GithubIcon';
|
||||
import {
|
||||
parsePathCustomTheme,
|
||||
parsePathCustomThemeId,
|
||||
parsePathThemeName,
|
||||
randomString,
|
||||
waitTimeout,
|
||||
|
@ -24,6 +24,7 @@ import { BeiAn } from './components/BeiAn';
|
|||
import { Info } from './components/Info';
|
||||
import { owTheme } from './themes/ow';
|
||||
import { ConfigDialog } from './components/ConfigDialog';
|
||||
import Bmob from 'hydrogen-js-sdk';
|
||||
|
||||
// 内置主题
|
||||
const builtInThemes: Theme<any>[] = [
|
||||
|
@ -159,7 +160,7 @@ const Symbol: FC<SymbolProps> = ({ x, y, icon, isCover, status, onClick }) => {
|
|||
>
|
||||
<div
|
||||
className="symbol-inner"
|
||||
style={{ opacity: isCover ? 0.5 : 1 }}
|
||||
style={{ opacity: isCover ? 0.4 : 1 }}
|
||||
>
|
||||
{typeof icon.content === 'string' ? (
|
||||
icon.content.startsWith('http') ? (
|
||||
|
@ -180,7 +181,7 @@ const Symbol: FC<SymbolProps> = ({ x, y, icon, isCover, status, onClick }) => {
|
|||
|
||||
// 从url初始化主题
|
||||
const themeFromPath: string = parsePathThemeName(location.href);
|
||||
const customThemeFromPath = parsePathCustomTheme(location.href);
|
||||
const customThemeIdFromPath = parsePathCustomThemeId(location.href);
|
||||
|
||||
const App: FC = () => {
|
||||
const [curTheme, setCurTheme] = useState<Theme<any>>(defaultTheme);
|
||||
|
@ -216,10 +217,25 @@ const App: FC = () => {
|
|||
|
||||
// 初始化主题
|
||||
useEffect(() => {
|
||||
if (customThemeFromPath) {
|
||||
if (customThemeIdFromPath) {
|
||||
// 自定义主题
|
||||
setThemes([...themes, customThemeFromPath]);
|
||||
setCurTheme(customThemeFromPath);
|
||||
Bmob.Query('config')
|
||||
.get(customThemeIdFromPath)
|
||||
.then((res) => {
|
||||
// @ts-ignore
|
||||
const { content } = res;
|
||||
|
||||
try {
|
||||
const customTheme = JSON.parse(content);
|
||||
setThemes([...themes, customTheme]);
|
||||
setCurTheme(customTheme);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
} else if (themeFromPath) {
|
||||
// 内置主题
|
||||
setCurTheme(
|
||||
|
@ -240,7 +256,7 @@ const App: FC = () => {
|
|||
}
|
||||
restart();
|
||||
// 更改路径query
|
||||
if (customThemeFromPath) return;
|
||||
if (customThemeIdFromPath) return;
|
||||
history.pushState(
|
||||
{},
|
||||
curTheme.title,
|
||||
|
|
|
@ -4,6 +4,7 @@ import classNames from 'classnames';
|
|||
import { Icon, Sound, Theme } from '../themes/interface';
|
||||
import { defaultSounds } from '../themes/default';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import Bmob from 'hydrogen-js-sdk';
|
||||
|
||||
const STORAGEKEY = 'customTheme';
|
||||
let storageTheme: Theme<any>;
|
||||
|
@ -78,7 +79,7 @@ export const ConfigDialog: FC<{
|
|||
|
||||
// 音效保存
|
||||
const saveSound = (sound: Sound, idx?: number) => {
|
||||
if (!sound.src.startsWith('http')) return '请输入http/https链接';
|
||||
if (!sound.src.startsWith('https')) return '请输入https链接';
|
||||
const newSounds = sounds.slice();
|
||||
const newIcons = icons.slice();
|
||||
if (idx != null) {
|
||||
|
@ -123,9 +124,9 @@ export const ConfigDialog: FC<{
|
|||
const saveIcon = (icon: Icon, idx?: number) => {
|
||||
if (
|
||||
typeof icon.content !== 'string' ||
|
||||
!icon.content?.startsWith('http')
|
||||
!icon.content?.startsWith('https')
|
||||
)
|
||||
return '请输入http/https链接';
|
||||
return '请输入https链接';
|
||||
const newIcons = icons.slice();
|
||||
if (idx != null) {
|
||||
// 编辑
|
||||
|
@ -202,8 +203,8 @@ export const ConfigDialog: FC<{
|
|||
// 生成主题
|
||||
const generateTheme: () => Promise<Theme<any>> = async () => {
|
||||
const { title, desc, bgm } = customThemeInfo;
|
||||
if (bgm && bgm.startsWith('http'))
|
||||
return Promise.reject('bgm请输入http/https链接');
|
||||
if (bgm && bgm.startsWith('https'))
|
||||
return Promise.reject('bgm请输入https链接');
|
||||
if (!title) return Promise.reject('请填写标题');
|
||||
if (icons.length !== 10) return Promise.reject('图片素材需要提供10张');
|
||||
|
||||
|
@ -258,10 +259,18 @@ export const ConfigDialog: FC<{
|
|||
.then((theme) => {
|
||||
const stringify = JSON.stringify(theme);
|
||||
localStorage.setItem(STORAGEKEY, stringify);
|
||||
const link = `${
|
||||
location.origin
|
||||
}?customTheme=${encodeURIComponent(stringify)}`;
|
||||
setGenLink(link);
|
||||
const query = Bmob.Query('config');
|
||||
query.set('content', stringify);
|
||||
query
|
||||
.save()
|
||||
.then((res) => {
|
||||
//@ts-ignore
|
||||
const link = `${location.origin}?customTheme=${res.objectId}`;
|
||||
setGenLink(link);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
setConfigError(e);
|
||||
|
@ -302,8 +311,8 @@ export const ConfigDialog: FC<{
|
|||
)}
|
||||
>
|
||||
<p>
|
||||
目前自定义仅支持配置链接,可网上自行搜索素材,或者将自己处理好的素材上传第三方存储服务上再复制外链,安利一波七牛云(七牛云打钱)对象存储,
|
||||
白嫖额度基本够用(<strong>但还是需要注意压缩素材</strong>)
|
||||
目前自定义仅支持配置https链接,可网上自行搜索素材复制链接,或者将自己处理好的素材上传第三方存储服务/图床上再复制外链
|
||||
(想白嫖的话自行搜索【免费图床】【免费对象存储】【免费mp3外链】等)
|
||||
</p>
|
||||
|
||||
{/*基本配置*/}
|
||||
|
@ -339,7 +348,7 @@ export const ConfigDialog: FC<{
|
|||
背景音乐:
|
||||
<input
|
||||
value={customThemeInfo.bgm}
|
||||
placeholder="可选 http(s)://example.com/src.audioOrImage"
|
||||
placeholder="可选 https://example.com/src.audioOrImage"
|
||||
className="flex-grow"
|
||||
onChange={(e) =>
|
||||
setCustomThemeInfo({
|
||||
|
@ -373,7 +382,7 @@ export const ConfigDialog: FC<{
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
<h4>图片素材 {icons.length}/10</h4>
|
||||
<h4>图片素材 {icons.length}/10 </h4>
|
||||
<div className="flex-container">
|
||||
{icons.map((icon, idx) => (
|
||||
<div className="flex-container flex-column" key={icon.name}>
|
||||
|
@ -440,7 +449,7 @@ export const ConfigDialog: FC<{
|
|||
<input
|
||||
ref={(ref) => ref && (inputRefMap.current.link = ref)}
|
||||
className="flex-grow"
|
||||
placeholder="http(s)://example.com/src.audioOrImage"
|
||||
placeholder="https://example.com/src.audioOrImage"
|
||||
onChange={(e) =>
|
||||
setAddDialog({
|
||||
...addDialog,
|
||||
|
|
|
@ -3,6 +3,14 @@ import ReactDOM from 'react-dom/client';
|
|||
import App from './App';
|
||||
import './styles/global.scss';
|
||||
import './styles/utils.scss';
|
||||
import Bmob from 'hydrogen-js-sdk';
|
||||
|
||||
// Bmob初始化
|
||||
// @ts-ignore
|
||||
Bmob.initialize(
|
||||
import.meta.env.VITE_BMOB_SECRETKEY,
|
||||
import.meta.env.VITE_BMOB_SECCODE
|
||||
);
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
|
|
18
src/utils.ts
18
src/utils.ts
|
@ -26,22 +26,8 @@ export const parsePathThemeName: (url: string) => string = (url) => {
|
|||
};
|
||||
|
||||
// 从url解析自定义主题JSON
|
||||
export const parsePathCustomTheme: (url: string) => Theme<string> | null = (
|
||||
url
|
||||
) => {
|
||||
export const parsePathCustomThemeId: (url: string) => string = (url) => {
|
||||
const urlObj = new URL(url);
|
||||
const params = urlObj.searchParams;
|
||||
const customThemeJsonString = params.get('customTheme');
|
||||
if (!customThemeJsonString) return null;
|
||||
try {
|
||||
const parseTheme = JSON.parse(
|
||||
decodeURIComponent(customThemeJsonString)
|
||||
);
|
||||
// TODO 解析内容校验
|
||||
console.log(parseTheme);
|
||||
return parseTheme;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return null;
|
||||
}
|
||||
return params.get('customTheme') || '';
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user