签入版本
This commit is contained in:
+2304
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
|||||||
|
allowBuilds:
|
||||||
|
'@parcel/watcher': set this to true or false
|
||||||
|
esbuild: set this to true or false
|
||||||
|
vue-demi: set this to true or false
|
||||||
@@ -53,6 +53,8 @@
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Axios 响应拦截器
|
// Axios 响应拦截器
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
axios.interceptors.response.use(response => {
|
axios.interceptors.response.use(response => {
|
||||||
const { code, msg, data } = response.data;
|
const { code, msg, data } = response.data;
|
||||||
|
|
||||||
@@ -67,12 +69,12 @@ axios.interceptors.response.use(response => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (code === 403) {
|
if (code === 403) {
|
||||||
ElMessage.error(msg || '无权限');
|
message.error(msg || '无权限');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其他错误
|
// 其他错误
|
||||||
ElMessage.error(msg || '操作失败');
|
message.error(msg || '操作失败');
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -253,6 +253,7 @@ $this->fail('缺少id参数', 1);
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// src/utils/http/axios/index.ts
|
// src/utils/http/axios/index.ts
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
axios.interceptors.response.use(
|
axios.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
@@ -272,16 +273,16 @@ axios.interceptors.response.use(
|
|||||||
|
|
||||||
// 权限不足
|
// 权限不足
|
||||||
if (code === 403) {
|
if (code === 403) {
|
||||||
ElMessage.error(msg || '无访问权限');
|
message.error(msg || '无访问权限');
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其他业务错误
|
// 其他业务错误
|
||||||
ElMessage.error(msg || '操作失败');
|
message.error(msg || '操作失败');
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg));
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
ElMessage.error('网络错误');
|
message.error('网络错误');
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -305,9 +306,9 @@ const handleImport = async (file) => {
|
|||||||
const res = await importUsers(file);
|
const res = await importUsers(file);
|
||||||
// res = { count: 8, errors: [{ row: 3, reason: "..." }] }
|
// res = { count: 8, errors: [{ row: 3, reason: "..." }] }
|
||||||
if (res.errors.length === 0) {
|
if (res.errors.length === 0) {
|
||||||
ElMessage.success(`成功导入 ${res.count} 条`);
|
message.success(`成功导入 ${res.count} 条`);
|
||||||
} else {
|
} else {
|
||||||
ElMessage.warning(`成功 ${res.count} 条,失败 ${res.errors.length} 条`);
|
message.warning(`成功 ${res.count} 条,失败 ${res.errors.length} 条`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export function exampleBatchDelete(data: any) {
|
|||||||
```vue
|
```vue
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getExamplePage, exampleDelete } from '@/api/tool/example';
|
import { getExamplePage, exampleDelete } from '@/api/tool/example';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { Modal, message } from 'ant-design-vue';
|
||||||
|
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
|
|
||||||
@@ -116,10 +116,15 @@ const fetchData = async () => {
|
|||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
const handleDelete = async (id) => {
|
const handleDelete = async (id) => {
|
||||||
await ElMessageBox.confirm('确认删除?', '提示', { type: 'warning' });
|
Modal.confirm({
|
||||||
await exampleDelete(id);
|
title: '提示',
|
||||||
ElMessage.success('删除成功');
|
content: '确认删除?',
|
||||||
fetchData();
|
onOk: async () => {
|
||||||
|
await exampleDelete(id);
|
||||||
|
message.success('删除成功');
|
||||||
|
fetchData();
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ config.headers['Authorization'] = `Bearer ${token}`;
|
|||||||
### 响应拦截器(统一错误处理)
|
### 响应拦截器(统一错误处理)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
// 响应处理逻辑
|
// 响应处理逻辑
|
||||||
const { code, data, msg } = res.data;
|
const { code, data, msg } = res.data;
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ if (code === 401) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 其他错误,显示提示
|
// 其他错误,显示提示
|
||||||
ElMessage.error(msg || '操作失败');
|
message.error(msg || '操作失败');
|
||||||
```
|
```
|
||||||
|
|
||||||
:::tip 响应处理规则
|
:::tip 响应处理规则
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 基础翻译 -->
|
<!-- 基础翻译 -->
|
||||||
<el-button>{{ $t('common.search') }}</el-button>
|
<a-button>{{ $t('common.search') }}</a-button>
|
||||||
<el-button>{{ $t('common.reset') }}</el-button>
|
<a-button>{{ $t('common.reset') }}</a-button>
|
||||||
|
|
||||||
<!-- 带参数翻译 -->
|
<!-- 带参数翻译 -->
|
||||||
<p>{{ $t('message.welcome', { name: 'Admin' }) }}</p>
|
<p>{{ $t('message.welcome', { name: 'Admin' }) }}</p>
|
||||||
@@ -134,15 +134,17 @@ const columns = computed(() => [
|
|||||||
```vue
|
```vue
|
||||||
<!-- ui/src/components/LangSwitch/index.vue -->
|
<!-- ui/src/components/LangSwitch/index.vue -->
|
||||||
<template>
|
<template>
|
||||||
<el-dropdown @command="switchLang">
|
<a-dropdown>
|
||||||
<el-button :icon="Icon" circle />
|
<a-button>
|
||||||
<template #dropdown>
|
<GlobeOutlined />
|
||||||
<el-dropdown-menu>
|
</a-button>
|
||||||
<el-dropdown-item command="zh-CN">中文</el-dropdown-item>
|
<template #overlay>
|
||||||
<el-dropdown-item command="en-US">English</el-dropdown-item>
|
<a-menu @click="({ key }) => switchLang(key)">
|
||||||
</el-dropdown-menu>
|
<a-menu-item key="zh-CN">中文</a-menu-item>
|
||||||
|
<a-menu-item key="en-US">English</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</a-dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
| `ui/src/views/{app}/{name}/index.vue` | index.vue.tpl | 列表页(含搜索、表格、新增/编辑/详情弹窗、导入导出按钮) |
|
| `ui/src/views/{app}/{name}/index.vue` | index.vue.tpl | 列表页(含搜索、表格、新增/编辑/详情弹窗、导入导出按钮) |
|
||||||
| `ui/src/views/{app}/{name}/edit.vue` | edit.vue.tpl | 编辑弹窗(新增/复用) |
|
| `ui/src/views/{app}/{name}/edit.vue` | edit.vue.tpl | 编辑弹窗(新增/复用) |
|
||||||
| `ui/src/views/{app}/{name}/detail.vue` | detail.vue.tpl | 详情弹窗 |
|
| `ui/src/views/{app}/{name}/detail.vue` | detail.vue.tpl | 详情弹窗 |
|
||||||
| `ui/src/views/{app}/{name}/columns.ts` | columns.ts.tpl | 表格列配置(含图片 ElAvatar、选项 ElTag、链接等渲染) |
|
| `ui/src/views/{app}/{name}/columns.ts` | columns.ts.tpl | 表格列配置(含图片 Avatar、选项 Tag、链接等渲染) |
|
||||||
| `ui/src/views/{app}/{name}/querySchemas.ts` | querySchemas.ts.tpl | 查询表单配置(按字段类型自动选 Input/Select/InputNumber/DatePicker) |
|
| `ui/src/views/{app}/{name}/querySchemas.ts` | querySchemas.ts.tpl | 查询表单配置(按字段类型自动选 Input/Select/InputNumber/DatePicker) |
|
||||||
|
|
||||||
### 前端文件(ui2/ 树形模板 — 4 个文件)
|
### 前端文件(ui2/ 树形模板 — 4 个文件)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public function getTableList(): array
|
|||||||
| 类型 | VARCHAR |
|
| 类型 | VARCHAR |
|
||||||
| 匹配 | 注释或字段名匹配 `/图片\|封面\|头像\|logo\|icon\|image\|avatar\|photo/i` |
|
| 匹配 | 注释或字段名匹配 `/图片\|封面\|头像\|logo\|icon\|image\|avatar\|photo/i` |
|
||||||
|
|
||||||
识别后:`is_image = true`,归入 `file_fields`,前端用 ElAvatar 渲染。
|
识别后:`is_image = true`,归入 `file_fields`,前端用 Avatar 渲染。
|
||||||
|
|
||||||
### 富文本字段
|
### 富文本字段
|
||||||
|
|
||||||
@@ -102,12 +102,12 @@ public function getTableList(): array
|
|||||||
|
|
||||||
标签颜色映射:
|
标签颜色映射:
|
||||||
|
|
||||||
| 选项值 | 标签颜色 | Element Plus type |
|
| 选项值 | 标签颜色 | Ant Design color |
|
||||||
|--------|---------|-------------------|
|
|--------|---------|-------------------|
|
||||||
| 1 | 绿色 | `success` |
|
| 1 | 绿色 | `success` |
|
||||||
| 2 | 红色 | `danger` |
|
| 2 | 红色 | `error` |
|
||||||
| 3 | 橙色 | `warning` |
|
| 3 | 橙色 | `warning` |
|
||||||
| 其他 | 灰色 | `info` |
|
| 其他 | 灰色 | `default` |
|
||||||
|
|
||||||
识别后:`choices` 数组非空,自动归入 `eq_fields`(精确匹配)和 `serialize_maps`(字典映射)。
|
识别后:`choices` 数组非空,自动归入 `eq_fields`(精确匹配)和 `serialize_maps`(字典映射)。
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ $field = [
|
|||||||
'default' => 0, // 默认值
|
'default' => 0, // 默认值
|
||||||
'is_image' => false, // 是否为图片字段
|
'is_image' => false, // 是否为图片字段
|
||||||
'is_rich_text' => false, // 是否为富文本字段
|
'is_rich_text' => false, // 是否为富文本字段
|
||||||
'choices' => [ // 选项列表(有值时可生成 ElTag 渲染)
|
'choices' => [ // 选项列表(有值时可生成 Tag 渲染)
|
||||||
['value' => 0, 'label' => '正常', 'type' => 'success'],
|
['value' => 0, 'label' => '正常', 'type' => 'success'],
|
||||||
['value' => 1, 'label' => '禁用', 'type' => 'danger'],
|
['value' => 1, 'label' => '禁用', 'type' => 'danger'],
|
||||||
],
|
],
|
||||||
@@ -159,28 +159,37 @@ class <?php echo $model_class_name ?>Logic extends BaseLogic
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
import { ElAvatar, ElTag } from 'element-plus';
|
import { Tag, Avatar } from 'ant-design-vue';
|
||||||
|
|
||||||
export const columns = [
|
export const columns = [
|
||||||
{ type: 'selection' },
|
{
|
||||||
{ label: 'ID', prop: 'id', fixed: 'left', width: 50 },
|
title: 'ID',
|
||||||
|
dataIndex: '<?php echo $primary_key ?>',
|
||||||
|
fixed: 'left',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
<?php foreach ($list_fields as $field): ?>
|
<?php foreach ($list_fields as $field): ?>
|
||||||
{
|
{
|
||||||
label: '<?php echo $field['label'] ?>',
|
title: '<?php echo $field['label'] ?>',
|
||||||
prop: '<?php echo $field['camel_name'] ?>',
|
dataIndex: '<?php echo $field['camel_name'] ?>',
|
||||||
|
key: '<?php echo $field['camel_name'] ?>',
|
||||||
<?php if ($field['is_image']): ?>
|
<?php if ($field['is_image']): ?>
|
||||||
render(record) {
|
customRender({ record }) {
|
||||||
return h(ElAvatar, { size: 48, src: record.row.<?php echo $field['camel_name'] ?> });
|
return h(Avatar, {
|
||||||
|
size: 48,
|
||||||
|
src: record.<?php echo $field['camel_name'] ?>,
|
||||||
|
shape: 'square',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
<?php elseif ($field['choices']): ?>
|
<?php elseif ($field['choices']): ?>
|
||||||
render(record) {
|
customRender({ record }) {
|
||||||
const map = {
|
const statusMap = {
|
||||||
<?php foreach ($field['choices'] as $choice): ?>
|
<?php foreach ($field['choices'] as $choice): ?>
|
||||||
<?php echo $choice['value'] ?>: { text: '<?php echo $choice['label'] ?>', type: '<?php echo $choice['type'] ?>' },
|
<?php echo $choice['value'] ?>: { text: '<?php echo $choice['label'] ?>', color: '<?php echo ($choice['type'] === 'danger') ? 'error' : (($choice['type'] === 'info') ? 'default' : $choice['type']) ?>' },
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
};
|
};
|
||||||
const s = map[record.row.<?php echo $field['camel_name'] ?>];
|
const status = statusMap[record.<?php echo $field['camel_name'] ?>];
|
||||||
return h(ElTag, { type: s?.type || 'info' }, { default: () => s?.text });
|
return h(Tag, { color: status?.color || 'default' }, { default: () => status?.text });
|
||||||
},
|
},
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
},
|
},
|
||||||
@@ -221,7 +230,7 @@ export const columns = [
|
|||||||
| `index.vue` | 列表页 | 导入 columns.ts、querySchemas.ts |
|
| `index.vue` | 列表页 | 导入 columns.ts、querySchemas.ts |
|
||||||
| `edit.vue` | 编辑弹窗 | 被 index.vue 动态加载 |
|
| `edit.vue` | 编辑弹窗 | 被 index.vue 动态加载 |
|
||||||
| `detail.vue` | 详情弹窗 | 被 index.vue 动态加载 |
|
| `detail.vue` | 详情弹窗 | 被 index.vue 动态加载 |
|
||||||
| `columns.ts` | 表格列配置 | 被 index.vue 导入,含 ElTag/ElAvatar 渲染 |
|
| `columns.ts` | 表格列配置 | 被 index.vue 导入,含 Tag/Avatar 渲染 |
|
||||||
| `querySchemas.ts` | 查询表单配置 | 被 index.vue 导入,含 Select/Input/DatePicker 组件 |
|
| `querySchemas.ts` | 查询表单配置 | 被 index.vue 导入,含 Select/Input/DatePicker 组件 |
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ feat(generator): 支持树形表格模板生成
|
|||||||
|
|
||||||
- 新增 ui2/ 树形模板目录
|
- 新增 ui2/ 树形模板目录
|
||||||
- 自动识别 parent_id/pid 字段
|
- 自动识别 parent_id/pid 字段
|
||||||
- 支持 el-tree-select 组件
|
- 支持 a-tree-select 组件
|
||||||
|
|
||||||
Closes #123
|
Closes #123
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user