1077 lines
38 KiB
HTML
1077 lines
38 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title id="page-title">彩先知 - 断组合</title>
|
||
<script src="../public/css/layui/layui.js"></script>
|
||
<script src="../config.js"></script>
|
||
<script src="../utils/ApiClient.js"></script>
|
||
<script src="../utils/DateUtil.js"></script>
|
||
<script src="../utils/CommonUtil.js"></script>
|
||
<link rel="stylesheet" href="../public/css/layui/css/layui.css" />
|
||
<link rel="stylesheet" href="../public/css/public.css" />
|
||
<link rel="stylesheet" href="../public/css/combo.css" />
|
||
</head>
|
||
<body>
|
||
<!-- Header -->
|
||
<nav class="topbar" id="navbar">
|
||
<div class="topbar__inner">
|
||
<a href="index.html" class="topbar__brand">
|
||
<img
|
||
src="../images/home-logo.png"
|
||
alt="彩先知"
|
||
class="topbar__logo"
|
||
/>
|
||
</a>
|
||
<div class="topbar__nav" id="navLotteryItems">
|
||
<a href="index.html" class="topbar__nav-link">首页</a>
|
||
</div>
|
||
<div class="topbar__user">
|
||
<div id="notLoggedInBox" class="topbar__guest">
|
||
<a href="login.html" class="topbar__btn topbar__btn--ghost">登录</a>
|
||
<a href="reg.html" class="topbar__btn topbar__btn--primary"
|
||
>免费注册</a
|
||
>
|
||
</div>
|
||
<div id="loggedInBox" class="topbar__logged is-hidden">
|
||
<a href="usercenter.html" class="topbar__profile">
|
||
<img
|
||
id="userAvatar"
|
||
src="../public/img/userimg.png"
|
||
alt=""
|
||
class="topbar__avatar"
|
||
/>
|
||
<div class="topbar__meta">
|
||
<span id="userName" class="topbar__uname">用户</span>
|
||
<span id="userLevel" class="topbar__ubadge">会员</span>
|
||
</div>
|
||
</a>
|
||
<button class="topbar__btn topbar__btn--logout" onclick="logout()">
|
||
退出登录
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Main Content -->
|
||
<main class="page-main">
|
||
<section class="content-section duan-scheme">
|
||
<div class="content-title">
|
||
<i class="layui-icon layui-icon-template-1"></i> 断组方案
|
||
</div>
|
||
<div class="duan-buy-panel" id="schemeBuyPanel">
|
||
<div class="duan-scheme-text" id="schemeSummary">正在加载方案...</div>
|
||
<div class="duan-scheme-actions">
|
||
<span class="duan-price"
|
||
>¥ <span id="schemePrice">--</span> 彩币</span
|
||
>
|
||
<button class="duan-buy-btn" type="button" onclick="buy()">
|
||
购买
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="duan-plan-panel" id="schemePlanPanel">
|
||
<div class="duan-scheme-text">计算公式说明:</div>
|
||
<div class="duan-scheme-actions">
|
||
<button class="duan-plan-btn" type="button" data-plan-index="1">
|
||
断组方案
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="content-section">
|
||
<div class="content-title">
|
||
<i class="layui-icon layui-icon-table"></i> 断组合推荐
|
||
</div>
|
||
<div class="duan-table-wrap">
|
||
<table class="duan-table">
|
||
<colgroup>
|
||
<col class="duan-col-name" />
|
||
<col class="duan-col-type" />
|
||
<col class="duan-col-issue" />
|
||
<col class="duan-col-open" />
|
||
<col class="duan-col-group" />
|
||
<col class="duan-col-status" />
|
||
<col class="duan-col-group" />
|
||
<col class="duan-col-status" />
|
||
<col class="duan-col-copy" />
|
||
<col class="duan-col-price" />
|
||
<col class="duan-col-action" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr>
|
||
<th>名称</th>
|
||
<th>类型</th>
|
||
<th>期号</th>
|
||
<th>开奖号</th>
|
||
<th>断组1</th>
|
||
<th>状态1</th>
|
||
<th>断组2</th>
|
||
<th>状态2</th>
|
||
<th>复制</th>
|
||
<th>彩币</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="predictBody">
|
||
<tr>
|
||
<td colspan="11">
|
||
<div class="duan-empty">正在加载断组数据...</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<div class="cxz-dialog-overlay" id="buyDialog">
|
||
<div class="cxz-dialog-box">
|
||
<div class="cxz-dialog-header">
|
||
<div class="cxz-dialog-title">购买断组方案</div>
|
||
<button class="cxz-dialog-close" type="button" onclick="closeBuyDialog()">
|
||
×
|
||
</button>
|
||
</div>
|
||
<div class="cxz-dialog-body">
|
||
<div class="cxz-pay-hero">
|
||
<div class="cxz-pay-hero-label">应付金额</div>
|
||
<div class="cxz-pay-hero-price">¥ <span id="payFinalAmount">--</span></div>
|
||
<div class="cxz-pay-hero-sub">
|
||
原价 ¥ <span id="payOriginalAmount">--</span>
|
||
<span class="cxz-pay-deduct">积分抵扣 ¥ <span id="pointDeductAmount">0.00</span></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="cxz-pay-section-title">选择支付余额</div>
|
||
<div class="cxz-pay-wallets">
|
||
<button class="cxz-pay-option selected" data-type="account" type="button" onclick="selectPayType(this)">
|
||
<span class="cxz-pay-radio"></span>
|
||
<span class="cxz-pay-info">
|
||
<span class="cxz-pay-name">账户余额</span>
|
||
<span class="cxz-pay-desc">通用余额</span>
|
||
</span>
|
||
<span class="cxz-pay-balance">¥ <span id="accountBalance">0.00</span></span>
|
||
</button>
|
||
<button class="cxz-pay-option" data-type="sales" type="button" onclick="selectPayType(this)">
|
||
<span class="cxz-pay-radio"></span>
|
||
<span class="cxz-pay-info">
|
||
<span class="cxz-pay-name">分销余额</span>
|
||
<span class="cxz-pay-desc">推广收益</span>
|
||
</span>
|
||
<span class="cxz-pay-balance">¥ <span id="distributionBalance">0.00</span></span>
|
||
</button>
|
||
<button class="cxz-pay-option" data-type="expert" type="button" onclick="selectPayType(this)">
|
||
<span class="cxz-pay-radio"></span>
|
||
<span class="cxz-pay-info">
|
||
<span class="cxz-pay-name">专家余额</span>
|
||
<span class="cxz-pay-desc">专家佣金</span>
|
||
</span>
|
||
<span class="cxz-pay-balance">¥ <span id="expertBalance">0.00</span></span>
|
||
</button>
|
||
</div>
|
||
|
||
<label class="cxz-point-card">
|
||
<span class="cxz-point-main">
|
||
<input type="checkbox" id="usePoint" />
|
||
<span>
|
||
<span class="cxz-point-title">积分抵扣</span>
|
||
<span class="cxz-point-desc" id="pointBalance">可用积分 --</span>
|
||
</span>
|
||
</span>
|
||
<span class="cxz-point-value">- ¥ <span id="pointDeductPreview">0.00</span></span>
|
||
</label>
|
||
|
||
<div class="cxz-pay-total-card">
|
||
<div>
|
||
<span id="selectedWalletLabel">账户余额</span>
|
||
<em id="payBalanceHint">余额 ¥ <span id="selectedWalletBalance">0.00</span></em>
|
||
</div>
|
||
<strong>实付 ¥ <span id="payFooterAmount">--</span></strong>
|
||
</div>
|
||
</div>
|
||
<div class="cxz-dialog-footer">
|
||
<button class="cxz-dialog-confirm" type="button" onclick="okbuy()">
|
||
确认购买
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<footer class="site-footer">
|
||
<div class="site-footer__inner">
|
||
<img
|
||
src="../images/home-logo.png"
|
||
alt="彩先知"
|
||
class="site-footer__logo"
|
||
/>
|
||
<p id="copyright-info">彩先知以开奖数据、免费文章、资讯推荐为核心</p>
|
||
<div class="site-footer__meta">
|
||
<a
|
||
id="beian"
|
||
href="https://beian.miit.gov.cn/"
|
||
target="_blank"
|
||
class="site-footer__beian-link"
|
||
>工信部备案号</a
|
||
>
|
||
<span id="additional-info">本站仅供数据分析参考</span>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<button
|
||
class="gotop"
|
||
id="backTop"
|
||
type="button"
|
||
onclick="window.scrollTo({ top: 0, behavior: 'smooth' })"
|
||
>
|
||
↑
|
||
</button>
|
||
|
||
<script>
|
||
layui.use(["layer", "jquery"], function () {
|
||
var layer = layui.layer;
|
||
var $ = layui.$;
|
||
var pageSize = 50;
|
||
var currentScheme = null;
|
||
var currentSchemes = [];
|
||
var currentPredictMenuId = "";
|
||
var currentPayAmount = 0;
|
||
var currentWalletOverview = {};
|
||
|
||
loadBasicConfig();
|
||
checkLogin();
|
||
renderNav();
|
||
loadScheme();
|
||
loadPredictMenu();
|
||
|
||
window.logout = function () {
|
||
localStorage.removeItem("token");
|
||
window.location.href = "login.html";
|
||
};
|
||
|
||
function esc(value) {
|
||
return CommonUtil.escapeHtml
|
||
? CommonUtil.escapeHtml(value)
|
||
: String(value || "");
|
||
}
|
||
|
||
function firstValue(source, keys, fallback) {
|
||
for (var i = 0; i < keys.length; i += 1) {
|
||
var key = keys[i];
|
||
if (
|
||
source &&
|
||
source[key] !== undefined &&
|
||
source[key] !== null &&
|
||
source[key] !== ""
|
||
)
|
||
return source[key];
|
||
}
|
||
return fallback === undefined ? "" : fallback;
|
||
}
|
||
|
||
function asRows(res) {
|
||
if (Array.isArray(res)) return res;
|
||
if (!res || typeof res !== "object") return [];
|
||
if (Array.isArray(res.rows)) return res.rows;
|
||
if (Array.isArray(res.records)) return res.records;
|
||
if (Array.isArray(res.list)) return res.list;
|
||
var data = ApiClient.pickData
|
||
? ApiClient.pickData(res, [])
|
||
: res.data;
|
||
return ApiClient.asArray ? ApiClient.asArray(data) : [];
|
||
}
|
||
|
||
function cleanParams(params) {
|
||
var result = {};
|
||
Object.keys(params || {}).forEach(function (key) {
|
||
if (
|
||
params[key] !== undefined &&
|
||
params[key] !== null &&
|
||
params[key] !== ""
|
||
)
|
||
result[key] = params[key];
|
||
});
|
||
return result;
|
||
}
|
||
|
||
function loadBasicConfig() {
|
||
Promise.all([
|
||
ApiClient.get("/api/web/config").catch(function () {
|
||
return { data: {} };
|
||
}),
|
||
ApiClient.get("/api/web/config/site").catch(function () {
|
||
return { data: {} };
|
||
}),
|
||
]).then(function (results) {
|
||
if (!CommonUtil.applyWebConfigs) return;
|
||
CommonUtil.applyWebConfigs(
|
||
ApiClient.pickData(results[0], {}) || {},
|
||
);
|
||
CommonUtil.applyWebConfigs(
|
||
ApiClient.pickData(results[1], {}) || {},
|
||
);
|
||
});
|
||
}
|
||
|
||
function checkLogin() {
|
||
if (!ApiClient.getToken()) return;
|
||
$("#notLoggedInBox").hide();
|
||
$("#loggedInBox").removeClass("is-hidden").css("display", "flex");
|
||
CommonUtil.getCurrentUserDetail(
|
||
function (data) {
|
||
if (!data) return;
|
||
$("#userName").text(data.nickName || data.nickname || "用户");
|
||
$("#userLevel").text(
|
||
data.isExpert === "1" || data.isExpert === true
|
||
? "专家"
|
||
: "会员",
|
||
);
|
||
if (data.avatar) $("#userAvatar").attr("src", data.avatar);
|
||
},
|
||
function () {
|
||
$("#notLoggedInBox").show();
|
||
$("#loggedInBox").addClass("is-hidden").hide();
|
||
},
|
||
);
|
||
}
|
||
|
||
function renderNav() {
|
||
ApiClient.get(ApiClient.API.homeNav).then(function (res) {
|
||
if (!ApiClient.isSuccess(res)) return;
|
||
var list = ApiClient.asArray(ApiClient.pickData(res, []));
|
||
var $nav = $("#navLotteryItems");
|
||
$nav.find(".topbar__nav-link").not(":first").remove();
|
||
list
|
||
.filter(function (item) {
|
||
return item.type === "lottery";
|
||
})
|
||
.forEach(function (item) {
|
||
$nav.append(
|
||
'<a href="cai.html?id=' +
|
||
(item.code || item.suoxie || "") +
|
||
'" class="topbar__nav-link">' +
|
||
esc(item.name || "") +
|
||
"</a>",
|
||
);
|
||
});
|
||
});
|
||
}
|
||
|
||
$(window).on("scroll", function () {
|
||
$(window).scrollTop() > 320
|
||
? $("#backTop").addClass("is-visible")
|
||
: $("#backTop").removeClass("is-visible");
|
||
});
|
||
|
||
function schemeIdOf(scheme) {
|
||
return firstValue(
|
||
scheme,
|
||
["id", "schemeId", "goodsId", "productId"],
|
||
"",
|
||
);
|
||
}
|
||
|
||
function schemePriceOf(scheme) {
|
||
return (
|
||
Number(
|
||
firstValue(
|
||
scheme,
|
||
["price", "amount", "coin", "points", "payAmount"],
|
||
0,
|
||
),
|
||
) || 0
|
||
);
|
||
}
|
||
|
||
function isSchemePurchased(scheme) {
|
||
return Boolean(
|
||
scheme &&
|
||
(scheme.isBuy === true ||
|
||
scheme.isBuy === 1 ||
|
||
scheme.isBuy === "1" ||
|
||
scheme.buyStatus === 1 ||
|
||
scheme.buyStatus === "1" ||
|
||
scheme.purchased === true ||
|
||
scheme.purchased === 1 ||
|
||
scheme.purchased === "1" ||
|
||
scheme.isPurchased === true ||
|
||
scheme.isPurchased === 1 ||
|
||
scheme.isPurchased === "1" ||
|
||
scheme.canView === true ||
|
||
scheme.canView === 1 ||
|
||
scheme.canView === "1"),
|
||
);
|
||
}
|
||
|
||
function findCurrentScheme(list) {
|
||
return (
|
||
ApiClient.asArray(list).find(function (item) {
|
||
if (
|
||
String(firstValue(item, ["schemeType", "type"], "")) ===
|
||
"break_group"
|
||
)
|
||
return true;
|
||
return (
|
||
String(
|
||
firstValue(
|
||
item,
|
||
["name", "title", "schemeName", "menuName"],
|
||
"",
|
||
),
|
||
).indexOf("断") >= 0
|
||
);
|
||
}) ||
|
||
ApiClient.asArray(list)[0] ||
|
||
null
|
||
);
|
||
}
|
||
|
||
function mergeSchemeDetail(scheme, detail) {
|
||
var merged = Object.assign({}, scheme || {}, detail || {});
|
||
var mergedId = schemeIdOf(merged);
|
||
if (mergedId) {
|
||
var index = currentSchemes.findIndex(function (item) {
|
||
return String(schemeIdOf(item)) === String(mergedId);
|
||
});
|
||
if (index >= 0) currentSchemes.splice(index, 1, merged);
|
||
else currentSchemes.push(merged);
|
||
}
|
||
if (
|
||
currentScheme &&
|
||
String(schemeIdOf(currentScheme)) === String(mergedId)
|
||
)
|
||
currentScheme = merged;
|
||
return merged;
|
||
}
|
||
|
||
function loadSchemeDetail(scheme) {
|
||
var id = schemeIdOf(scheme);
|
||
if (!id) return Promise.resolve(scheme || null);
|
||
return ApiClient.get(ApiClient.API.fc3dSchemeDetail(id))
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res)) return scheme;
|
||
return mergeSchemeDetail(
|
||
scheme,
|
||
ApiClient.pickData(res, {}) || {},
|
||
);
|
||
})
|
||
.catch(function () {
|
||
return scheme;
|
||
});
|
||
}
|
||
|
||
function renderCurrentScheme(scheme) {
|
||
currentScheme = scheme || null;
|
||
var price = schemePriceOf(currentScheme);
|
||
$("#schemePrice").text(price.toFixed(2));
|
||
$("#schemeSummary").text(
|
||
"购买此方案-此方案适合:所有开奖号码为三个号码,包括前三,后三彩种",
|
||
);
|
||
if (isSchemePurchased(currentScheme)) {
|
||
$("#schemeBuyPanel").hide();
|
||
$("#schemePlanPanel").css("display", "flex");
|
||
} else {
|
||
$("#schemeBuyPanel").css("display", "flex");
|
||
$("#schemePlanPanel").hide();
|
||
}
|
||
}
|
||
|
||
function loadScheme() {
|
||
return ApiClient.get(ApiClient.API.fc3dSchemeList)
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res))
|
||
throw new Error(res.msg || "获取方案失败");
|
||
currentSchemes = asRows(res);
|
||
var scheme = findCurrentScheme(currentSchemes);
|
||
renderCurrentScheme(scheme);
|
||
return loadSchemeDetail(scheme).then(renderCurrentScheme);
|
||
})
|
||
.catch(function () {
|
||
renderCurrentScheme(null);
|
||
});
|
||
}
|
||
|
||
function schemePlanContent(index, scheme) {
|
||
return firstValue(
|
||
scheme || currentScheme,
|
||
[
|
||
"plan" + index,
|
||
"plan" + index + "Content",
|
||
"scheme" + index,
|
||
"scheme" + index + "Content",
|
||
"formula" + index,
|
||
"content" + index,
|
||
index === 1 ? "planOne" : "planTwo",
|
||
index === 1 ? "schemeOne" : "schemeTwo",
|
||
"content",
|
||
"detail",
|
||
"htmlContent",
|
||
],
|
||
"暂无方案内容",
|
||
);
|
||
}
|
||
|
||
function openSchemePlan(index) {
|
||
if (!isSchemePurchased(currentScheme)) {
|
||
layer.msg("购买后可查看方案", { icon: 2 });
|
||
return;
|
||
}
|
||
var loading = layer.load(1);
|
||
loadSchemeDetail(currentScheme).then(function (scheme) {
|
||
layer.close(loading);
|
||
var content = String(schemePlanContent(index, scheme) || "");
|
||
var html = /<[a-z][\s\S]*>/i.test(content)
|
||
? content
|
||
: esc(content).replace(/\n/g, "<br>");
|
||
layer.open({
|
||
type: 1,
|
||
title: "断组方案",
|
||
skin: "cxz-plan-layer",
|
||
area: "760px",
|
||
resize: false,
|
||
shadeClose: true,
|
||
btn: ["我知道了"],
|
||
btnAlign: "c",
|
||
content:
|
||
'<div class="duan-plan-content duan-plan-content--brand"><div class="duan-plan-doc">' +
|
||
html +
|
||
"</div></div>",
|
||
});
|
||
});
|
||
}
|
||
|
||
$(".duan-plan-btn").on("click", function () {
|
||
openSchemePlan(Number($(this).data("plan-index")) || 1);
|
||
});
|
||
|
||
function loadPredictMenu() {
|
||
ApiClient.get(ApiClient.API.fc3dFreePredictMenus)
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res))
|
||
throw new Error(res.msg || "获取断组菜单失败");
|
||
var menus = ApiClient.asArray(ApiClient.pickData(res, []));
|
||
var menu =
|
||
menus.find(function (item) {
|
||
return (
|
||
String(
|
||
item.name || item.title || item.menuName || "",
|
||
).indexOf("断") >= 0
|
||
);
|
||
}) ||
|
||
menus[0] ||
|
||
{};
|
||
currentPredictMenuId = menu.id || menu.menuId || "";
|
||
loadPredictList();
|
||
})
|
||
.catch(function (error) {
|
||
renderPredictRows([], error.message || "获取断组菜单失败");
|
||
});
|
||
}
|
||
|
||
function formatCodeBalls(value) {
|
||
var text = String(value || "");
|
||
if (!text) return "-";
|
||
return text
|
||
.split(/[,\s+]+/)
|
||
.filter(Boolean)
|
||
.map(function (num) {
|
||
return '<span class="duan-code-ball">' + esc(num) + "</span>";
|
||
})
|
||
.join("");
|
||
}
|
||
|
||
function splitRecommend(row) {
|
||
var list = ApiClient.asArray(
|
||
row.recommends ||
|
||
row.recommendList ||
|
||
row.predictList ||
|
||
row.items ||
|
||
row.children,
|
||
);
|
||
if (list.length) {
|
||
return [
|
||
firstValue(
|
||
list[0],
|
||
[
|
||
"code",
|
||
"number",
|
||
"value",
|
||
"recommendCode",
|
||
"predictedCode",
|
||
"content",
|
||
],
|
||
list[0],
|
||
),
|
||
firstValue(
|
||
list[1],
|
||
[
|
||
"code",
|
||
"number",
|
||
"value",
|
||
"recommendCode",
|
||
"predictedCode",
|
||
"content",
|
||
],
|
||
"",
|
||
),
|
||
];
|
||
}
|
||
var text = String(
|
||
firstValue(
|
||
row,
|
||
["predictedCode", "recommendCode", "recommend", "content"],
|
||
"",
|
||
),
|
||
);
|
||
var parts = text.split(/[_;;]+/).filter(Boolean);
|
||
return [parts[0] || text, parts[1] || ""];
|
||
}
|
||
|
||
function predictGroupIndex(row) {
|
||
var name = String(
|
||
firstValue(
|
||
row,
|
||
["typeName", "playName", "menuName", "name", "title"],
|
||
"",
|
||
),
|
||
);
|
||
return /2|二/.test(name) ? 2 : 1;
|
||
}
|
||
|
||
function compactRecommend(pairs) {
|
||
var left = [];
|
||
var right = [];
|
||
pairs.forEach(function (pair) {
|
||
if (pair[0]) left.push(String(pair[0]).trim());
|
||
if (pair[1]) right.push(String(pair[1]).trim());
|
||
});
|
||
return left.join("") + (right.length ? "|" + right.join("") : "");
|
||
}
|
||
|
||
function normalizeCodeList(value) {
|
||
if (Array.isArray(value)) {
|
||
return value
|
||
.map(function (item) {
|
||
return String(item || "").replace(/[^0-9]/g, "");
|
||
})
|
||
.filter(Boolean);
|
||
}
|
||
return String(value || "")
|
||
.split(/[||,,、\s]+/)
|
||
.map(function (item) {
|
||
return item.replace(/[^0-9]/g, "");
|
||
})
|
||
.filter(Boolean);
|
||
}
|
||
|
||
function rowHitCodes(row) {
|
||
return normalizeCodeList(firstValue(row, ["hitCodes", "hitCode", "hitList"], ""));
|
||
}
|
||
|
||
function rowMissCodes(row) {
|
||
return normalizeCodeList(firstValue(row, ["missCodes", "missCode", "missList"], ""));
|
||
}
|
||
|
||
function rowStatus(row) {
|
||
var status = firstValue(row, ["status", "statusText", "resultText"], "");
|
||
if (status) return String(status);
|
||
var result = firstValue(row, ["result", "correct", "isCorrect"], "");
|
||
if (result === -1 || result === "-1" || result === false || result === "false") return "错";
|
||
if (result === 1 || result === "1" || result === true || result === "true") return "正确";
|
||
if (rowMissCodes(row).length) return "错";
|
||
if (rowHitCodes(row).length) return "正确";
|
||
return "待开奖";
|
||
}
|
||
|
||
function groupStatus(items) {
|
||
var statuses = items.map(function (item) {
|
||
return rowStatus(item.row);
|
||
});
|
||
if (statuses.some(function (item) { return /错|错误|error|fail/i.test(item); })) return "错";
|
||
if (statuses.some(function (item) { return /正确|全对|命中/.test(item); })) return "正确";
|
||
return statuses[0] || "待开奖";
|
||
}
|
||
|
||
function statusClass(value) {
|
||
if (/正确|全对|命中/.test(String(value || ""))) return "duan-ok";
|
||
if (/错|错误|待|未|error|fail|pending/i.test(String(value || ""))) return "duan-wrong";
|
||
return "";
|
||
}
|
||
|
||
function collectGroupCodes(items, getter) {
|
||
var map = {};
|
||
items.forEach(function (item) {
|
||
getter(item.row).forEach(function (code) {
|
||
map[code] = true;
|
||
});
|
||
});
|
||
return Object.keys(map);
|
||
}
|
||
|
||
function mergePredictRows(rows) {
|
||
var map = {};
|
||
(rows || []).forEach(function (row) {
|
||
var issue = firstValue(row, ["issue", "expect", "period"], "--");
|
||
var key = [
|
||
firstValue(row, ["lotteryName", "codeName"], "福彩3D"),
|
||
issue,
|
||
].join("_");
|
||
if (!map[key]) {
|
||
map[key] = {
|
||
base: row,
|
||
group1: [],
|
||
group2: [],
|
||
openCode: firstValue(
|
||
row,
|
||
["openCode", "lotteryResult", "resultCode", "openResult"],
|
||
"",
|
||
),
|
||
};
|
||
}
|
||
var recs = splitRecommend(row);
|
||
if (!map[key].openCode)
|
||
map[key].openCode = firstValue(
|
||
row,
|
||
["openCode", "lotteryResult", "resultCode", "openResult"],
|
||
"",
|
||
);
|
||
var item = { row: row, recs: recs };
|
||
if (predictGroupIndex(row) === 2) map[key].group2.push(item);
|
||
else map[key].group1.push(item);
|
||
});
|
||
|
||
return Object.keys(map).map(function (key) {
|
||
var group = map[key];
|
||
var rec1 = compactRecommend(group.group1.map(function (item) { return item.recs; }));
|
||
var rec2 = compactRecommend(group.group2.map(function (item) { return item.recs; }));
|
||
return Object.assign({}, group.base, {
|
||
typeName: "超级断组",
|
||
mergedRecommend1: rec1,
|
||
mergedRecommend2: rec2,
|
||
mergedStatus1: groupStatus(group.group1),
|
||
mergedStatus2: groupStatus(group.group2),
|
||
mergedHitCodes1: collectGroupCodes(group.group1, rowHitCodes),
|
||
mergedHitCodes2: collectGroupCodes(group.group2, rowHitCodes),
|
||
mergedMissCodes1: collectGroupCodes(group.group1, rowMissCodes),
|
||
mergedMissCodes2: collectGroupCodes(group.group2, rowMissCodes),
|
||
openCode: group.openCode,
|
||
});
|
||
});
|
||
}
|
||
|
||
function recommendHtml(value, hitCodes, missCodes, status) {
|
||
var text = String(value || "-").replace(/\s+/g, "");
|
||
var hitMap = {};
|
||
var missMap = {};
|
||
var state = String(status || "");
|
||
(hitCodes || []).forEach(function (code) {
|
||
hitMap[String(code)] = true;
|
||
});
|
||
(missCodes || []).forEach(function (code) {
|
||
missMap[String(code)] = true;
|
||
});
|
||
return text
|
||
.split(/([||,,、])/)
|
||
.map(function (part) {
|
||
if (/^[||,,、]$/.test(part)) return esc(part);
|
||
var code = part.replace(/[^0-9]/g, "");
|
||
if (missMap[code]) {
|
||
return '<span class="duan-rec-miss">' + esc(part) + "</span>";
|
||
}
|
||
if (hitMap[code] || /正确|全对|命中/.test(state)) {
|
||
return '<span class="duan-rec-hit">' + esc(part) + "</span>";
|
||
}
|
||
if (/待|未|pending/i.test(state)) {
|
||
return '<span class="duan-rec-miss">' + esc(part) + "</span>";
|
||
}
|
||
return esc(part);
|
||
})
|
||
.join("");
|
||
}
|
||
|
||
function renderPredictRows(rows, message) {
|
||
var $body = $("#predictBody");
|
||
var mergedRows = mergePredictRows(rows);
|
||
if (!mergedRows.length) {
|
||
$body.html(
|
||
'<tr><td colspan="11"><div class="duan-empty">' +
|
||
esc(message || "暂无断组数据") +
|
||
"</div></td></tr>",
|
||
);
|
||
return;
|
||
}
|
||
$body.html(
|
||
mergedRows
|
||
.map(function (row) {
|
||
var recs = [row.mergedRecommend1, row.mergedRecommend2];
|
||
var copyText = recs.filter(Boolean).join(",");
|
||
var openCode = firstValue(
|
||
row,
|
||
["openCode", "lotteryResult", "resultCode", "openResult"],
|
||
"",
|
||
);
|
||
var price = firstValue(
|
||
row,
|
||
["price", "amount", "coin", "points"],
|
||
"0.00",
|
||
);
|
||
var actionText = firstValue(
|
||
row,
|
||
["actionText", "payText", "freeText"],
|
||
"免费",
|
||
);
|
||
return (
|
||
'<tr title="' +
|
||
esc(copyText) +
|
||
'">' +
|
||
"<td>" +
|
||
esc(
|
||
firstValue(
|
||
row,
|
||
["lotteryName", "name", "codeName"],
|
||
"福彩3D",
|
||
),
|
||
) +
|
||
"</td>" +
|
||
"<td>" +
|
||
esc(
|
||
firstValue(
|
||
row,
|
||
["typeName", "playName", "menuName"],
|
||
"超级断组",
|
||
),
|
||
) +
|
||
"</td>" +
|
||
"<td>" +
|
||
esc(firstValue(row, ["issue", "expect", "period"], "--")) +
|
||
"</td>" +
|
||
'<td><div class="duan-cell">' +
|
||
formatCodeBalls(openCode) +
|
||
"</div></td>" +
|
||
'<td><div class="duan-cell">' +
|
||
recommendHtml(recs[0], row.mergedHitCodes1, row.mergedMissCodes1, row.mergedStatus1) +
|
||
"</div></td>" +
|
||
'<td><span class="' +
|
||
statusClass(row.mergedStatus1) +
|
||
'">' +
|
||
esc(row.mergedStatus1) +
|
||
"</span></td>" +
|
||
'<td><div class="duan-cell">' +
|
||
recommendHtml(recs[1], row.mergedHitCodes2, row.mergedMissCodes2, row.mergedStatus2) +
|
||
"</div></td>" +
|
||
'<td><span class="' +
|
||
statusClass(row.mergedStatus2) +
|
||
'">' +
|
||
esc(row.mergedStatus2) +
|
||
"</span></td>" +
|
||
'<td><button class="duan-copy-btn" type="button" data-copy="' +
|
||
esc(copyText) +
|
||
'">复制</button></td>' +
|
||
"<td>" +
|
||
esc(price) +
|
||
"</td>" +
|
||
"<td>" +
|
||
esc(actionText) +
|
||
"</td>" +
|
||
"</tr>"
|
||
);
|
||
})
|
||
.join(""),
|
||
);
|
||
$(".duan-copy-btn")
|
||
.off("click")
|
||
.on("click", function () {
|
||
var text = $(this).data("copy") || "";
|
||
if (!text) return;
|
||
navigator.clipboard.writeText(String(text)).then(function () {
|
||
layer.msg("复制成功", { icon: 1, time: 1200 });
|
||
});
|
||
});
|
||
}
|
||
|
||
function loadPredictList() {
|
||
if (!currentPredictMenuId) {
|
||
renderPredictRows([], "断组菜单加载失败");
|
||
return;
|
||
}
|
||
$("#predictBody").html(
|
||
'<tr><td colspan="11"><div class="duan-empty">正在加载断组数据...</div></td></tr>',
|
||
);
|
||
ApiClient.get(
|
||
ApiClient.API.fc3dFreePredictList,
|
||
cleanParams({
|
||
menuId: currentPredictMenuId,
|
||
pageNum: 1,
|
||
pageSize: pageSize,
|
||
}),
|
||
)
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res))
|
||
throw new Error(res.msg || "获取断组数据失败");
|
||
renderPredictRows(asRows(res));
|
||
})
|
||
.catch(function (error) {
|
||
renderPredictRows([], error.message || "获取断组数据失败");
|
||
});
|
||
}
|
||
|
||
window.buy = function () {
|
||
if (!ApiClient.getToken()) {
|
||
layer.msg("请先登录后购买", { icon: 2 });
|
||
setTimeout(function () {
|
||
window.location.href = "login.html";
|
||
}, 800);
|
||
return;
|
||
}
|
||
if (!schemeIdOf(currentScheme)) {
|
||
layer.msg("方案信息加载失败,请刷新后重试", { icon: 2 });
|
||
return;
|
||
}
|
||
currentPayAmount = schemePriceOf(currentScheme);
|
||
$("#buyDialog").addClass("active");
|
||
$(".cxz-pay-option").removeClass("selected");
|
||
$('.cxz-pay-option[data-type="account"]').addClass("selected");
|
||
$("#usePoint").prop("checked", false);
|
||
updatePayCalculation();
|
||
loadWalletInfo();
|
||
};
|
||
|
||
window.closeBuyDialog = function () {
|
||
$("#buyDialog").removeClass("active");
|
||
};
|
||
|
||
$("#buyDialog").on("click", function (event) {
|
||
if (event.target === this) closeBuyDialog();
|
||
});
|
||
$(".cxz-dialog-box").on("click", function (event) {
|
||
event.stopPropagation();
|
||
});
|
||
|
||
window.selectPayType = function (element) {
|
||
$(".cxz-pay-option").removeClass("selected");
|
||
$(element).addClass("selected");
|
||
updatePayCalculation();
|
||
};
|
||
|
||
function parseMoney(value) {
|
||
var number = Number(String(value == null ? 0 : value).replace(/[^\d.-]/g, ""));
|
||
return Number.isFinite(number) ? number : 0;
|
||
}
|
||
|
||
function formatMoney(value) {
|
||
var number = Number(value || 0);
|
||
return Number.isFinite(number) ? number.toFixed(2) : "0.00";
|
||
}
|
||
|
||
function formatPoint(value) {
|
||
var number = Number(value || 0);
|
||
return Number.isFinite(number) ? String(Math.floor(number)) : "0";
|
||
}
|
||
|
||
function walletValue(type) {
|
||
var data = currentWalletOverview || {};
|
||
if (type === "sales") {
|
||
return parseMoney(
|
||
firstValue(
|
||
data,
|
||
["salesBalance", "referralBalance", "distributionBalance", "rebateBalance", "saleBalance"],
|
||
0,
|
||
),
|
||
);
|
||
}
|
||
if (type === "expert") {
|
||
return parseMoney(
|
||
firstValue(data, ["expertBalance", "expertCommission", "expertWallet", "commissionBalance"], 0),
|
||
);
|
||
}
|
||
return parseMoney(firstValue(data, ["accountBalance", "balance", "walletBalance"], 0));
|
||
}
|
||
|
||
function pointValue() {
|
||
return parseMoney(firstValue(currentWalletOverview || {}, ["points", "point", "score", "integral"], 0));
|
||
}
|
||
|
||
function currentWalletType() {
|
||
var type = $(".cxz-pay-option.selected").data("type") || "account";
|
||
return type === "sales" || type === "expert" ? type : "account";
|
||
}
|
||
|
||
function walletLabel(type) {
|
||
if (type === "sales") return "分销余额";
|
||
if (type === "expert") return "专家余额";
|
||
return "账户余额";
|
||
}
|
||
|
||
function updatePayCalculation() {
|
||
var walletType = currentWalletType();
|
||
var usePoint = $("#usePoint").prop("checked") === true;
|
||
var pointDeduct = usePoint ? Math.min(currentPayAmount, pointValue()) : 0;
|
||
var finalAmount = Math.max(currentPayAmount - pointDeduct, 0);
|
||
var balance = walletValue(walletType);
|
||
|
||
$("#payOriginalAmount").text(formatMoney(currentPayAmount));
|
||
$("#pointDeductAmount").text(formatMoney(pointDeduct));
|
||
$("#pointDeductPreview").text(formatMoney(pointDeduct));
|
||
$("#payFinalAmount").text(formatMoney(finalAmount));
|
||
$("#payFooterAmount").text(formatMoney(finalAmount));
|
||
$("#selectedWalletLabel").text(walletLabel(walletType));
|
||
$("#selectedWalletBalance").text(formatMoney(balance));
|
||
$("#payBalanceHint").toggleClass("is-insufficient", balance < finalAmount);
|
||
$(".cxz-dialog-confirm").prop("disabled", balance < finalAmount);
|
||
$(".cxz-dialog-confirm").text(balance < finalAmount ? "余额不足" : "确认购买");
|
||
}
|
||
|
||
function loadWalletInfo() {
|
||
ApiClient.get(ApiClient.API.walletOverview)
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res)) return;
|
||
currentWalletOverview = ApiClient.pickData(res, {}) || {};
|
||
$("#accountBalance").text(formatMoney(walletValue("account")));
|
||
$("#distributionBalance").text(formatMoney(walletValue("sales")));
|
||
$("#expertBalance").text(formatMoney(walletValue("expert")));
|
||
$("#pointBalance").text("可用积分 " + formatPoint(pointValue()));
|
||
updatePayCalculation();
|
||
})
|
||
.catch(function () {});
|
||
}
|
||
|
||
$("#usePoint").on("change", updatePayCalculation);
|
||
|
||
window.okbuy = function () {
|
||
var schemeId = schemeIdOf(currentScheme);
|
||
if (!schemeId) {
|
||
layer.msg("方案信息加载失败,请刷新后重试", { icon: 2 });
|
||
return;
|
||
}
|
||
$(".cxz-dialog-confirm").prop("disabled", true).text("购买中...");
|
||
ApiClient.post(ApiClient.API.walletPurchaseFc3dScheme, {
|
||
schemeId: schemeId,
|
||
walletType: currentWalletType(),
|
||
usePoints: $("#usePoint").prop("checked") === true,
|
||
})
|
||
.then(function (res) {
|
||
if (!ApiClient.isSuccess(res))
|
||
throw new Error(res.msg || "购买失败");
|
||
layer.msg("购买成功", { icon: 1, time: 1200 });
|
||
renderCurrentScheme(
|
||
Object.assign({}, currentScheme || {}, { purchased: true }),
|
||
);
|
||
closeBuyDialog();
|
||
loadPredictList();
|
||
})
|
||
.catch(function (error) {
|
||
layer.msg(error.message || "购买失败", { icon: 2 });
|
||
})
|
||
.finally(function () {
|
||
updatePayCalculation();
|
||
});
|
||
};
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|