Commit 5bc183dc authored by 刘小敏's avatar 刘小敏

管理后台用户管理增加生日提醒逻辑

parent 1ce55c68
......@@ -11,4 +11,31 @@ use think\db\Query;
class UserFilter extends BaseFilter
{
protected $keywordFields = ['id', 'username', 'nickname', 'mobile', 'email'];
/**
* 生日范围查询(date 类型字段)
*/
public function birthday(Query $query, $data)
{
$operator = $this->getOperator($data);
$value = $this->getValue($data);
if ($operator == 'range' || $operator == 'not range') {
$currentValue = explode(' - ', $value);
// 对 date 类型字段去除时间部分
$dateArr = [];
foreach ($currentValue as $v) {
$v = trim($v);
if ($v !== '') {
$dateArr[] = date('Y-m-d', strtotime($v));
}
}
if (count($dateArr) == 1) {
return $query->where('birthday', $operator == 'range' ? '>=' : '<', $dateArr[0]);
} else if (count($dateArr) == 2) {
return $query->whereBetween('birthday', $dateArr);
}
}
return $query;
}
}
......@@ -64,10 +64,14 @@ class User extends Common
public function edit($id = null)
{
operate_filter();
$params = $this->request->only(['username', 'nickname', 'mobile', 'password', 'avatar', 'gender', 'email', 'status']);
$params = $this->request->only(['username', 'nickname', 'mobile', 'password', 'avatar', 'gender', 'email', 'status', 'birthday']);
if (empty($params['password'])) unset($params['password']);
if (empty($params['username'])) unset($params['username']);
if (isset($params['birthday']) && trim($params['birthday']) === '') {
$params['birthday'] = null;
}
$params['id'] = $id;
$this->svalidate($params, '.edit');
......@@ -200,4 +204,80 @@ class User extends Common
}
/**
* 导出用户列表(分页多选导出)
*/
public function export()
{
$ids = $this->request->param('ids', '');
if (empty($ids)) {
$this->error('请选择要导出的用户');
}
$idArr = array_filter(array_map('intval', explode(',', $ids)));
if (empty($idArr)) {
$this->error('导出数据为空');
}
$cellTitles = [
'id' => 'ID',
'username' => '用户名',
'nickname' => '昵称',
'mobile' => '手机号',
'email' => '邮箱',
'gender_text' => '性别',
'birthday' => '生日',
'status_text' => '状态',
'commission' => '佣金',
'total_consume' => '总消费',
'score' => '积分',
'money' => '余额',
'createtime' => '注册时间',
'logintime' => '上次登录',
];
$total = count($idArr);
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '用户列表',
'cell_titles' => $cellTitles,
'total' => $total,
];
$result = $export->export($params, function ($pages) use ($idArr) {
$ids = array_slice($idArr, ($pages['page'] - 1) * $pages['list_rows'], $pages['list_rows']);
$datas = $this->model->with(['shopro_user_tag'])
->where('id', 'in', $ids)
->select();
$datas = collection($datas)->toArray();
$newDatas = [];
foreach ($datas as $user) {
$newDatas[] = [
'id' => $user['id'] ?? '',
'username' => $user['username'] ?? '',
'nickname' => $user['nickname'] ?? '',
'mobile' => $user['mobile'] ?? '',
'email' => $user['email'] ?? '',
'gender_text' => $user['gender_text'] ?? '',
'birthday' => $user['birthday'] ?? '',
'status_text' => $user['status_text'] ?? '',
'commission' => $user['commission'] ?? '',
'total_consume' => $user['total_consume'] ?? '',
'score' => $user['score'] ?? '',
'money' => $user['money'] ?? '',
'createtime' => $user['createtime'] ?? '',
'logintime' => $user['logintime'] ?? '',
];
}
return $newDatas;
});
return $result;
}
}
......@@ -153,6 +153,10 @@
</el-input>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24">
<div class="left">生日</div>
<div class="right">{{ state.detail.birthday || '-' }}</div>
</el-col>
<!-- 新增用户标签选择器 -->
<el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24">
......
{include file="/shopro/common/script" /}
<style>
.sa-birthday-soon {
color: #f56c6c;
font-weight: bold;
background: #fef0f0;
padding: 2px 8px;
border-radius: 4px;
}
</style>
<div id="index" class="user-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
......@@ -10,13 +20,17 @@
</sa-filter-condition>
</div>
<div class="sa-title-right">
{if $auth->check('shopro/user/user/export')}
<el-button :loading="exportLoading" :disabled="exportLoading || selectedIds.length === 0" @click="onExport">导出Excel</el-button>
{/if}
<el-button class="sa-button-refresh" icon="RefreshRight" @click="getData"></el-button>
<el-button class="sa-button-refresh" icon="Search" @click="onOpenFilter"></el-button>
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-table height="100%" class="sa-table" :data="state.data" stripe @sort-change="onChangeSort">
<el-table height="100%" class="sa-table" :data="state.data" stripe @sort-change="onChangeSort" @selection-change="onSelectionChange" ref="tableRef">
<el-table-column type="selection" min-width="50"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90" sortable="custom"> </el-table-column>
<el-table-column label="用户信息" min-width="150">
<template #default="scope">
......@@ -37,6 +51,11 @@
</el-table-column>
<el-table-column sortable="custom" prop="createtime" label="注册时间" min-width="172"></el-table-column>
<el-table-column sortable="custom" prop="logintime" label="上次登录" min-width="172"></el-table-column>
<el-table-column prop="birthday" label="生日" min-width="160">
<template #default="scope">
<span :class="{ 'sa-birthday-soon': isBirthdaySoon(scope.row.birthday) }">{{ scope.row.birthday || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="用户标签" min-width="100">
<template #default="scope">
<div v-for="item in scope.row.shopro_user_tag" :key="item.tag_code">
......
......@@ -2,7 +2,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { reactive, ref, onMounted } = Vue
const index = {
setup() {
const state = reactive({
......@@ -16,6 +16,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
status: '',
createtime: [],
logintime: [],
birthday: [],
},
tools: {
user: {
......@@ -82,6 +83,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
label: '上次登录',
value: [],
},
birthday: {
type: 'tdatetimerange',
label: '生日',
value: [],
},
},
condition: {},
}
......@@ -96,6 +102,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
email: 'like',
createtime: 'range',
logintime: 'range',
birthday: 'range',
});
Fast.api.ajax({
url: 'shopro/user/user',
......@@ -150,6 +157,43 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}, function (ret, res) { })
}
/**
* 判断是否距生日还有7天(仅剩7天时高亮)
*/
function isBirthdaySoon(birthday) {
if (!birthday) return false;
let now = new Date();
let birth = new Date(birthday);
// 构造今年的生日日期
let thisYearBirthday = new Date(now.getFullYear(), birth.getMonth(), birth.getDate());
// 如果今年的生日已过,则判断明年的生日
if (thisYearBirthday < now) {
thisYearBirthday = new Date(now.getFullYear() + 1, birth.getMonth(), birth.getDate());
}
let diffDays = Math.ceil((thisYearBirthday - now) / (1000 * 60 * 60 * 24));
return diffDays === 7;
}
const selectedIds = ref([]);
const tableRef = ref(null);
function onSelectionChange(selection) {
selectedIds.value = selection.map(item => item.id);
}
const exportLoading = ref(false);
function onExport() {
if (selectedIds.value.length === 0) {
Fast.api.msg('请先选择要导出的用户');
return;
}
exportLoading.value = true;
let ids = selectedIds.value.join(',');
window.location.href = `${Config.moduleurl}/shopro/user/user/export?ids=${ids}`;
setTimeout(function () {
exportLoading.value = false;
}, 3000);
}
onMounted(() => {
getData()
})
......@@ -162,7 +206,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
onChangeFilter,
pagination,
onDetail,
onDelete
onDelete,
isBirthdaySoon,
selectedIds,
tableRef,
onSelectionChange,
exportLoading,
onExport
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment