提交代码

This commit is contained in:
manghe 2025-03-23 09:21:41 +00:00
parent 38d34a554d
commit 1caa11ebd6
10 changed files with 1918 additions and 65 deletions

View File

@ -17,6 +17,7 @@ use app\common\model\Order;
use app\common\model\OrderList;
use app\common\model\UserAccount;
use app\common\model\UserLoginIp;
use app\common\model\Goods;
use think\facade\Db;
use think\helper\Str;
@ -962,22 +963,11 @@ class User extends Base
*/
public function user_order()
{
$user_id = request()->param('id', 0);
$nickname = request()->param('nickname', '');
// 将UID转换为用户ID
$user_id = $this->convertUidToUserId($user_id);
// 验证参数
if (empty($user_id)) {
$this->renderError('参数错误');
}
// 传递用户ID和昵称到模板
View::assign('user_id', $user_id);
View::assign('nickname', $nickname);
return View::fetch('User/user_order');
$id = input('id');
View::assign('id',$id);
$nickname = input('nickname');
View::assign('nickname',$nickname);
return View::fetch();
}
/**
@ -1036,4 +1026,245 @@ class User extends Base
'data' => $list
]);
}
/**
* 用户余额流水明细
*/
public function user_money_detail()
{
$user_id = input('user_id');
$nickname = input('nickname', '');
View::assign('user_id', $user_id);
View::assign('nickname', $nickname);
return View::fetch('User/user_money_detail');
}
/**
* 获取用户余额流水明细数据
*/
public function user_money_detail_data()
{
$param = input();
$user_id = isset($param['user_id']) ? intval($param['user_id']) : 0;
if (empty($user_id)) {
return json(['code' => 1, 'msg' => '参数错误', 'count' => 0, 'data' => []]);
}
$where = [
['user_id', '=', $user_id]
];
// 时间范围
if (!empty($param['start_time']) && !empty($param['end_time'])) {
$start_time = strtotime($param['start_time']);
$end_time = strtotime($param['end_time']);
$where[] = ['addtime', 'between', [$start_time, $end_time]];
}
// 类型筛选
if (isset($param['type']) && $param['type'] !== '') {
$where[] = ['type', '=', intval($param['type'])];
}
// 变化类型(收入/消耗)
if (isset($param['change_type']) && $param['change_type'] !== '') {
if ($param['change_type'] === 'add') {
$where[] = ['change_money', '>', 0];
} elseif ($param['change_type'] === 'sub') {
$where[] = ['change_money', '<', 0];
}
}
// 备注搜索
if (isset($param['content']) && $param['content'] !== '') {
$where[] = ['content|other', 'like', '%' . $param['content'] . '%'];
}
// 获取数据
$model = new \app\common\model\ProfitMoney();
// 获取总数
$count = $model->where($where)->count();
// 分页
$page = isset($param['page']) ? max(1, intval($param['page'])) : 1;
$limit = isset($param['limit']) ? max(1, intval($param['limit'])) : 50;
$list = $model->where($where)
->order('id desc')
->page($page, $limit)
->select()
->toArray();
return json([
'code' => 0,
'msg' => '',
'count' => $count,
'data' => $list
]);
}
/**
* 用户货币2流水明细
*/
public function user_integral_detail()
{
$user_id = input('user_id');
$nickname = input('nickname', '');
View::assign('user_id', $user_id);
View::assign('nickname', $nickname);
View::assign('currency_name', getConfig('app_setting')['currency1_name'] ?? '货币2');
return View::fetch('User/user_integral_detail');
}
/**
* 获取用户货币2流水明细数据
*/
public function user_integral_detail_data()
{
$param = input();
$user_id = isset($param['user_id']) ? intval($param['user_id']) : 0;
if (empty($user_id)) {
return json(['code' => 1, 'msg' => '参数错误', 'count' => 0, 'data' => []]);
}
$where = [
['user_id', '=', $user_id]
];
// 时间范围
if (!empty($param['start_time']) && !empty($param['end_time'])) {
$start_time = strtotime($param['start_time']);
$end_time = strtotime($param['end_time']);
$where[] = ['addtime', 'between', [$start_time, $end_time]];
}
// 类型筛选
if (isset($param['type']) && $param['type'] !== '') {
$where[] = ['type', '=', intval($param['type'])];
}
// 变化类型(收入/消耗)
if (isset($param['change_type']) && $param['change_type'] !== '') {
if ($param['change_type'] === 'add') {
$where[] = ['change_money', '>', 0];
} elseif ($param['change_type'] === 'sub') {
$where[] = ['change_money', '<', 0];
}
}
// 备注搜索
if (isset($param['content']) && $param['content'] !== '') {
// 使用content字段进行搜索
$where[] = ['content', 'like', '%' . $param['content'] . '%'];
}
try {
// 使用DB类进行查询避免使用模型方法
$list = Db::name('profit_integral')
->where($where)
->order('id desc')
->page(isset($param['page']) ? max(1, intval($param['page'])) : 1, isset($param['limit']) ? max(1, intval($param['limit'])) : 50)
->select()
->toArray();
$count = Db::name('profit_integral')
->where($where)
->count();
return json([
'code' => 0,
'msg' => '',
'count' => $count,
'data' => $list
]);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '数据查询出错: ' . $e->getMessage(), 'count' => 0, 'data' => []]);
}
}
/**
* 用户货币3流水明细
*/
public function user_score_detail()
{
$user_id = input('user_id');
$nickname = input('nickname', '');
View::assign('user_id', $user_id);
View::assign('nickname', $nickname);
View::assign('currency_name', getConfig('app_setting')['currency2_name'] ?? '货币3');
return View::fetch('User/user_score_detail');
}
/**
* 获取用户货币3流水明细数据
*/
public function user_score_detail_data()
{
$param = input();
$user_id = isset($param['user_id']) ? intval($param['user_id']) : 0;
if (empty($user_id)) {
return json(['code' => 1, 'msg' => '参数错误', 'count' => 0, 'data' => []]);
}
$where = [
['user_id', '=', $user_id]
];
// 时间范围
if (!empty($param['start_time']) && !empty($param['end_time'])) {
$start_time = strtotime($param['start_time']);
$end_time = strtotime($param['end_time']);
$where[] = ['addtime', 'between', [$start_time, $end_time]];
}
// 类型筛选
if (isset($param['type']) && $param['type'] !== '') {
$where[] = ['type', '=', intval($param['type'])];
}
// 变化类型(收入/消耗)
if (isset($param['change_type']) && $param['change_type'] !== '') {
if ($param['change_type'] === 'add') {
$where[] = ['change_money', '>', 0];
} elseif ($param['change_type'] === 'sub') {
$where[] = ['change_money', '<', 0];
}
}
// 备注搜索
if (isset($param['content']) && $param['content'] !== '') {
// 使用content字段进行搜索
$where[] = ['content', 'like', '%' . $param['content'] . '%'];
}
try {
// 使用DB类进行查询避免使用模型方法
$list = Db::name('profit_money2')
->where($where)
->order('id desc')
->page(isset($param['page']) ? max(1, intval($param['page'])) : 1, isset($param['limit']) ? max(1, intval($param['limit'])) : 50)
->select()
->toArray();
$count = Db::name('profit_money2')
->where($where)
->count();
return json([
'code' => 0,
'msg' => '',
'count' => $count,
'data' => $list
]);
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '数据查询出错: ' . $e->getMessage(), 'count' => 0, 'data' => []]);
}
}
}

View File

@ -47,6 +47,16 @@ Route::rule('detailed_flow', 'User/detailed_flow', 'GET|POST');
Route::rule('user_team', 'User/user_team', 'GET|POST');
Route::rule('ip_list', 'User/ip_list', 'GET|POST');
Route::rule('ipzh', 'User/ipzh', 'GET|POST');
Route::rule('user_box', 'User/user_box', 'GET|POST');
Route::rule('user_box_list', 'User/user_box_list', 'GET|POST');
Route::rule('user_order', 'User/user_order', 'GET|POST');
Route::rule('user_order_list', 'User/user_order_list', 'GET|POST');
Route::rule('user_money_detail', 'User/user_money_detail', 'GET|POST');
Route::rule('user_money_detail_data', 'User/user_money_detail_data', 'GET|POST');
Route::rule('user_integral_detail', 'User/user_integral_detail', 'GET|POST');
Route::rule('user_integral_detail_data', 'User/user_integral_detail_data', 'GET|POST');
Route::rule('user_score_detail', 'User/user_score_detail', 'GET|POST');
Route::rule('user_score_detail_data', 'User/user_score_detail_data', 'GET|POST');
Route::rule('usermobileclear', 'User/usermobileclear', 'POST');//清空手机号
Route::rule('userwxclear', 'User/userwxclear', 'POST');//清空微信登录数据

View File

