245 lines
8.4 KiB
PHP
245 lines
8.4 KiB
PHP
<?php
|
|
|
|
namespace app\controller\admin;
|
|
|
|
use support\Request;
|
|
use support\think\Db;
|
|
|
|
class UsersController
|
|
{
|
|
public function overview(Request $request)
|
|
{
|
|
$this->ensurePasswordColumn();
|
|
return api_success([
|
|
'cards' => [
|
|
[
|
|
'title' => '用户总量',
|
|
'value' => (int)Db::name('users')->count(),
|
|
'desc' => '当前数据库中的用户数量',
|
|
],
|
|
[
|
|
'title' => '正常用户',
|
|
'value' => (int)Db::name('users')->where('status', 'enabled')->count(),
|
|
'desc' => '当前可正常使用系统的用户数量',
|
|
],
|
|
[
|
|
'title' => '地址数量',
|
|
'value' => (int)Db::name('user_addresses')->count(),
|
|
'desc' => '用户维护的寄送与收货地址总数',
|
|
],
|
|
[
|
|
'title' => '消息总量',
|
|
'value' => (int)Db::name('user_messages')->count(),
|
|
'desc' => '已发送给用户的站内消息数量',
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$this->ensurePasswordColumn();
|
|
$keyword = trim((string)$request->input('keyword', ''));
|
|
$status = trim((string)$request->input('status', ''));
|
|
|
|
$query = Db::name('users')
|
|
->alias('u')
|
|
->leftJoin('user_addresses a', 'a.user_id = u.id AND a.is_default = 1')
|
|
->field([
|
|
'u.id',
|
|
'u.nickname',
|
|
'u.mobile',
|
|
'u.password',
|
|
'u.status',
|
|
'u.created_at',
|
|
'u.updated_at',
|
|
'a.province',
|
|
'a.city',
|
|
'a.district',
|
|
'a.detail_address',
|
|
])
|
|
->order('u.id', 'desc');
|
|
|
|
if ($keyword !== '') {
|
|
$query->where(function ($builder) use ($keyword) {
|
|
$builder->whereLike('u.nickname', "%{$keyword}%")
|
|
->whereOrLike('u.mobile', "%{$keyword}%");
|
|
});
|
|
}
|
|
|
|
if ($status !== '') {
|
|
$query->where('u.status', $status);
|
|
}
|
|
|
|
$rows = $query->select()->toArray();
|
|
|
|
$list = array_map(function (array $item) {
|
|
$userId = (int)$item['id'];
|
|
|
|
return [
|
|
'id' => $userId,
|
|
'nickname' => $item['nickname'] ?: '未命名用户',
|
|
'mobile' => $item['mobile'] ?: '',
|
|
'status' => $item['status'],
|
|
'status_text' => $this->userStatusText($item['status']),
|
|
'password_set' => ((string)($item['password'] ?? '')) !== '',
|
|
'default_address' => trim(sprintf(
|
|
'%s%s%s%s',
|
|
$item['province'] ?? '',
|
|
$item['city'] ?? '',
|
|
$item['district'] ?? '',
|
|
$item['detail_address'] ?? ''
|
|
)),
|
|
'order_count' => (int)Db::name('orders')->where('user_id', $userId)->count(),
|
|
'message_count' => (int)Db::name('user_messages')->where('user_id', $userId)->count(),
|
|
'ticket_count' => (int)Db::name('tickets')->where('user_id', $userId)->count(),
|
|
'created_at' => $item['created_at'],
|
|
'updated_at' => $item['updated_at'],
|
|
];
|
|
}, $rows);
|
|
|
|
return api_success(['list' => $list]);
|
|
}
|
|
|
|
public function detail(Request $request)
|
|
{
|
|
$this->ensurePasswordColumn();
|
|
$id = (int)$request->input('id', 0);
|
|
if ($id <= 0) {
|
|
return api_error('用户 ID 不能为空', 422);
|
|
}
|
|
|
|
$user = Db::name('users')->where('id', $id)->find();
|
|
if (!$user) {
|
|
return api_error('用户不存在', 404);
|
|
}
|
|
|
|
$addresses = Db::name('user_addresses')
|
|
->where('user_id', $id)
|
|
->order('is_default', 'desc')
|
|
->order('id', 'desc')
|
|
->select()
|
|
->toArray();
|
|
|
|
$recentOrders = Db::name('orders')
|
|
->where('user_id', $id)
|
|
->order('id', 'desc')
|
|
->limit(5)
|
|
->select()
|
|
->toArray();
|
|
|
|
$recentMessages = Db::name('user_messages')
|
|
->where('user_id', $id)
|
|
->order('id', 'desc')
|
|
->limit(5)
|
|
->select()
|
|
->toArray();
|
|
|
|
return api_success([
|
|
'user_info' => [
|
|
'id' => (int)$user['id'],
|
|
'nickname' => $user['nickname'] ?: '未命名用户',
|
|
'mobile' => $user['mobile'] ?: '',
|
|
'status' => $user['status'],
|
|
'status_text' => $this->userStatusText($user['status']),
|
|
'password_set' => ((string)($user['password'] ?? '')) !== '',
|
|
'created_at' => $user['created_at'],
|
|
'updated_at' => $user['updated_at'],
|
|
],
|
|
'addresses' => array_map(fn (array $item) => [
|
|
'consignee' => $item['consignee'],
|
|
'mobile' => $item['mobile'],
|
|
'full_address' => trim(sprintf('%s%s%s%s', $item['province'], $item['city'], $item['district'], $item['detail_address'])),
|
|
'is_default' => (bool)$item['is_default'],
|
|
], $addresses),
|
|
'recent_orders' => array_map(fn (array $item) => [
|
|
'order_no' => $item['order_no'],
|
|
'display_status' => $item['display_status'],
|
|
'pay_amount' => (float)$item['pay_amount'],
|
|
'created_at' => $item['created_at'],
|
|
], $recentOrders),
|
|
'recent_messages' => array_map(fn (array $item) => [
|
|
'title' => $item['title'],
|
|
'content' => $item['content'],
|
|
'is_read' => (bool)$item['is_read'],
|
|
'created_at' => $item['created_at'],
|
|
], $recentMessages),
|
|
]);
|
|
}
|
|
|
|
public function save(Request $request)
|
|
{
|
|
$this->ensurePasswordColumn();
|
|
$id = (int)$request->input('id', 0);
|
|
$nickname = trim((string)$request->input('nickname', ''));
|
|
$mobile = trim((string)$request->input('mobile', ''));
|
|
$status = trim((string)$request->input('status', 'enabled'));
|
|
$password = trim((string)$request->input('password', ''));
|
|
|
|
if ($nickname === '' || $mobile === '') {
|
|
return api_error('昵称和手机号不能为空', 422);
|
|
}
|
|
|
|
$now = date('Y-m-d H:i:s');
|
|
$payload = [
|
|
'nickname' => $nickname,
|
|
'mobile' => $mobile,
|
|
'status' => $status !== '' ? $status : 'enabled',
|
|
'updated_at' => $now,
|
|
];
|
|
if ($password !== '') {
|
|
$payload['password'] = password_hash($password, PASSWORD_BCRYPT);
|
|
}
|
|
|
|
if ($id > 0) {
|
|
$user = Db::name('users')->where('id', $id)->find();
|
|
if (!$user) {
|
|
return api_error('用户不存在', 404);
|
|
}
|
|
|
|
$exists = Db::name('users')
|
|
->where('mobile', $mobile)
|
|
->where('id', '<>', $id)
|
|
->find();
|
|
if ($exists) {
|
|
return api_error('手机号已存在', 422);
|
|
}
|
|
|
|
Db::name('users')->where('id', $id)->update($payload);
|
|
return api_success(['id' => $id], '用户已更新');
|
|
}
|
|
|
|
$exists = Db::name('users')->where('mobile', $mobile)->find();
|
|
if ($exists) {
|
|
return api_error('手机号已存在', 422);
|
|
}
|
|
|
|
$payload['avatar'] = '';
|
|
$payload['password'] = $payload['password'] ?? '';
|
|
$payload['last_login_at'] = null;
|
|
$payload['created_at'] = $now;
|
|
$newId = (int)Db::name('users')->insertGetId($payload);
|
|
|
|
return api_success(['id' => $newId], '用户已创建');
|
|
}
|
|
|
|
private function userStatusText(string $status): string
|
|
{
|
|
return match ($status) {
|
|
'enabled' => '正常',
|
|
'disabled' => '已停用',
|
|
default => $status,
|
|
};
|
|
}
|
|
|
|
private function ensurePasswordColumn(): void
|
|
{
|
|
$column = Db::query("SHOW COLUMNS FROM users LIKE 'password'");
|
|
if ($column) {
|
|
return;
|
|
}
|
|
|
|
Db::execute("ALTER TABLE users ADD COLUMN password VARCHAR(255) NOT NULL DEFAULT '' AFTER mobile");
|
|
}
|
|
}
|