add 添加 4 种道具
This commit is contained in:
parent
200b2a47d0
commit
9b8077c536
25
src/App.vue
25
src/App.vue
@ -3,20 +3,6 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
|
||||||
鱼了个鱼 ©2022 by
|
|
||||||
<a href="https://github.com/liyupi" target="_blank" style="color: #fff">
|
|
||||||
程序员鱼皮
|
|
||||||
</a>
|
|
||||||
|
|
|
||||||
<a
|
|
||||||
href="https://github.com/liyupi/yulegeyu"
|
|
||||||
target="_blank"
|
|
||||||
style="color: #fff"
|
|
||||||
>
|
|
||||||
代码开源
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts"></script>
|
<script setup lang="ts"></script>
|
||||||
@ -27,15 +13,4 @@
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
|
||||||
background: rgba(0, 0, 0, 0.6);
|
|
||||||
color: #fff;
|
|
||||||
padding: 12px;
|
|
||||||
text-align: center;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
120
src/core/game.ts
120
src/core/game.ts
@ -24,6 +24,7 @@ const useGame = () => {
|
|||||||
const currSlotNum = ref(0);
|
const currSlotNum = ref(0);
|
||||||
|
|
||||||
// 保存所有块(包括随机块)
|
// 保存所有块(包括随机块)
|
||||||
|
const allBlocks: BlockType[] = [];
|
||||||
const blockData: Record<number, BlockType> = {};
|
const blockData: Record<number, BlockType> = {};
|
||||||
|
|
||||||
// 总块数
|
// 总块数
|
||||||
@ -43,6 +44,9 @@ const useGame = () => {
|
|||||||
// 保存整个 "棋盘" 的每个格子状态(下标为格子起始点横纵坐标)
|
// 保存整个 "棋盘" 的每个格子状态(下标为格子起始点横纵坐标)
|
||||||
let chessBoard: ChessBoardUnitType[][] = [];
|
let chessBoard: ChessBoardUnitType[][] = [];
|
||||||
|
|
||||||
|
// 操作历史(存储点击的块)
|
||||||
|
let opHistory: BlockType[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化指定大小的棋盘
|
* 初始化指定大小的棋盘
|
||||||
* @param width
|
* @param width
|
||||||
@ -80,9 +84,12 @@ const useGame = () => {
|
|||||||
console.log("块数单位", blockNumUnit);
|
console.log("块数单位", blockNumUnit);
|
||||||
|
|
||||||
// 随机生成的总块数
|
// 随机生成的总块数
|
||||||
const totalRandomBlockNum = gameConfig.randomBlocks.reduce((pre, curr) => {
|
const totalRandomBlockNum = gameConfig.randomBlocks.reduce(
|
||||||
|
(pre: number, curr: number) => {
|
||||||
return pre + curr;
|
return pre + curr;
|
||||||
}, 0);
|
},
|
||||||
|
0
|
||||||
|
);
|
||||||
console.log("随机生成的总块数", totalRandomBlockNum);
|
console.log("随机生成的总块数", totalRandomBlockNum);
|
||||||
|
|
||||||
// 需要的最小块数
|
// 需要的最小块数
|
||||||
@ -112,7 +119,6 @@ const useGame = () => {
|
|||||||
const randomAnimalBlocks = _.shuffle(animalBlocks);
|
const randomAnimalBlocks = _.shuffle(animalBlocks);
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
const allBlocks: BlockType[] = [];
|
|
||||||
for (let i = 0; i < totalBlockNum; i++) {
|
for (let i = 0; i < totalBlockNum; i++) {
|
||||||
const newBlock = {
|
const newBlock = {
|
||||||
id: i,
|
id: i,
|
||||||
@ -130,7 +136,7 @@ const useGame = () => {
|
|||||||
|
|
||||||
// 3. 计算随机生成的块
|
// 3. 计算随机生成的块
|
||||||
const randomBlocks: BlockType[][] = [];
|
const randomBlocks: BlockType[][] = [];
|
||||||
gameConfig.randomBlocks.forEach((randomBlock, idx) => {
|
gameConfig.randomBlocks.forEach((randomBlock: number, idx: number) => {
|
||||||
randomBlocks[idx] = [];
|
randomBlocks[idx] = [];
|
||||||
for (let i = 0; i < randomBlock; i++) {
|
for (let i = 0; i < randomBlock; i++) {
|
||||||
randomBlocks[idx].push(allBlocks[pos]);
|
randomBlocks[idx].push(allBlocks[pos]);
|
||||||
@ -271,15 +277,15 @@ const useGame = () => {
|
|||||||
/**
|
/**
|
||||||
* 点击块事件
|
* 点击块事件
|
||||||
* @param block
|
* @param block
|
||||||
* @param e
|
|
||||||
* @param randomIdx 随机区域下标,>= 0 表示点击的是随机块
|
* @param randomIdx 随机区域下标,>= 0 表示点击的是随机块
|
||||||
|
* @param force 强制移除
|
||||||
*/
|
*/
|
||||||
const doClickBlock = (block: BlockType, e: Event, randomIdx = -1) => {
|
const doClickBlock = (block: BlockType, randomIdx = -1, force = false) => {
|
||||||
// 已经输了 / 已经被点击 / 有上层块,不能再点击
|
// 已经输了 / 已经被点击 / 有上层块,不能再点击
|
||||||
if (
|
if (
|
||||||
currSlotNum.value >= gameConfig.slotNum ||
|
currSlotNum.value >= gameConfig.slotNum ||
|
||||||
block.status !== 0 ||
|
block.status !== 0 ||
|
||||||
block.lowerThanBlocks.length > 0
|
(block.lowerThanBlocks.length > 0 && !force)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -293,9 +299,8 @@ const useGame = () => {
|
|||||||
randomBlocksVal.value[randomIdx].length
|
randomBlocksVal.value[randomIdx].length
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// 删除节点
|
// 非随机区才可撤回
|
||||||
// @ts-ignore
|
opHistory.push(block);
|
||||||
e.target.remove();
|
|
||||||
// 移除覆盖关系
|
// 移除覆盖关系
|
||||||
block.higherThanBlocks.forEach((higherThanBlock) => {
|
block.higherThanBlocks.forEach((higherThanBlock) => {
|
||||||
_.remove(higherThanBlock.lowerThanBlocks, (lowerThanBlock) => {
|
_.remove(higherThanBlock.lowerThanBlocks, (lowerThanBlock) => {
|
||||||
@ -333,6 +338,8 @@ const useGame = () => {
|
|||||||
slotBlock.status = 2;
|
slotBlock.status = 2;
|
||||||
// 已消除块数 +1
|
// 已消除块数 +1
|
||||||
clearBlockNum++;
|
clearBlockNum++;
|
||||||
|
// 清除操作记录,防止撤回
|
||||||
|
opHistory = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
newSlotAreaVal[tempSlotNum++] = slotBlock;
|
newSlotAreaVal[tempSlotNum++] = slotBlock;
|
||||||
@ -364,6 +371,93 @@ const useGame = () => {
|
|||||||
gameStatus.value = 1;
|
gameStatus.value = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// region 技能
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 洗牌
|
||||||
|
*
|
||||||
|
* @desc 随机重洗所有未被点击的块
|
||||||
|
*/
|
||||||
|
const doShuffle = () => {
|
||||||
|
// 遍历所有未消除的块
|
||||||
|
const originBlocks = allBlocks.filter((block) => block.status === 0);
|
||||||
|
const newBlockTypes = _.shuffle(originBlocks.map((block) => block.type));
|
||||||
|
let pos = 0;
|
||||||
|
originBlocks.forEach((block) => {
|
||||||
|
block.type = newBlockTypes[pos++];
|
||||||
|
});
|
||||||
|
levelBlocksVal.value = [...levelBlocksVal.value];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 破坏
|
||||||
|
*
|
||||||
|
* @desc 消除一组层级块
|
||||||
|
*/
|
||||||
|
const doBroke = () => {
|
||||||
|
// 类型,块列表映射
|
||||||
|
const typeBlockMap: Record<string, BlockType[]> = {};
|
||||||
|
const blocks = levelBlocksVal.value.filter((block) => block.status === 0);
|
||||||
|
// 遍历所有未消除的层级块
|
||||||
|
for (let i = 0; i < blocks.length; i++) {
|
||||||
|
const block = blocks[i];
|
||||||
|
if (!typeBlockMap[block.type]) {
|
||||||
|
typeBlockMap[block.type] = [];
|
||||||
|
}
|
||||||
|
typeBlockMap[block.type].push(block);
|
||||||
|
// 有能消除的一组块
|
||||||
|
if (typeBlockMap[block.type].length >= gameConfig.composeNum) {
|
||||||
|
typeBlockMap[block.type].forEach((clickBlock) => {
|
||||||
|
doClickBlock(clickBlock, -1, true);
|
||||||
|
});
|
||||||
|
console.log("doBroke", typeBlockMap[block.type]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤回
|
||||||
|
*
|
||||||
|
* @desc 后退一步
|
||||||
|
*/
|
||||||
|
const doRevert = () => {
|
||||||
|
if (opHistory.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
opHistory[opHistory.length - 1].status = 0;
|
||||||
|
// @ts-ignore
|
||||||
|
slotAreaVal.value[currSlotNum.value - 1] = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移出块
|
||||||
|
*/
|
||||||
|
const doRemove = () => {
|
||||||
|
// 移除第一个块
|
||||||
|
const block = slotAreaVal.value[0];
|
||||||
|
if (!block) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 槽移除块
|
||||||
|
for (let i = 0; i < slotAreaVal.value.length - 1; i++) {
|
||||||
|
slotAreaVal.value[i] = slotAreaVal.value[i - 1];
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
slotAreaVal.value[slotAreaVal.value.length - 1] = null;
|
||||||
|
// 改变新块的坐标
|
||||||
|
block.x = Math.floor(Math.random() * (boxWidthNum - 2));
|
||||||
|
block.y = boxHeightNum - 2;
|
||||||
|
block.status = 0;
|
||||||
|
// 移除的是随机块的元素,移到层级区域
|
||||||
|
if (block.level < 1) {
|
||||||
|
block.level = 10000;
|
||||||
|
levelBlocksVal.value.push(block);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gameStatus,
|
gameStatus,
|
||||||
levelBlocksVal,
|
levelBlocksVal,
|
||||||
@ -371,8 +465,14 @@ const useGame = () => {
|
|||||||
slotAreaVal,
|
slotAreaVal,
|
||||||
widthUnit,
|
widthUnit,
|
||||||
heightUnit,
|
heightUnit,
|
||||||
|
currSlotNum,
|
||||||
|
opHistory,
|
||||||
doClickBlock,
|
doClickBlock,
|
||||||
doStart,
|
doStart,
|
||||||
|
doShuffle,
|
||||||
|
doBroke,
|
||||||
|
doRemove,
|
||||||
|
doRevert,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const animals = [
|
|||||||
"🐂",
|
"🐂",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const defaultGameConfig: GameConfig = {
|
export const defaultGameConfig: GameConfigType = {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: 7,
|
slotNum: 7,
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
@ -45,7 +45,7 @@ export const defaultGameConfig: GameConfig = {
|
|||||||
/**
|
/**
|
||||||
* 简单难度
|
* 简单难度
|
||||||
*/
|
*/
|
||||||
export const easyGameConfig: GameConfig = {
|
export const easyGameConfig: GameConfigType = {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: 7,
|
slotNum: 7,
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
@ -67,7 +67,7 @@ export const easyGameConfig: GameConfig = {
|
|||||||
/**
|
/**
|
||||||
* 中等难度
|
* 中等难度
|
||||||
*/
|
*/
|
||||||
export const middleGameConfig: GameConfig = {
|
export const middleGameConfig: GameConfigType = {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: 7,
|
slotNum: 7,
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
@ -89,7 +89,7 @@ export const middleGameConfig: GameConfig = {
|
|||||||
/**
|
/**
|
||||||
* 困难难度
|
* 困难难度
|
||||||
*/
|
*/
|
||||||
export const hardGameConfig: GameConfig = {
|
export const hardGameConfig: GameConfigType = {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: 7,
|
slotNum: 7,
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
@ -111,7 +111,7 @@ export const hardGameConfig: GameConfig = {
|
|||||||
/**
|
/**
|
||||||
* 地狱难度
|
* 地狱难度
|
||||||
*/
|
*/
|
||||||
export const lunaticGameConfig: GameConfig = {
|
export const lunaticGameConfig: GameConfigType = {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: 7,
|
slotNum: 7,
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
|
@ -24,10 +24,10 @@ export const useGlobalStore = defineStore("global", {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setGameConfig(gameConfig: GameConfig) {
|
setGameConfig(gameConfig: GameConfigType) {
|
||||||
this.gameConfig = gameConfig;
|
this.gameConfig = gameConfig;
|
||||||
},
|
},
|
||||||
setCustomConfig(customConfig: GameConfig) {
|
setCustomConfig(customConfig: GameConfigType) {
|
||||||
this.customConfig = customConfig;
|
this.customConfig = customConfig;
|
||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
|
14
src/core/type.d.ts
vendored
14
src/core/type.d.ts
vendored
@ -24,9 +24,9 @@ interface ChessBoardUnitType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 游戏配置
|
* 游戏配置类型
|
||||||
*/
|
*/
|
||||||
interface GameConfig {
|
interface GameConfigType {
|
||||||
// 槽容量
|
// 槽容量
|
||||||
slotNum: number;
|
slotNum: number;
|
||||||
// 需要多少个一样块的才能合成
|
// 需要多少个一样块的才能合成
|
||||||
@ -48,3 +48,13 @@ interface GameConfig {
|
|||||||
// 最下层块数最小值(已废弃)
|
// 最下层块数最小值(已废弃)
|
||||||
// minBottomBlockNum: 20,
|
// minBottomBlockNum: 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 技能类型
|
||||||
|
*/
|
||||||
|
interface SkillType {
|
||||||
|
name: string;
|
||||||
|
desc: string;
|
||||||
|
icon: string;
|
||||||
|
action: function;
|
||||||
|
}
|
||||||
|
@ -53,9 +53,9 @@ import { defaultGameConfig } from "../core/gameConfig";
|
|||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { setGameConfig, setCustomConfig } = useGlobalStore();
|
const { setGameConfig, setCustomConfig } = useGlobalStore();
|
||||||
const config = reactive<GameConfig>({ ...defaultGameConfig });
|
const config = reactive<GameConfigType>({ ...defaultGameConfig });
|
||||||
|
|
||||||
const handleFinish = (values: GameConfig) => {
|
const handleFinish = (values: GameConfigType) => {
|
||||||
setGameConfig(config);
|
setGameConfig(config);
|
||||||
setCustomConfig(config);
|
setCustomConfig(config);
|
||||||
router.push("/game");
|
router.push("/game");
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
<!-- 胜利 -->
|
<!-- 胜利 -->
|
||||||
<div v-if="gameStatus === 3" style="text-align: center">
|
<div v-if="gameStatus === 3" style="text-align: center">
|
||||||
<h2>恭喜,你赢啦!🎉</h2>
|
<h2>恭喜,你赢啦!🎉</h2>
|
||||||
<img src="../assets/kunkun.png" />
|
<img alt="程序员鱼皮" src="../assets/kunkun.png" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 分层选块 -->
|
<!-- 分层选块 -->
|
||||||
<div class="level-board">
|
<div v-show="gameStatus > 0" class="level-board">
|
||||||
|
<div v-for="(block, idx) in levelBlocksVal" :key="idx">
|
||||||
<div
|
<div
|
||||||
v-for="(block, idx) in levelBlocksVal"
|
v-if="block.status === 0"
|
||||||
v-show="gameStatus > 0"
|
|
||||||
:key="idx"
|
|
||||||
class="block level-block"
|
class="block level-block"
|
||||||
:class="{ disabled: block.lowerThanBlocks.length > 0 }"
|
:class="{ disabled: block.lowerThanBlocks.length > 0 }"
|
||||||
:data-id="block.id"
|
:data-id="block.id"
|
||||||
@ -21,11 +20,12 @@
|
|||||||
left: block.x * widthUnit + 'px',
|
left: block.x * widthUnit + 'px',
|
||||||
top: block.y * heightUnit + 'px',
|
top: block.y * heightUnit + 'px',
|
||||||
}"
|
}"
|
||||||
@click="(e) => doClickBlock(block, e)"
|
@click="() => doClickBlock(block)"
|
||||||
>
|
>
|
||||||
{{ block.type }}
|
{{ block.type }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<!-- 随机选块 -->
|
<!-- 随机选块 -->
|
||||||
<div class="random-board">
|
<div class="random-board">
|
||||||
<div
|
<div
|
||||||
@ -35,11 +35,13 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="randomBlock.length > 0"
|
v-if="randomBlock.length > 0"
|
||||||
|
:data-id="randomBlock[0].id"
|
||||||
class="block"
|
class="block"
|
||||||
@click="(e) => doClickBlock(randomBlock[0], e, index)"
|
@click="() => doClickBlock(randomBlock[0], index)"
|
||||||
>
|
>
|
||||||
{{ randomBlock[0].type }}
|
{{ randomBlock[0].type }}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 隐藏 -->
|
||||||
<div
|
<div
|
||||||
v-for="num in Math.max(randomBlock.length - 1, 0)"
|
v-for="num in Math.max(randomBlock.length - 1, 0)"
|
||||||
:key="num"
|
:key="num"
|
||||||
@ -57,6 +59,13 @@
|
|||||||
{{ slotBlock?.type }}
|
{{ slotBlock?.type }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 技能 -->
|
||||||
|
<a-space style="margin-top: 16px">
|
||||||
|
<a-button size="small" @click="doRevert">撤回</a-button>
|
||||||
|
<a-button size="small" @click="doRemove">移出</a-button>
|
||||||
|
<a-button size="small" @click="doShuffle">洗牌</a-button>
|
||||||
|
<a-button size="small" @click="doBroke">破坏</a-button>
|
||||||
|
</a-space>
|
||||||
</a-row>
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -77,6 +86,10 @@ const {
|
|||||||
heightUnit,
|
heightUnit,
|
||||||
doClickBlock,
|
doClickBlock,
|
||||||
doStart,
|
doStart,
|
||||||
|
doShuffle,
|
||||||
|
doBroke,
|
||||||
|
doRemove,
|
||||||
|
doRevert,
|
||||||
} = useGame();
|
} = useGame();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +39,20 @@
|
|||||||
代码完全开源,欢迎 star
|
代码完全开源,欢迎 star
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<div class="footer">
|
||||||
|
鱼了个鱼 ©2022 by
|
||||||
|
<a href="https://github.com/liyupi" target="_blank" style="color: #fff">
|
||||||
|
程序员鱼皮
|
||||||
|
</a>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/liyupi/yulegeyu"
|
||||||
|
target="_blank"
|
||||||
|
style="color: #fff"
|
||||||
|
>
|
||||||
|
代码开源
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -57,7 +71,7 @@ const router = useRouter();
|
|||||||
|
|
||||||
const { setGameConfig } = useGlobalStore();
|
const { setGameConfig } = useGlobalStore();
|
||||||
|
|
||||||
const toGamePage = (config?: GameConfig) => {
|
const toGamePage = (config?: GameConfigType) => {
|
||||||
if (config) {
|
if (config) {
|
||||||
setGameConfig(config);
|
setGameConfig(config);
|
||||||
router.push("/game");
|
router.push("/game");
|
||||||
@ -71,4 +85,15 @@ const toGamePage = (config?: GameConfig) => {
|
|||||||
#indexPage {
|
#indexPage {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
color: #fff;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: center;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user