feat: 新增发票抬头、晒单、钱包日志等模型及后台管理功能
- 新增 invoice_title、showcase、wallet_log 模型及对应语言包 - 新增后台控制器、视图及搜索字段配置 - 修复服务类目删除保护逻辑 - 优化后台登录页面文案及样式 - 新增前端角色切换逻辑及页面拦截 - 新增 SVG 图标及样式变量 - 修复接口权限及下拉框默认值问题
这个提交包含在:
@@ -51,23 +51,14 @@ class Auth extends Base
|
||||
if ($user['status'] !== 'normal') {
|
||||
$this->error('账号已被禁用');
|
||||
}
|
||||
// 若微信手机号快捷登录初始化的用户未设密码,直接落库更新密码
|
||||
if (empty($user['password'])) {
|
||||
$salt = Random::alnum();
|
||||
$encryptPassword = $this->auth->getEncryptPassword($password, $salt);
|
||||
Db::name('user')->where('id', $user['id'])->update([
|
||||
'password' => $encryptPassword,
|
||||
'salt' => $salt,
|
||||
'updatetime' => time(),
|
||||
]);
|
||||
$this->auth->direct($user['id']);
|
||||
} else {
|
||||
$encryptPassword = $this->auth->getEncryptPassword($password, $user['salt']);
|
||||
if ($user['password'] !== $encryptPassword) {
|
||||
$this->error('手机号或密码不正确');
|
||||
}
|
||||
$this->auth->direct($user['id']);
|
||||
$this->error('该账号尚未设置登录密码,请使用验证码或微信登录后设置密码');
|
||||
}
|
||||
$encryptPassword = $this->auth->getEncryptPassword($password, $user['salt']);
|
||||
if ($user['password'] !== $encryptPassword) {
|
||||
$this->error('手机号或密码不正确');
|
||||
}
|
||||
$this->auth->direct($user['id']);
|
||||
}
|
||||
|
||||
// 直查真实数据库返回用户完整信息
|
||||
@@ -153,6 +144,7 @@ class Auth extends Base
|
||||
$merchantRole = $merchantRel ? $merchantRel['role'] : null;
|
||||
$merchantInfo = null;
|
||||
if ($merchant) {
|
||||
$memberCount = (int)Db::name('merchant_member')->where('merchant_id', (int)$merchant['id'])->count();
|
||||
$merchantInfo = [
|
||||
'id' => (int)$merchant['id'],
|
||||
'name' => $merchant['name'],
|
||||
@@ -165,12 +157,42 @@ class Auth extends Base
|
||||
'role' => $merchantRole,
|
||||
'is_owner' => $merchantRole === 'owner',
|
||||
'can_order' => $merchant['verify_status'] === 'pass',
|
||||
'member_count' => $memberCount,
|
||||
];
|
||||
}
|
||||
|
||||
$userType = (!empty($user['user_type']) && $user['user_type'] === 'merchant') || ($merchant && $merchant['verify_status'] === 'pass')
|
||||
? 'merchant'
|
||||
: 'personal';
|
||||
// 统计发单端各状态订单数量(与 Order::index 共享同一套团队归属口径)
|
||||
$team = $this->currentMerchantTeam();
|
||||
$teamUids = $team ? $team['user_ids'] : [$uid];
|
||||
$statusGroups = Db::name('order')
|
||||
->field('status, count(*) as cnt')
|
||||
->where('user_id', 'in', $teamUids)
|
||||
->where('user_deleted', 0)
|
||||
->group('status')
|
||||
->select();
|
||||
$rawCounts = [];
|
||||
foreach ($statusGroups as $sg) {
|
||||
$rawCounts[(int)$sg['status']] = (int)$sg['cnt'];
|
||||
}
|
||||
$getCnt = function ($st) use ($rawCounts) {
|
||||
return isset($rawCounts[$st]) ? $rawCounts[$st] : 0;
|
||||
};
|
||||
$orderCounts = [
|
||||
'pending_pay' => $getCnt(0),
|
||||
'pending_accept' => $getCnt(1),
|
||||
'quoting' => $getCnt(2),
|
||||
'scheduled' => $getCnt(3),
|
||||
'serving' => $getCnt(4) + $getCnt(5) + $getCnt(6),
|
||||
'pending_verify' => $getCnt(7),
|
||||
];
|
||||
|
||||
if ($merchantRole === 'member' && $merchant && $merchant['verify_status'] === 'pass') {
|
||||
$userType = 'merchant';
|
||||
} elseif (!empty($user['user_type']) && in_array($user['user_type'], ['personal', 'merchant'], true)) {
|
||||
$userType = $user['user_type'];
|
||||
} else {
|
||||
$userType = ($merchant && $merchant['verify_status'] === 'pass') ? 'merchant' : 'personal';
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int)$user['id'],
|
||||
@@ -187,6 +209,7 @@ class Auth extends Base
|
||||
'balance' => (float)$user['money'],
|
||||
'coupon_count' => (int)$couponCount,
|
||||
'unread_count' => (int)$unread,
|
||||
'order_counts' => $orderCounts,
|
||||
'is_master' => $master ? true : false,
|
||||
'master' => $masterInfo,
|
||||
'is_merchant' => $merchant ? true : false,
|
||||
@@ -230,6 +253,13 @@ class Auth extends Base
|
||||
$this->error('电子邮箱格式不正确');
|
||||
}
|
||||
|
||||
$merchantRel = $this->merchantOf($uid);
|
||||
if ($userType === 'merchant') {
|
||||
if (!$merchantRel || ($merchantRel['merchant']['verify_status'] ?? '') !== 'pass') {
|
||||
$this->error('请先提交企业入驻申请并通过审核后再启用商家账号');
|
||||
}
|
||||
}
|
||||
|
||||
$userUpdate = [
|
||||
'nickname' => $nickname,
|
||||
'user_type' => $userType,
|
||||
@@ -246,11 +276,11 @@ class Auth extends Base
|
||||
}
|
||||
Db::name('user')->where('id', $uid)->update($userUpdate);
|
||||
|
||||
if ($userType === 'merchant') {
|
||||
$existMerchant = Db::name('merchant')->where('user_id', $uid)->find();
|
||||
if ($userType === 'merchant' && $merchantRel && $merchantRel['role'] === 'owner') {
|
||||
$existMerchant = $merchantRel['merchant'];
|
||||
$curUser = Db::name('user')->where('id', $uid)->find();
|
||||
$merchantSave = [
|
||||
'name' => $companyName !== '' ? $companyName : ($existMerchant ? $existMerchant['name'] : $nickname),
|
||||
'name' => $companyName !== '' ? $companyName : (!empty($existMerchant['name']) ? $existMerchant['name'] : $nickname),
|
||||
'legal_person' => $legalPerson,
|
||||
'legal_mobile' => $legalMobile,
|
||||
'tech_mobile' => $techMobile,
|
||||
@@ -260,15 +290,7 @@ class Auth extends Base
|
||||
'email' => $email,
|
||||
'updatetime' => time(),
|
||||
];
|
||||
if ($existMerchant) {
|
||||
Db::name('merchant')->where('id', $existMerchant['id'])->update($merchantSave);
|
||||
} else {
|
||||
$merchantSave['user_id'] = $uid;
|
||||
$merchantSave['license_no'] = '';
|
||||
$merchantSave['verify_status'] = 'pass';
|
||||
$merchantSave['createtime'] = time();
|
||||
Db::name('merchant')->insert($merchantSave);
|
||||
}
|
||||
Db::name('merchant')->where('id', (int)$existMerchant['id'])->update($merchantSave);
|
||||
}
|
||||
|
||||
$this->success('保存成功', ['userinfo' => $this->profileData()]);
|
||||
@@ -405,7 +427,7 @@ class Auth extends Base
|
||||
if ($role === 'master') {
|
||||
$redirect = '/pages/master/hall';
|
||||
} elseif ($role === 'merchant') {
|
||||
$redirect = '/pages/merchant/workbench';
|
||||
$redirect = '/pages/mine/mine';
|
||||
}
|
||||
|
||||
$this->success('切换成功', ['role' => $role, 'redirect' => $redirect]);
|
||||
|
||||
在新工单中引用
屏蔽一个用户