1659 lines
55 KiB
HTML
1659 lines
55 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/layout-fix.css" />
|
|
<link rel="stylesheet" href="../public/css/usercenter.css" />
|
|
<link rel="stylesheet" href="../public/css/usercenter-signin.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" style="display: none">
|
|
<a href="usercenter.html" class="topbar__profile">
|
|
<img
|
|
id="headerAvatar"
|
|
src="../public/img/userimg.png"
|
|
alt=""
|
|
class="topbar__avatar"
|
|
/>
|
|
<div class="topbar__meta">
|
|
<span id="headerUserName" class="topbar__uname">用户</span>
|
|
<span id="headerUserLevel" class="topbar__ubadge">会员</span>
|
|
</div>
|
|
</a>
|
|
<button
|
|
class="topbar__btn topbar__btn--logout"
|
|
onclick="handleLogout()"
|
|
>
|
|
退出登录
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- ====== Main Content ====== -->
|
|
<div class="uc-container">
|
|
<!-- Profile Card -->
|
|
<div class="uc-profile-card">
|
|
<div class="uc-avatar-wrap">
|
|
<img
|
|
id="userAvatar"
|
|
class="uc-avatar"
|
|
src="../public/img/userimg.png"
|
|
alt="头像"
|
|
onclick="openEditProfile()"
|
|
/>
|
|
</div>
|
|
<div class="uc-info">
|
|
<div class="uc-nickname" id="userNickName">未登录</div>
|
|
<div class="uc-level" id="userLevel">普通会员</div>
|
|
<div class="uc-phone" id="userPhone"></div>
|
|
<div class="wechatBindCard" id="wechat-bind-card">
|
|
<div class="wechatBindTop">
|
|
<div class="wechatBindIconBox">
|
|
<img class="wechatBindIcon" src="../public/img/pay-wechat.png" alt="微信" />
|
|
</div>
|
|
<div class="wechatBindInfo">
|
|
<div class="wechatBindTitle">微信账号</div>
|
|
<div class="wechatBindDesc" id="wechat-bind-desc">检测中...</div>
|
|
</div>
|
|
<div class="wechatBindStateDot"></div>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
class="wechatBindButton"
|
|
id="wechat-bind-button"
|
|
onclick="openWeChatBindPopup()"
|
|
>
|
|
绑定微信
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="uc-actions">
|
|
<button
|
|
class="uc-btn uc-btn-signin"
|
|
id="signInBtn"
|
|
onclick="handleSignIn()"
|
|
>
|
|
每日签到
|
|
</button>
|
|
<button class="uc-btn uc-btn-edit" onclick="openEditProfile()">
|
|
编辑资料
|
|
</button>
|
|
<button
|
|
class="uc-btn uc-btn-edit"
|
|
id="referralBindButton"
|
|
onclick="openReferralBindPrompt()"
|
|
>
|
|
绑定邀请码
|
|
</button>
|
|
<button
|
|
class="uc-btn uc-btn-expert"
|
|
id="expertApplyBtn"
|
|
onclick="NavigationUtil.open('apply.html')"
|
|
>
|
|
专家申请
|
|
</button>
|
|
<button
|
|
class="uc-btn uc-btn-publish"
|
|
id="publishArticleBtn"
|
|
onclick="NavigationUtil.open('fabumianfeiwenzhang.html')"
|
|
>
|
|
发布文章
|
|
</button>
|
|
<button
|
|
class="uc-btn uc-btn-collection"
|
|
onclick="NavigationUtil.open('mianfeishoucang.html?tab=free')"
|
|
>
|
|
我的收藏
|
|
</button>
|
|
<button
|
|
class="uc-btn uc-btn-tuiguang"
|
|
onclick="NavigationUtil.open('tuiguang.html')"
|
|
>
|
|
分享推广
|
|
</button>
|
|
<button class="uc-btn uc-btn-logout2" onclick="handleLogout()">
|
|
退出登录
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- Balance Cards -->
|
|
<div class="uc-balance-grid">
|
|
<div class="uc-balance-item">
|
|
<div class="uc-balance-label">
|
|
<span
|
|
class="balance-icon"
|
|
style="background: var(--gold); color: var(--primary)"
|
|
>P</span
|
|
>
|
|
积分
|
|
</div>
|
|
<div class="uc-balance-value" id="userPoints">0<span>点</span></div>
|
|
<div class="uc-balance-links">
|
|
<a href="jine.html?type=POINTS">明细</a>
|
|
</div>
|
|
</div>
|
|
<div class="uc-balance-item">
|
|
<div class="uc-balance-label">
|
|
<span class="balance-icon" style="background: var(--primary)"
|
|
>B</span
|
|
>
|
|
余额
|
|
</div>
|
|
<div class="uc-balance-value" id="userBalance">0<span>元</span></div>
|
|
<div class="uc-balance-links">
|
|
<a href="jine.html?type=BALANCE">明细</a
|
|
><a href="chongzhi.html">充值</a><a href="tixian.html">提现</a>
|
|
</div>
|
|
</div>
|
|
<div class="uc-balance-item">
|
|
<div class="uc-balance-label">
|
|
<span class="balance-icon" style="background: var(--orange)"
|
|
>S</span
|
|
>
|
|
销售余额
|
|
</div>
|
|
<div class="uc-balance-value" id="userSalesBalance">
|
|
0<span>元</span>
|
|
</div>
|
|
<div class="uc-balance-links">
|
|
<a href="jine.html?type=SALES_BALANCE">明细</a>
|
|
</div>
|
|
</div>
|
|
<div class="uc-balance-item">
|
|
<div class="uc-balance-label">
|
|
<span class="balance-icon" style="background: var(--purple)"
|
|
>E</span
|
|
>
|
|
专家余额
|
|
</div>
|
|
<div class="uc-balance-value" id="userExpertBalance">
|
|
0<span>元</span>
|
|
</div>
|
|
<div class="uc-balance-links">
|
|
<a href="jine.html?type=EXPERT_BALANCE">明细</a
|
|
><a href="tixian.html">提现</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sign-in Records -->
|
|
<div class="uc-section">
|
|
<div class="uc-section-header">
|
|
<div class="uc-section-title">签到记录</div>
|
|
</div>
|
|
<table class="uc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>日期</th>
|
|
<th>类型</th>
|
|
<th>积分变化</th>
|
|
<th>说明</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="signInTableBody">
|
|
<tr>
|
|
<td
|
|
colspan="4"
|
|
style="
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
padding: 30px;
|
|
"
|
|
>
|
|
加载中...
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="uc-pagination" id="signInPager"></div>
|
|
</div>
|
|
|
|
<!-- Free Article Section -->
|
|
<div class="uc-section">
|
|
<div class="uc-section-header">
|
|
<div class="uc-section-title">我的免费文章</div>
|
|
</div>
|
|
<div class="uc-filter-bar">
|
|
<label>彩种:</label>
|
|
<select id="filterLottery"></select>
|
|
<button class="uc-filter-btn" onclick="loadFreeArticles(1)">
|
|
筛选
|
|
</button>
|
|
</div>
|
|
<table class="uc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>标题</th>
|
|
<th>彩种</th>
|
|
<th>方案</th>
|
|
<th>类型</th>
|
|
<th>发布时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="articleTableBody">
|
|
<tr>
|
|
<td
|
|
colspan="6"
|
|
style="
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
padding: 30px;
|
|
"
|
|
>
|
|
加载中...
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="uc-pagination" id="articlePager"></div>
|
|
</div>
|
|
|
|
<!-- Paid Article Section -->
|
|
<div class="uc-section">
|
|
<div class="uc-section-header">
|
|
<div class="uc-section-title">我的付费文章</div>
|
|
</div>
|
|
<div class="uc-filter-bar">
|
|
<label>彩种:</label>
|
|
<select
|
|
id="paidFilterLottery"
|
|
onchange="onPaidLotteryChange()"
|
|
></select>
|
|
<label>方案:</label>
|
|
<select id="paidFilterPlan" onchange="onPaidPlanChange()">
|
|
<option value="">请选择方案</option>
|
|
</select>
|
|
<label>类型:</label>
|
|
<select id="paidFilterType">
|
|
<option value="">请选择类型</option>
|
|
</select>
|
|
<button class="uc-filter-btn" onclick="loadPaidArticles(1)">
|
|
筛选
|
|
</button>
|
|
</div>
|
|
<table class="uc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>标题</th>
|
|
<th>彩种</th>
|
|
<th>价格</th>
|
|
<th>发布时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="paidArticleTableBody">
|
|
<tr>
|
|
<td
|
|
colspan="5"
|
|
style="
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
padding: 30px;
|
|
"
|
|
>
|
|
加载中...
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="uc-pagination" id="paidArticlePager"></div>
|
|
</div>
|
|
|
|
<!-- Purchase Records Section -->
|
|
<div class="uc-section">
|
|
<div class="uc-section-header">
|
|
<div class="uc-section-title">我的购买记录</div>
|
|
</div>
|
|
<table class="uc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>类型</th>
|
|
<th>商品名称</th>
|
|
<th>期号</th>
|
|
<th>专家</th>
|
|
<th>购买时间</th>
|
|
<th>金额</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="purchaseTableBody">
|
|
<tr>
|
|
<td
|
|
colspan="7"
|
|
style="
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
padding: 30px;
|
|
"
|
|
>
|
|
加载中...
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="uc-pagination" id="purchasePager"></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"
|
|
style="font-size: 12px; color: rgba(255, 255, 255, 0.5)"
|
|
>工信部备案号</a
|
|
>
|
|
<span id="additional-info">本站仅供数据分析参考</span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
<button
|
|
class="gotop"
|
|
id="backTop"
|
|
type="button"
|
|
onclick="window.scrollTo({ top: 0, behavior: 'smooth' })"
|
|
>
|
|
↑
|
|
</button>
|
|
|
|
<div id="mask-layer"></div>
|
|
<div id="wechat-bind-popup">
|
|
<div class="wechatBindPopupHeader">
|
|
<div>
|
|
<div class="wechatBindPopupTitle">绑定微信</div>
|
|
<div class="wechatBindPopupSub">绑定后可使用微信快捷登录当前账号</div>
|
|
</div>
|
|
<div class="popup-close" onclick="closeWeChatBindPopup()">
|
|
<i class="layui-icon layui-icon-close"></i>
|
|
</div>
|
|
</div>
|
|
<div class="wechatBindPopupBody">
|
|
<div class="wechatBindFormRow">
|
|
<label>手机号</label>
|
|
<input id="wechatBindPhone" type="text" placeholder="请输入手机号" />
|
|
</div>
|
|
<div class="wechatBindFormRow">
|
|
<label>短信验证码</label>
|
|
<div class="wechatBindCodeBox">
|
|
<input id="wechatBindSmsCode" type="text" placeholder="请输入验证码" />
|
|
<button type="button" onclick="sendWeChatBindSms()">获取验证码</button>
|
|
</div>
|
|
</div>
|
|
<div class="wechatBindFormRow">
|
|
<label>登录密码</label>
|
|
<input id="wechatBindPassword" type="password" placeholder="请输入登录密码" />
|
|
</div>
|
|
<div class="wechatBindTip">当前接口需要微信授权参数、手机号、短信验证码和密码。</div>
|
|
<button type="button" class="wechatBindSubmit" onclick="submitWeChatBind()">确认绑定</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="../public/js/md5.js"></script>
|
|
<script>
|
|
const $ = layui.$;
|
|
var currentUserData = null;
|
|
var accountInfoData = {};
|
|
var menuListData = [];
|
|
var signInPageNum = 1;
|
|
var articlePageNum = 1;
|
|
var pageSize = 10;
|
|
var signedToday = false;
|
|
|
|
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 pageRows(res) {
|
|
return ApiClient.asArray(ApiClient.pickData(res, {}));
|
|
}
|
|
|
|
function pageTotal(res) {
|
|
var data = ApiClient.pickData(res, {}) || {};
|
|
return Number(data.totalRow || data.total || res.total || 0);
|
|
}
|
|
|
|
function money(value) {
|
|
var number = Number(value || 0);
|
|
return Number.isFinite(number) ? number.toFixed(2) : "0.00";
|
|
}
|
|
|
|
function safeText(value) {
|
|
return CommonUtil.escapeHtml
|
|
? CommonUtil.escapeHtml(value)
|
|
: String(value || "");
|
|
}
|
|
|
|
function setSignInButtonSigned(signed) {
|
|
signedToday = !!signed;
|
|
var $btn = $("#signInBtn");
|
|
$btn.text(signedToday ? "已签到" : "每日签到");
|
|
$btn.prop("disabled", signedToday);
|
|
$btn.toggleClass("is-signed", signedToday);
|
|
}
|
|
|
|
function hasSignedTodayValue(data) {
|
|
return (
|
|
data &&
|
|
(data.signedToday !== undefined ||
|
|
data.todaySigned !== undefined ||
|
|
data.isSignedToday !== undefined)
|
|
);
|
|
}
|
|
|
|
function readSignedToday(data) {
|
|
var value = firstValue(
|
|
data,
|
|
["signedToday", "todaySigned", "isSignedToday"],
|
|
false,
|
|
);
|
|
return value === true || value === 1 || value === "1";
|
|
}
|
|
|
|
function isExpertUser(data) {
|
|
if (!data) return false;
|
|
var levelText = CommonUtil.getUserLevelText
|
|
? CommonUtil.getUserLevelText(data)
|
|
: "";
|
|
return (
|
|
data.expert === true ||
|
|
data.regularExpert === true ||
|
|
data.internExpert === true ||
|
|
data.isExpert === true ||
|
|
data.isExpert === 1 ||
|
|
data.isExpert === "1" ||
|
|
/专家/.test(levelText || "") ||
|
|
/regular|intern|formal|trial|expert|实习|正式/.test(
|
|
String(data.expertStatus || data.expert_status || "")
|
|
)
|
|
);
|
|
}
|
|
|
|
function updateExpertActions(data) {
|
|
var state = CommonUtil.getExpertState
|
|
? CommonUtil.getExpertState(data)
|
|
: { isExpert: isExpertUser(data), isApplying: false };
|
|
var $applyBtn = $("#expertApplyBtn");
|
|
var $publishBtn = $("#publishArticleBtn");
|
|
$publishBtn.toggle(state.isExpert);
|
|
$applyBtn.toggle(!state.isExpert);
|
|
if (state.isExpert) {
|
|
return;
|
|
}
|
|
$applyBtn
|
|
.text(state.isApplying ? "申请审核中" : "专家申请")
|
|
.prop("disabled", !!state.isApplying);
|
|
if (state.isApplying) {
|
|
$applyBtn.removeAttr("onclick");
|
|
} else {
|
|
$applyBtn.attr("onclick", "NavigationUtil.open('apply.html')");
|
|
}
|
|
}
|
|
|
|
function loadAccountInfoForWechat() {
|
|
ApiClient.get(ApiClient.API.accountInfo, null, { headers: CommonUtil.authHeaders() })
|
|
.then(function (res) {
|
|
accountInfoData = ApiClient.isSuccess(res) && res.data ? res.data : {};
|
|
updateWechatBindPanel();
|
|
})
|
|
.catch(function () {
|
|
accountInfoData = {};
|
|
updateWechatBindPanel();
|
|
});
|
|
}
|
|
|
|
function isWechatBound() {
|
|
var data = Object.assign({}, currentUserData || {}, accountInfoData || {});
|
|
return Boolean(
|
|
data.openId ||
|
|
data.openid ||
|
|
data.wxOpenId ||
|
|
data.wechatOpenId ||
|
|
data.wechatOpenid ||
|
|
data.unionId ||
|
|
data.wechatUnionId ||
|
|
data.wechatBound ||
|
|
data.isWechatBound,
|
|
);
|
|
}
|
|
|
|
function updateWechatBindPanel() {
|
|
var $desc = $("#wechat-bind-desc");
|
|
var $button = $("#wechat-bind-button");
|
|
var $card = $("#wechat-bind-card");
|
|
if (!$desc.length || !$button.length) return;
|
|
|
|
$card.removeClass("is-bound is-pending is-ready");
|
|
if (isWechatBound()) {
|
|
$desc.text("微信已绑定");
|
|
$card.addClass("is-bound");
|
|
$button
|
|
.text("已绑定")
|
|
.removeClass("is-pending")
|
|
.addClass("is-bound")
|
|
.prop("disabled", true);
|
|
return;
|
|
}
|
|
|
|
$desc.text("未绑定微信");
|
|
$card.addClass("is-ready");
|
|
$button
|
|
.text("绑定微信")
|
|
.removeClass("is-bound is-pending")
|
|
.prop("disabled", false);
|
|
}
|
|
|
|
function getWechatAuthParams() {
|
|
var params = new URLSearchParams(window.location.search);
|
|
return {
|
|
socialCode: params.get("socialCode") || params.get("code") || "",
|
|
socialState: params.get("socialState") || params.get("state") || "",
|
|
};
|
|
}
|
|
|
|
function openWeChatBindPopup() {
|
|
var authParams = getWechatAuthParams();
|
|
if (isWechatBound()) {
|
|
layui.layer.msg("当前账号已绑定微信", { icon: 1 });
|
|
return;
|
|
}
|
|
if (!authParams.socialCode) {
|
|
layui.layer.msg("请先通过微信授权入口进入绑定流程", { icon: 0 });
|
|
return;
|
|
}
|
|
|
|
$("#wechatBindPhone").val(
|
|
(currentUserData && currentUserData.phoneNumber) ||
|
|
accountInfoData.phoneNumber ||
|
|
"",
|
|
);
|
|
$("#wechatBindSmsCode").val("");
|
|
$("#wechatBindPassword").val("");
|
|
$("#mask-layer").show();
|
|
$("#wechat-bind-popup").show();
|
|
}
|
|
|
|
function closeWeChatBindPopup() {
|
|
$("#wechat-bind-popup").hide();
|
|
$("#mask-layer").hide();
|
|
}
|
|
|
|
function sendWeChatBindSms() {
|
|
var phoneNumber = $("#wechatBindPhone").val().trim();
|
|
if (!phoneNumber) {
|
|
layui.layer.msg("请输入手机号", { icon: 2 });
|
|
return;
|
|
}
|
|
|
|
ApiClient.get(ApiClient.API.authSocialBindPhoneSmsCode, {
|
|
phoneNumber: phoneNumber,
|
|
}).then(function (res) {
|
|
if (ApiClient.isSuccess(res)) {
|
|
layui.layer.msg("验证码已发送", { icon: 1 });
|
|
} else {
|
|
layui.layer.msg(res.msg || "验证码发送失败", { icon: 2 });
|
|
}
|
|
});
|
|
}
|
|
|
|
function submitWeChatBind() {
|
|
var authParams = getWechatAuthParams();
|
|
var phoneNumber = $("#wechatBindPhone").val().trim();
|
|
var smsCode = $("#wechatBindSmsCode").val().trim();
|
|
var password = $("#wechatBindPassword").val();
|
|
|
|
if (!authParams.socialCode) {
|
|
layui.layer.msg("缺少微信授权参数", { icon: 2 });
|
|
return;
|
|
}
|
|
if (!phoneNumber || !smsCode || !password) {
|
|
layui.layer.msg("请完整填写绑定信息", { icon: 2 });
|
|
return;
|
|
}
|
|
|
|
ApiClient.post(ApiClient.API.authSocialBind, {
|
|
source: "wechat_open",
|
|
socialCode: authParams.socialCode,
|
|
socialState: authParams.socialState,
|
|
phoneNumber: phoneNumber,
|
|
smsCode: smsCode,
|
|
password: hex_md5(password),
|
|
}).then(function (res) {
|
|
if (ApiClient.isSuccess(res)) {
|
|
layui.layer.msg("微信绑定成功", { icon: 1 });
|
|
try {
|
|
sessionStorage.setItem("wechatAccountBindSuccess", "1");
|
|
} catch (e) {}
|
|
closeWeChatBindPopup();
|
|
loadUserDetail();
|
|
} else {
|
|
layui.layer.msg(res.msg || "微信绑定失败", { icon: 2 });
|
|
}
|
|
});
|
|
}
|
|
|
|
function isTodayTime(value) {
|
|
if (!value) return false;
|
|
var dateText = String(value).slice(0, 10);
|
|
var today = new Date();
|
|
var month = String(today.getMonth() + 1).padStart(2, "0");
|
|
var day = String(today.getDate()).padStart(2, "0");
|
|
return dateText === today.getFullYear() + "-" + month + "-" + day;
|
|
}
|
|
|
|
// ====== Auth Check ======
|
|
function checkAuth() {
|
|
var token = localStorage.getItem("token");
|
|
if (!token) {
|
|
layui.use("layer", function () {
|
|
layui.layer.confirm(
|
|
"请先登录",
|
|
{ btn: ["去登录", "取消"] },
|
|
function (index) {
|
|
layui.layer.close(index);
|
|
NavigationUtil.open("login.html");
|
|
},
|
|
);
|
|
});
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ====== Header Login State ======
|
|
function updateHeaderState() {
|
|
var token = localStorage.getItem("token");
|
|
if (token) {
|
|
$("#notLoggedInBox").hide();
|
|
$("#loggedInBox").show();
|
|
} else {
|
|
$("#notLoggedInBox").show();
|
|
$("#loggedInBox").hide();
|
|
}
|
|
}
|
|
|
|
// ====== Load User Detail ======
|
|
function loadUserDetail() {
|
|
CommonUtil.getCurrentUserDetail(
|
|
function (data) {
|
|
currentUserData = data;
|
|
$("#userNickName").text(data.nickName || "用户");
|
|
$("#userAvatar").attr(
|
|
"src",
|
|
data.avatar || "../public/img/userimg.png",
|
|
);
|
|
$("#headerAvatar").attr(
|
|
"src",
|
|
data.avatar || "../public/img/userimg.png",
|
|
);
|
|
$("#headerUserName").text(data.nickName || "用户");
|
|
$("#userPhone").text(
|
|
data.phoneNumber
|
|
? data.phoneNumber.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")
|
|
: "",
|
|
);
|
|
$("#userLevel").text(
|
|
CommonUtil.getUserLevelText
|
|
? CommonUtil.getUserLevelText(data)
|
|
: data.isExpert === "1"
|
|
? "专家"
|
|
: "普通会员",
|
|
);
|
|
updateExpertActions(data);
|
|
loadAccountInfoForWechat();
|
|
$("#userPoints").html((data.points || 0) + "<span>点</span>");
|
|
if (hasSignedTodayValue(data)) {
|
|
setSignInButtonSigned(readSignedToday(data));
|
|
}
|
|
loadWalletOverview();
|
|
},
|
|
function () {
|
|
layui.use("layer", function () {
|
|
layui.layer.msg("登录已过期,请重新登录", { icon: 2 });
|
|
});
|
|
localStorage.removeItem("token");
|
|
setTimeout(function () {
|
|
NavigationUtil.open("login.html");
|
|
}, 1500);
|
|
},
|
|
);
|
|
}
|
|
|
|
function loadWalletOverview() {
|
|
ApiClient.get(
|
|
ApiClient.API.walletOverview,
|
|
null,
|
|
{ headers: CommonUtil.authHeaders() },
|
|
)
|
|
.then(function (res) {
|
|
if (!ApiClient.isSuccess(res)) return;
|
|
var data = ApiClient.pickData(res, {}) || {};
|
|
$("#userBalance").html(
|
|
money(
|
|
firstValue(data, ["accountBalance", "balance", "walletBalance"], 0),
|
|
) + "<span>元</span>",
|
|
);
|
|
$("#userSalesBalance").html(
|
|
money(
|
|
firstValue(
|
|
data,
|
|
["salesBalance", "distributionBalance", "referralBalance", "rebateBalance"],
|
|
0,
|
|
),
|
|
) + "<span>元</span>",
|
|
);
|
|
$("#userExpertBalance").html(
|
|
money(
|
|
firstValue(data, ["expertBalance", "expertCommission", "expertWallet"], 0),
|
|
) + "<span>元</span>",
|
|
);
|
|
})
|
|
.catch(function () {});
|
|
}
|
|
|
|
// ====== Sign In ======
|
|
function handleSignIn() {
|
|
if (signedToday || $("#signInBtn").prop("disabled")) return;
|
|
CommonUtil.signIn(function (res) {
|
|
if (ApiClient.isSuccess ? ApiClient.isSuccess(res) : res.code === 0) {
|
|
setSignInButtonSigned(true);
|
|
loadUserDetail();
|
|
loadSignInRecords(1);
|
|
}
|
|
});
|
|
}
|
|
|
|
// ====== Logout ======
|
|
function handleLogout() {
|
|
ApiClient.post(ApiClient.API.authLogout, null, { headers: CommonUtil.authHeaders() })
|
|
.then(function (res) {
|
|
localStorage.removeItem("token");
|
|
NavigationUtil.open("login.html");
|
|
})
|
|
.catch(function () {
|
|
localStorage.removeItem("token");
|
|
NavigationUtil.open("login.html");
|
|
});
|
|
}
|
|
|
|
function bindReferralInviteCode(inviteCode) {
|
|
var $button = $("#referralBindButton");
|
|
$button.prop("disabled", true).text("绑定中...");
|
|
ApiClient.post(ApiClient.API.referralBind, { inviteCode: inviteCode })
|
|
.then(function (res) {
|
|
if (!ApiClient.isSuccess(res)) {
|
|
throw new Error((res && res.msg) || "邀请码绑定失败");
|
|
}
|
|
$button.text("已绑定");
|
|
layui.layer.msg("邀请码绑定成功", { icon: 1 });
|
|
})
|
|
.catch(function (error) {
|
|
$button.prop("disabled", false).text("绑定邀请码");
|
|
layui.layer.msg(error.message || "邀请码绑定失败,请稍后重试", { icon: 2 });
|
|
});
|
|
}
|
|
|
|
function openReferralBindPrompt() {
|
|
layui.layer.prompt(
|
|
{ title: "请输入邀请人的邀请码", formType: 0, btn: ["下一步", "取消"] },
|
|
function (value, promptIndex) {
|
|
var inviteCode = String(value || "").trim();
|
|
if (!inviteCode) {
|
|
layui.layer.msg("请输入邀请码", { icon: 2 });
|
|
return;
|
|
}
|
|
layui.layer.close(promptIndex);
|
|
layui.layer.confirm(
|
|
"每个账号只能绑定一个邀请人,绑定后不能更换。确认继续吗?",
|
|
{ title: "确认绑定", btn: ["确认绑定", "取消"] },
|
|
function (confirmIndex) {
|
|
layui.layer.close(confirmIndex);
|
|
bindReferralInviteCode(inviteCode);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
// ====== Sign-in Records ======
|
|
function loadSignInRecords(pageNum) {
|
|
signInPageNum = pageNum || 1;
|
|
ApiClient.get(
|
|
ApiClient.API.mineSignInList,
|
|
{
|
|
pageNum: signInPageNum,
|
|
pageSize: 5,
|
|
pointsType: 1,
|
|
},
|
|
{ headers: CommonUtil.authHeaders() },
|
|
).then(function (res) {
|
|
if (res.code === 0 && res.data) {
|
|
renderSignInTable(res.data.records || []);
|
|
renderSignInPager(res.data.totalRow || res.data.total || 0);
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderSignInTable(records) {
|
|
var $tbody = $("#signInTableBody");
|
|
$tbody.empty();
|
|
if (!records || records.length === 0) {
|
|
$tbody.html(
|
|
'<tr><td colspan="4" style="text-align:center;color:var(--text-muted);padding:30px;">暂无签到记录</td></tr>',
|
|
);
|
|
return;
|
|
}
|
|
$.each(records, function (i, item) {
|
|
if (isTodayTime(item.createTime || item.signTime || item.signDate)) {
|
|
setSignInButtonSigned(true);
|
|
}
|
|
$tbody.append(
|
|
"<tr>" +
|
|
"<td>" +
|
|
(item.createTime || "") +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.pointsType == 1 ? "签到" : item.pointsType || "") +
|
|
"</td>" +
|
|
'<td style="color:var(--orange);font-weight:600;">+' +
|
|
(item.pointsAwarded || 0) +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.remark || "每日签到") +
|
|
"</td>" +
|
|
"</tr>",
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderSignInPager(total) {
|
|
var laypage = layui.laypage;
|
|
laypage.render({
|
|
elem: "signInPager",
|
|
count: total,
|
|
limit: 5,
|
|
curr: signInPageNum,
|
|
theme: "#102b6a",
|
|
jump: function (obj, first) {
|
|
if (!first) loadSignInRecords(obj.curr);
|
|
},
|
|
});
|
|
}
|
|
|
|
// ====== Load Menu for Filter ======
|
|
function loadMenuList() {
|
|
ApiClient.loadMenuCompat().then(function (res) {
|
|
if (res.code === 0 && res.data) {
|
|
menuListData = res.data;
|
|
// 免费文章 - 只需彩种
|
|
var $lottery = $("#filterLottery");
|
|
$lottery.empty();
|
|
$.each(res.data, function (i, lottery) {
|
|
$lottery.append(
|
|
'<option value="' +
|
|
lottery.id +
|
|
'">' +
|
|
lottery.name +
|
|
"</option>",
|
|
);
|
|
});
|
|
// 付费文章 - 三级联动,默认选第一个
|
|
var $paidLottery = $("#paidFilterLottery");
|
|
$paidLottery.empty();
|
|
$.each(res.data, function (i, lottery) {
|
|
$paidLottery.append(
|
|
'<option value="' +
|
|
lottery.id +
|
|
'">' +
|
|
lottery.name +
|
|
"</option>",
|
|
);
|
|
});
|
|
// 触发联动:加载第一个彩种的方案和类型
|
|
if (res.data.length > 0) {
|
|
onPaidLotteryChange();
|
|
var firstPlan = $("#paidFilterPlan option:not(:first)").val();
|
|
if (firstPlan) {
|
|
$("#paidFilterPlan").val(firstPlan);
|
|
onPaidPlanChange();
|
|
var firstType = $("#paidFilterType option:not(:first)").val();
|
|
if (firstType) {
|
|
$("#paidFilterType").val(firstType);
|
|
}
|
|
}
|
|
}
|
|
loadFreeArticles(1);
|
|
loadPaidArticles(1);
|
|
}
|
|
});
|
|
}
|
|
|
|
// ====== Free Articles ======
|
|
function loadFreeArticles(pageNum) {
|
|
articlePageNum = pageNum || 1;
|
|
var menuId = $("#filterLottery").val() || "";
|
|
ApiClient.get(
|
|
ApiClient.API.mineFreeArticleList,
|
|
{
|
|
menuId: menuId,
|
|
pageNum: articlePageNum,
|
|
pageSize: pageSize,
|
|
},
|
|
{ headers: CommonUtil.authHeaders() },
|
|
).then(function (res) {
|
|
if (ApiClient.isSuccess(res)) {
|
|
renderArticleTable(pageRows(res));
|
|
renderArticlePager(pageTotal(res));
|
|
} else {
|
|
renderArticleTable([]);
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderArticleTable(records) {
|
|
var $tbody = $("#articleTableBody");
|
|
$tbody.empty();
|
|
if (!records || records.length === 0) {
|
|
$tbody.html(
|
|
'<tr><td colspan="6" style="text-align:center;color:var(--text-muted);padding:30px;">暂无文章</td></tr>',
|
|
);
|
|
return;
|
|
}
|
|
$.each(records, function (i, item) {
|
|
$tbody.append(
|
|
"<tr>" +
|
|
'<td><a href="' +
|
|
CommonUtil.freeArticleHref(item.id || "") +
|
|
'" target="_blank">' +
|
|
(item.title || item.articleTitle || item.name || "") +
|
|
"</a></td>" +
|
|
"<td>" +
|
|
(item.lotteryName || item.menuName || item.codeName || "") +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.planName || item.schemeName || item.groupName || item.playName || "") +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.typeName || item.categoryName || item.menuTypeName || "") +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.createTime || "") +
|
|
"</td>" +
|
|
'<td><a href="' +
|
|
CommonUtil.freeArticleHref(item.id || "") +
|
|
'" target="_blank">查看</a></td>' +
|
|
"</tr>",
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderArticlePager(total) {
|
|
layui.laypage.render({
|
|
elem: "articlePager",
|
|
count: total,
|
|
limit: pageSize,
|
|
curr: articlePageNum,
|
|
theme: "#102b6a",
|
|
jump: function (obj, first) {
|
|
if (!first) loadFreeArticles(obj.curr);
|
|
},
|
|
});
|
|
}
|
|
|
|
// ====== Paid Articles ======
|
|
var paidArticlePageNum = 1;
|
|
|
|
function onPaidLotteryChange() {
|
|
var lotteryId = $("#paidFilterLottery").val();
|
|
var $plan = $("#paidFilterPlan");
|
|
var $type = $("#paidFilterType");
|
|
$plan.html('<option value="">请选择方案</option>');
|
|
$type.html('<option value="">请选择类型</option>');
|
|
if (lotteryId) {
|
|
var selected = menuListData.find(function (item) {
|
|
return item.id == lotteryId;
|
|
});
|
|
if (selected && selected.children) {
|
|
var plans = CommonUtil.filterDuanzu(
|
|
selected.children,
|
|
selected.name || selected.lotteryName || "",
|
|
);
|
|
$.each(plans, function (i, plan) {
|
|
$plan.append(
|
|
'<option value="' + plan.id + '">' + plan.name + "</option>",
|
|
);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function onPaidPlanChange() {
|
|
var lotteryId = $("#paidFilterLottery").val();
|
|
var planId = $("#paidFilterPlan").val();
|
|
var $type = $("#paidFilterType");
|
|
$type.html('<option value="">请选择类型</option>');
|
|
if (lotteryId && planId) {
|
|
var selected = menuListData.find(function (item) {
|
|
return item.id == lotteryId;
|
|
});
|
|
if (selected && selected.children) {
|
|
var plan = selected.children.find(function (item) {
|
|
return item.id == planId;
|
|
});
|
|
if (plan && plan.children) {
|
|
$.each(plan.children, function (i, type) {
|
|
$type.append(
|
|
'<option value="' + type.id + '">' + type.name + "</option>",
|
|
);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function buildPaidArticleHref(item) {
|
|
var params = new URLSearchParams();
|
|
var articleId = item.id || item.articleId || item.payArticleId || "";
|
|
if (articleId) params.set("articleId", articleId);
|
|
if (item.expertId || item.createBy) params.set("expertId", item.expertId || item.createBy);
|
|
if (item.code || item.lotteryCode || item.menuCode) params.set("code", item.code || item.lotteryCode || item.menuCode);
|
|
if (item.menuId || item.parentId || item.lotteryId) params.set("menuId", item.menuId || item.parentId || item.lotteryId);
|
|
if (item.accountType) params.set("accountType", item.accountType);
|
|
return params.toString() ? "caiinfo.html?" + params.toString() : "cai.html";
|
|
}
|
|
|
|
function loadPaidArticles(pageNum) {
|
|
paidArticlePageNum = pageNum || 1;
|
|
var menuId =
|
|
$("#paidFilterType").val() ||
|
|
$("#paidFilterPlan").val() ||
|
|
$("#paidFilterLottery").val() ||
|
|
"";
|
|
ApiClient.get(
|
|
ApiClient.API.minePayArticleList,
|
|
{
|
|
menuId: menuId,
|
|
pageNum: paidArticlePageNum,
|
|
pageSize: pageSize,
|
|
},
|
|
{ headers: CommonUtil.authHeaders() },
|
|
).then(function (res) {
|
|
if (ApiClient.isSuccess(res)) {
|
|
renderPaidArticleTable(pageRows(res));
|
|
renderPaidArticlePager(pageTotal(res));
|
|
} else {
|
|
renderPaidArticleTable([]);
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderPaidArticleTable(records) {
|
|
var $tbody = $("#paidArticleTableBody");
|
|
$tbody.empty();
|
|
if (!records || records.length === 0) {
|
|
$tbody.html(
|
|
'<tr><td colspan="5" style="text-align:center;color:var(--text-muted);padding:30px;">暂无付费文章</td></tr>',
|
|
);
|
|
return;
|
|
}
|
|
$.each(records, function (i, item) {
|
|
$tbody.append(
|
|
"<tr>" +
|
|
'<td><a href="' +
|
|
buildPaidArticleHref(item) +
|
|
'" target="_blank">' +
|
|
(item.title || item.articleTitle || item.name || "") +
|
|
"</a></td>" +
|
|
"<td>" +
|
|
(item.lotteryName || item.menuName || item.codeName || "") +
|
|
"</td>" +
|
|
'<td style="color:var(--orange);font-weight:600;">' +
|
|
(item.price || item.amount || item.payAmount || 0) +
|
|
(item.payUnit || item.unit || "积分") +
|
|
"</td>" +
|
|
"<td>" +
|
|
(item.createTime || "") +
|
|
"</td>" +
|
|
'<td><a href="' +
|
|
buildPaidArticleHref(item) +
|
|
'" target="_blank">查看</a></td>' +
|
|
"</tr>",
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderPaidArticlePager(total) {
|
|
layui.laypage.render({
|
|
elem: "paidArticlePager",
|
|
count: total,
|
|
limit: pageSize,
|
|
curr: paidArticlePageNum,
|
|
theme: "#102b6a",
|
|
jump: function (obj, first) {
|
|
if (!first) loadPaidArticles(obj.curr);
|
|
},
|
|
});
|
|
}
|
|
|
|
// ====== Purchase Records ======
|
|
var purchasePageNum = 1;
|
|
var purchaseTotalRow = 0;
|
|
|
|
function loadPurchaseRecords(pageNum) {
|
|
purchasePageNum = pageNum || 1;
|
|
ApiClient.get(
|
|
ApiClient.API.minePurchasedPayArticleList,
|
|
{
|
|
pageNum: purchasePageNum,
|
|
pageSize: pageSize,
|
|
},
|
|
{ headers: CommonUtil.authHeaders() },
|
|
)
|
|
.then(function (res) {
|
|
if (ApiClient.isSuccess(res)) {
|
|
purchaseTotalRow = pageTotal(res);
|
|
renderPurchaseTable(pageRows(res));
|
|
renderPurchasePager(purchaseTotalRow);
|
|
} else {
|
|
purchaseTotalRow = 0;
|
|
renderPurchaseTable([]);
|
|
}
|
|
})
|
|
.catch(function () {
|
|
purchaseTotalRow = 0;
|
|
renderPurchaseTable([]);
|
|
});
|
|
}
|
|
|
|
function purchaseSourceText(item) {
|
|
var source = String(firstValue(item, ["sourceType", "type", "bizType"], ""));
|
|
if (source === "fc3d_scheme") return "方案";
|
|
if (source === "pay_article") return "付费文章";
|
|
if (/方案|断组|杀组合/.test(String(firstValue(item, ["title", "goodsName", "productName"], "")))) return "方案";
|
|
return "付费文章";
|
|
}
|
|
|
|
function purchaseTitle(item) {
|
|
return firstValue(
|
|
item,
|
|
["title", "articleTitle", "goodsName", "productName", "schemeName", "name"],
|
|
"未命名商品",
|
|
);
|
|
}
|
|
|
|
function purchaseIssueText(item) {
|
|
var issue = firstValue(item, ["issue", "issueNo", "period", "expect"], "");
|
|
var start = firstValue(item, ["issueStartNo", "startIssue"], "");
|
|
var end = firstValue(item, ["issueEndNo", "endIssue"], "");
|
|
if (issue) return issue;
|
|
if (start && end && String(start) !== String(end)) return start + "-" + end;
|
|
return start || end || "-";
|
|
}
|
|
|
|
function purchaseAmountText(item) {
|
|
var amount = firstValue(item, ["paidAmount", "payAmount", "amount", "price", "totalAmount"], 0);
|
|
return money(amount) + (item.payUnit || item.unit || "积分");
|
|
}
|
|
|
|
function purchaseDeleteSourceType(item) {
|
|
var directSourceType = firstValue(item, ["sourceType", "recordSourceType", "bizSourceType", "type", "bizType"], "");
|
|
var sourceTypeText = String(directSourceType || "").toLowerCase();
|
|
if (/fc3d|scheme/.test(sourceTypeText) || /方案/.test(String(directSourceType || ""))) {
|
|
return "fc3d_scheme";
|
|
}
|
|
if (/pay[_-]?article|article|preorder/.test(sourceTypeText) || /预购|付费文章/.test(String(directSourceType || ""))) {
|
|
return "pay_article";
|
|
}
|
|
|
|
return /断组|杀组合|方案/.test(purchaseTitle(item))
|
|
? "fc3d_scheme"
|
|
: "pay_article";
|
|
}
|
|
|
|
function purchaseDeleteRecordId(item) {
|
|
return firstValue(
|
|
item,
|
|
[
|
|
"recordId",
|
|
"purchaseRecordId",
|
|
"purchasedRecordId",
|
|
"buyRecordId",
|
|
"payRecordId",
|
|
"orderRecordId",
|
|
"id",
|
|
],
|
|
"",
|
|
);
|
|
}
|
|
|
|
function purchaseDetailUrl(item) {
|
|
var source = String(firstValue(item, ["sourceType", "type", "bizType"], ""));
|
|
var title = purchaseTitle(item);
|
|
if (source === "fc3d_scheme" || /断组|杀组合|方案/.test(title)) {
|
|
if (/杀组合/.test(title)) return "https://www.3dyjs.cn/shazuhe.html";
|
|
if (/断组/.test(title)) return "https://www.3dyjs.cn/duanzuhe.html";
|
|
return "https://www.3dyjs.cn/duanzuhe.html";
|
|
}
|
|
var expertId = firstValue(item, ["expertId", "createBy", "accountId"], "");
|
|
var code = firstValue(item, ["code", "lotteryCode", "suoxie"], "");
|
|
var parentId = firstValue(item, ["menuId", "parentId", "typeId"], "");
|
|
if (!expertId) return "javascript:void(0)";
|
|
return (
|
|
"caiinfo.html?createBy=" +
|
|
encodeURIComponent(expertId) +
|
|
"&code=" +
|
|
encodeURIComponent(code) +
|
|
"&parentId=" +
|
|
encodeURIComponent(parentId)
|
|
);
|
|
}
|
|
|
|
function renderPurchaseTable(records) {
|
|
var $tbody = $("#purchaseTableBody");
|
|
$tbody.empty();
|
|
if (!records || records.length === 0) {
|
|
$tbody.html(
|
|
'<tr><td colspan="7" style="text-align:center;color:var(--text-muted);padding:30px;">暂无购买记录</td></tr>',
|
|
);
|
|
return;
|
|
}
|
|
$.each(records, function (i, item) {
|
|
var url = purchaseDetailUrl(item);
|
|
var sourceType = purchaseDeleteSourceType(item);
|
|
var recordId = purchaseDeleteRecordId(item);
|
|
var actionList = [];
|
|
if (url !== "javascript:void(0)") {
|
|
actionList.push('<a href="' + safeText(url) + '" target="_blank">查看</a>');
|
|
}
|
|
if (sourceType && recordId) {
|
|
actionList.push(
|
|
'<button class="purchase-delete-btn" type="button" data-source-type="' +
|
|
safeText(sourceType) +
|
|
'" data-record-id="' +
|
|
safeText(recordId) +
|
|
'">删除</button>',
|
|
);
|
|
}
|
|
var action = actionList.length
|
|
? '<div class="purchase-action-box">' + actionList.join("") + "</div>"
|
|
: "-";
|
|
$tbody.append(
|
|
"<tr>" +
|
|
"<td>" +
|
|
safeText(purchaseSourceText(item)) +
|
|
"</td>" +
|
|
"<td>" +
|
|
safeText(purchaseTitle(item)) +
|
|
"</td>" +
|
|
"<td>" +
|
|
safeText(purchaseIssueText(item)) +
|
|
"</td>" +
|
|
"<td>" +
|
|
safeText(firstValue(item, ["expertName", "createUserName", "nickname"], "-")) +
|
|
"</td>" +
|
|
"<td>" +
|
|
safeText(firstValue(item, ["purchaseTime", "payTime", "createTime"], "-")) +
|
|
"</td>" +
|
|
'<td style="color:var(--orange);font-weight:600;">' +
|
|
safeText(purchaseAmountText(item)) +
|
|
"</td>" +
|
|
"<td>" +
|
|
action +
|
|
"</td>" +
|
|
"</tr>",
|
|
);
|
|
});
|
|
}
|
|
|
|
function deletePurchaseRecord(sourceType, recordId) {
|
|
if (!sourceType || !recordId) {
|
|
layui.layer.msg("缺少购买记录信息,无法删除", { icon: 2 });
|
|
return;
|
|
}
|
|
|
|
layui.layer.confirm(
|
|
"确定删除这条购买记录吗?",
|
|
{
|
|
title: "删除购买记录",
|
|
btn: ["删除", "取消"],
|
|
},
|
|
function (index) {
|
|
layui.layer.close(index);
|
|
ApiClient.delete(
|
|
ApiClient.API.minePurchasedPayArticleDelete(sourceType, recordId),
|
|
null,
|
|
{ headers: CommonUtil.authHeaders() },
|
|
)
|
|
.then(function (res) {
|
|
if (!ApiClient.isSuccess(res)) {
|
|
throw new Error((res && (res.msg || res.message)) || "删除购买记录失败");
|
|
}
|
|
layui.layer.msg("删除成功", { icon: 1 });
|
|
var nextPage =
|
|
purchaseTotalRow > 1 &&
|
|
purchasePageNum > 1 &&
|
|
purchaseTotalRow - 1 <= (purchasePageNum - 1) * pageSize
|
|
? purchasePageNum - 1
|
|
: purchasePageNum;
|
|
loadPurchaseRecords(nextPage);
|
|
})
|
|
.catch(function (error) {
|
|
layui.layer.msg((error && error.message) || "删除购买记录失败", { icon: 2 });
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
function renderPurchasePager(total) {
|
|
layui.laypage.render({
|
|
elem: "purchasePager",
|
|
count: total,
|
|
limit: pageSize,
|
|
curr: purchasePageNum,
|
|
theme: "#102b6a",
|
|
jump: function (obj, first) {
|
|
if (!first) loadPurchaseRecords(obj.curr);
|
|
},
|
|
});
|
|
}
|
|
|
|
// ====== Edit Profile Popup ======
|
|
function openEditProfile() {
|
|
layui.use("layer", function () {
|
|
var layer = layui.layer;
|
|
var avatar = currentUserData
|
|
? currentUserData.avatar || "../public/img/userimg.png"
|
|
: "../public/img/userimg.png";
|
|
var nickName = currentUserData
|
|
? currentUserData.nickName || currentUserData.username || ""
|
|
: "";
|
|
|
|
uploadedAvatarId = "";
|
|
userAvatarFile = null;
|
|
|
|
var content =
|
|
'<div class="uc-edit-profile-panel">' +
|
|
'<div class="uc-edit-avatar-zone">' +
|
|
'<button class="uc-edit-avatar-button" type="button" onclick="document.getElementById(\'editAvatarInput\').click()">' +
|
|
'<img id="editAvatarImg" src="' +
|
|
safeText(avatar) +
|
|
'" class="uc-edit-avatar" alt="头像" />' +
|
|
"</button>" +
|
|
'<div class="uc-edit-avatar-tip">点击头像更换</div>' +
|
|
'<input class="uc-edit-file-input" type="file" id="editAvatarInput" accept="image/*" onchange="previewAndUploadAvatar(this)" />' +
|
|
"</div>" +
|
|
'<div class="uc-edit-field">' +
|
|
"<label>昵称</label>" +
|
|
'<input type="text" id="editNickName" value="' +
|
|
safeText(nickName) +
|
|
'" placeholder="请输入昵称" maxlength="20" />' +
|
|
"</div>" +
|
|
'<div class="uc-edit-field">' +
|
|
"<label>新密码(不修改请留空)</label>" +
|
|
'<input type="password" id="editPassword" placeholder="不修改请留空" maxlength="20" />' +
|
|
"</div>" +
|
|
'<div class="uc-edit-field">' +
|
|
"<label>确认密码</label>" +
|
|
'<input type="password" id="editPasswordConfirm" placeholder="再次输入新密码" maxlength="20" />' +
|
|
"</div>" +
|
|
'<div class="uc-edit-actions">' +
|
|
'<button class="uc-edit-cancel" type="button" onclick="closeEditProfile()">取消</button>' +
|
|
'<button class="uc-edit-submit" id="editProfileSubmitBtn" type="button" onclick="submitEditProfile()">保存修改</button>' +
|
|
"</div>" +
|
|
"</div>";
|
|
|
|
editProfileLayerIndex = layer.open({
|
|
type: 1,
|
|
title: "编辑资料",
|
|
area: ["420px", "auto"],
|
|
skin: "uc-edit-popup",
|
|
shadeClose: true,
|
|
content: content,
|
|
end: function () {
|
|
editProfileLayerIndex = null;
|
|
uploadedAvatarId = "";
|
|
userAvatarFile = null;
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
var uploadedAvatarId = "";
|
|
var editProfileLayerIndex = null;
|
|
var userAvatarFile = null;
|
|
|
|
function closeEditProfile() {
|
|
if (editProfileLayerIndex !== null) {
|
|
layui.layer.close(editProfileLayerIndex);
|
|
}
|
|
}
|
|
|
|
function previewAndUploadAvatar(input) {
|
|
if (!input.files || !input.files[0]) return;
|
|
|
|
var file = input.files[0];
|
|
if (!/^(image\/jpeg|image\/png)$/.test(file.type || "")) {
|
|
layui.layer.msg("只支持 JPG/PNG 格式的图片", { icon: 2 });
|
|
input.value = "";
|
|
return;
|
|
}
|
|
if (file.size > 2 * 1024 * 1024) {
|
|
layui.layer.msg("图片大小不能超过 2MB", { icon: 2 });
|
|
input.value = "";
|
|
return;
|
|
}
|
|
|
|
userAvatarFile = file;
|
|
uploadedAvatarId = "";
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function (e) {
|
|
$("#editAvatarImg").attr("src", e.target.result);
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
|
|
function getAvatarIdFromUploadResponse(res) {
|
|
var data = ApiClient.pickData(res, null);
|
|
if (data === null || data === undefined || data === "") return "";
|
|
if (typeof data === "string" || typeof data === "number") {
|
|
return String(data);
|
|
}
|
|
return String(
|
|
firstValue(
|
|
data,
|
|
[
|
|
"id",
|
|
"fileId",
|
|
"avatarId",
|
|
"ossId",
|
|
"resourceId",
|
|
"attachmentId",
|
|
"file_id",
|
|
"avatar_id",
|
|
"url",
|
|
"avatar",
|
|
],
|
|
""
|
|
)
|
|
);
|
|
}
|
|
|
|
function isApiSuccess(res) {
|
|
return res && (res.code === 0 || res.code === 200);
|
|
}
|
|
|
|
function uploadSelectedAvatarIfNeeded() {
|
|
if (!userAvatarFile) return Promise.resolve("");
|
|
|
|
var formData = new FormData();
|
|
formData.append("file", userAvatarFile);
|
|
|
|
return ApiClient.post(ApiClient.API.accountProfileAvatar, formData).then(
|
|
function (res) {
|
|
if (!isApiSuccess(res)) {
|
|
throw new Error(res && res.msg ? res.msg : "头像上传失败");
|
|
}
|
|
var avatarId = getAvatarIdFromUploadResponse(res);
|
|
if (!avatarId) {
|
|
throw new Error("头像上传返回缺少文件编号");
|
|
}
|
|
uploadedAvatarId = avatarId;
|
|
return avatarId;
|
|
}
|
|
);
|
|
}
|
|
|
|
function validateEditProfileNickname(nickName) {
|
|
var nicknameWidth = Array.from(nickName).reduce(function (total, char) {
|
|
return total + (/[\u4e00-\u9fa5\uff00-\uffef]/.test(char) ? 2 : 1);
|
|
}, 0);
|
|
|
|
if (nickName.length < 2 || nicknameWidth > 12) {
|
|
layui.layer.msg("昵称长度应为2-6个汉字或2-12个英文", { icon: 2 });
|
|
$("#editNickName").focus();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function submitEditProfile() {
|
|
var nickName = $("#editNickName").val().trim();
|
|
var password = $("#editPassword").val();
|
|
var passwordConfirm = $("#editPasswordConfirm").val();
|
|
var currentNickName = currentUserData
|
|
? currentUserData.nickName || currentUserData.username || ""
|
|
: "";
|
|
|
|
if (!nickName) {
|
|
layui.layer.msg("昵称不能为空", { icon: 2 });
|
|
return;
|
|
}
|
|
if (nickName !== currentNickName && !validateEditProfileNickname(nickName)) {
|
|
return;
|
|
}
|
|
if ((password || passwordConfirm) && (!password || !passwordConfirm)) {
|
|
layui.layer.msg("请输入并确认新密码", { icon: 2 });
|
|
return;
|
|
}
|
|
if (password && password !== passwordConfirm) {
|
|
layui.layer.msg("两次密码输入不一致", { icon: 2 });
|
|
return;
|
|
}
|
|
if (password && (password.length < 6 || password.length > 20)) {
|
|
layui.layer.msg("密码长度应为6-20位", { icon: 2 });
|
|
return;
|
|
}
|
|
|
|
var params = {};
|
|
if (nickName !== currentNickName) {
|
|
params.nickName = nickName;
|
|
}
|
|
if (password) {
|
|
params.password = hex_md5(password);
|
|
}
|
|
|
|
if (!userAvatarFile && Object.keys(params).length === 0) {
|
|
layui.layer.msg("暂无修改", { icon: 0 });
|
|
return;
|
|
}
|
|
|
|
var $submitBtn = $("#editProfileSubmitBtn");
|
|
$submitBtn.prop("disabled", true).text("保存中...");
|
|
|
|
uploadSelectedAvatarIfNeeded()
|
|
.then(function (avatarId) {
|
|
if (avatarId) params.avatar = avatarId;
|
|
return ApiClient.put(ApiClient.API.accountProfile, params);
|
|
})
|
|
.then(function (res) {
|
|
if (isApiSuccess(res)) {
|
|
layui.layer.msg("修改成功", { icon: 1, time: 1500 });
|
|
closeEditProfile();
|
|
loadUserDetail();
|
|
} else {
|
|
layui.layer.msg("修改失败: " + (res.msg || "未知错误"), {
|
|
icon: 2,
|
|
});
|
|
}
|
|
})
|
|
.catch(function (err) {
|
|
layui.layer.msg((err && err.message) || "网络错误", { icon: 2 });
|
|
})
|
|
.finally(function () {
|
|
$submitBtn.prop("disabled", false).text("保存修改");
|
|
});
|
|
}
|
|
|
|
// ====== Initialize ======
|
|
$(function () {
|
|
updateHeaderState();
|
|
if (checkAuth()) {
|
|
loadUserDetail();
|
|
loadSignInRecords(1);
|
|
loadMenuList();
|
|
loadPurchaseRecords(1);
|
|
}
|
|
|
|
$("#purchaseTableBody").on("click", ".purchase-delete-btn", function () {
|
|
deletePurchaseRecord($(this).data("sourceType"), $(this).data("recordId"));
|
|
});
|
|
});
|
|
|
|
CommonUtil.loadPageConfig();
|
|
</script>
|
|
</body>
|
|
</html>
|