签入版本
This commit is contained in:
@@ -113,9 +113,9 @@ php artisan db:migrate [选项]
|
||||
# --drop-target-first → 迁移前先删除目标库中的同名表(避免表已存在报错)
|
||||
php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=pgsql --dst-host=127.0.0.1 --dst-port=5432 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=postgres --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=postgres --dst-password=123456 \
|
||||
--drop-target-first
|
||||
```
|
||||
|
||||
@@ -129,9 +129,9 @@ php artisan db:migrate \
|
||||
# --dst-port=1433 → SQL Server 默认端口
|
||||
php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=sqlsrv --dst-host=127.0.0.1 --dst-port=1433 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=sa --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=sa --dst-password=123456 \
|
||||
--drop-target-first
|
||||
```
|
||||
|
||||
@@ -145,8 +145,8 @@ php artisan db:migrate \
|
||||
# --dst-database → SQLite 文件路径(文件不存在时自动创建)
|
||||
php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--dst-type=sqlite --dst-database=database/rxthinkcmf.laravel13.elevue.db
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=sqlite --dst-database=database/rxthinkcmf.laravel13.naivevue.db
|
||||
```
|
||||
|
||||
### MySQL → Oracle
|
||||
@@ -158,9 +158,9 @@ php artisan db:migrate \
|
||||
# --dst-type=oracle → 目标驱动为 Oracle(自动建用户 + 序列 + 触发器)
|
||||
php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=oracle --dst-host=127.0.0.1 --dst-port=1521 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=system --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=system --dst-password=123456 \
|
||||
--drop-target-first
|
||||
```
|
||||
|
||||
@@ -186,9 +186,9 @@ php artisan db:migrate \
|
||||
# -----------------------------------------------------------------------------
|
||||
php artisan db:migrate \
|
||||
--src-type=pgsql --src-host=127.0.0.1 --src-port=5432 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=postgres --src-password=123456 \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=postgres --src-password=123456 \
|
||||
--dst-type=mysql --dst-host=127.0.0.1 --dst-port=3306 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=root --dst-password=root \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=root --dst-password=root \
|
||||
--drop-target-first
|
||||
```
|
||||
|
||||
@@ -200,9 +200,9 @@ php artisan db:migrate \
|
||||
# -----------------------------------------------------------------------------
|
||||
php artisan db:migrate \
|
||||
--src-type=sqlsrv --src-host=127.0.0.1 --src-port=1433 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=sa --src-password=123456 \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=sa --src-password=123456 \
|
||||
--dst-type=mysql --dst-host=127.0.0.1 --dst-port=3306 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=root --dst-password=root \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=root --dst-password=root \
|
||||
--drop-target-first
|
||||
```
|
||||
|
||||
@@ -215,9 +215,9 @@ php artisan db:migrate \
|
||||
# --tables=laravel_user,laravel_role,laravel_menu → 只迁移这 3 张表
|
||||
php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=pgsql --dst-host=127.0.0.1 --dst-port=5432 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=postgres --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=postgres --dst-password=123456 \
|
||||
--tables=laravel_user,laravel_role,laravel_menu \
|
||||
--drop-target-first
|
||||
```
|
||||
@@ -229,17 +229,17 @@ php artisan db:migrate \
|
||||
```bash
|
||||
$ php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=pgsql --dst-host=127.0.0.1 --dst-port=5432 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=postgres --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=postgres --dst-password=123456 \
|
||||
--drop-target-first
|
||||
|
||||
==============================================================
|
||||
[迁移开始] 源: mysql:rxthinkcmf.laravel13.elevue → 目标: pgsql:rxthinkcmf.laravel13.elevue
|
||||
[迁移开始] 源: mysql:rxthinkcmf.laravel13.naivevue → 目标: pgsql:rxthinkcmf.laravel13.naivevue
|
||||
[迁移开始] 待迁移 25 张表
|
||||
==============================================================
|
||||
[·] [1/5] 建目标库...
|
||||
· 目标库 "rxthinkcmf.laravel13.elevue" 已就绪
|
||||
· 目标库 "rxthinkcmf.laravel13.naivevue" 已就绪
|
||||
[✓] [1/5] 建目标库 完成(耗时 0ms)
|
||||
[·] [2/5] 建表结构(25 张表)...
|
||||
[✓] [2/5] 建表结构 完成(耗时 440ms),25 张表,118 个索引,0 个外键
|
||||
@@ -271,13 +271,13 @@ $ php artisan db:migrate \
|
||||
```bash
|
||||
$ php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=oracle --dst-host=127.0.0.1 --dst-port=1521 \
|
||||
--dst-database=rxthinkcmf --dst-username=system --dst-password=123456 \
|
||||
--drop-target-first
|
||||
|
||||
==============================================================
|
||||
[迁移开始] 源: mysql:rxthinkcmf.laravel13.elevue → 目标: oracle:rxthinkcmf.laravel13.elevue
|
||||
[迁移开始] 源: mysql:rxthinkcmf.laravel13.naivevue → 目标: oracle:rxthinkcmf.laravel13.naivevue
|
||||
==============================================================
|
||||
[·] [1/5] 建目标库...
|
||||
· 目标库 "rxthinkcmf" 已就绪(CREATE USER + GRANT)
|
||||
@@ -314,9 +314,9 @@ $ php artisan db:migrate \
|
||||
```bash
|
||||
$ php artisan db:migrate \
|
||||
--src-type=mysql --src-host=127.0.0.1 --src-port=3306 \
|
||||
--src-database=rxthinkcmf.laravel13.elevue --src-username=root --src-password=root \
|
||||
--src-database=rxthinkcmf.laravel13.naivevue --src-username=root --src-password=root \
|
||||
--dst-type=pgsql --dst-host=127.0.0.1 --dst-port=5432 \
|
||||
--dst-database=rxthinkcmf.laravel13.elevue --dst-username=postgres --dst-password=123456 \
|
||||
--dst-database=rxthinkcmf.laravel13.naivevue --dst-username=postgres --dst-password=123456 \
|
||||
--tables=laravel_user,laravel_role,laravel_menu \
|
||||
--drop-target-first
|
||||
|
||||
@@ -693,7 +693,7 @@ $PHP_HOME\php.exe -m | findstr sqlite
|
||||
5. `--drop-target-first` 会删除目标表的全部数据(含索引、外键和注释),请谨慎使用
|
||||
6. 大表迁移建议调大 `--batch-size`(如 5000)以提高效率
|
||||
7. 迁移过程中如遇中断,已提交的 `--batch-size` 批次数据不会回滚,建议使用 `--drop-target-first` 重试
|
||||
8. 含点号的数据库名(如 `rxthinkcmf.laravel13.elevue`)各驱动均已适配
|
||||
8. 含点号的数据库名(如 `rxthinkcmf.laravel13.naivevue`)各驱动均已适配
|
||||
9. 索引、外键和注释在建表阶段同步迁移,使用 `--drop-target-first` 重建时会一并重建
|
||||
10. 外键约束在所有表创建后统一添加,避免引用顺序问题
|
||||
11. 命令退出码:成功返回 0,失败或行数校验未通过返回 1(可用于 CI/CD 判断)
|
||||
@@ -721,7 +721,7 @@ A: 调大 `--batch-size`,如 `--batch-size=5000`。默认 1000 行一批,增
|
||||
|
||||
A: 会。所有驱动(MySQL / PostgreSQL / SQL Server / Oracle / SQLite)在目标库不存在时都会自动创建,无需手动建库。建库时会自动从源库读取 collation 并应用(仅当源与目标驱动相同时)。
|
||||
|
||||
PostgreSQL 走维护库 `postgres` 执行 `CREATE DATABASE`,含点号的库名会自动加双引号(如 `"rxthinkcmf.laravel13.elevue"`);建库失败时抛出 `创建目标数据库失败: …` 并把原始异常保留在 previous 中。
|
||||
PostgreSQL 走维护库 `postgres` 执行 `CREATE DATABASE`,含点号的库名会自动加双引号(如 `"rxthinkcmf.laravel13.naivevue"`);建库失败时抛出 `创建目标数据库失败: …` 并把原始异常保留在 previous 中。
|
||||
|
||||
### Q: 报 `could not find driver` 怎么办?
|
||||
|
||||
@@ -763,7 +763,7 @@ A: Oracle 没有原生自增语法。迁移工具会自动为自增列创建序
|
||||
|
||||
### Q: 含点号的数据库名支持吗?
|
||||
|
||||
A: 支持。如 `rxthinkcmf.laravel13.elevue` 这类含点号的库名,各驱动均已适配。
|
||||
A: 支持。如 `rxthinkcmf.laravel13.naivevue` 这类含点号的库名,各驱动均已适配。
|
||||
|
||||
### Q: SQLite 作为目标有什么限制?
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ public function export(): JsonResponse
|
||||
"code": 0,
|
||||
"ok": true,
|
||||
"msg": "导出成功",
|
||||
"data": "http://file.laravel13.elevue/temp/20261006/用户数据_20261006050143.xlsx"
|
||||
"data": "http://file.laravel13.naivevue/temp/20261006/用户数据_20261006050143.xlsx"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -328,32 +328,28 @@ public function export(array $params = []): string
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-upload
|
||||
:action="'/api/example/import'"
|
||||
:headers="{ Authorization: `Bearer ${token}` }"
|
||||
:on-success="handleImportSuccess"
|
||||
accept=".xls,.xlsx"
|
||||
>
|
||||
<el-button type="primary">导入</el-button>
|
||||
</el-upload>
|
||||
<!-- 导入按钮 + 导入弹窗(内置 n-upload 直传与模板下载,来自项目实际的 example 模块) -->
|
||||
<n-button @click="importVisible = true">导入</n-button>
|
||||
<fileUpload
|
||||
v-if="importVisible"
|
||||
v-model:visible="importVisible"
|
||||
api="/api/example/import"
|
||||
templateCode="example_import"
|
||||
dialogTitle="导入案例演示"
|
||||
@success="refreshTable()"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const handleImportSuccess = (response) => {
|
||||
if (response.code === 0) {
|
||||
const { count, errors } = response.data;
|
||||
if (errors.length === 0) {
|
||||
ElMessage.success(`成功导入 ${count} 条数据`);
|
||||
} else {
|
||||
ElMessage.warning(`成功 ${count} 条,失败 ${errors.length} 条`);
|
||||
// 可展开 errors 查看行号与原因
|
||||
}
|
||||
refreshTable();
|
||||
}
|
||||
};
|
||||
import { ref } from 'vue';
|
||||
import fileUpload from '@/components/importFile/index.vue';
|
||||
|
||||
const importVisible = ref(false);
|
||||
</script>
|
||||
```
|
||||
|
||||
导入结果由组件内 `useMessage` 统一反馈:全部成功提示 `成功导入 N 条数据`;存在失败时提示成功/失败条数,`errors` 中含行号与原因。
|
||||
|
||||
### 导出
|
||||
|
||||
```typescript
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 7.5 前端文件组件
|
||||
|
||||
:::tip 概述
|
||||
本节介绍前端项目(独立 EleVue 仓库)中的文件处理组件,包括上传组件(BasicUpload)、富文本编辑器(Editor)与 Excel 导入导出组件的使用方法。组件封装了 [7.1 文件上传全流程](/zh/tools/upload.html) 的接口调用。
|
||||
本节介绍前端项目(独立 NaiveVue 仓库)中的文件处理组件,包括上传组件(BasicUpload)、富文本编辑器(Editor)与 Excel 导入导出组件的使用方法。组件封装了 [7.1 文件上传全流程](/zh/tools/upload.html) 的接口调用。
|
||||
:::
|
||||
|
||||
## Upload 上传组件
|
||||
@@ -9,9 +9,11 @@
|
||||
```vue
|
||||
<template>
|
||||
<BasicUpload
|
||||
v-model="formData.avatar"
|
||||
:value="formData.avatar"
|
||||
:action="uploadUrl"
|
||||
:maxCount="1"
|
||||
:maxNumber="1"
|
||||
:data="{ type: 'image' }"
|
||||
@uploadChange="handleUploadChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -19,21 +21,26 @@
|
||||
import { BasicUpload } from '@/components/Upload';
|
||||
|
||||
const uploadUrl = '/api/upload/uploadFile';
|
||||
const formData = ref({ avatar: '' });
|
||||
const formData = ref({ avatar: [] });
|
||||
|
||||
// 上传/删除后回写文件值数组(相对路径)
|
||||
const handleUploadChange = (files) => {
|
||||
formData.value.avatar = files;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
:::tip 字段值约定
|
||||
`BasicUpload` 绑定的值建议存 **`filePath`(相对路径)**——提交表单后由 Service 的 `fileFields` 归一化,读取时自动补全 `FILE_DOMAIN_URL` 域名。上传需携带 `Authorization: Bearer <token>` 请求头(组件内部或 http 封装统一处理)。
|
||||
`BasicUpload` 绑定的值(`value` 数组)建议存 **`filePath`(相对路径)**——提交表单后由 Service 的 `fileFields` 归一化,读取时自动补全 `FILE_DOMAIN_URL` 域名。上传需携带 `Authorization: Bearer <token>` 请求头(组件内部或 http 封装统一处理)。
|
||||
:::
|
||||
|
||||
### 常用属性
|
||||
|
||||
| 属性 | 说明 |
|
||||
|------|------|
|
||||
| `v-model` | 绑定的文件值(相对路径) |
|
||||
| `value`(配合 `@uploadChange` 回写) | 绑定的文件值数组(相对路径) |
|
||||
| `action` | 上传接口地址(`/api/upload/uploadFile`) |
|
||||
| `maxCount` | 最大上传数量(1 = 单文件,如头像) |
|
||||
| `maxNumber` | 最大上传数量(1 = 单文件,如头像) |
|
||||
| `:data="{ type: 'image' }"` | 上传类型(image 校验图片后缀白名单,两类均存入 `temp/` 临时目录) |
|
||||
|
||||
## Editor 富文本编辑器
|
||||
@@ -72,7 +79,7 @@ const handleImportSuccess = (data) => {
|
||||
```
|
||||
|
||||
:::tip 前端解析 vs 后端导入
|
||||
- **后端导入(推荐,走业务校验)**:`el-upload` 直传 `/api/{module}/import`,由 Service 逐行 `add()`(字典反查、唯一校验、事务),见 [7.4 数据导入导出](/zh/tools/excel.html);
|
||||
- **后端导入(推荐,走业务校验)**:`n-upload` 直传 `/api/{module}/import`,由 Service 逐行 `add()`(字典反查、唯一校验、事务),见 [7.4 数据导入导出](/zh/tools/excel.html);
|
||||
- **前端解析**:`ImportExcel` 组件用 `xlsx` 库本地解析为数组,适合导入前预览、无业务校验的场景。
|
||||
:::
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ FILE_DOMAIN_URL=https://cdn.example.com
|
||||
| 环境 | 域名示例 |
|
||||
|------|---------|
|
||||
| 本地开发 | (留空,使用相对路径) |
|
||||
| 虚拟域名开发 | `http://file.laravel13.elevue` |
|
||||
| 虚拟域名开发 | `http://file.laravel13.naivevue` |
|
||||
| 测试环境 | `https://test-cdn.example.com` |
|
||||
| 生产环境 | `https://cdn.example.com` 或对象存储域名 |
|
||||
|
||||
|
||||
@@ -247,33 +247,40 @@ function save_remote_file(string $url, string $saveDir = ''): string|false
|
||||
|
||||
## 前端集成
|
||||
|
||||
### Element Plus 上传组件
|
||||
### NaiveUI 上传组件
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-upload
|
||||
<n-upload
|
||||
:action="'/api/upload/uploadFile'"
|
||||
:data="{ type: 'image' }"
|
||||
:headers="{ Authorization: `Bearer ${token}` }"
|
||||
:on-success="handleUploadSuccess"
|
||||
:before-upload="beforeUpload"
|
||||
:headers="uploadHeaders"
|
||||
@before-upload="beforeUpload"
|
||||
@finish="handleUploadFinish"
|
||||
>
|
||||
<el-button type="primary">上传图片</el-button>
|
||||
</el-upload>
|
||||
<n-button type="primary">上传图片</n-button>
|
||||
</n-upload>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const token = localStorage.getItem('access_token');
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
|
||||
const beforeUpload = (file) => {
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
const $message = useMessage();
|
||||
const token = localStorage.getItem('access_token');
|
||||
const uploadHeaders = { Authorization: `Bearer ${token}` };
|
||||
|
||||
// n-upload 的 before-upload 参数为 { file },原生文件对象在 file.file
|
||||
const beforeUpload = ({ file }) => {
|
||||
const isLt10M = file.file.size / 1024 / 1024 < 10;
|
||||
if (!isLt10M) {
|
||||
ElMessage.error('文件大小不能超过 10MB');
|
||||
$message.error('文件大小不能超过 10MB');
|
||||
}
|
||||
return isLt10M;
|
||||
};
|
||||
|
||||
const handleUploadSuccess = (response) => {
|
||||
// 上传结束,finish 事件拿到原始 event,需自行解析响应
|
||||
const handleUploadFinish = ({ event }) => {
|
||||
const response = JSON.parse(event.target.response);
|
||||
// 提交表单时保存相对路径(filePath)最稳妥
|
||||
form.value.avatar = response.data.filePath;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user