更新ab 复活金币
This commit is contained in:
parent
6351520e35
commit
05f5f3f6ea
|
|
@ -13,6 +13,7 @@ import { MiniGameSdk } from "./Sdk/MiniGameSdk";
|
|||
import Animation = cc.Animation;
|
||||
// import Revive from "./Revive";
|
||||
import Utils from "./module/Pay/Utils";
|
||||
import { getABReviveCoinCost, MAX_REVIVE_COST_STEP } from "./module/Config/ReviveCostConfig";
|
||||
import Vine from "./prop/vine";
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
|
|
@ -21,7 +22,6 @@ const { ccclass, property } = cc._decorator;
|
|||
@ccclass
|
||||
export default class MapConroler extends cc.Component {
|
||||
private MAX_RETRY_COUNT = 6; // 最大重试次数
|
||||
private readonly reviveCoinCosts: number[] = [500, 500, 500, 500, 500, 500];
|
||||
private _blocksEmptyTime: number | null = null; // 保底机制计时
|
||||
static _instance: any;
|
||||
@property(cc.SpriteAtlas)
|
||||
|
|
@ -4242,8 +4242,9 @@ export default class MapConroler extends cc.Component {
|
|||
}
|
||||
|
||||
private getReviveCoinCost(): number {
|
||||
const reviveCount = Math.max(0, cc.fx.GameConfig.GM_INFO.review || 0);
|
||||
return this.reviveCoinCosts[Math.min(reviveCount, this.reviveCoinCosts.length - 1)];
|
||||
const assignment = cc.fx.GameConfig.GM_INFO.abTestAssignments
|
||||
&& cc.fx.GameConfig.GM_INFO.abTestAssignments.layer_3;
|
||||
return getABReviveCoinCost(assignment, cc.fx.GameConfig.GM_INFO.review);
|
||||
}
|
||||
|
||||
private updateReviveCoinDisplay(buyBtn: cc.Node) {
|
||||
|
|
@ -4355,7 +4356,7 @@ export default class MapConroler extends cc.Component {
|
|||
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;
|
||||
|
||||
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'
|
||||
const db = cloud.database();
|
||||
import Utils from "@/Utils";
|
||||
const CDKreward={
|
||||
wucaixiaoxiaole666:{
|
||||
1001:1000,
|
||||
2001:1,
|
||||
2002:1,
|
||||
2003:1,
|
||||
const CDKreward = {
|
||||
wucaixiaoxiaole666: {
|
||||
1001: 1000,
|
||||
2001: 1,
|
||||
2002: 1,
|
||||
2003: 1,
|
||||
}
|
||||
}
|
||||
export default async function (ctx: FunctionContext) {
|
||||
|
|
@ -14,9 +14,9 @@ export default async function (ctx: FunctionContext) {
|
|||
if (!uid) {
|
||||
return { code: 0, data: null, msg: "参数错误" };
|
||||
}
|
||||
let cdk= ctx.body.cdk;
|
||||
if(!cdk){
|
||||
return {code:0, data:null, msg:"未获取到cdk"}
|
||||
let cdk = ctx.body.cdk;
|
||||
if (!cdk) {
|
||||
return { code: 0, data: null, msg: "未获取到cdk" }
|
||||
}
|
||||
cdk = cdk.toLowerCase();
|
||||
let dbname = "users";
|
||||
|
|
@ -64,30 +64,34 @@ export default async function (ctx: FunctionContext) {
|
|||
}, msg: "可以购买"
|
||||
};
|
||||
}
|
||||
let info = await db.collection("idcount").where({ _id:"694e064b35004ffb5aba0dc6"}).getOne();
|
||||
let count= info.data.count;
|
||||
if(count.includes(cdk)){
|
||||
let index=count.indexOf(cdk);
|
||||
count.splice(index,1);
|
||||
let info = await db.collection("idcount").where({ _id: "69fac04fb4d89b170da4bf64" }).getOne();
|
||||
let count = info.data.count;
|
||||
if (count.includes(cdk)) {
|
||||
let index = count.indexOf(cdk);
|
||||
count.splice(index, 1);
|
||||
redeem.push(cdk);
|
||||
db.collection(dbname).where({ _id: uid }).update({ redeem: redeem });
|
||||
await db.collection("idcount").where({ _id: "694e064b35004ffb5aba0dc6" }).update({count:count});
|
||||
let money=600;
|
||||
let num=1;
|
||||
if(cdk.length==6){
|
||||
money=1500;
|
||||
num=3;
|
||||
}else if(cdk.length==8){
|
||||
money=600;
|
||||
num=1;
|
||||
await db.collection("idcount").where({ _id: "69fac04fb4d89b170da4bf64" }).update({ count: count });
|
||||
let money = 600;
|
||||
let num = 1;
|
||||
if (cdk.length == 6) {
|
||||
money = 1500;
|
||||
num = 3;
|
||||
} else if (cdk.length == 8) {
|
||||
money = 600;
|
||||
num = 1;
|
||||
}
|
||||
return { code: 1, data: { reward: {
|
||||
1001:money,
|
||||
2001: num,
|
||||
2002: num,
|
||||
2003: num,
|
||||
} }, msg: "可以购买" };
|
||||
}else{
|
||||
return {
|
||||
code: 1, data: {
|
||||
reward: {
|
||||
1001: money,
|
||||
2001: num,
|
||||
2002: num,
|
||||
2003: num,
|
||||
}
|
||||
}, msg: "可以购买"
|
||||
};
|
||||
} else {
|
||||
let reward = CDKreward[cdk];
|
||||
if (!reward) {
|
||||
return { code: 0, data: null, msg: "未获取到奖励信息" };
|
||||
|
|
@ -96,5 +100,5 @@ export default async function (ctx: FunctionContext) {
|
|||
db.collection(dbname).where({ _id: uid }).update({ redeem: redeem });
|
||||
return { code: 1, data: { reward: reward }, 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 () => {
|
||||
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, /关闭后未登录用户不补做/);
|
||||
|
|
|
|||
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