签入版本

This commit is contained in:
2026-10-11 19:06:33 +08:00
parent 17d28de8b7
commit 4084c6bd17
674 changed files with 58855 additions and 1892 deletions
@@ -293,7 +293,7 @@ ALTER TABLE laravel_city ADD INDEX idx_parent_code (parent_code);
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=rxthinkcmf.laravel13.elevue
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=root
DB_PASSWORD=root
DB_PREFIX=laravel_
@@ -303,7 +303,7 @@ DB_PREFIX=laravel_
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=rxthinkcmf.laravel13.elevue
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=postgres
DB_PASSWORD=root
DB_PREFIX=laravel_
@@ -313,7 +313,7 @@ DB_PREFIX=laravel_
DB_CONNECTION=sqlsrv
DB_HOST=127.0.0.1
DB_PORT=1433
DB_DATABASE=rxthinkcmf.laravel13.elevue
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=sa
DB_PASSWORD=root
DB_PREFIX=laravel_
@@ -323,7 +323,7 @@ DB_PREFIX=laravel_
DB_CONNECTION=oracle
DB_HOST=127.0.0.1
DB_PORT=1521
DB_DATABASE=rxthinkcmf.laravel13.elevue
DB_DATABASE=rxthinkcmf.laravel13.naivevue
DB_USERNAME=root
DB_PASSWORD=root
DB_PREFIX=laravel_
@@ -383,15 +383,15 @@ Eloquent 的方言层自动处理大部分 SQL 差异,切换数据库只需修
```text
document/
├── mysql/
│ └── rxthinkcmf.laravel13.elevue.sql # MySQL 版本
│ └── rxthinkcmf.laravel13.naivevue.sql # MySQL 版本
├── postgresql/
│ └── rxthinkcmf.laravel13.elevue.sql # PostgreSQL 版本
│ └── rxthinkcmf.laravel13.naivevue.sql # PostgreSQL 版本
├── sqlserver/
│ └── rxthinkcmf.laravel13.elevue.sql # SQL Server 版本
│ └── rxthinkcmf.laravel13.naivevue.sql # SQL Server 版本
├── oracle/
│ └── rxthinkcmf.laravel13.elevue.sql # Oracle 版本
│ └── rxthinkcmf.laravel13.naivevue.sql # Oracle 版本
└── sqlite/
└── rxthinkcmf.laravel13.elevue.sql # SQLite 版本
└── rxthinkcmf.laravel13.naivevue.sql # SQLite 版本
```
各数据库脚本包含完整的表结构定义和初始数据(用户、角色、菜单、字典、城市行政区划等),已针对各数据库的 SQL 语法做了适配,可直接导入使用。
@@ -1,7 +1,7 @@
# 4.4 前端分层架构
:::tip 概述
前端采用 Vue 3 + TypeScript 组件化架构,分为 View(视图)→ API(接口)→ Store(状态)→ HTTP(请求)四层。辅以 Router(路由)、Directives(指令)、Hooks(组合式函数)、Utils(工具)等支撑模块。前端为本仓库 `ui/` 目录内的 EleVue 管理后台。
前端采用 Vue 3 + TypeScript 组件化架构,分为 View(视图)→ API(接口)→ Store(状态)→ HTTP(请求)四层。辅以 Router(路由)、Directives(指令)、Hooks(组合式函数)、Utils(工具)等支撑模块。前端为本仓库 `ui/` 目录内的 NaiveVue 管理后台。
:::
## 架构全景
@@ -80,52 +80,69 @@ src/views/
```vue
<template>
<!-- 搜索区 -->
<el-form :model="searchForm" inline>
<el-form-item label="名称">
<el-input v-model="searchForm.name" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="fetchData">搜索</el-button>
</el-form-item>
</el-form>
<n-card :bordered="false" class="pt-3 mb-3 proCard">
<!-- 搜索区(BasicForm 驱动,字段来自 querySchemas) -->
<BasicForm @register="registerForm" @submit="handleSubmit" @reset="handleReset" />
</n-card>
<!-- 操作栏 -->
<el-button v-perm="'sys:example:add'" type="primary" @click="handleAdd">新增</el-button>
<!-- 数据表格 -->
<el-table :data="tableData">
<el-table-column prop="id" label="ID" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="statusText" label="状态" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button v-perm="'sys:example:update'" @click="handleEdit(row)">编辑</el-button>
<el-button v-perm="'sys:example:delete'" type="danger" @click="handleDelete(row.id)">删除</el-button>
<n-card :bordered="false" class="proCard">
<!-- 操作栏 + 数据表格(BasicTable 驱动,分页内置) -->
<BasicTable
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="basicTableRef"
:actionColumn="actionColumn"
>
<template #tableTitle>
<n-space>
<n-button v-perm="'sys:example:add'" type="primary" @click="handleAdd">
新增
</n-button>
</n-space>
</template>
</el-table-column>
</el-table>
<!-- 分页(后端固定返回 records / total / current / size / pages) -->
<el-pagination v-model:current-page="pageNo" v-model:page-size="pageSize"
:total="total" @change="fetchData" />
</BasicTable>
</n-card>
</template>
<script setup lang="ts">
import { h } from 'vue';
import { BasicTable, TableAction } from '@/components/Table';
import { BasicForm, useForm } from '@/components/Form';
import { getExamplePage, exampleDelete } from '@/api/tool/example';
const tableData = ref([]);
const pageNo = ref(1);
const pageSize = ref(20);
const total = ref(0);
// 注册搜索表单
const [registerForm, { handleSubmit, handleReset }] = useForm({
schemas: [{ field: 'name', label: '名称', component: 'NInput' }],
});
const fetchData = async () => {
const res = await getExamplePage({ pageNo: pageNo.value, pageSize: pageSize.value });
tableData.value = res.records;
total.value = res.total;
// 表格列定义(columns 数组:{ title, key, ... })
const columns = [
{ title: 'ID', key: 'id', width: 80 },
{ title: '名称', key: 'name' },
{ title: '状态', key: 'statusText' },
];
// 操作列(固定右侧,auth 声明权限码,配合 v-perm 控制显隐)
const actionColumn = {
width: 200,
title: '操作',
key: 'action',
render(record) {
return h(TableAction, {
actions: [
{ label: '编辑', type: 'info', onClick: () => handleEdit(record), auth: ['sys:example:update'] },
{ label: '删除', type: 'error', onClick: () => handleDelete(record), auth: ['sys:example:delete'] },
],
});
},
};
onMounted(() => fetchData());
// 分页数据请求(BasicTable 内置分页,后端固定返回 records / total / current / size / pages)
const loadDataTable = async (params) => {
const res = await getExamplePage({ pageNo: params.pageNo, pageSize: params.pageSize });
return { records: res.records, total: res.total };
};
</script>
```
@@ -318,10 +335,10 @@ src/utils/http/axios/
```vue
<!-- v-perm:单权限 -->
<el-button v-perm="'sys:user:add'" type="primary">新增</el-button>
<n-button v-perm="'sys:user:add'" type="primary">新增</n-button>
<!-- v-perms:多权限(满足任一即可) -->
<el-button v-perms="['sys:user:add', 'sys:user:update']">操作</el-button>
<n-button v-perms="['sys:user:add', 'sys:user:update']">操作</n-button>
```
无权限时元素直接从 DOM 移除,而非仅隐藏。
@@ -341,8 +358,11 @@ src/utils/http/axios/
| Hook | 文件 | 说明 |
|------|------|------|
| `usePermission` | `hooks/web/usePermission.ts` | 权限判断(hasPermission、hasSomePermission) |
| `useTable` | `hooks/web/useTable.ts` | 表格通用逻辑(分页、搜索、刷新) |
| `useForm` | `hooks/web/useForm.ts` | 表单通用逻辑(提交、重置、校验) |
| `useMessage` / `useDialog` | `hooks/web/useMessage.ts`、`useDialog.ts` | 消息提示 / 确认弹窗(离散 API,可在非组件上下文调用) |
| `useLoadingBar` | `hooks/web/useLoadingBar.ts` | 顶部加载条 |
| `useLockFn` | `utils/useLockFn.ts` | 请求级防重复提交 |
| `useForm` | `components/Form/src/hooks/useForm.ts` | 表单通用逻辑(注册、提交、重置、校验) |
| 表格逻辑 | `components/Table/src/hooks/*` | BasicTable 内部钩子(分页、数据源、搜索) |
### Directives(自定义指令)
@@ -419,7 +439,7 @@ v-perm 指令读取 permissions 列表 → 控制元素显隐
| `routes/api.php` | `src/api/**/*.ts` | 路由 ↔ API 函数 |
| 字典数据(`dict` 表) | `src/enums/` + 字典 Store | 枚举常量 |
| `#[Permission]` 注解 | `v-perm` 指令 | 权限码对应 |
| 分页 `records/total/current/size/pages` | el-pagination 绑定 | 固定分页结构 |
| 分页 `records/total/current/size/pages` | BasicTable 分页绑定 | 固定分页结构 |
## 层间通信规范
@@ -8,7 +8,7 @@
```text
┌─────────────────────────────────────────────────────────────────┐
│ 浏览器(Vue3 + ElementPlus) │
│ 浏览器(Vue3 + NaiveUI) │
│ Axios HTTP 请求 / Vite 开发代理 │
└──────────────────────────────┬──────────────────────────────────┘
│
@@ -71,7 +71,7 @@
### 1. 前后端分离
前端 Vue3 应用通过 HTTP API 调用后端 Laravel 服务,两者独立开发、独立部署。前端开发阶段通过 Vite 的 `proxy` 配置将 `/api` 请求代理到后端 `http://localhost:8000`,生产环境由 Nginx 统一反向代理。
前端 Vue3 应用通过 HTTP API 调用后端 Laravel 服务,两者独立开发、独立部署。前端开发阶段通过 Vite 的 `proxy` 配置将 `/api` 请求代理到后端 `http://admin.laravel13.naivevue`,生产环境由 Nginx 统一反向代理。
### 2. 分层架构
@@ -243,7 +243,7 @@ static::updating(function ($model) {
```text
┌──────────────────────────────────────────────────────────────┐
│ 前端(Vue3 + ElementPlus) │
│ 前端(Vue3 + NaiveUI) │
│ Pinia · Vue Router · Axios · TinyMce · ECharts │
└──────────────────────────┬───────────────────────────────────┘
│ HTTP / JSON
@@ -43,7 +43,7 @@ location / {
server: {
proxy: {
'/api': {
target: 'http://localhost:8000',
target: 'http://admin.laravel13.naivevue',
changeOrigin: true,
},
},