feat(nginx-log): curd 生成 raw/position 后台并改只读

- NginxAccessLog + NginxLogPosition Scheme 加 #[Component] 注解
- Scheme Table name 补 ul_ 前缀(curd 严格校验要求)
- curd 生成 nginx 模块完整后台(controller/model/view/js)
- Base/App 双层只读控制器(参照 TimerLogBase 范式)
  - AccessLogBase: add/edit/delete/modify 全部 error
  - LogPositionBase: 同上
- 视图改造:
  - access_log 裁剪到 8 列核心字段(time_local/method/uri/status/remote_addr/request_time/body_bytes_sent/http_user_agent)
  - status/request_time 自定义 badge 渲染
  - toolbar 清空 + operat 仅保留详情(B 类只读页面)
  - log_position 全字段 + 只读化
- HTTP 验证:index 200 OK + add/edit/delete/modify 全部返回错误
This commit is contained in:
augushong
2026-07-28 06:21:13 +08:00
parent 7987001cd2
commit d5329cdd45
26 changed files with 1203 additions and 34 deletions

View File

@@ -5,9 +5,10 @@ namespace app\admin\scheme;
use app\common\scheme\BaseScheme;
use app\common\scheme\attribute\Table;
use app\common\scheme\attribute\Field;
use app\common\scheme\attribute\Component;
use app\common\scheme\attribute\Index;
#[Table(name: 'nginx_log_position', comment: 'nginx 日志文件读取位置(增量读取状态)')]
#[Table(name: 'ul_nginx_log_position', comment: 'nginx 日志文件读取位置(增量读取状态)')]
#[Index(columns: ['file_path'], name: 'uniq_file_path', type: 'UNIQUE')]
class NginxLogPosition extends BaseScheme
{
@@ -15,29 +16,38 @@ class NginxLogPosition extends BaseScheme
public $id;
#[Field(type: 'varchar', length: 500, nullable: false, comment: '日志文件绝对路径')]
#[Component(type: 'text', options: [])]
public $file_path;
#[Field(type: 'bigint', default: '0', unsigned: true, comment: '文件 inode用于检测日志轮转')]
#[Component(type: 'text', options: [])]
public $inode;
#[Field(type: 'bigint', default: '0', unsigned: true, comment: '上次读取到的字节偏移')]
#[Component(type: 'text', options: [])]
public $offset;
#[Field(type: 'int', length: 11, default: '0', unsigned: true, comment: '上次读取时间戳')]
#[Component(type: 'date', options: [])]
public $last_read_time;
#[Field(type: 'varchar', length: 32, default: '', comment: '上次最后一行的 md5 哈希(容错校验)')]
#[Component(type: 'text', options: [])]
public $last_line_hash;
#[Field(type: 'int', length: 11, default: '0', unsigned: true, comment: '解析失败累计次数')]
#[Component(type: 'text', options: [])]
public $parse_fail_count;
#[Field(type: 'text', nullable: true, comment: '解析失败样本行(最多保留若干条)')]
#[Component(type: 'textarea', options: [])]
public $parse_fail_samples;
#[Field(type: 'int', length: 11, unsigned: true, comment: '创建时间戳')]
#[Component(type: 'date', options: [])]
public $create_time;
#[Field(type: 'int', length: 11, unsigned: true, comment: '更新时间戳')]
#[Component(type: 'date', options: [])]
public $update_time;
}