更新ab 复活金币
This commit is contained in:
parent
6351520e35
commit
05f5f3f6ea
|
|
@ -13,6 +13,7 @@ import { MiniGameSdk } from "./Sdk/MiniGameSdk";
|
||||||
import Animation = cc.Animation;
|
import Animation = cc.Animation;
|
||||||
// import Revive from "./Revive";
|
// import Revive from "./Revive";
|
||||||
import Utils from "./module/Pay/Utils";
|
import Utils from "./module/Pay/Utils";
|
||||||
|
import { getABReviveCoinCost, MAX_REVIVE_COST_STEP } from "./module/Config/ReviveCostConfig";
|
||||||
import Vine from "./prop/vine";
|
import Vine from "./prop/vine";
|
||||||
const { ccclass, property } = cc._decorator;
|
const { ccclass, property } = cc._decorator;
|
||||||
|
|
||||||
|
|
@ -21,7 +22,6 @@ const { ccclass, property } = cc._decorator;
|
||||||
@ccclass
|
@ccclass
|
||||||
export default class MapConroler extends cc.Component {
|
export default class MapConroler extends cc.Component {
|
||||||
private MAX_RETRY_COUNT = 6; // 最大重试次数
|
private MAX_RETRY_COUNT = 6; // 最大重试次数
|
||||||
private readonly reviveCoinCosts: number[] = [500, 500, 500, 500, 500, 500];
|
|
||||||
private _blocksEmptyTime: number | null = null; // 保底机制计时
|
private _blocksEmptyTime: number | null = null; // 保底机制计时
|
||||||
static _instance: any;
|
static _instance: any;
|
||||||
@property(cc.SpriteAtlas)
|
@property(cc.SpriteAtlas)
|
||||||
|
|
@ -4242,8 +4242,9 @@ export default class MapConroler extends cc.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getReviveCoinCost(): number {
|
private getReviveCoinCost(): number {
|
||||||
const reviveCount = Math.max(0, cc.fx.GameConfig.GM_INFO.review || 0);
|
const assignment = cc.fx.GameConfig.GM_INFO.abTestAssignments
|
||||||
return this.reviveCoinCosts[Math.min(reviveCount, this.reviveCoinCosts.length - 1)];
|
&& cc.fx.GameConfig.GM_INFO.abTestAssignments.layer_3;
|
||||||
|
return getABReviveCoinCost(assignment, cc.fx.GameConfig.GM_INFO.review);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateReviveCoinDisplay(buyBtn: cc.Node) {
|
private updateReviveCoinDisplay(buyBtn: cc.Node) {
|
||||||
|
|
@ -4355,7 +4356,7 @@ export default class MapConroler extends cc.Component {
|
||||||
this.node.parent.getChildByName("Ice").active = false;
|
this.node.parent.getChildByName("Ice").active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cc.fx.GameConfig.GM_INFO.review < this.reviveCoinCosts.length - 1)
|
if (cc.fx.GameConfig.GM_INFO.review < MAX_REVIVE_COST_STEP)
|
||||||
cc.fx.GameConfig.GM_INFO.review += 1;
|
cc.fx.GameConfig.GM_INFO.review += 1;
|
||||||
|
|
||||||
this.icetimeNode[0].active = true;
|
this.icetimeNode[0].active = true;
|
||||||
|
|
|
||||||
25
assets/Script/module/Config/ReviveCostConfig.ts
Normal file
25
assets/Script/module/Config/ReviveCostConfig.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
export const REVIVE_COST_AB_NAME = "revive_cost_ascend";
|
||||||
|
export const MAX_REVIVE_COST_STEP = 5;
|
||||||
|
|
||||||
|
const DEFAULT_REVIVE_COSTS = [500];
|
||||||
|
const REVIVE_COSTS_BY_GROUP = {
|
||||||
|
B: [500, 700, 900],
|
||||||
|
C: [500, 700, 900, 1100, 1300, 1500]
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getABReviveCoinCost(assignment: any, reviveCount: any): number {
|
||||||
|
const isTargetExperiment = assignment
|
||||||
|
&& String(assignment.layer) === "3"
|
||||||
|
&& assignment.name === REVIVE_COST_AB_NAME
|
||||||
|
&& assignment.enabled !== false;
|
||||||
|
const group = isTargetExperiment
|
||||||
|
? String(assignment.group || "Default").toUpperCase()
|
||||||
|
: "DEFAULT";
|
||||||
|
const costs = group === "B"
|
||||||
|
? REVIVE_COSTS_BY_GROUP.B
|
||||||
|
: group === "C"
|
||||||
|
? REVIVE_COSTS_BY_GROUP.C
|
||||||
|
: DEFAULT_REVIVE_COSTS;
|
||||||
|
const step = Math.max(0, Math.floor(Number(reviveCount) || 0));
|
||||||
|
return costs[Math.min(step, costs.length - 1)];
|
||||||
|
}
|
||||||
10
assets/Script/module/Config/ReviveCostConfig.ts.meta
Normal file
10
assets/Script/module/Config/ReviveCostConfig.ts.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"ver": "1.1.0",
|
||||||
|
"uuid": "763b8065-12e6-4c06-9796-051f0a1d89d8",
|
||||||
|
"importer": "typescript",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import cloud from '@lafjs/cloud'
|
import cloud from '@lafjs/cloud'
|
||||||
const db = cloud.database();
|
const db = cloud.database();
|
||||||
import Utils from "@/Utils";
|
import Utils from "@/Utils";
|
||||||
const CDKreward={
|
const CDKreward = {
|
||||||
wucaixiaoxiaole666:{
|
wucaixiaoxiaole666: {
|
||||||
1001:1000,
|
1001: 1000,
|
||||||
2001:1,
|
2001: 1,
|
||||||
2002:1,
|
2002: 1,
|
||||||
2003:1,
|
2003: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default async function (ctx: FunctionContext) {
|
export default async function (ctx: FunctionContext) {
|
||||||
|
|
@ -14,9 +14,9 @@ export default async function (ctx: FunctionContext) {
|
||||||
if (!uid) {
|
if (!uid) {
|
||||||
return { code: 0, data: null, msg: "参数错误" };
|
return { code: 0, data: null, msg: "参数错误" };
|
||||||
}
|
}
|
||||||
let cdk= ctx.body.cdk;
|
let cdk = ctx.body.cdk;
|
||||||
if(!cdk){
|
if (!cdk) {
|
||||||
return {code:0, data:null, msg:"未获取到cdk"}
|
return { code: 0, data: null, msg: "未获取到cdk" }
|
||||||
}
|
}
|
||||||
cdk = cdk.toLowerCase();
|
cdk = cdk.toLowerCase();
|
||||||
let dbname = "users";
|
let dbname = "users";
|
||||||
|
|
@ -64,30 +64,34 @@ export default async function (ctx: FunctionContext) {
|
||||||
}, msg: "可以购买"
|
}, msg: "可以购买"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let info = await db.collection("idcount").where({ _id:"694e064b35004ffb5aba0dc6"}).getOne();
|
let info = await db.collection("idcount").where({ _id: "69fac04fb4d89b170da4bf64" }).getOne();
|
||||||
let count= info.data.count;
|
let count = info.data.count;
|
||||||
if(count.includes(cdk)){
|
if (count.includes(cdk)) {
|
||||||
let index=count.indexOf(cdk);
|
let index = count.indexOf(cdk);
|
||||||
count.splice(index,1);
|
count.splice(index, 1);
|
||||||
redeem.push(cdk);
|
redeem.push(cdk);
|
||||||
db.collection(dbname).where({ _id: uid }).update({ redeem: redeem });
|
db.collection(dbname).where({ _id: uid }).update({ redeem: redeem });
|
||||||
await db.collection("idcount").where({ _id: "694e064b35004ffb5aba0dc6" }).update({count:count});
|
await db.collection("idcount").where({ _id: "69fac04fb4d89b170da4bf64" }).update({ count: count });
|
||||||
let money=600;
|
let money = 600;
|
||||||
let num=1;
|
let num = 1;
|
||||||
if(cdk.length==6){
|
if (cdk.length == 6) {
|
||||||
money=1500;
|
money = 1500;
|
||||||
num=3;
|
num = 3;
|
||||||
}else if(cdk.length==8){
|
} else if (cdk.length == 8) {
|
||||||
money=600;
|
money = 600;
|
||||||
num=1;
|
num = 1;
|
||||||
}
|
}
|
||||||
return { code: 1, data: { reward: {
|
return {
|
||||||
1001:money,
|
code: 1, data: {
|
||||||
2001: num,
|
reward: {
|
||||||
2002: num,
|
1001: money,
|
||||||
2003: num,
|
2001: num,
|
||||||
} }, msg: "可以购买" };
|
2002: num,
|
||||||
}else{
|
2003: num,
|
||||||
|
}
|
||||||
|
}, msg: "可以购买"
|
||||||
|
};
|
||||||
|
} else {
|
||||||
let reward = CDKreward[cdk];
|
let reward = CDKreward[cdk];
|
||||||
if (!reward) {
|
if (!reward) {
|
||||||
return { code: 0, data: null, msg: "未获取到奖励信息" };
|
return { code: 0, data: null, msg: "未获取到奖励信息" };
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ test("Default is a case-insensitive reserved group name", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the admin page explains edge-triggered reset behavior", async () => {
|
test("the admin page explains edge-triggered reset behavior", async () => {
|
||||||
const ui = await readFile(new URL("../../xxwzUI.html", import.meta.url), "utf8");
|
const ui = await readFile(new URL("../../xxwz.html", import.meta.url), "utf8");
|
||||||
|
|
||||||
assert.match(ui, /关闭→开启并发布/);
|
assert.match(ui, /关闭→开启并发布/);
|
||||||
assert.match(ui, /关闭后未登录用户不补做/);
|
assert.match(ui, /关闭后未登录用户不补做/);
|
||||||
|
|
|
||||||
48
server/laf-cloud/tests/revive-cost-ab.test.mjs
Normal file
48
server/laf-cloud/tests/revive-cost-ab.test.mjs
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
|
||||||
|
const configUrl = new URL("../../../assets/Script/module/Config/ReviveCostConfig.ts", import.meta.url);
|
||||||
|
const { getABReviveCoinCost, MAX_REVIVE_COST_STEP, REVIVE_COST_AB_NAME } = await import(configUrl);
|
||||||
|
|
||||||
|
function assignment(group, overrides = {}) {
|
||||||
|
return {
|
||||||
|
experimentId: "exp_layer_3_003",
|
||||||
|
layer: "3",
|
||||||
|
name: REVIVE_COST_AB_NAME,
|
||||||
|
enabled: true,
|
||||||
|
group,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Default and group A always cost 500", () => {
|
||||||
|
for (const group of ["Default", "A"]) {
|
||||||
|
assert.deepEqual(
|
||||||
|
Array.from({ length: 9 }, (_, count) => getABReviveCoinCost(assignment(group), count)),
|
||||||
|
Array(9).fill(500),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("group B ascends 500, 700, 900 and stays at 900", () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
Array.from({ length: 7 }, (_, count) => getABReviveCoinCost(assignment("B"), count)),
|
||||||
|
[500, 700, 900, 900, 900, 900, 900],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("group C ascends through 1500 and stays at 1500", () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
Array.from({ length: 8 }, (_, count) => getABReviveCoinCost(assignment("C"), count)),
|
||||||
|
[500, 700, 900, 1100, 1300, 1500, 1500, 1500],
|
||||||
|
);
|
||||||
|
assert.equal(MAX_REVIVE_COST_STEP, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("disabled, missing, or unrelated assignments use the 500 fallback", () => {
|
||||||
|
assert.equal(getABReviveCoinCost(null, 5), 500);
|
||||||
|
assert.equal(getABReviveCoinCost(assignment("C", { enabled: false }), 5), 500);
|
||||||
|
assert.equal(getABReviveCoinCost(assignment("C", { layer: "2" }), 5), 500);
|
||||||
|
assert.equal(getABReviveCoinCost(assignment("C", { name: "another_experiment" }), 5), 500);
|
||||||
|
assert.equal(getABReviveCoinCost(assignment("D"), 5), 500);
|
||||||
|
});
|
||||||
348
server/消消王者cdk.html
Normal file
348
server/消消王者cdk.html
Normal file
|
|
@ -0,0 +1,348 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>兑换码生成器</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.generator-section {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.generator-section h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.input-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
button.secondary {
|
||||||
|
background-color: #2196F3;
|
||||||
|
}
|
||||||
|
button.secondary:hover {
|
||||||
|
background-color: #0b7dda;
|
||||||
|
}
|
||||||
|
.code-display {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
word-break: break-all;
|
||||||
|
min-height: 20px;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
.success-message {
|
||||||
|
color: #4CAF50;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.error-message {
|
||||||
|
color: #f44336;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>兑换码生成器</h1>
|
||||||
|
|
||||||
|
<!-- 6位兑换码生成器 -->
|
||||||
|
<div class="generator-section">
|
||||||
|
<h2>6位兑换码</h2>
|
||||||
|
<p class="note">1500金币 + 锤子,时间停止,魔法棒各3个道具</p>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="code6">兑换码(留空则随机生成):</label>
|
||||||
|
<input type="text" id="code6" placeholder="输入6位字母数字组合或留空">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onclick="generateCode(6)">随机生成</button>
|
||||||
|
<button onclick="copyCode('code6')">复制兑换码</button>
|
||||||
|
<button class="secondary" onclick="sendToServer('code6')">保存到服务器</button>
|
||||||
|
|
||||||
|
<div class="code-display" id="display6"></div>
|
||||||
|
<div id="message6"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 7位兑换码生成器 -->
|
||||||
|
<div class="generator-section">
|
||||||
|
<h2>7位兑换码</h2>
|
||||||
|
<p class="note">600金币 + 锤子,时间停止,魔法棒各1个道具</p>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="code7">兑换码(留空则随机生成):</label>
|
||||||
|
<input type="text" id="code7" placeholder="输入7位字母数字组合或留空">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onclick="generateCode(7)">随机生成</button>
|
||||||
|
<button onclick="copyCode('code7')">复制兑换码</button>
|
||||||
|
<button class="secondary" onclick="sendToServer('code7')">保存到服务器</button>
|
||||||
|
|
||||||
|
<div class="code-display" id="display7"></div>
|
||||||
|
<div id="message7"></div>
|
||||||
|
</div>
|
||||||
|
<!-- 8位兑换码生成器 -->
|
||||||
|
<!-- <div class="generator-section">
|
||||||
|
<h2>8位兑换码</h2>
|
||||||
|
<p class="note">600金币 + 1个道具</p>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="code8">兑换码(留空则随机生成):</label>
|
||||||
|
<input type="text" id="code8" placeholder="输入8位字母数字组合或留空">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onclick="generateCode(8)">随机生成</button>
|
||||||
|
<button onclick="copyCode('code8')">复制兑换码</button>
|
||||||
|
<button class="secondary" onclick="sendToServer('code8')">保存到服务器</button>
|
||||||
|
|
||||||
|
<div class="code-display" id="display8"></div>
|
||||||
|
<div id="message8"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 生成随机兑换码
|
||||||
|
function generateRandomCode(length) {
|
||||||
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成兑换码
|
||||||
|
function generateCode(length) {
|
||||||
|
let inputId;
|
||||||
|
let displayId;
|
||||||
|
let messageId;
|
||||||
|
switch(length){
|
||||||
|
case 6:
|
||||||
|
inputId="code6";
|
||||||
|
displayId="display6";
|
||||||
|
messageId="message6";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
inputId="code7";
|
||||||
|
displayId="display7";
|
||||||
|
messageId="message7";
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
inputId="code8";
|
||||||
|
displayId="display8";
|
||||||
|
messageId="message8";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const input = document.getElementById(inputId);
|
||||||
|
const display = document.getElementById(displayId);
|
||||||
|
const message = document.getElementById(messageId);
|
||||||
|
|
||||||
|
// 清空消息
|
||||||
|
message.innerHTML = '';
|
||||||
|
|
||||||
|
// 如果输入为空,则生成随机码
|
||||||
|
if (!input.value.trim()) {
|
||||||
|
input.value = generateRandomCode(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证长度
|
||||||
|
if (input.value.length !== length) {
|
||||||
|
message.innerHTML = `<div class="error-message">错误:兑换码必须是${length}位</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证字符(只允许字母和数字)
|
||||||
|
if (!/^[A-Za-z0-9]+$/.test(input.value)) {
|
||||||
|
message.innerHTML = '<div class="error-message">错误:兑换码只能包含字母和数字</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示兑换码
|
||||||
|
display.textContent = input.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制兑换码
|
||||||
|
function copyCode(inputId) {
|
||||||
|
const input = document.getElementById(inputId);
|
||||||
|
let displayId;
|
||||||
|
let messageId;
|
||||||
|
switch(inputId){
|
||||||
|
case "code6":
|
||||||
|
displayId="display6";
|
||||||
|
messageId="message6";
|
||||||
|
break;
|
||||||
|
case "code7":
|
||||||
|
displayId="display7";
|
||||||
|
messageId="message7";
|
||||||
|
break;
|
||||||
|
case "code8":
|
||||||
|
displayId="display8";
|
||||||
|
messageId="message8";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const display = document.getElementById(displayId);
|
||||||
|
|
||||||
|
const message = document.getElementById(messageId);
|
||||||
|
|
||||||
|
if (!display.textContent) {
|
||||||
|
message.innerHTML = '<div class="error-message">错误:没有可复制的兑换码</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个临时的textarea元素来复制文本
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
textarea.value = display.textContent;
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand('copy');
|
||||||
|
if (successful) {
|
||||||
|
message.innerHTML = '<div class="success-message">兑换码已复制到剪贴板</div>';
|
||||||
|
} else {
|
||||||
|
message.innerHTML = '<div class="error-message">复制失败,请手动选择并复制</div>';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
message.innerHTML = '<div class="error-message">复制失败,请手动选择并复制</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送到服务器
|
||||||
|
function sendToServer(inputId) {
|
||||||
|
let displayId;
|
||||||
|
let messageId;
|
||||||
|
switch(inputId){
|
||||||
|
case "code6":
|
||||||
|
displayId="display6";
|
||||||
|
messageId="message6";
|
||||||
|
break;
|
||||||
|
case "code7":
|
||||||
|
displayId="display7";
|
||||||
|
messageId="message7";
|
||||||
|
break;
|
||||||
|
case "code8":
|
||||||
|
displayId="display8";
|
||||||
|
messageId="message8";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const input = document.getElementById(inputId);
|
||||||
|
const display = document.getElementById(displayId);
|
||||||
|
const message = document.getElementById(messageId);
|
||||||
|
|
||||||
|
if (!display.textContent) {
|
||||||
|
message.innerHTML = '<div class="error-message">错误:没有可保存的兑换码</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备发送的数据
|
||||||
|
const codeType = inputId === 'code6' ? 'type6' : 'type7';
|
||||||
|
const data = {
|
||||||
|
cdk: display.textContent,
|
||||||
|
type: codeType,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
};
|
||||||
|
console.log(data);
|
||||||
|
// 发送POST请求
|
||||||
|
fetch('https://q6rvwvtnga.sealoshzh.site/creatCdk', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('网络响应不正常');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
message.innerHTML = '<div class="success-message">兑换码已成功保存到服务器</div>';
|
||||||
|
console.log('成功:', data);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
message.innerHTML = `<div class="error-message">保存失败: ${error.message}</div>`;
|
||||||
|
console.error('错误:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('https://cnsl1li6q4.sealoshzh.site/creatCdk', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('网络响应不正常');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
message.innerHTML = '<div class="success-message">兑换码已成功保存到服务器</div>';
|
||||||
|
console.log('成功:', data);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
message.innerHTML = `<div class="error-message">保存失败: ${error.message}</div>`;
|
||||||
|
console.error('错误:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
263
server/消消王者一次性通用兑换码.html
Normal file
263
server/消消王者一次性通用兑换码.html
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>兑换码生成器</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
input[type="text"], input[type="datetime-local"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.code-display {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
#codeInput {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
button.secondary {
|
||||||
|
background-color: #2196F3;
|
||||||
|
}
|
||||||
|
button.secondary:hover {
|
||||||
|
background-color: #0b7dda;
|
||||||
|
}
|
||||||
|
button.danger {
|
||||||
|
background-color: #f44336;
|
||||||
|
}
|
||||||
|
button.danger:hover {
|
||||||
|
background-color: #da190b;
|
||||||
|
}
|
||||||
|
.response-area {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
.copy-btn {
|
||||||
|
background-color: #ff9800;
|
||||||
|
padding: 10px;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.copy-btn:hover {
|
||||||
|
background-color: #e68a00;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>兑换码生成器</h1>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="codeInput">兑换码</label>
|
||||||
|
<div class="code-display">
|
||||||
|
<input type="text" id="codeInput" placeholder="5位兑换码" maxlength="5">
|
||||||
|
<button class="copy-btn" onclick="copyCode()">复制</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<button onclick="generateCode()">生成随机兑换码</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="startTime">开始时间</label>
|
||||||
|
<input type="datetime-local" id="startTime">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="endTime">结束时间</label>
|
||||||
|
<input type="datetime-local" id="endTime">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<button class="secondary" onclick="sendToServer(1)">发送到服务器</button>
|
||||||
|
<button class="danger" onclick="sendToServer(2)">删除兑换码</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>服务器响应</label>
|
||||||
|
<div id="responseArea" class="response-area">
|
||||||
|
等待操作...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 生成5位随机兑换码(数字和字母组合)
|
||||||
|
function generateCode() {
|
||||||
|
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
let code = '';
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
code += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
|
}
|
||||||
|
document.getElementById('codeInput').value = code;
|
||||||
|
document.getElementById('responseArea').textContent = '已生成新的兑换码: ' + code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制兑换码到剪贴板
|
||||||
|
function copyCode() {
|
||||||
|
const codeInput = document.getElementById('codeInput');
|
||||||
|
codeInput.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.getElementById('responseArea').textContent = '兑换码已复制到剪贴板: ' + codeInput.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送数据到服务器
|
||||||
|
function sendToServer(type) {
|
||||||
|
const code = document.getElementById('codeInput').value.trim();
|
||||||
|
const startTime = document.getElementById('startTime').value;
|
||||||
|
const endTime = document.getElementById('endTime').value;
|
||||||
|
|
||||||
|
if (!code) {
|
||||||
|
document.getElementById('responseArea').textContent = '请输入或生成兑换码';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code.length !== 5) {
|
||||||
|
document.getElementById('responseArea').textContent = '兑换码必须是5位';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 1 && (!startTime || !endTime)) {
|
||||||
|
document.getElementById('responseArea').textContent = '请设置开始时间和结束时间';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 1 && new Date(startTime) >= new Date(endTime)) {
|
||||||
|
document.getElementById('responseArea').textContent = '开始时间必须早于结束时间';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
code: code.toLowerCase(),
|
||||||
|
type: type,
|
||||||
|
start_time: type === 1 ? startTime : undefined,
|
||||||
|
end_time: type === 1 ? endTime : undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('responseArea').textContent = '正在发送请求...';
|
||||||
|
|
||||||
|
fetch('https://q6rvwvtnga.sealoshzh.site/creatCDkTwo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('网络响应不正常');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
// document.getElementById('responseArea').textContent =
|
||||||
|
// `服务器响应 (${type === 1 ? '创建' : '删除'}): ${JSON.stringify(data)}`;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// document.getElementById('responseArea').textContent =
|
||||||
|
// '请求失败: ' + error.message;
|
||||||
|
});
|
||||||
|
fetch('https://cnsl1li6q4.sealoshzh.site/creatCDkTwo', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('网络响应不正常');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('responseArea').textContent =
|
||||||
|
`服务器响应 (${type === 1 ? '创建' : '删除'}): ${JSON.stringify(data)}`;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
document.getElementById('responseArea').textContent =
|
||||||
|
'请求失败: ' + error.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化:设置默认时间(当前时间和明天)
|
||||||
|
function initDefaultTimes() {
|
||||||
|
const now = new Date();
|
||||||
|
const tomorrow = new Date(now);
|
||||||
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
|
|
||||||
|
// 格式化日期时间字符串以适应datetime-local输入
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('startTime').value = formatDate(now);
|
||||||
|
document.getElementById('endTime').value = formatDate(tomorrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载时初始化
|
||||||
|
window.onload = initDefaultTimes;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user