Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
loveisland
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
刘小敏
loveisland
Commits
5bc183dc
Commit
5bc183dc
authored
Jun 22, 2026
by
刘小敏
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
管理后台用户管理增加生日提醒逻辑
parent
1ce55c68
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
184 additions
and
4 deletions
+184
-4
UserFilter.php
addons/shopro/filter/user/UserFilter.php
+27
-0
User.php
application/admin/controller/shopro/user/User.php
+81
-1
detail.html
application/admin/view/shopro/user/user/detail.html
+4
-0
index.html
application/admin/view/shopro/user/user/index.html
+20
-1
user.js
public/assets/js/backend/shopro/user/user.js
+52
-2
No files found.
addons/shopro/filter/user/UserFilter.php
View file @
5bc183dc
...
...
@@ -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
;
}
}
application/admin/controller/shopro/user/User.php
View file @
5bc183dc
...
...
@@ -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
;
}
}
application/admin/view/shopro/user/user/detail.html
View file @
5bc183dc
...
...
@@ -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"
>
...
...
application/admin/view/shopro/user/user/index.html
View file @
5bc183dc
{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"
>
...
...
public/assets/js/backend/shopro/user/user.js
View file @
5bc183dc
...
...
@@ -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
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment