feat: 新增发票抬头、晒单、钱包日志等模型及后台管理功能

- 新增 invoice_title、showcase、wallet_log 模型及对应语言包
- 新增后台控制器、视图及搜索字段配置
- 修复服务类目删除保护逻辑
- 优化后台登录页面文案及样式
- 新增前端角色切换逻辑及页面拦截
- 新增 SVG 图标及样式变量
- 修复接口权限及下拉框默认值问题
这个提交包含在:
2026-11-11 17:02:35 +08:00
父节点 5908cf6b16
当前提交 fafddceaf2
共有 332 个文件被更改,包括 33892 次插入 和 8835 次删除

查看文件

@@ -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]);