refactor: fix directory structure and namespaces for webman conventions

- Rename directories to lowercase: Controller→controller, Model→model, Service→service, Util→util, Bootstrap→bootstrap
- Update all namespaces from App\Xxx to app\xxx (webman convention)
- Update all import statements across the codebase
- Update route.php to use lowercase namespaces
- Remove unused CompanyFeishuApp model
- Comment out unimplemented controller routes

Following webman 2.x framework conventions:
- Models: app\model\{ClassName}
- Controllers: app\controller\{ClassName}
- Services: app\service\{ClassName}
- Utils: app\util\{ClassName}
- Middleware: app\middleware\{ClassName}

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-24 18:28:23 +08:00
parent 423a04a610
commit 8629f4a4ce
20 changed files with 55 additions and 341 deletions
-47
View File
@@ -1,47 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class ApprovalFlow extends Model
{
protected $table = 'approval_flow';
protected $fillable = [
'business_type',
'name',
'description',
'status',
];
protected $casts = [
'status' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* 关联审批节点
*/
public function nodes()
{
return $this->hasMany(ApprovalNode::class, 'flow_id')->orderBy('order');
}
/**
* 获取启用的流程
*/
public function scopeActive($query)
{
return $query->where('status', 1);
}
/**
* 根据业务类型获取流程
*/
public function scopeByBusinessType($query, string $businessType)
{
return $query->where('business_type', $businessType);
}
}
-79
View File
@@ -1,79 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class ApprovalNode extends Model
{
protected $table = 'approval_node';
protected $fillable = [
'flow_id',
'type',
'name',
'order',
'approvers',
'conditions',
];
protected $casts = [
'approvers' => 'array',
'conditions' => 'array',
'order' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* 节点类型常量
*/
const TYPE_APPROVER = 'approver'; // 审批人(单人)
const TYPE_AND_APPROVE = 'and_approve'; // 会签(需所有人通过)
const TYPE_OR_APPROVE = 'or_approve'; // 或签(任一人通过)
const TYPE_NOTIFY = 'notify'; // 抄送(通知用)
/**
* 关联流程
*/
public function flow()
{
return $this->belongsTo(ApprovalFlow::class, 'flow_id');
}
/**
* 获取指定顺序的节点
*/
public function scopeByOrder($query, int $order)
{
return $query->where('order', $order);
}
/**
* 判断是否是审批节点
*/
public function isApprovalNode(): bool
{
return in_array($this->type, [
self::TYPE_APPROVER,
self::TYPE_AND_APPROVE,
self::TYPE_OR_APPROVE,
]);
}
/**
* 判断是否是会签
*/
public function isAndApprove(): bool
{
return $this->type === self::TYPE_AND_APPROVE;
}
/**
* 判断是否是或签
*/
public function isOrApprove(): bool
{
return $this->type === self::TYPE_OR_APPROVE;
}
}
-91
View File
@@ -1,91 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class ApprovalOrder extends Model
{
protected $table = 'approval_order';
protected $fillable = [
'business_type',
'business_id',
'title',
'applicant_id',
'status',
'current_nodes',
'flow_id',
'form_data',
'attachments',
];
protected $casts = [
'current_nodes' => 'array',
'form_data' => 'array',
'attachments' => 'array',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* 审批状态常量
*/
const STATUS_DRAFT = 'draft'; // 草稿
const STATUS_PENDING = 'pending'; // 审批中
const STATUS_APPROVED = 'approved'; // 已通过
const STATUS_REJECTED = 'rejected'; // 已拒绝
const STATUS_CANCELLED = 'cancelled'; // 已撤销
/**
* 关联流程
*/
public function flow()
{
return $this->belongsTo(ApprovalFlow::class, 'flow_id');
}
/**
* 关联申请人
*/
public function applicant()
{
return $this->belongsTo(User::class, 'applicant_id');
}
/**
* 关联审批记录
*/
public function records()
{
return $this->hasMany(ApprovalRecord::class, 'order_id')->orderBy('created_at');
}
/**
* 判断是否可以编辑
*/
public function canEdit(): bool
{
return $this->status === self::STATUS_DRAFT;
}
/**
* 判断是否可以审批
*/
public function canApprove(): bool
{
return $this->status === self::STATUS_PENDING;
}
/**
* 判断是否已结束
*/
public function isEnded(): bool
{
return in_array($this->status, [
self::STATUS_APPROVED,
self::STATUS_REJECTED,
self::STATUS_CANCELLED,
]);
}
}
-63
View File
@@ -1,63 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class ApprovalRecord extends Model
{
protected $table = 'approval_record';
protected $fillable = [
'order_id',
'node_id',
'node_type',
'approver_id',
'action',
'comment',
];
protected $casts = [
'created_at' => 'datetime',
];
/**
* 操作类型常量
*/
const ACTION_SUBMIT = 'submit'; // 提交
const ACTION_APPROVE = 'approve'; // 通过
const ACTION_REJECT = 'reject'; // 拒绝
const ACTION_CANCEL = 'cancel'; // 撤销
/**
* 关联审批单
*/
public function order()
{
return $this->belongsTo(ApprovalOrder::class, 'order_id');
}
/**
* 关联审批人
*/
public function approver()
{
return $this->belongsTo(User::class, 'approver_id');
}
/**
* 判断是否是批准操作
*/
public function isApproved(): bool
{
return $this->action === self::ACTION_APPROVE;
}
/**
* 判断是否是拒绝操作
*/
public function isRejected(): bool
{
return $this->action === self::ACTION_REJECT;
}
}
-96
View File
@@ -1,96 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class Company extends Model
{
protected $table = 'companies';
protected $fillable = [
'name',
'abbr',
'tenant_key',
'sort',
'status',
'feishu_enabled',
];
protected $casts = [
'sort' => 'integer',
'status' => 'integer',
'feishu_enabled' => 'boolean',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* 关联用户
*/
public function users()
{
return $this->hasMany(User::class, 'company_id');
}
/**
* 获取启用的公司
*/
public function scopeActive($query)
{
return $query->where('status', 1);
}
/**
* 根据租户Key查找
*/
public function scopeByTenantKey($query, string $tenantKey)
{
return $query->where('tenant_key', $tenantKey);
}
/**
* 根据缩写查找
*/
public function scopeByAbbr($query, string $abbr)
{
return $query->where('abbr', $abbr);
}
/**
* 搜索公司
*/
public function scopeSearch($query, ?string $keyword)
{
if (!$keyword) {
return $query;
}
return $query->where(function ($q) use ($keyword) {
$q->where('name', 'like', "%{$keyword}%")
->orWhere('abbr', 'like', "%{$keyword}%");
});
}
/**
* 获取默认飞书应用配置
*/
public function getDefaultFeishuApp(): ?array
{
$sql = "SELECT * FROM company_feishu_apps WHERE company_id = ? AND system_id = 1 AND status = 1 ORDER BY sort ASC LIMIT 1";
$stmt = \App\Util\Db::connection()->getPdo()->prepare($sql);
$stmt->execute([$this->id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* 获取所有飞书应用配置
*/
public function getFeishuApps(): array
{
$sql = "SELECT * FROM company_feishu_apps WHERE company_id = ? AND status = 1 ORDER BY sort";
$stmt = \App\Util\Db::connection()->getPdo()->prepare($sql);
$stmt->execute([$this->id]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
-91
View File
@@ -1,91 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class CompanyFeishuApp extends Model
{
protected $table = 'company_feishu_apps';
protected $fillable = [
'company_id',
'system_id',
'name',
'tenant_key',
'app_id',
'app_secret',
'encrypt_key',
'verification_token',
'base_uri',
'callback_url',
'mobile_callback_url',
'scopes',
'state',
'sort',
'status',
];
protected $casts = [
'company_id' => 'integer',
'system_id' => 'integer',
'sort' => 'integer',
'status' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
protected $hidden = [
'app_secret',
'encrypt_key',
'verification_token',
];
/**
* 关联公司
*/
public function company()
{
return $this->belongsTo(Company::class, 'company_id');
}
/**
* 获取启用的应用
*/
public function scopeActive($query)
{
return $query->where('status', 1);
}
/**
* 根据系统ID查找
*/
public function scopeBySystemId($query, int $systemId)
{
return $query->where('system_id', $systemId);
}
/**
* 获取X-Server应用
*/
public function scopeXServer($query)
{
return $query->where('system_id', 1);
}
/**
* 获取工单应用
*/
public function scopeTicket($query)
{
return $query->where('system_id', 2);
}
/**
* 获取CRM应用
*/
public function scopeCrm($query)
{
return $query->where('system_id', 3);
}
}
-134
View File
@@ -1,134 +0,0 @@
<?php
namespace App\Model;
use support\Model;
class User extends Model
{
protected $table = 'users';
protected $fillable = [
'company_id',
'sn',
'report_to',
'name',
'avatar',
'sex',
'email',
'phone',
'password',
'status',
'user_type',
'union_id',
'feishu_user_id',
'feishu_open_id',
'tenant_key',
'position',
'sign_img',
];
protected $casts = [
'company_id' => 'integer',
'report_to' => 'integer',
'sex' => 'integer',
'status' => 'integer',
'user_type' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
protected $hidden = [
'password',
];
/**
* 关联公司
*/
public function company()
{
return $this->belongsTo(Company::class, 'company_id');
}
/**
* 上级用户
*/
public function parent()
{
return $this->belongsTo(User::class, 'report_to');
}
/**
* 下级用户
*/
public function children()
{
return $this->hasMany(User::class, 'report_to');
}
/**
* 获取启用的用户
*/
public function scopeActive($query)
{
return $query->where('status', 1);
}
/**
* 根据公司ID查找
*/
public function scopeByCompany($query, int $companyId)
{
return $query->where('company_id', $companyId);
}
/**
* 根据飞书用户ID查找
*/
public function scopeByFeishuUserId($query, ?string $feishuUserId)
{
if ($feishuUserId === null) {
return $query;
}
return $query->where('feishu_user_id', $feishuUserId);
}
/**
* 根据飞书 UnionID 查找
*/
public function scopeByFeishuUnionId($query, ?string $feishuUnionId)
{
if ($feishuUnionId === null) {
return $query;
}
return $query->where('union_id', $feishuUnionId);
}
/**
* 根据OpenID查找
*/
public function scopeByFeishuOpenId($query, ?string $openId)
{
if ($openId === null) {
return $query;
}
return $query->where('feishu_open_id', $openId);
}
/**
* 搜索用户
*/
public function scopeSearch($query, ?string $keyword)
{
if (!$keyword) {
return $query;
}
return $query->where(function ($q) use ($keyword) {
$q->where('name', 'like', "%{$keyword}%")
->orWhere('email', 'like', "%{$keyword}%")
->orWhere('phone', 'like', "%{$keyword}%")
->orWhere('sn', 'like', "%{$keyword}%");
});
}
}