公司管理者与员工体系分析
公司管理者、公司员工、项目员工 — 关系梳理与后台方案报告
基于当前 D:\www\baoan 代码库(ThinkPHP3.1)梳理,供产品与二次开发参考。
涉及模块:会员中心User/Member、商家中心Merchant、Distributors、员工端Worker、shop/shop_worker/project_worker、认领Shoprecognition、组织权限org_*。
一、核心结论(先看这个)
| 问题 | 结论 |
|---|---|
「公司管理」是否只看 shop.user_id? | 是。 Merchant 与 Distributors 的 CommonAction 都用 Shop 表里 user_id = 当前登录 uid 且 closed=0、audit=1 来定位唯一公司上下文。 |
| 其他员工登个人后台能否进「公司管理」? | 不能进商家/分销公司中心(同一套规则),除非他的账号在 shop 表上也是该公司 user_id。个人中心里可出现 「员工登录」(走 shop_worker),跳转 /worker/...,与商家中心不是同一套 URL。 |
| 有部分后台权限的员工能否在公司管理里只显示部分功能? | Merchant 内已有 org_user_role / org_role_permission / org_permission 与 hasPermission(),但 进场条件仍为店主身份(见下文)。非 shop.user_id 的账号 目前进不了 Merchant,权限点无法发挥作用(除非改造登录上下文)。 |
导入时全用同一个 管理者用户ID 有无冲突? | 数据库层:shop.user_id 一般无唯一索引,允许多行同 uid。业务层:认领审核要求认领人「名下不能再有其他公司」;多店同 uid 时 Merchant 用 find() 只取一条,行为不确定。 |
二、三类角色与数据表
1. 公司管理者(店主 / 绑定会员)
- 主字段:
by_shop.user_id(代码里表前缀可能为配置,模型为ShopModel,$tableName = 'shop')。 - 含义:该公司在系统内的「归属账号」:商家后台登录、公司资料编辑、财务维度默认关联等,都以此为准。
- 相关状态字段(常见):
audit(审核)、closed(删除/屏蔽)、recognition(是否已认领:0未认领,1已绑定真实运营者)。
2. 公司员工(门店员工 / 律师员工等)
- 主表:
by_shop_worker(模型ShopworkerModel/WorkerModel,$tableName = 'shop_worker')。 - 关键字段:
user_id(员工会员 ID)、shop_id(所属公司)、status(邀约流程里 待确认 / 已生效,Merchant 里创建时status=0,员工在user/information/worker同意后应为1— 以库内实际为准)。 - 约束逻辑(代码侧):
Merchant/WorkerAction::create中会校验该user_id是否已属于其他公司(status==1时提示「已属于其他公司」),避免一人同时在两家公司当全职店员(按当前实现)。
3. 项目员工(项目维度成员)
- 主表:
by_project_worker(ProjectworkerModel,$tableName = 'project_worker')。 - 关系:把 公司员工(
shop_worker.worker_id)挂到 具体项目(project_id)上;用于法律服务/招投标等项目协作(如Worker/ProjectAction、Merchant/ProjectAction中的统计与权限判断)。
层次关系(概念上):
flowchart TB
U[Users 会员账号]
S[Shop 公司]
SW[Shopworker 公司员工]
P[Project 项目]
PW[Projectworker 项目参与]
U -->|shop.user_id 店主| S
S -->|shop_id| SW
U -->|shop_worker.user_id| SW
SW -->|worker_id| PW
P -->|project_id| PW
三、各入口登录与鉴权逻辑(代码事实)
1. 会员中心:User/MemberAction::index + 模板 themes/default/User/member/index.html
- 「公司管理」 链接指向:
U('distributors/index/index')(PC 分销商/公司中心)。 - 展示名称
is_shop_name:
D('Shop')->find(array('where' => array('user_id' => $this->uid)))
注意:此处 未 同时约束 closed、audit,与下文「能登入公司中心」的条件不完全一致,可能出现「有字样但进中心报错」的边缘情况(以实际数据为准)。
- 「员工登录」:模板内判断
D('Shopworker')->where(array('user_id'=>$MEMBER['user_id']))->find()
有记录则显示入口,跳转 worker/index/index(员工独立模块)。
2. 商家中心:Merchant/CommonAction::_initialize
$this->shop = D('Shop')->find(array(
"where" => array(
'user_id' => $this->uid,
'closed' => 0,
'audit' => 1
)
));
if (empty($this->shop)) {
$this->error('该用户没有开通公司', ...);
}
$this->shop_id = $this->shop['shop_id'];
- 唯一键逻辑上是「当前 uid + 状态」;若存在多条记录,
find()只返回一条(实现依赖框架与 SQL,通常为排序不确定的一条),多店同 uid 时在商家中心属于未定义行为。
3. 分销/公司中心:Distributors/CommonAction
与 Merchant 同样 使用 user_id = uid 且 closed=0、audit=1 查找 Shop。结论与上相同。
4. 员工端:Worker/CommonAction::_initialize
- 不要求
shop.user_id = uid。 - 流程:根据
shop_worker.user_id = uid取员工行 → 校验status为已通过 → 用shop_worker.shop_id加载Shop。 - 员工使用的是
/worker/...路由与模板,菜单能力集与Merchant分离。
5. 组织权限点(仅 Merchant 内)
Merchant/CommonAction::getPermissionCodes() 摘要:
shop.user_id === 当前 uid→ 权限码视为'*'(全开)。- 否则查
org_user_role(shop_id+user_id):
- 若未配置角色:当前实现为 '*'(改造期兼容,相当于未挂角色也全放行 — 但前提是已能进入 Merchant)。
- 若配置了角色:按 org_role_permission → org_permission 聚合 permission_code,再 hasPermission('xxx') 控制菜单/动作。
矛盾点(重要):_initialize 先把 shop 限制为 shop.user_id = uid,非店主 无法进入 Merchant,因此 org_user_role 对「普通员工 uid」目前无法在该入口生效。若要「店员登商家后台但仅部分菜单」,必须 改造 shop 解析逻辑(例如:允许 org_user_role 反查 shop_id 再加载 Shop)。
四、认领(Shoprecognition)与 shop.user_id 变更
前台提交认领申请后,后台 ShoprecognitionAction::audit 在通过时会执行(核心一行):
$obj_shop->save(array(
'shop_id' => $detail['shop_id'],
'recognition' => 1,
'user_id' => $detail['user_id'], // 认领人会员ID
));
前置校验(摘要):
- 认领人 不能 已拥有任意
user_id为其的Shop记录(find()有则失败:「认领会员已经有管理的公司了」)。 - 目标店铺须存在、
closed正常、且recognition != 1(未认领完)。
对批量导入的影响:
- 若导入时把
user_id填成占位账号 且recognition=0,真实运营者仍可通过前台认领 → 审核通过后将user_id改认领人,占位号失去店主身份。 - 若导入时 直接
audit=1且user_id=占位且recognition=1:则语义上已是「已认领/已绑定」,认领流程可能不再适用,需人工在后台「编辑公司」改user_id或通过业务规则调整。
(具体以当前导入实现写入的 recognition 字段为准。)
五、问题 2 的逐项回答(会员中心与权限)
「公司管理」是不是只能是 shop.user_id?
在 能打开 Distributors / Merchant 公司后台 这一层,是,必须是该公司在 shop 表上的 user_id。
「其他员工登个人后台还能出现在这里吗」
- 会员中心列表:
- 「公司管理」链接 始终显示,公司名称是否显示取决于 MemberAction 里对 Shop 的查询(见第三节)。
- 「员工登录」另起一行,依赖 shop_worker,与是否店主无关。
- 能否像店主一样进公司管理后台:默认不能;只能进
Worker员工端(若已开通账号且审核通过)。
「有的员工有一部分后台权限,能否在这里显示、只显示部分功能」
- 现状:部分权限设计在
Merchant+org_permission,但 进店门仍为店主。 - 要做成产品能力:需要 统一「公司上下文」解析(见第八节方案)。
六、问题 3:批量导入同一管理者 ID
1. 会不会「数据库冲突」?
- 一般不会因 主键 冲突(每行
shop_id不同)。 - 业务冲突 主要体现在:
- 认领:针对的是「认领人是否已有一家店」,不是「一家公司是否已被别人认领」的唯一约束(店侧靠 recognition 等字段 + 审核逻辑)。
- 店主登录商家后台:多行 shop.user_id 相同 → find() 随机一条,运维与功能风险高。
2. 别人如何「申请/认领」本站公司?
- 前台 认领接口(如
Home/ShopAction::recognition):校验申请人 不能 已拥有Shop,不能 已有未完结认领申请等;写入Shoprecognition。 - 后台
ShoprecognitionAction::audit:通过后把该公司user_id改为认领人,并标记recognition=1。
若占位账号下挂 大量 公司且均需不同真实主体运营,应 避免 长期共用同一 user_id,否则登录与资金/订单归属都会混乱。
3. 建议导入策略
| 场景 | 建议 |
|---|---|
| 仅入库展示、暂不运营 | 可用统一占位 user_id,并 recognition=0,便于后续认领替换 |
| 已明确运营者 | 直接填该运营者 user_id,并保持 一 uid 一主店(商) 或接受多店 uid 的框架限制 |
| 多店同一集团 | 考虑 分店表(如 shop_branch)或 组织账号改造,勿只堆在同一 shop.user_id |
七、改进方案(按优先级)
短期(低风险)
- 会员中心
is_shop_name查询 与Distributors/Merchant条件对齐(增加closed=0, audit=1),避免展示与可进性不一致。 - 导入说明与约束:文档约定「占位 uid + recognition 状态」;后台导入页提示 多店同 uid 不适用于商家登录。
- 员工入口:
member/index.html里Shopworker判断建议增加status=1(若业务如此),避免待审核也出现「员工登录」。
中期(架构)
- 商家登录上下文改造(选一):
- 方案 A:登录后若 shop.user_id != uid,查 org_user_role 得 shop_id,再 Shop::find(shop_id) 作为当前公司;getPermissionCodes() 非店主走角色权限(去掉未配角色即 '*' 的宽松策略,改为最小权限)。
- 方案 B:引入 「当前操作公司」session,支持 uid 切换多店(需完整审计所有 shop_id 来源)。
- 统一「员工端 vs 商家端」能力地图:哪些能力只在
Worker,哪些应在Merchant受 RBAC 控制,避免两套重复。 - 认领与导入:后台批量导入默认
recognition=0+ 占位 uid;提供「批量触发认领通知」可选。
长期(产品)
- 集团/多公司账号模型:主账号、子公司、店员委派、
shop与users多对多中间表等,替代「多行 shop 同 user_id」的隐含约定。
八、关键文件索引(便于开发跳转)
| 路径 | 说明 |
|---|---|
Banyan/Lib/Action/Merchant/CommonAction.class.php | 商家 shop 加载、getPermissionCodes / hasPermission |
Banyan/Lib/Action/Distributors/CommonAction.class.php | 分销公司中心 shop 加载 |
Banyan/Lib/Action/Worker/CommonAction.class.php | 员工 shop_worker → shop |
Banyan/Lib/Action/User/MemberAction.class.php | 会员中心 is_shop/is_shop_name |
themes/default/User/member/index.html | 「公司管理」「员工登录」展示 |
Banyan/Lib/Action/Merchant/WorkerAction.class.php | 公司员工维护、邀约 |
Banyan/Lib/Action/Backstage/ShoprecognitionAction.class.php | 认领审核、写回 shop.user_id |
Banyan/Lib/Action/Home/ShopAction.class.php | 前台认领提交 recognition |
Banyan/Lib/Model/ShopworkerModel.class.php | shop_worker |
Banyan/Lib/Model/ProjectworkerModel.class.php | project_worker |
九、免责声明
本报告依据当前仓库静态代码归纳;数据库是否额外加了唯一索引、以及部分 status/audit 字段在库中的真实取值,以线上库结构及运行数据为准。若你方有定制分支,请以合并后的代码为准做最终评审。
*文档版本:2026-03-28*
