@dskripchenko/laravel-admin 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +139 -0
- package/README.md +104 -195
- package/README.ru.md +135 -0
- package/README.zh.md +130 -0
- package/dist/components/dashboard/StatWidget.vue.d.ts +26 -0
- package/dist/components/fields/SelectField.vue.d.ts +6 -0
- package/dist/components/infolist/IconEntry.vue.d.ts +2 -3
- package/dist/components/infolist/RepeatableEntry.vue.d.ts +23 -0
- package/dist/components/layouts/ColumnsLayout.vue.d.ts +1 -1
- package/dist/components/render/FieldRenderer.vue.d.ts +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +23967 -4929
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/README.zh.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# dskripchenko/laravel-admin
|
|
2
|
+
|
|
3
|
+
> 🌐 [English](README.md) · [Русский](README.ru.md) · [Deutsch](README.de.md) · **中文**
|
|
4
|
+
|
|
5
|
+
受 Orchid 启发的 Laravel 管理面板构造器,配备 Vue 3 SPA 前端。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@dskripchenko/laravel-admin)
|
|
8
|
+
[](https://packagist.org/packages/dskripchenko/laravel-admin)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
```php
|
|
12
|
+
Admin::resources([UserResource::class, ArticleResource::class]);
|
|
13
|
+
Admin::screen([ContactScreen::class, SystemStatusScreen::class]);
|
|
14
|
+
Admin::menu()->add(
|
|
15
|
+
MenuNode::make('content', '内容')->icon('book')->children([
|
|
16
|
+
MenuNode::resource('articles'),
|
|
17
|
+
MenuNode::dashboard('analytics'),
|
|
18
|
+
]),
|
|
19
|
+
);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 内含功能
|
|
23
|
+
|
|
24
|
+
- **CRUD 流水线** — 将 Eloquent 模型声明为 `Resource`,自动获得
|
|
25
|
+
list/create/edit/view 屏幕。
|
|
26
|
+
- **自定义 Screen** — 通过 `Admin::screen()` 实现非 CRUD 页面(表单、
|
|
27
|
+
报表、仪表板)。处理 state、layout、command-bar、验证、权限。
|
|
28
|
+
- **层级菜单** — 流式 API `Admin::menu()->add(MenuNode::...)`,任意深
|
|
29
|
+
度,自动解析 `resource()`/`screen()`/`dashboard()`。
|
|
30
|
+
- **30+ 字段类型** — Input/Number/Select/Combobox/DatePicker/
|
|
31
|
+
ColorPicker/FileUpload/Wysiwyg/Markdown/TranslatableInput/Repeater/
|
|
32
|
+
RelationSelect/Cascader/TreeSelect/Slug/KeyValue/TagsInput/...
|
|
33
|
+
- **15+ 布局** — Rows/Columns/Tabs/Wizard+Step/Block/Modal/Drawer/
|
|
34
|
+
Wrapper/Infolist/Dashboard/Accordion/View/...
|
|
35
|
+
- **表格** — 可排序列、preset、过滤器、行内编辑、汇总、保存视图、
|
|
36
|
+
分组、轮询、导出(CSV/XLSX/PDF)。
|
|
37
|
+
- **仪表板** — 8 种小部件类型(Stats/Chart/RecentList/Markdown/
|
|
38
|
+
Iframe/Table/Heatmap/Gauge),每用户布局覆盖、拖动/调整大小、轮询。
|
|
39
|
+
- **认证 & RBAC** — 多 guard、AdminUser、Roles、2FA TOTP、profile、
|
|
40
|
+
模拟、密码重置、邮箱验证。
|
|
41
|
+
- **审计** — 管理员动作的只追加日志(`AuditLog` + `Loggable` trait)。
|
|
42
|
+
- **设置** — 单例配置屏幕。
|
|
43
|
+
- **通知** — 铃铛徽章 + 抽屉(Database notifications)。
|
|
44
|
+
- **API tokens** — Profile 中的 Sanctum 集成(可选)。
|
|
45
|
+
- **主题** — 浅色/深色 + 用户偏好,`@dskripchenko/ui` 设计 token。
|
|
46
|
+
- **i18n** — locale 解析器(5 步优先级),与
|
|
47
|
+
`dskripchenko/laravel-translatable` 的 `TranslatableField` 桥接。
|
|
48
|
+
- **多租户** — `TenantResolver` / `TenantContext` / `TenantScoped`
|
|
49
|
+
trait。策略由主机端决定;我们仅提供契约。
|
|
50
|
+
- **插件** — `AdminPlugin` 接口;姐妹包使用相同的 hook。
|
|
51
|
+
- **测试** — `ResourceTestCase`、`ScreenTestCase`、`ActsAsAdmin` trait。
|
|
52
|
+
- **OpenAPI 3.0** — 从 docblock 标签 `@input`/`@output` 生成。
|
|
53
|
+
|
|
54
|
+
## 安装
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
composer require dskripchenko/laravel-admin
|
|
58
|
+
php artisan vendor:publish --tag=admin-config
|
|
59
|
+
php artisan migrate
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
// resources/js/admin.js
|
|
64
|
+
import { createAdminApp } from '@dskripchenko/laravel-admin'
|
|
65
|
+
import '@dskripchenko/ui/styles/all.css'
|
|
66
|
+
import '@dskripchenko/laravel-admin/style.css'
|
|
67
|
+
|
|
68
|
+
const { app } = createAdminApp(window.__ADMIN_BOOTSTRAP__)
|
|
69
|
+
app.mount('#admin-app')
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm i @dskripchenko/laravel-admin @dskripchenko/ui
|
|
74
|
+
npm run build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
访问 `/admin/login`。第一个 resource 见
|
|
78
|
+
[getting-started.md](docs/zh/getting-started.md)。
|
|
79
|
+
|
|
80
|
+
## 文档
|
|
81
|
+
|
|
82
|
+
- [快速开始](docs/zh/getting-started.md)
|
|
83
|
+
- [架构](docs/zh/architecture.md)
|
|
84
|
+
- 概念: [Resources](docs/zh/concepts/resources.md) ·
|
|
85
|
+
[Screens](docs/zh/concepts/screens.md) ·
|
|
86
|
+
[Widgets & Dashboards](docs/zh/concepts/widgets-and-dashboards.md) ·
|
|
87
|
+
[菜单](docs/zh/concepts/menu.md) ·
|
|
88
|
+
[Actions](docs/en/concepts/actions.md) (en) ·
|
|
89
|
+
[权限](docs/en/concepts/permissions.md) (en) ·
|
|
90
|
+
[i18n](docs/en/concepts/i18n.md) (en) ·
|
|
91
|
+
[租户](docs/en/concepts/tenancy.md) (en)
|
|
92
|
+
- [字段参考](docs/en/fields-reference.md) (en)
|
|
93
|
+
- [布局参考](docs/en/layouts-reference.md) (en)
|
|
94
|
+
- [API 参考](docs/en/api-reference.md) (en)
|
|
95
|
+
- [前端扩展](docs/en/frontend-extension.md) (en)
|
|
96
|
+
- [测试](docs/en/testing.md) (en)
|
|
97
|
+
- [迁移指南](docs/en/migration-guide.md) (en)
|
|
98
|
+
- [术语表](docs/zh/glossary.md)
|
|
99
|
+
|
|
100
|
+
## 技术栈
|
|
101
|
+
|
|
102
|
+
- **PHP** ^8.5
|
|
103
|
+
- **Laravel** ^12
|
|
104
|
+
- **Vue** ^3.4 + TypeScript + Pinia + Vue Router
|
|
105
|
+
- **Bundle** — `@dskripchenko/laravel-admin` ~62 KB gz (esm + cjs)
|
|
106
|
+
- **无 vendor lock-in** 用于编辑器/图表 — 自带(姐妹包适配器:
|
|
107
|
+
`quill`、`tinymce`)
|
|
108
|
+
|
|
109
|
+
## 姐妹包
|
|
110
|
+
|
|
111
|
+
可选扩展,仅安装所需:
|
|
112
|
+
|
|
113
|
+
| 包 | 用途 |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `dskripchenko/laravel-admin-starter` | User/Role/Audit/Settings/Translations/Blocks resources |
|
|
116
|
+
| `dskripchenko/laravel-admin-tinymce` | TinyMCE WYSIWYG 适配器 |
|
|
117
|
+
| `dskripchenko/laravel-admin-quill` | Quill WYSIWYG 适配器 |
|
|
118
|
+
| `dskripchenko/laravel-admin-search` | ⌘K 命令面板 + Scout suggest |
|
|
119
|
+
| `dskripchenko/laravel-admin-media` | 媒体库(无 Spatie/medialibrary 依赖) |
|
|
120
|
+
| `dskripchenko/laravel-admin-health` | 健康检查(无 Spatie/laravel-health 依赖) |
|
|
121
|
+
| `dskripchenko/laravel-admin-pulse` | 遥测(无 laravel/pulse 依赖) |
|
|
122
|
+
| `dskripchenko/laravel-admin-jobs` | Failed jobs / batches 查看器 |
|
|
123
|
+
|
|
124
|
+
## 贡献
|
|
125
|
+
|
|
126
|
+
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。欢迎 PR。
|
|
127
|
+
|
|
128
|
+
## 许可证
|
|
129
|
+
|
|
130
|
+
[MIT](LICENSE) © Denis Skripchenko
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
type SemanticTone = 'neutral' | 'positive' | 'negative' | 'warning' | 'info';
|
|
2
|
+
/**
|
|
3
|
+
* Backend StatsOverviewWidget::data() отдаёт массив `stats: [{label, value,
|
|
4
|
+
* change: {delta, direction}, color, icon}]`. Frontend StatWidget берёт
|
|
5
|
+
* первый stat и рендерит UidStat. Несколько stats в одном виджете пока
|
|
6
|
+
* не поддерживаются (если нужно — host задаёт несколько StatWidget'ов).
|
|
7
|
+
*
|
|
8
|
+
* Для legacy scalar-values (если widget сам прислал `value` напрямую) тоже
|
|
9
|
+
* работает — приоритет имеет stats[0].
|
|
10
|
+
*/
|
|
11
|
+
interface StatChange {
|
|
12
|
+
delta?: number;
|
|
13
|
+
direction?: 'up' | 'down' | 'flat';
|
|
14
|
+
}
|
|
15
|
+
interface StatItem {
|
|
16
|
+
label?: string;
|
|
17
|
+
value?: number | string;
|
|
18
|
+
prefix?: string;
|
|
19
|
+
suffix?: string;
|
|
20
|
+
change?: StatChange | null;
|
|
21
|
+
color?: string | null;
|
|
22
|
+
icon?: string | null;
|
|
23
|
+
}
|
|
2
24
|
interface Props {
|
|
3
25
|
title?: string;
|
|
26
|
+
/** Backend payload from StatsOverviewWidget. */
|
|
27
|
+
stats?: StatItem[];
|
|
28
|
+
/** Legacy scalar value (если host передал не через массив). */
|
|
4
29
|
value?: number | string;
|
|
5
30
|
prefix?: string;
|
|
6
31
|
suffix?: string;
|
|
@@ -14,6 +39,7 @@ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, imp
|
|
|
14
39
|
title: string;
|
|
15
40
|
loading: boolean;
|
|
16
41
|
prefix: string;
|
|
42
|
+
stats: StatItem[];
|
|
17
43
|
suffix: string;
|
|
18
44
|
trend: number;
|
|
19
45
|
precision: number;
|
|
@@ -11,6 +11,11 @@ interface Props {
|
|
|
11
11
|
required?: boolean;
|
|
12
12
|
placeholder?: string | null;
|
|
13
13
|
disabled?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Read-only — бэкенд может пометить Select через `->readonly()`. UidSelect
|
|
16
|
+
* не различает readonly/disabled — мапим в disabled (визуально совпадает).
|
|
17
|
+
*/
|
|
18
|
+
readonly?: boolean;
|
|
14
19
|
searchable?: boolean;
|
|
15
20
|
clearable?: boolean;
|
|
16
21
|
size?: 'sm' | 'md' | 'lg';
|
|
@@ -22,6 +27,7 @@ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, imp
|
|
|
22
27
|
placeholder: string | null;
|
|
23
28
|
required: boolean;
|
|
24
29
|
searchable: boolean;
|
|
30
|
+
readonly: boolean;
|
|
25
31
|
clearable: boolean;
|
|
26
32
|
help: string | null;
|
|
27
33
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -2,11 +2,10 @@ interface Props {
|
|
|
2
2
|
name?: string;
|
|
3
3
|
label?: string;
|
|
4
4
|
value?: boolean | null;
|
|
5
|
-
/**
|
|
5
|
+
/** lucide-vue-next icon name, e.g. 'check-circle-2'. */
|
|
6
6
|
trueIcon?: string;
|
|
7
|
-
/**
|
|
7
|
+
/** lucide-vue-next icon name, e.g. 'x-circle'. */
|
|
8
8
|
falseIcon?: string;
|
|
9
|
-
/** Текстовые подписи. */
|
|
10
9
|
trueLabel?: string;
|
|
11
10
|
falseLabel?: string;
|
|
12
11
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface EntryMeta extends Record<string, unknown> {
|
|
2
|
+
type: string;
|
|
3
|
+
name: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
attributes?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
name?: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
entries?: EntryMeta[];
|
|
11
|
+
layout?: 'columns' | 'rows' | 'inline';
|
|
12
|
+
value?: unknown;
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
}
|
|
15
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
16
|
+
entries: EntryMeta[];
|
|
17
|
+
value: undefined;
|
|
18
|
+
label: string;
|
|
19
|
+
name: string;
|
|
20
|
+
placeholder: string;
|
|
21
|
+
layout: "columns" | "rows" | "inline";
|
|
22
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
23
|
+
export default _default;
|
|
@@ -7,7 +7,7 @@ interface Props {
|
|
|
7
7
|
cols?: number;
|
|
8
8
|
}
|
|
9
9
|
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
10
|
-
cols: number;
|
|
11
10
|
gap: string;
|
|
11
|
+
cols: number;
|
|
12
12
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
13
|
export default _default;
|