feat: 接入Bmob储存自定义配置

This commit is contained in:
streakingman 2022-09-25 02:56:32 +08:00
parent e35ddfa44e
commit f6681cabb0
8 changed files with 2064 additions and 75 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
VITE_BMOB_SECRETKEY=yourBmobAppSecretKey
VITE_BMOB_SECCODE=youBmobAppSecurityCode

View File

@ -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>

View File

@ -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"

View File

@ -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,

View File

@ -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,

View File

@ -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>

View File

@ -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') || '';
};

2008
yarn.lock

File diff suppressed because it is too large Load Diff