@ -13,81 +13,113 @@
<div class="layui-form-item">
<label class="layui-form-label">项目名称</label>
<div class="layui-input-block">
<input type="text" name="app_name" value="{$app_setting.app_name|default=''}" autocomplete="off" class="layui-input" placeholder="请输入项目名称">
<input type="text" name="app_name" value="{$app_setting.app_name|default=''}"
autocomplete="off" class="layui-input" placeholder="请输入项目名称">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">购买弹窗</label>
<div class="layui-input-block">
<input type="radio" name="purchase_popup" value="0" title="弹出一次" {if !isset($app_setting.purchase_popup) || $app_setting.purchase_popup==0}checked{/if}>
<input type="radio" name="purchase_popup" value="1" title="每天显示" {if isset($app_setting.purchase_popup) && $app_setting.purchase_popup==1}checked{/if}>
<input type="radio" name="purchase_popup" value="0" title="弹出一次" {if
!isset($app_setting.purchase_popup) ||
$app_setting.purchase_popup==0}checked{/if}>
<input type="radio" name="purchase_popup" value="1" title="每天显示" {if
isset($app_setting.purchase_popup) &&
$app_setting.purchase_popup==1}checked{/if}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商城兑换次数</label>
<div class="layui-input-block">
<input type="number" name="exchange_times" value="{$app_setting.exchange_times|default=0}" autocomplete="off" class="layui-input" min="0">
<input type="number" name="exchange_times"
value="{$app_setting.exchange_times|default=0}" autocomplete="off"
class="layui-input" min="0">
<div class="layui-form-mid layui-word-aux">每天允许兑换几次0不限次数</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">余额名称</label>
<div class="layui-input-inline">
<input type="text" name="balance_name" value="{$app_setting.balance_name|default=''}" autocomplete="off" class="layui-input" placeholder="请输入余额名称">
<input type="text" name="balance_name"
value="{$app_setting.balance_name|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入余额名称">
</div>
<label class="layui-form-label">余额图标</label>
<div class="layui-input-inline">
<input type="text" name="balance_icon" value="{$app_setting.balance_icon|default=''}" autocomplete="off" class="layui-input" placeholder="请输入余额图标地址">
<input type="text" name="balance_icon"
value="{$app_setting.balance_icon|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入余额图标地址">
</div>
<button type="button" class="layui-btn upload-icon" data-input="balance_icon">
<i class="layui-icon">&#xe67c;</i>上传图片
</button>
<div class="icon-preview" id="balance_icon_preview">
{if !empty($app_setting.balance_icon)}
<img src="{$app_setting.balance_icon}" style="height:38px;max-width:100px;margin-left:10px;">
<img src="{$app_setting.balance_icon}"
style="height:38px;max-width:100px;margin-left:10px;">
{/if}
</div>
<div class="icon-preview">
人民币单位,只能充值,可以抽赏
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">货币1名称</label>
<div class="layui-input-inline">
<input type="text" name="currency1_name" value="{$app_setting.currency1_name|default=''}" autocomplete="off" class="layui-input" placeholder="请输入货币1名称">
<input type="text" name="currency1_name"
value="{$app_setting.currency1_name|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入货币1名称">
</div>
<label class="layui-form-label">货币1图片</label>
<div class="layui-input-inline">
<input type="text" name="currency1_icon" value="{$app_setting.currency1_icon|default=''}" autocomplete="off" class="layui-input" placeholder="请输入货币1图片地址">
<input type="text" name="currency1_icon"
value="{$app_setting.currency1_icon|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入货币1图片地址">
</div>
<button type="button" class="layui-btn upload-icon" data-input="currency1_icon">
<i class="layui-icon">&#xe67c;</i>上传图片
</button>
<div class="icon-preview" id="currency1_icon_preview">
{if !empty($app_setting.currency1_icon)}
<img src="{$app_setting.currency1_icon}" style="height:38px;max-width:100px;margin-left:10px;">
<img src="{$app_setting.currency1_icon}"
style="height:38px;max-width:100px;margin-left:10px;">
{/if}
</div>
<div class="icon-preview">
道具币,活动获得,签到等,不计入消费额度,可以抽赏
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">货币2名称</label>
<div class="layui-input-inline">
<input type="text" name="currency2_name" value="{$app_setting.currency2_name|default=''}" autocomplete="off" class="layui-input" placeholder="请输入货币2名称">
<input type="text" name="currency2_name"
value="{$app_setting.currency2_name|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入货币2名称">
</div>
<label class="layui-form-label">货币2图片</label>
<div class="layui-input-inline">
<input type="text" name="currency2_icon" value="{$app_setting.currency2_icon|default=''}" autocomplete="off" class="layui-input" placeholder="请输入货币2图片地址">
<input type="text" name="currency2_icon"
value="{$app_setting.currency2_icon|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入货币2图片地址">
</div>
<button type="button" class="layui-btn upload-icon" data-input="currency2_icon">
<i class="layui-icon">&#xe67c;</i>上传图片
</button>
<div class="icon-preview" id="currency2_icon_preview">
{if !empty($app_setting.currency2_icon)}
<img src="{$app_setting.currency2_icon}" style="height:38px;max-width:100px;margin-left:10px;">
<img src="{$app_setting.currency2_icon}"
style="height:38px;max-width:100px;margin-left:10px;">
{/if}
</div>
<div class="icon-preview">
兑换获得,可以抽赏,可以去商城兑换,不计入消费额度
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">中奖音频</label>
<div class="layui-input-inline" style="width: 450px;">
<input type="text" name="win_audio" value="{$app_setting.win_audio|default=''}" autocomplete="off" class="layui-input" placeholder="请输入中奖音频文件地址">
<input type="text" name="win_audio" value="{$app_setting.win_audio|default=''}"
autocomplete="off" class="layui-input" placeholder="请输入中奖音频文件地址">
</div>
<button type="button" class="layui-btn upload-audio" data-input="win_audio">
<i class="layui-icon">&#xe67c;</i>选择文件
@ -159,13 +191,15 @@
<div class="layui-form-item">
<label class="layui-form-label">Appid</label>
<div class="layui-input-block">
<input type="text" name="appid" value="{$wechat_setting.appid|default=''}" autocomplete="off" class="layui-input" placeholder="请输入微信AppID">
<input type="text" name="appid" value="{$wechat_setting.appid|default=''}"
autocomplete="off" class="layui-input" placeholder="请输入微信AppID">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">AppSecret</label>
<div class="layui-input-block">
<input type="text" name="appSecret" value="{$wechat_setting.appSecret|default=''}" autocomplete="off" class="layui-input" placeholder="请输入微信AppSecret">
<input type="text" name="appSecret" value="{$wechat_setting.appSecret|default=''}"
autocomplete="off" class="layui-input" placeholder="请输入微信AppSecret">
</div>
</div>
<div class="layui-form-item">
@ -232,7 +266,7 @@
</div>
</div>
</div>
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-header">微信公众号设置</div>
@ -242,25 +276,30 @@
<div class="layui-form-item">
<label class="layui-form-label">Appid</label>
<div class="layui-input-block">
<input type="text" name="appid" value="{$wechatofficialaccount_setting.appid|default=''}" autocomplete="off" class="layui-input" placeholder="请输入微信公众号AppID">
<input type="text" name="appid"
value="{$wechatofficialaccount_setting.appid|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入微信公众号AppID">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">AppSecret</label>
<div class="layui-input-block">
<input type="text" name="appSecret" value="{$wechatofficialaccount_setting.appSecret|default=''}" autocomplete="off" class="layui-input" placeholder="请输入微信公众号AppSecret">
<input type="text" name="appSecret"
value="{$wechatofficialaccount_setting.appSecret|default=''}" autocomplete="off"
class="layui-input" placeholder="请输入微信公众号AppSecret">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="wechatofficialaccount-setting-form">保存</button>
<button class="layui-btn" lay-submit
lay-filter="wechatofficialaccount-setting-form">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@ -274,7 +313,7 @@
var upload = layui.upload;
// 图标上传功能
$('.upload-icon').each(function() {
$('.upload-icon').each(function () {
var inputName = $(this).data('input');
upload.render({
elem: this,
@ -286,10 +325,10 @@
acceptMime: 'image/*',
exts: 'jpg|png|jpeg|gif',
size: 2048, // 最大2MB
before: function(obj) {
before: function (obj) {
layer.load(); // 显示等待框
},
done: function(res) {
done: function (res) {
layer.closeAll('loading'); // 关闭等待框
if (res.status) {
// 设置输入框的值
@ -298,18 +337,18 @@
$('#' + inputName + '_preview').html('<img src="' + res.data.path + '" style="height:38px;max-width:100px;margin-left:10px;">');
layer.msg('上传成功');
} else {
layer.msg(res.msg || '上传失败', {icon: 2});
layer.msg(res.msg || '上传失败', { icon: 2 });
}
},
error: function() {
error: function () {
layer.closeAll('loading');
layer.msg('上传失败', {icon: 2});
layer.msg('上传失败', { icon: 2 });
}
});
});
// 音频上传功能
$('.upload-audio').each(function() {
$('.upload-audio').each(function () {
var inputName = $(this).data('input');
upload.render({
elem: this,
@ -321,10 +360,10 @@
acceptMime: 'audio/*',
exts: 'mp3|wav|ogg',
size: 5120, // 最大5MB
before: function(obj) {
before: function (obj) {
layer.load(); // 显示等待框
},
done: function(res) {
done: function (res) {
layer.closeAll('loading'); // 关闭等待框
if (res.status) {
// 设置输入框的值
@ -333,12 +372,12 @@
$('#' + inputName + '_preview').html('<audio controls style="height:38px;margin-left:10px;"><source src="' + res.data.path + '" type="audio/mpeg">您的浏览器不支持音频播放</audio>');
layer.msg('上传成功');
} else {
layer.msg(res.msg || '上传失败', {icon: 2});
layer.msg(res.msg || '上传失败', { icon: 2 });
}
},
error: function() {
error: function () {
layer.closeAll('loading');
layer.msg('上传失败', {icon: 2});
layer.msg('上传失败', { icon: 2 });
}
});
});
@ -371,12 +410,12 @@
// 表单提交 - 不再在前端处理数据转换,交给后端处理
form.on('submit(component-form-element)', function (data) {
var field = data.field;
// 检查并移除空的file字段
if ('file' in field && !field.file) {
delete field.file;
}
// 提交到后台
$.ajax({
url: '{:url("/admin/update")}',
@ -529,23 +568,23 @@
.layui-input-block {
margin-left: 150px;
}
.icon-preview {
display: inline-block;
vertical-align: middle;
}
.upload-icon {
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
.audio-preview {
display: inline-block;
vertical-align: middle;
}
.upload-audio {
display: inline-block;
vertical-align: middle;

View File

@ -37,8 +37,8 @@
<thead>
<tr>
<th>用户信息</th>
<th>变化吧唧币数量</th>
<th>变后吧唧币数量</th>
<th>变化{$app_setting.currency1_name}数量</th>
<th>变后{$app_setting.currency1_name}数量</th>
<th>描述</th>
<th>变化时间</th>
</tr>

View File

@ -37,8 +37,8 @@
<thead>
<tr>
<th>用户信息</th>
<th>变化余额数量</th>
<th>变后余额数量</th>
<th>变化{$app_setting.balance_name}数量</th>
<th>变后{$app_setting.balance_name}数量</th>
<th>描述</th>
<th>变化时间</th>
</tr>

View File

@ -109,17 +109,20 @@
<!-- 余额模板 -->
<script type="text/html" id="moneyTpl">
<span class="value-display">{{d.money}}</span>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeMoney">充值</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeMoney">充值</a><br />
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="moneyDetail">流水明细</a>
</script>
<!--货币2按钮模板-->
<script type="text/html" id="integralTpl">
<span class="value-display">{{d.integral}}</span>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeIntegral">充值</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeIntegral">充值</a><br />
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="integralDetail">流水明细</a>
</script>
<!--货币3按钮模板-->
<script type="text/html" id="scoreTpl">
<span class="value-display">{{d.money2}}</span>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeScore">充值</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="rechargeScore">充值</a><br />
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="scoreDetail">流水明细</a>
</script>
<!-- 修改状态模板 -->
@ -227,7 +230,7 @@
, cols: [[
{ field: 'userInfo', title: '用户信息', templet: '#userInfoTpl', width: 200 }
, { field: 'pid_info', title: '推荐人', templet: '#pidInfoTpl', width: 200 }
, { field: 'money', title: '{$app_setting.balance_name}', templet: '#moneyTpl', width: 120 }
, { field: 'money', title: '{$app_setting.balance_name}', templet: '#moneyTpl', width: 150 }
, { field: 'integral', title: '{$app_setting.currency1_name}', templet: '#integralTpl', width: 120 }
, { field: 'score', title: '{$app_setting.currency2_name}', templet: '#scoreTpl', width: 120 }
, { field: 'combined', title: '货币信息', templet: '#combinedTpl', width: 200 }
@ -327,6 +330,33 @@
maxmin: true
});
break;
case 'moneyDetail':
layer.open({
type: 2,
title: data.nickname + ' 的余额流水明细',
content: '/admin/user_money_detail?user_id=' + data.id + '&nickname=' + encodeURIComponent(data.nickname),
area: ['95%', '90%'],
maxmin: true
});
break;
case 'integralDetail':
layer.open({
type: 2,
title: data.nickname + ' 的{$app_setting.currency1_name}流水明细',
content: '/admin/user_integral_detail?user_id=' + data.id + '&nickname=' + encodeURIComponent(data.nickname),
area: ['95%', '90%'],
maxmin: true
});
break;
case 'scoreDetail':
layer.open({
type: 2,
title: data.nickname + ' 的{$app_setting.currency2_name}流水明细',
content: '/admin/user_score_detail?user_id=' + data.id + '&nickname=' + encodeURIComponent(data.nickname),
area: ['95%', '90%'],
maxmin: true
});
break;
}
});

View File

@ -0,0 +1,486 @@
{include file="Public:header2"/}
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb">
<a href="{:url('/admin/user')}">用户管理</a>
<a><cite>{$currency_name}流水明细</cite></a>
</span>
<span class="user-info">当前用户:{$nickname}</span>
</div>
<!-- 搜索表单 -->
<div class="layui-form layui-card-header layuiadmin-card-header-auto" id="searchForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">变化时间</label>
<div class="layui-input-inline">
<input type="text" id="timerange" name="timerange" class="layui-input" placeholder="选择时间范围">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">类型</label>
<div class="layui-input-inline">
<select name="type" id="type">
<option value="">全部类型</option>
<option value="1">后台充值</option>
<option value="2">在线充值</option>
<option value="3">抽赏消费</option>
<option value="4">背包回收</option>
<option value="5">推荐奖励</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">变化类型</label>
<div class="layui-input-inline">
<select name="change_type" id="change_type">
<option value="">全部</option>
<option value="add">收入</option>
<option value="sub">消耗</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">备注内容</label>
<div class="layui-input-inline">
<input type="text" name="content" id="content" placeholder="请输入备注内容关键词" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-useradmin" id="searchBtn">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i> 搜索
</button>
<button class="layui-btn layui-btn-primary" id="resetBtn">
<i class="layui-icon layui-icon-refresh"></i> 重置
</button>
</div>
</div>
</div>
<!-- 数据表格 -->
<div class="layui-card-body">
<!-- 时间线视图 -->
<div id="timeline-container">
<ul class="layui-timeline" id="money-timeline">
<!-- 时间线内容将通过JavaScript动态生成 -->
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis">&#xe63f;</i>
<div class="layui-timeline-content layui-text">
<div class="layui-timeline-title">加载中...</div>
</div>
</li>
</ul>
<!-- 分页控件 -->
<div id="timeline-page" class="layui-box layui-laypage layui-laypage-default"></div>
</div>
<!-- 表格视图(默认隐藏) -->
<div id="table-container" style="display: none;">
<table id="money-detail-table" lay-filter="money-detail-table"></table>
</div>
<!-- 视图切换按钮 -->
<div class="view-toggle-container">
<button class="layui-btn layui-btn-primary layui-btn-sm" id="toggleViewBtn">
<i class="layui-icon">&#xe857;</i> 切换视图
</button>
</div>
</div>
</div>
</div>
<!-- 金额模板 -->
<script type="text/html" id="moneyTpl">
{{# if(d.change_money > 0) { }}
<span class="money-add">+{{d.change_money}}</span>
{{# } else { }}
<span class="money-sub">{{d.change_money}}</span>
{{# } }}
</script>
<!-- 类型模板 -->
<script type="text/html" id="typeTpl">
{{# if(d.type == 1) { }}
<span class="type-badge type-1">后台充值</span>
{{# } else if(d.type == 2) { }}
<span class="type-badge type-2">在线充值</span>
{{# } else if(d.type == 3) { }}
<span class="type-badge type-3">抽赏消费</span>
{{# } else if(d.type == 4) { }}
<span class="type-badge type-4">背包回收</span>
{{# } else if(d.type == 5) { }}
<span class="type-badge type-5">推荐奖励</span>
{{# } else { }}
<span class="type-badge">其他({{d.type}})</span>
{{# } }}
</script>
{include file="Public:footer"/}
<script>
layui.use(['table', 'form', 'laydate', 'laypage', 'util'], function(){
var table = layui.table;
var form = layui.form;
var laydate = layui.laydate;
var laypage = layui.laypage;
var util = layui.util;
var $ = layui.$;
// 当前视图状态timeline 或 table
var currentView = 'timeline';
var currentPage = 1;
var itemsPerPage = 20;
var totalItems = 0;
var currentData = [];
var currentFilter = {
user_id: '{$user_id}'
};
// 初始化日期范围选择器
laydate.render({
elem: '#timerange',
type: 'datetime',
range: true,
format: 'yyyy-MM-dd HH:mm:ss'
});
// 加载时间线数据
function loadTimelineData(filter, page, limit) {
// 显示加载中
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">加载中...</div></div></li>');
// 发送请求获取数据
$.ajax({
url: '{:url("/admin/user_integral_detail_data")}',
type: 'GET',
data: {
...filter,
page: page,
limit: limit
},
success: function(res) {
if (res.code === 0) {
currentData = res.data;
totalItems = res.count;
renderTimeline(res.data);
renderPagination(res.count, page, limit);
} else {
layer.msg(res.msg || '加载数据失败', {icon: 2});
}
},
error: function() {
layer.msg('网络错误,请稍后重试', {icon: 2});
}
});
}
// 渲染时间线
function renderTimeline(data) {
if (!data || data.length === 0) {
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">暂无数据</div></div></li>');
return;
}
var html = '';
data.forEach(function(item) {
// 根据金额变化设置不同的颜色和图标
var colorClass = item.change_money > 0 ? 'timeline-add' : 'timeline-sub';
var icon = item.change_money > 0 ? '&#xe68e;' : '&#xe659;';
// 获取类型标签
var typeLabel = getTypeLabel(item.type);
html += `
<li class="layui-timeline-item ${colorClass}">
<i class="layui-icon layui-timeline-axis">${icon}</i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">${util.toDateString(item.addtime * 1000, 'yyyy-MM-dd HH:mm:ss')}</h3>
<div class="timeline-card">
<div class="timeline-item">
<span class="timeline-label">变化金额:</span>
<span class="timeline-value ${item.change_money > 0 ? 'money-add' : 'money-sub'}">${item.change_money > 0 ? '+' + item.change_money : item.change_money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">剩余金额:</span>
<span class="timeline-value">${item.money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">类型:</span>
<span class="timeline-value">${typeLabel}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">描述:</span>
<span class="timeline-value">${item.content || '-'}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">备注:</span>
<span class="timeline-value">${item.other || '-'}</span>
</div>
</div>
</div>
</li>
`;
});
$('#money-timeline').html(html);
}
// 渲染分页
function renderPagination(count, currentPage, limit) {
laypage.render({
elem: 'timeline-page',
count: count,
curr: currentPage,
limit: limit,
limits: [10, 20, 50, 100],
layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
jump: function(obj, first) {
if (!first) {
currentPage = obj.curr;
itemsPerPage = obj.limit;
loadTimelineData(currentFilter, obj.curr, obj.limit);
}
}
});
}
// 获取类型标签HTML
function getTypeLabel(type) {
var typeMap = {
1: '<span class="type-badge type-1">后台充值</span>',
2: '<span class="type-badge type-2">在线充值</span>',
3: '<span class="type-badge type-3">抽赏消费</span>',
4: '<span class="type-badge type-4">背包回收</span>',
5: '<span class="type-badge type-5">推荐奖励</span>'
};
return typeMap[type] || `<span class="type-badge">其他(${type})</span>`;
}
// 初始化表格
var tableIns = table.render({
elem: '#money-detail-table',
url: '{:url("/admin/user_integral_detail_data")}',
where: {
user_id: '{$user_id}'
},
cols: [[
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'change_money', title: '变化金额', width: 120, templet: '#moneyTpl', sort: true},
{field: 'money', title: '剩余金额', width: 120},
{field: 'type', title: '消耗类型', width: 120, templet: '#typeTpl'},
{field: 'content', title: '描述', width: 200},
{field: 'other', title: '备注', width: 200},
{field: 'addtime', title: '添加时间', width: 180, templet: function(d){
return util.toDateString(d.addtime * 1000, 'yyyy-MM-dd HH:mm:ss');
}, sort: true}
]],
page: true,
limit: itemsPerPage,
limits: [10, 20, 50, 100, 200],
height: 'full-220'
});
// 搜索按钮事件
$('#searchBtn').on('click', function(){
var timerange = $('#timerange').val();
var startTime = '';
var endTime = '';
if(timerange) {
var times = timerange.split(' - ');
startTime = times[0];
endTime = times[1];
}
// 更新当前筛选条件
currentFilter = {
user_id: '{$user_id}',
start_time: startTime,
end_time: endTime,
type: $('#type').val(),
change_type: $('#change_type').val(),
content: $('#content').val()
};
// 根据当前视图执行搜索
if (currentView === 'table') {
// 执行表格搜索
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 执行时间线搜索
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 重置按钮事件
$('#resetBtn').on('click', function(){
$('#searchForm')[0].reset();
form.render();
// 重置筛选条件
currentFilter = {
user_id: '{$user_id}'
};
// 根据当前视图重新加载数据
if (currentView === 'table') {
// 重新加载表格
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 重新加载时间线
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 视图切换按钮事件
$('#toggleViewBtn').on('click', function() {
if (currentView === 'timeline') {
// 切换到表格视图
$('#timeline-container').hide();
$('#table-container').show();
currentView = 'table';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到时间线视图');
// 刷新表格以适应新的大小
tableIns.resize();
} else {
// 切换到时间线视图
$('#table-container').hide();
$('#timeline-container').show();
currentView = 'timeline';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到表格视图');
}
});
// 初始加载时间线数据
loadTimelineData(currentFilter, currentPage, itemsPerPage);
});
</script>
<style>
.layui-card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info {
font-weight: bold;
color: #1E9FFF;
}
.money-add {
color: #FF5722;
font-weight: bold;
}
.money-sub {
color: #009688;
font-weight: bold;
}
.type-badge {
display: inline-block;
padding: 2px 5px;
border-radius: 2px;
color: #fff;
font-size: 12px;
}
.type-1 {
background-color: #FF5722;
}
.type-2 {
background-color: #FFB800;
}
.type-3 {
background-color: #009688;
}
.type-4 {
background-color: #1E9FFF;
}
.type-5 {
background-color: #5FB878;
}
/* 时间线相关样式 */
.timeline-card {
background-color: #f9f9f9;
border-radius: 4px;
padding: 15px;
margin-top: 10px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.timeline-item {
margin-bottom: 8px;
line-height: 24px;
}
.timeline-label {
color: #666;
font-weight: bold;
margin-right: 5px;
}
.timeline-value {
color: #333;
}
/* 收入项目样式 */
.timeline-add .layui-timeline-axis {
color: #FF5722;
background-color: #fff;
border-color: #FF5722;
}
/* 支出项目样式 */
.timeline-sub .layui-timeline-axis {
color: #009688;
background-color: #fff;
border-color: #009688;
}
/* 时间线标题 */
.layui-timeline-title {
font-weight: bold;
color: #333;
}
/* 分页区域样式 */
#timeline-page {
margin-top: 20px;
text-align: center;
}
/* 视图切换按钮容器 */
.view-toggle-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 999;
}
.view-toggle-container .layui-btn {
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
</style>
</body>
</html>

View File

@ -0,0 +1,571 @@
{include file="Public:header2"/}
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb">
<a href="{:url('/admin/user')}">用户管理</a>
<a><cite>余额流水明细</cite></a>
</span>
<span class="user-info">当前用户:{$nickname}</span>
</div>
<!-- 搜索表单 -->
<div class="layui-form layui-card-header layuiadmin-card-header-auto" id="searchForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">变化时间</label>
<div class="layui-input-inline">
<input type="text" id="timerange" name="timerange" class="layui-input" placeholder="选择时间范围">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">类型</label>
<div class="layui-input-inline">
<select name="type" id="type">
<option value="">全部类型</option>
<option value="1">后台充值</option>
<option value="2">在线充值</option>
<option value="3">抽赏消费</option>
<option value="4">背包回收</option>
<option value="5">推荐奖励</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">变化类型</label>
<div class="layui-input-inline">
<select name="change_type" id="change_type">
<option value="">全部</option>
<option value="add">收入</option>
<option value="sub">消耗</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">备注内容</label>
<div class="layui-input-inline">
<input type="text" name="content" id="content" placeholder="请输入备注内容关键词" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-useradmin" id="searchBtn">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i> 搜索
</button>
<button class="layui-btn layui-btn-primary" id="resetBtn">
<i class="layui-icon layui-icon-refresh"></i> 重置
</button>
</div>
</div>
</div>
<!-- 数据表格 -->
<div class="layui-card-body">
<!-- 时间线视图 -->
<div id="timeline-container">
<ul class="layui-timeline" id="money-timeline">
<!-- 时间线内容将通过JavaScript动态生成 -->
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis">&#xe63f;</i>
<div class="layui-timeline-content layui-text">
<div class="layui-timeline-title">加载中...</div>
</div>
</li>
</ul>
<!-- 分页控件 -->
<div id="timeline-page" class="layui-box layui-laypage layui-laypage-default"></div>
</div>
<!-- 表格视图(默认隐藏) -->
<div id="table-container" style="display: none;">
<table id="money-detail-table" lay-filter="money-detail-table"></table>
</div>
<!-- 视图切换按钮 -->
<div class="view-toggle-container">
<button class="layui-btn layui-btn-primary layui-btn-sm" id="toggleViewBtn">
<i class="layui-icon">&#xe857;</i> 切换视图
</button>
</div>
</div>
</div>
</div>
<!-- 金额模板 -->
<script type="text/html" id="moneyTpl">
{{# if(d.change_money > 0) { }}
<span class="money-add">+{{d.change_money}}</span>
{{# } else { }}
<span class="money-sub">{{d.change_money}}</span>
{{# } }}
</script>
<!-- 类型模板 -->
<script type="text/html" id="typeTpl">
{{# if(d.type == 1) { }}
<span class="type-badge type-1">后台充值</span>
{{# } else if(d.type == 2) { }}
<span class="type-badge type-2">在线充值</span>
{{# } else if(d.type == 3) { }}
<span class="type-badge type-3">抽赏消费</span>
{{# } else if(d.type == 4) { }}
<span class="type-badge type-4">背包回收</span>
{{# } else if(d.type == 5) { }}
<span class="type-badge type-5">推荐奖励</span>
{{# } else { }}
<span class="type-badge">其他({{d.type}})</span>
{{# } }}
</script>
{include file="Public:footer"/}
<script>
layui.use(['table', 'form', 'laydate'], function(){
var table = layui.table;
var form = layui.form;
var laydate = layui.laydate;
var $ = layui.$;
// 初始化日期范围选择器
laydate.render({
elem: '#timerange',
type: 'datetime',
range: true,
format: 'yyyy-MM-dd HH:mm:ss'
});
// 初始化表格
table.render({
elem: '#money-detail-table',
url: '{:url("/admin/user_money_detail_data")}',
where: {
user_id: '{$user_id}'
},
cols: [[
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'change_money', title: '变化金额', width: 120, templet: '#moneyTpl', sort: true},
{field: 'money', title: '剩余金额', width: 120},
{field: 'type', title: '消耗类型', width: 120, templet: '#typeTpl'},
{field: 'content', title: '描述', width: 200},
{field: 'other', title: '备注', width: 200},
{field: 'addtime', title: '添加时间', width: 180, templet: function(d){
return layui.util.toDateString(d.addtime * 1000, 'yyyy-MM-dd HH:mm:ss');
}, sort: true}
]],
page: true,
limit: 50,
limits: [20, 50, 100, 200],
height: 'full-220'
});
// 搜索按钮事件
$('#searchBtn').on('click', function(){
var timerange = $('#timerange').val();
var startTime = '';
var endTime = '';
if(timerange) {
var times = timerange.split(' - ');
startTime = times[0];
endTime = times[1];
}
// 执行搜索
table.reload('money-detail-table', {
where: {
user_id: '{$user_id}',
start_time: startTime,
end_time: endTime,
type: $('#type').val(),
change_type: $('#change_type').val(),
content: $('#content').val()
},
page: {
curr: 1
}
});
});
// 重置按钮事件
$('#resetBtn').on('click', function(){
$('#searchForm')[0].reset();
form.render();
// 重新加载表格
table.reload('money-detail-table', {
where: {
user_id: '{$user_id}'
},
page: {
curr: 1
}
});
});
});
</script>
{include file="Public:footer"/}
<script>
layui.use(['table', 'form', 'laydate', 'laypage', 'util'], function(){
var table = layui.table;
var form = layui.form;
var laydate = layui.laydate;
var laypage = layui.laypage;
var util = layui.util;
var $ = layui.$;
// 当前视图状态timeline 或 table
var currentView = 'timeline';
var currentPage = 1;
var itemsPerPage = 20;
var totalItems = 0;
var currentData = [];
var currentFilter = {
user_id: '{$user_id}'
};
// 初始化日期范围选择器
laydate.render({
elem: '#timerange',
type: 'datetime',
range: true,
format: 'yyyy-MM-dd HH:mm:ss'
});
// 加载时间线数据
function loadTimelineData(filter, page, limit) {
// 显示加载中
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">加载中...</div></div></li>');
// 发送请求获取数据
$.ajax({
url: '{:url("/admin/user_money_detail_data")}',
type: 'GET',
data: {
...filter,
page: page,
limit: limit
},
success: function(res) {
if (res.code === 0) {
currentData = res.data;
totalItems = res.count;
renderTimeline(res.data);
renderPagination(res.count, page, limit);
} else {
layer.msg(res.msg || '加载数据失败', {icon: 2});
}
},
error: function() {
layer.msg('网络错误,请稍后重试', {icon: 2});
}
});
}
// 渲染时间线
function renderTimeline(data) {
if (!data || data.length === 0) {
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">暂无数据</div></div></li>');
return;
}
var html = '';
data.forEach(function(item) {
// 根据金额变化设置不同的颜色和图标
var colorClass = item.change_money > 0 ? 'timeline-add' : 'timeline-sub';
var icon = item.change_money > 0 ? '&#xe68e;' : '&#xe659;';
// 获取类型标签
var typeLabel = getTypeLabel(item.type);
html += `
<li class="layui-timeline-item ${colorClass}">
<i class="layui-icon layui-timeline-axis">${icon}</i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">${util.toDateString(item.addtime * 1000, 'yyyy-MM-dd HH:mm:ss')}</h3>
<div class="timeline-card">
<div class="timeline-item">
<span class="timeline-label">变化金额:</span>
<span class="timeline-value ${item.change_money > 0 ? 'money-add' : 'money-sub'}">${item.change_money > 0 ? '+' + item.change_money : item.change_money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">剩余金额:</span>
<span class="timeline-value">${item.money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">类型:</span>
<span class="timeline-value">${typeLabel}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">描述:</span>
<span class="timeline-value">${item.content || '-'}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">备注:</span>
<span class="timeline-value">${item.other || '-'}</span>
</div>
</div>
</div>
</li>
`;
});
$('#money-timeline').html(html);
}
// 渲染分页
function renderPagination(count, currentPage, limit) {
laypage.render({
elem: 'timeline-page',
count: count,
curr: currentPage,
limit: limit,
limits: [10, 20, 50, 100],
layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
jump: function(obj, first) {
if (!first) {
currentPage = obj.curr;
itemsPerPage = obj.limit;
loadTimelineData(currentFilter, obj.curr, obj.limit);
}
}
});
}
// 获取类型标签HTML
function getTypeLabel(type) {
var typeMap = {
1: '<span class="type-badge type-1">后台充值</span>',
2: '<span class="type-badge type-2">在线充值</span>',
3: '<span class="type-badge type-3">抽赏消费</span>',
4: '<span class="type-badge type-4">背包回收</span>',
5: '<span class="type-badge type-5">推荐奖励</span>'
};
return typeMap[type] || `<span class="type-badge">其他(${type})</span>`;
}
// 初始化表格
var tableIns = table.render({
elem: '#money-detail-table',
url: '{:url("/admin/user_money_detail_data")}',
where: {
user_id: '{$user_id}'
},
cols: [[
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'change_money', title: '变化金额', width: 120, templet: '#moneyTpl', sort: true},
{field: 'money', title: '剩余金额', width: 120},
{field: 'type', title: '消耗类型', width: 120, templet: '#typeTpl'},
{field: 'content', title: '描述', width: 200},
{field: 'other', title: '备注', width: 200},
{field: 'addtime', title: '添加时间', width: 180, templet: function(d){
return util.toDateString(d.addtime * 1000, 'yyyy-MM-dd HH:mm:ss');
}, sort: true}
]],
page: true,
limit: itemsPerPage,
limits: [10, 20, 50, 100, 200],
height: 'full-220'
});
// 搜索按钮事件
$('#searchBtn').on('click', function(){
var timerange = $('#timerange').val();
var startTime = '';
var endTime = '';
if(timerange) {
var times = timerange.split(' - ');
startTime = times[0];
endTime = times[1];
}
// 更新当前筛选条件
currentFilter = {
user_id: '{$user_id}',
start_time: startTime,
end_time: endTime,
type: $('#type').val(),
change_type: $('#change_type').val(),
content: $('#content').val()
};
// 根据当前视图执行搜索
if (currentView === 'table') {
// 执行表格搜索
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 执行时间线搜索
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 重置按钮事件
$('#resetBtn').on('click', function(){
$('#searchForm')[0].reset();
form.render();
// 重置筛选条件
currentFilter = {
user_id: '{$user_id}'
};
// 根据当前视图重新加载数据
if (currentView === 'table') {
// 重新加载表格
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 重新加载时间线
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 视图切换按钮事件
$('#toggleViewBtn').on('click', function() {
if (currentView === 'timeline') {
// 切换到表格视图
$('#timeline-container').hide();
$('#table-container').show();
currentView = 'table';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到时间线视图');
// 刷新表格以适应新的大小
tableIns.resize();
} else {
// 切换到时间线视图
$('#table-container').hide();
$('#timeline-container').show();
currentView = 'timeline';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到表格视图');
}
});
// 初始加载时间线数据
loadTimelineData(currentFilter, currentPage, itemsPerPage);
});
</script>
<style>
.layui-card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info {
font-weight: bold;
color: #1E9FFF;
}
.money-add {
color: #FF5722;
font-weight: bold;
}
.money-sub {
color: #009688;
font-weight: bold;
}
.type-badge {
display: inline-block;
padding: 2px 5px;
border-radius: 2px;
color: #fff;
font-size: 12px;
}
.type-1 {
background-color: #FF5722;
}
.type-2 {
background-color: #FFB800;
}
.type-3 {
background-color: #009688;
}
.type-4 {
background-color: #1E9FFF;
}
.type-5 {
background-color: #5FB878;
}
/* 时间线相关样式 */
.timeline-card {
background-color: #f9f9f9;
border-radius: 4px;
padding: 15px;
margin-top: 10px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.timeline-item {
margin-bottom: 8px;
line-height: 24px;
}
.timeline-label {
color: #666;
font-weight: bold;
margin-right: 5px;
}
.timeline-value {
color: #333;
}
/* 收入项目样式 */
.timeline-add .layui-timeline-axis {
color: #FF5722;
background-color: #fff;
border-color: #FF5722;
}
/* 支出项目样式 */
.timeline-sub .layui-timeline-axis {
color: #009688;
background-color: #fff;
border-color: #009688;
}
/* 时间线标题 */
.layui-timeline-title {
font-weight: bold;
color: #333;
}
/* 分页区域样式 */
#timeline-page {
margin-top: 20px;
text-align: center;
}
/* 视图切换按钮容器 */
.view-toggle-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 999;
}
.view-toggle-container .layui-btn {
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
</style>
</body>
</html>

View File

@ -0,0 +1,486 @@
{include file="Public:header2"/}
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb">
<a href="{:url('/admin/user')}">用户管理</a>
<a><cite>{$currency_name}流水明细</cite></a>
</span>
<span class="user-info">当前用户:{$nickname}</span>
</div>
<!-- 搜索表单 -->
<div class="layui-form layui-card-header layuiadmin-card-header-auto" id="searchForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">变化时间</label>
<div class="layui-input-inline">
<input type="text" id="timerange" name="timerange" class="layui-input" placeholder="选择时间范围">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">类型</label>
<div class="layui-input-inline">
<select name="type" id="type">
<option value="">全部类型</option>
<option value="1">后台充值</option>
<option value="2">在线充值</option>
<option value="3">抽赏消费</option>
<option value="4">背包回收</option>
<option value="5">推荐奖励</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">变化类型</label>
<div class="layui-input-inline">
<select name="change_type" id="change_type">
<option value="">全部</option>
<option value="add">收入</option>
<option value="sub">消耗</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">备注内容</label>
<div class="layui-input-inline">
<input type="text" name="content" id="content" placeholder="请输入备注内容关键词" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-useradmin" id="searchBtn">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i> 搜索
</button>
<button class="layui-btn layui-btn-primary" id="resetBtn">
<i class="layui-icon layui-icon-refresh"></i> 重置
</button>
</div>
</div>
</div>
<!-- 数据表格 -->
<div class="layui-card-body">
<!-- 时间线视图 -->
<div id="timeline-container">
<ul class="layui-timeline" id="money-timeline">
<!-- 时间线内容将通过JavaScript动态生成 -->
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis">&#xe63f;</i>
<div class="layui-timeline-content layui-text">
<div class="layui-timeline-title">加载中...</div>
</div>
</li>
</ul>
<!-- 分页控件 -->
<div id="timeline-page" class="layui-box layui-laypage layui-laypage-default"></div>
</div>
<!-- 表格视图(默认隐藏) -->
<div id="table-container" style="display: none;">
<table id="money-detail-table" lay-filter="money-detail-table"></table>
</div>
<!-- 视图切换按钮 -->
<div class="view-toggle-container">
<button class="layui-btn layui-btn-primary layui-btn-sm" id="toggleViewBtn">
<i class="layui-icon">&#xe857;</i> 切换视图
</button>
</div>
</div>
</div>
</div>
<!-- 金额模板 -->
<script type="text/html" id="moneyTpl">
{{# if(d.change_money > 0) { }}
<span class="money-add">+{{d.change_money}}</span>
{{# } else { }}
<span class="money-sub">{{d.change_money}}</span>
{{# } }}
</script>
<!-- 类型模板 -->
<script type="text/html" id="typeTpl">
{{# if(d.type == 1) { }}
<span class="type-badge type-1">后台充值</span>
{{# } else if(d.type == 2) { }}
<span class="type-badge type-2">在线充值</span>
{{# } else if(d.type == 3) { }}
<span class="type-badge type-3">抽赏消费</span>
{{# } else if(d.type == 4) { }}
<span class="type-badge type-4">背包回收</span>
{{# } else if(d.type == 5) { }}
<span class="type-badge type-5">推荐奖励</span>
{{# } else { }}
<span class="type-badge">其他({{d.type}})</span>
{{# } }}
</script>
{include file="Public:footer"/}
<script>
layui.use(['table', 'form', 'laydate', 'laypage', 'util'], function(){
var table = layui.table;
var form = layui.form;
var laydate = layui.laydate;
var laypage = layui.laypage;
var util = layui.util;
var $ = layui.$;
// 当前视图状态timeline 或 table
var currentView = 'timeline';
var currentPage = 1;
var itemsPerPage = 20;
var totalItems = 0;
var currentData = [];
var currentFilter = {
user_id: '{$user_id}'
};
// 初始化日期范围选择器
laydate.render({
elem: '#timerange',
type: 'datetime',
range: true,
format: 'yyyy-MM-dd HH:mm:ss'
});
// 加载时间线数据
function loadTimelineData(filter, page, limit) {
// 显示加载中
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">加载中...</div></div></li>');
// 发送请求获取数据
$.ajax({
url: '{:url("/admin/user_score_detail_data")}',
type: 'GET',
data: {
...filter,
page: page,
limit: limit
},
success: function(res) {
if (res.code === 0) {
currentData = res.data;
totalItems = res.count;
renderTimeline(res.data);
renderPagination(res.count, page, limit);
} else {
layer.msg(res.msg || '加载数据失败', {icon: 2});
}
},
error: function() {
layer.msg('网络错误,请稍后重试', {icon: 2});
}
});
}
// 渲染时间线
function renderTimeline(data) {
if (!data || data.length === 0) {
$('#money-timeline').html('<li class="layui-timeline-item"><i class="layui-icon layui-timeline-axis">&#xe63f;</i><div class="layui-timeline-content layui-text"><div class="layui-timeline-title">暂无数据</div></div></li>');
return;
}
var html = '';
data.forEach(function(item) {
// 根据金额变化设置不同的颜色和图标
var colorClass = item.change_money > 0 ? 'timeline-add' : 'timeline-sub';
var icon = item.change_money > 0 ? '&#xe68e;' : '&#xe659;';
// 获取类型标签
var typeLabel = getTypeLabel(item.type);
html += `
<li class="layui-timeline-item ${colorClass}">
<i class="layui-icon layui-timeline-axis">${icon}</i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">${util.toDateString(item.addtime * 1000, 'yyyy-MM-dd HH:mm:ss')}</h3>
<div class="timeline-card">
<div class="timeline-item">
<span class="timeline-label">变化金额:</span>
<span class="timeline-value ${item.change_money > 0 ? 'money-add' : 'money-sub'}">${item.change_money > 0 ? '+' + item.change_money : item.change_money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">剩余金额:</span>
<span class="timeline-value">${item.money}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">类型:</span>
<span class="timeline-value">${typeLabel}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">描述:</span>
<span class="timeline-value">${item.content || '-'}</span>
</div>
<div class="timeline-item">
<span class="timeline-label">备注:</span>
<span class="timeline-value">${item.other || '-'}</span>
</div>
</div>
</div>
</li>
`;
});
$('#money-timeline').html(html);
}
// 渲染分页
function renderPagination(count, currentPage, limit) {
laypage.render({
elem: 'timeline-page',
count: count,
curr: currentPage,
limit: limit,
limits: [10, 20, 50, 100],
layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
jump: function(obj, first) {
if (!first) {
currentPage = obj.curr;
itemsPerPage = obj.limit;
loadTimelineData(currentFilter, obj.curr, obj.limit);
}
}
});
}
// 获取类型标签HTML
function getTypeLabel(type) {
var typeMap = {
1: '<span class="type-badge type-1">后台充值</span>',
2: '<span class="type-badge type-2">在线充值</span>',
3: '<span class="type-badge type-3">抽赏消费</span>',
4: '<span class="type-badge type-4">背包回收</span>',
5: '<span class="type-badge type-5">推荐奖励</span>'
};
return typeMap[type] || `<span class="type-badge">其他(${type})</span>`;
}
// 初始化表格
var tableIns = table.render({
elem: '#money-detail-table',
url: '{:url("/admin/user_score_detail_data")}',
where: {
user_id: '{$user_id}'
},
cols: [[
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'change_money', title: '变化金额', width: 120, templet: '#moneyTpl', sort: true},
{field: 'money', title: '剩余金额', width: 120},
{field: 'type', title: '消耗类型', width: 120, templet: '#typeTpl'},
{field: 'content', title: '描述', width: 200},
{field: 'other', title: '备注', width: 200},
{field: 'addtime', title: '添加时间', width: 180, templet: function(d){
return util.toDateString(d.addtime * 1000, 'yyyy-MM-dd HH:mm:ss');
}, sort: true}
]],
page: true,
limit: itemsPerPage,
limits: [10, 20, 50, 100, 200],
height: 'full-220'
});
// 搜索按钮事件
$('#searchBtn').on('click', function(){
var timerange = $('#timerange').val();
var startTime = '';
var endTime = '';
if(timerange) {
var times = timerange.split(' - ');
startTime = times[0];
endTime = times[1];
}
// 更新当前筛选条件
currentFilter = {
user_id: '{$user_id}',
start_time: startTime,
end_time: endTime,
type: $('#type').val(),
change_type: $('#change_type').val(),
content: $('#content').val()
};
// 根据当前视图执行搜索
if (currentView === 'table') {
// 执行表格搜索
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 执行时间线搜索
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 重置按钮事件
$('#resetBtn').on('click', function(){
$('#searchForm')[0].reset();
form.render();
// 重置筛选条件
currentFilter = {
user_id: '{$user_id}'
};
// 根据当前视图重新加载数据
if (currentView === 'table') {
// 重新加载表格
tableIns.reload({
where: currentFilter,
page: {
curr: 1
}
});
} else {
// 重新加载时间线
currentPage = 1;
loadTimelineData(currentFilter, 1, itemsPerPage);
}
});
// 视图切换按钮事件
$('#toggleViewBtn').on('click', function() {
if (currentView === 'timeline') {
// 切换到表格视图
$('#timeline-container').hide();
$('#table-container').show();
currentView = 'table';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到时间线视图');
// 刷新表格以适应新的大小
tableIns.resize();
} else {
// 切换到时间线视图
$('#table-container').hide();
$('#timeline-container').show();
currentView = 'timeline';
$(this).html('<i class="layui-icon">&#xe857;</i> 切换到表格视图');
}
});
// 初始加载时间线数据
loadTimelineData(currentFilter, currentPage, itemsPerPage);
});
</script>
<style>
.layui-card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info {
font-weight: bold;
color: #1E9FFF;
}
.money-add {
color: #FF5722;
font-weight: bold;
}
.money-sub {
color: #009688;
font-weight: bold;
}
.type-badge {
display: inline-block;
padding: 2px 5px;
border-radius: 2px;
color: #fff;
font-size: 12px;
}
.type-1 {
background-color: #FF5722;
}
.type-2 {
background-color: #FFB800;
}
.type-3 {
background-color: #009688;
}
.type-4 {
background-color: #1E9FFF;
}
.type-5 {
background-color: #5FB878;
}
/* 时间线相关样式 */
.timeline-card {
background-color: #f9f9f9;
border-radius: 4px;
padding: 15px;
margin-top: 10px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.timeline-item {
margin-bottom: 8px;
line-height: 24px;
}
.timeline-label {
color: #666;
font-weight: bold;
margin-right: 5px;
}
.timeline-value {
color: #333;
}
/* 收入项目样式 */
.timeline-add .layui-timeline-axis {
color: #FF5722;
background-color: #fff;
border-color: #FF5722;
}
/* 支出项目样式 */
.timeline-sub .layui-timeline-axis {
color: #009688;
background-color: #fff;
border-color: #009688;
}
/* 时间线标题 */
.layui-timeline-title {
font-weight: bold;
color: #333;
}
/* 分页区域样式 */
#timeline-page {
margin-top: 20px;
text-align: center;
}
/* 视图切换按钮容器 */
.view-toggle-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 999;
}
.view-toggle-container .layui-btn {
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
</style>
</body>
</html>

View File

@ -40,7 +40,7 @@ return [
],
[
'url' => '/admin/integral_list',
'name' => '吧唧币明细',
'name' => '货币1明细',
],
[