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:
@@ -0,0 +1,47 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?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}%");
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user