mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-10-04 09:10:59 +00:00
refactor(代码生成器): 优化模板文件格式和类型检查逻辑
style: 统一代码格式并移除多余空行 fix(前端): 修复富文本编辑器在详情页的显示问题 feat(前端): 为代码编辑器添加主题切换功能 docs: 更新README中的命令说明
This commit is contained in:
+4
-5
@@ -136,15 +136,14 @@ cd backend
|
|||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
# Start the backend service
|
# Start the backend service
|
||||||
python3 main.py run
|
python main.py run
|
||||||
# Or specify environment
|
# Or specify environment
|
||||||
python3 main.py run --env=dev
|
python main.py run --env=dev
|
||||||
|
|
||||||
# Database migration (first run)
|
|
||||||
# Generate migration files
|
# Generate migration files
|
||||||
python3 main.py revision "Initial migration" --env=dev
|
python main.py revision --env=dev
|
||||||
# Apply migrations
|
# Apply migrations
|
||||||
python3 main.py upgrade --env=dev
|
python main.py upgrade --env=dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Frontend Setup
|
### Frontend Setup
|
||||||
|
|||||||
@@ -136,15 +136,14 @@ cd backend
|
|||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
# 启动后端服务
|
# 启动后端服务
|
||||||
python3 main.py run
|
python main.py run
|
||||||
# 或指定环境
|
# 或指定环境
|
||||||
python3 main.py run --env=dev
|
python main.py run --env=dev
|
||||||
|
|
||||||
# 数据库迁移(首次运行)
|
|
||||||
# 生成迁移文件
|
# 生成迁移文件
|
||||||
python3 main.py revision "初始化迁移" --env=dev
|
python main.py revision --env=dev
|
||||||
# 应用迁移
|
# 应用迁移
|
||||||
python3 main.py upgrade --env=dev
|
python main.py upgrade --env=dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### 前端启动
|
### 前端启动
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ module_*/
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 生成迁移文件(仅首次或模型变更时)
|
# 生成迁移文件(仅首次或模型变更时)
|
||||||
python main.py revision "数据迁移" --env=dev(不加默认为dev)
|
python main.py revision --env=dev(不加默认为dev)
|
||||||
|
|
||||||
# 应用数据库迁移
|
# 应用数据库迁移
|
||||||
python main.py upgrade --env=dev(不加默认为dev)
|
python main.py upgrade --env=dev(不加默认为dev)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class {{ class_name }}Model(CreatorMixin):
|
|||||||
"""
|
"""
|
||||||
{{ function_name }}表
|
{{ function_name }}表
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__tablename__ = '{{ table_name }}'
|
__tablename__ = '{{ table_name }}'
|
||||||
__table_args__ = {'comment': '{{ function_name }}'}
|
__table_args__ = {'comment': '{{ function_name }}'}
|
||||||
__loader_options__ = ["creator"]
|
__loader_options__ = ["creator"]
|
||||||
|
|||||||
@@ -15,13 +15,11 @@ class {{ class_name }}QueryParam:
|
|||||||
{{ column.column_name }}: Optional[{{ column.python_type }}] = Query(None, description="{{ column.column_comment }}"),
|
{{ column.column_name }}: Optional[{{ column.python_type }}] = Query(None, description="{{ column.column_comment }}"),
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.column_name == 'EQ' %}
|
{% if column.query_type == 'EQ' %}
|
||||||
{{ column.column_name }}: Optional[{{ column.python_type }}] = Query(None, description="{{ column.column_comment }}"),
|
{{ column.column_name }}: Optional[{{ column.python_type }}] = Query(None, description="{{ column.column_comment }}"),
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
creator: Optional[int] = Query(None, description="创建人"),
|
creator: Optional[int] = Query(None, description="创建人"),
|
||||||
start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2025-01-01 00:00:00"),
|
start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2025-01-01 00:00:00"),
|
||||||
end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2025-12-31 23:59:59"),
|
end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2025-12-31 23:59:59"),
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class {{ class_name }}CreateSchema(BaseModel):
|
|||||||
"""
|
"""
|
||||||
{{ function_name }}新增模型
|
{{ function_name }}新增模型
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.column_name not in ['id', 'creator_id', 'created_at', 'updated_at'] %}
|
{% if column.column_name not in ['id', 'creator_id', 'created_at', 'updated_at'] %}
|
||||||
{{ column.column_name }}: Optional[{{ column.python_type }}] = Field(default=None, description='{{ column.column_comment }}')
|
{{ column.column_name }}: Optional[{{ column.python_type }}] = Field(default=None, description='{{ column.column_comment }}')
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
{% set b_true = 1 if db_type == 'mysql' else true %}
|
{% set b_true = 1 if db_type == 'mysql' else true %}
|
||||||
{% set b_false = 0 if db_type == 'mysql' else false %}
|
{% set b_false = 0 if db_type == 'mysql' else false %}
|
||||||
{% set order_col = '`order`' if db_type == 'mysql' else '"order"' %}
|
{% set order_col = '`order`' if db_type == 'mysql' else '"order"' %}
|
||||||
|
|
||||||
{# 公共字段列表(按实际库字段) #}
|
{# 公共字段列表(按实际库字段) #}
|
||||||
{# name, type, order, status, permission, icon, route_name, route_path, component_path, redirect, hidden, keep_alive, always_show, title, params, affix, parent_id, description, created_at, updated_at #}
|
{# name, type, order, status, permission, icon, route_name, route_path, component_path, redirect, hidden, keep_alive, always_show, title, params, affix, parent_id, description, created_at, updated_at #}
|
||||||
|
|
||||||
{% if db_type == 'mysql' %}
|
{% if db_type == 'mysql' %}
|
||||||
-- 父菜单(类型=2:菜单)
|
-- 父菜单(类型=2:菜单)
|
||||||
INSERT INTO `system_menu` (name, type, {{ order_col }}, status, permission, icon, route_name, route_path, component_path, redirect, hidden, keep_alive, always_show, title, params, affix, parent_id, description, created_at, updated_at)
|
INSERT INTO `system_menu` (name, type, {{ order_col }}, status, permission, icon, route_name, route_path, component_path, redirect, hidden, keep_alive, always_show, title, params, affix, parent_id, description, created_at, updated_at)
|
||||||
|
|||||||
@@ -92,9 +92,10 @@ export default {{ class_name }}API;
|
|||||||
// TS 类型声明
|
// TS 类型声明
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
|
// 列表查询参数
|
||||||
export interface {{ class_name }}PageQuery extends PageQuery {
|
export interface {{ class_name }}PageQuery extends PageQuery {
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_query == "1" and column.query_type != "BETWEEN" %}
|
{% if column.is_query and column.column != "BETWEEN" %}
|
||||||
{{ column.python_field }}?: {{
|
{{ column.python_field }}?: {{
|
||||||
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
||||||
else 'number' if column.is_pk == '1'
|
else 'number' if column.is_pk == '1'
|
||||||
@@ -102,29 +103,30 @@ export interface {{ class_name }}PageQuery extends PageQuery {
|
|||||||
}};
|
}};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
// 时间范围查询(按示例统一字段名,如需按字段拆分可在页面层处理)
|
|
||||||
start_time?: string;
|
start_time?: string;
|
||||||
end_time?: string;
|
end_time?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 列表查询结果
|
||||||
export interface {{ class_name }}Table {
|
export interface {{ class_name }}Table {
|
||||||
|
index?: number;
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{{ column.python_field }}?: {{
|
{{ column.python_field }}?: {{
|
||||||
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
||||||
else 'number' if column.is_pk == '1'
|
else 'number' if column.is_pk == 1
|
||||||
else 'string'
|
else 'string'
|
||||||
}};
|
}};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
creator?: creatorType;
|
creator?: creatorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增/修改/详情表单参数
|
||||||
export interface {{ class_name }}Form {
|
export interface {{ class_name }}Form {
|
||||||
id?: number;
|
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_insert == "1" or column.is_edit == "1" %}
|
{% if (column.is_insert == 1 or column.is_edit == 1) and column.python_field not in ['creatorId', 'createdAt', 'updatedAt'] %}
|
||||||
{{ column.python_field }}?: {{
|
{{ column.python_field }}?: {{
|
||||||
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
'boolean' if ('status' in (column.python_field|lower)) or (column.html_type == 'radio')
|
||||||
else 'number' if column.is_pk == '1'
|
else 'number' if column.is_pk == 1
|
||||||
else 'string'
|
else 'string'
|
||||||
}};
|
}};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -4,34 +4,33 @@
|
|||||||
<div v-show="visible" class="search-container">
|
<div v-show="visible" class="search-container">
|
||||||
<el-form ref="queryFormRef" :model="queryFormData" label-suffix=":" :inline="true" @submit.prevent="handleQuery">
|
<el-form ref="queryFormRef" :model="queryFormData" label-suffix=":" :inline="true" @submit.prevent="handleQuery">
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_query == "1" %}
|
{% if column.is_query == 1 %}
|
||||||
{% set dict_type = column.dict_type %}
|
{% set dict_type = column.dict_type %}
|
||||||
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
||||||
{% set parentheseIndex = column_comment.find("(") %}
|
{% set parentheseIndex = column_comment.find("(") %}
|
||||||
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
||||||
|
{% if column.html_type == "input" %}
|
||||||
{% if column.html_type == "input" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<el-input v-model="queryFormData.{{ column.python_field }}" placeholder="请输入{{ comment }}" clearable />
|
||||||
<el-input v-model="queryFormData.{{ column.python_field }}" placeholder="请输入{{ comment }}" clearable />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type != "" %}
|
||||||
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type != "" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<el-select v-model="queryFormData.{{ column.python_field }}" placeholder="请选择{{ comment }}" style="width: 180px" clearable>
|
||||||
<el-select v-model="queryFormData.{{ column.python_field }}" placeholder="请选择{{ comment }}" style="width: 180px" clearable>
|
<el-option v-for="dict in dictStore.getDictArray('{{ dict_type }}')" :key="dict.dict_value" :label="dict.dict_label" :value="dict.dict_value" />
|
||||||
<el-option v-for="dict in dictStore.getDictArray('{{ dict_type }}')" :key="dict.dict_value" :label="dict.dict_label" :value="dict.dict_value" />
|
</el-select>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type %}
|
||||||
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<el-select v-model="queryFormData.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
|
||||||
<el-select v-model="queryFormData.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
|
<el-option label="请选择字典生成" value="" />
|
||||||
<el-option label="请选择字典生成" value="" />
|
</el-select>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
|
||||||
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<el-date-picker v-model="queryFormData.{{ column.python_field }}" type="date" value-format="YYYY-MM-DD" clearable placeholder="请选择{{ comment }}" />
|
||||||
<el-date-picker v-model="queryFormData.{{ column.python_field }}" type="date" value-format="YYYY-MM-DD" clearable placeholder="请选择{{ comment }}" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<!-- 可选:创建人选择与统一日期范围(展开后显示) -->
|
<!-- 可选:创建人选择与统一日期范围(展开后显示) -->
|
||||||
<el-form-item v-if="isExpand" prop="creator" label="创建人">
|
<el-form-item v-if="isExpand" prop="creator" label="创建人">
|
||||||
@@ -156,23 +155,23 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% set python_field = column.python_field %}
|
{% set python_field = column.python_field %}
|
||||||
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
||||||
{% set parentheseIndex = column_comment.find("(") %}
|
{% set parentheseIndex = column_comment.find("(") %}
|
||||||
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
||||||
{% if column.is_list == "1" %}
|
{% if column.is_list == 1 %}
|
||||||
<el-table-column v-if="tableColumns.find((col) => col.prop === '{{ python_field }}')?.show" label="{{ comment }}" prop="{{ python_field }}" min-width="140">
|
<el-table-column v-if="tableColumns.find((col) => col.prop === '{{ python_field }}')?.show" label="{{ comment }}" prop="{{ python_field }}" min-width="140">
|
||||||
{% if python_field == "status" %}
|
{% if python_field == "status" %}
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag :type="scope.row.status ? 'success' : 'info'">{{ '{{' }} scope.row.status ? '启用' : '停用' {{ '}}' }}</el-tag>
|
<el-tag :type="scope.row.status ? 'success' : 'info'">{{ '{{' }} scope.row.status ? '启用' : '停用' {{ '}}' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
{% elif python_field == "creator" %}
|
{% elif python_field == "creator" %}
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag>{{ '{{' }} scope.row.creator?.name {{ '}}' }}</el-tag>
|
<el-tag>{{ '{{' }} scope.row.creator?.name {{ '}}' }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<el-table-column v-if="tableColumns.find(col => col.prop === 'operation')?.show" fixed="right" label="操作" align="center" min-width="180">
|
<el-table-column v-if="tableColumns.find(col => col.prop === 'operation')?.show" fixed="right" label="操作" align="center" min-width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -209,58 +208,57 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-suffix=":" label-width="auto" label-position="right">
|
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-suffix=":" label-width="auto" label-position="right">
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_insert == "1" or column.is_edit == "1" %}
|
{% if column.is_insert == 1 or column.is_edit == 1 %}
|
||||||
{% set dict_type = column.dict_type %}
|
{% set dict_type = column.dict_type %}
|
||||||
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
{% set column_comment = column.column_comment if column.column_comment else '' %}
|
||||||
{% set parentheseIndex = column_comment.find("(") %}
|
{% set parentheseIndex = column_comment.find("(") %}
|
||||||
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
||||||
{% set required = 'true' if column.is_nullable == '1' else 'false' %}
|
{% set required = 'true' if column.is_nullable == '1' else 'false' %}
|
||||||
|
{% if column.python_field == "status" %}
|
||||||
{% if column.python_field == "status" %}
|
<el-form-item label="状态" prop="status" :required="true">
|
||||||
<el-form-item label="状态" prop="status" :required="true">
|
<el-radio-group v-model="formData.status">
|
||||||
<el-radio-group v-model="formData.status">
|
<el-radio :value="true">启用</el-radio>
|
||||||
<el-radio :value="true">启用</el-radio>
|
<el-radio :value="false">停用</el-radio>
|
||||||
<el-radio :value="false">停用</el-radio>
|
</el-radio-group>
|
||||||
</el-radio-group>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "input" %}
|
||||||
{% elif column.html_type == "input" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-input v-model="formData.{{ column.python_field }}" placeholder="请输入{{ comment }}" />
|
||||||
<el-input v-model="formData.{{ column.python_field }}" placeholder="请输入{{ comment }}" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "textarea" %}
|
||||||
{% elif column.html_type == "textarea" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-input v-model="formData.{{ column.python_field }}" type="textarea" placeholder="请输入{{ comment }}" rows="4" />
|
||||||
<el-input v-model="formData.{{ column.python_field }}" type="textarea" placeholder="请输入{{ comment }}" rows="4" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type != "" %}
|
||||||
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type != "" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-select v-model="formData.{{ column.python_field }}" placeholder="请选择{{ comment }}">
|
||||||
<el-select v-model="formData.{{ column.python_field }}" placeholder="请选择{{ comment }}">
|
<el-option v-for="dict in dictStore.getDictArray('{{ dict_type }}')" :key="dict.dict_value" :label="dict.dict_label" :value="dict.dict_value" />
|
||||||
<el-option v-for="dict in dictStore.getDictArray('{{ dict_type }}')" :key="dict.dict_value" :label="dict.dict_label" :value="dict.dict_value" />
|
</el-select>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type %}
|
||||||
{% elif (column.html_type == "select" or column.html_type == "radio") and dict_type %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-select v-model="formData.{{ column.python_field }}" placeholder="请选择{{ comment }}">
|
||||||
<el-select v-model="formData.{{ column.python_field }}" placeholder="请选择{{ comment }}">
|
<el-option label="请选择字典生成" value="" />
|
||||||
<el-option label="请选择字典生成" value="" />
|
</el-select>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "date" %}
|
||||||
{% elif column.html_type == "date" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-date-picker v-model="formData.{{ column.python_field }}" type="date" value-format="YYYY-MM-DD" placeholder="请选择{{ comment }}" />
|
||||||
<el-date-picker v-model="formData.{{ column.python_field }}" type="date" value-format="YYYY-MM-DD" placeholder="请选择{{ comment }}" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "datetime" %}
|
||||||
{% elif column.html_type == "datetime" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}" :required="{{ required }}">
|
<el-date-picker v-model="formData.{{ column.python_field }}" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择{{ comment }}" />
|
||||||
<el-date-picker v-model="formData.{{ column.python_field }}" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择{{ comment }}" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "checkbox" %}
|
||||||
{% elif column.html_type == "checkbox" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<el-checkbox v-model="formData.{{ column.python_field }}">{{ comment }}</el-checkbox>
|
||||||
<el-checkbox v-model="formData.{{ column.python_field }}">{{ comment }}</el-checkbox>
|
</el-form-item>
|
||||||
</el-form-item>
|
{% elif column.html_type == "imageUpload" %}
|
||||||
{% elif column.html_type == "imageUpload" %}
|
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
||||||
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
|
<SingleImageUpload v-model="formData.{{ column.python_field }}" />
|
||||||
<SingleImageUpload v-model="formData.{{ column.python_field }}" />
|
</el-form-item>
|
||||||
</el-form-item>
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
@@ -339,7 +337,7 @@ const tableColumns = ref([
|
|||||||
{ prop: 'selection', label: '选择框', show: true },
|
{ prop: 'selection', label: '选择框', show: true },
|
||||||
{ prop: 'index', label: '序号', show: true },
|
{ prop: 'index', label: '序号', show: true },
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_list == "1" %}
|
{% if column.is_list == 1 %}
|
||||||
{ prop: '{{ column.python_field }}', label: '{{ column.column_comment or column.python_field }}', show: true },
|
{ prop: '{{ column.python_field }}', label: '{{ column.column_comment or column.python_field }}', show: true },
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -349,7 +347,7 @@ const tableColumns = ref([
|
|||||||
// 导出列(不含选择/序号/操作)
|
// 导出列(不含选择/序号/操作)
|
||||||
const exportColumns = [
|
const exportColumns = [
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_list == "1" %}
|
{% if column.is_list == 1 %}
|
||||||
{ prop: '{{ column.python_field }}', label: '{{ column.column_comment or column.python_field }}' },
|
{ prop: '{{ column.python_field }}', label: '{{ column.column_comment or column.python_field }}' },
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -391,7 +389,7 @@ const dialogVisible = reactive({
|
|||||||
const formData = reactive<{{ class_name }}Form>({
|
const formData = reactive<{{ class_name }}Form>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_insert == "1" or column.is_edit == "1" %}
|
{% if column.is_insert == 1 or column.is_edit == 1 %}
|
||||||
{{ column.python_field }}: undefined,
|
{{ column.python_field }}: undefined,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -401,7 +399,7 @@ const formData = reactive<{{ class_name }}Form>({
|
|||||||
const initialFormData: {{ class_name }}Form = {
|
const initialFormData: {{ class_name }}Form = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_insert == "1" or column.is_edit == "1" %}
|
{% if column.is_insert == 1 or column.is_edit == 1 %}
|
||||||
{{ column.python_field }}: {{ 'true' if column.python_field == 'status' else ('' if column.html_type == 'textarea' else 'undefined') }},
|
{{ column.python_field }}: {{ 'true' if column.python_field == 'status' else ('' if column.html_type == 'textarea' else 'undefined') }},
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -420,8 +418,8 @@ async function resetForm() {
|
|||||||
// 表单验证规则(必填项按 is_nullable 生成)
|
// 表单验证规则(必填项按 is_nullable 生成)
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_insert == "1" or column.is_edit == "1" %}
|
{% if column.is_insert == 1 or column.is_edit == 1 %}
|
||||||
{% set required = 'true' if column.is_nullable == '1' else 'false' %}
|
{% set required = 'true' if column.is_nullable == 1 else 'false' %}
|
||||||
{{ column.python_field }}: [
|
{{ column.python_field }}: [
|
||||||
{ required: {{ required }}, message: '请输入{{ column.column_comment or column.python_field }}', trigger: 'blur' },
|
{ required: {{ required }}, message: '请输入{{ column.column_comment or column.python_field }}', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
@@ -451,7 +449,7 @@ const queryFormData = reactive<{{ class_name }}PageQuery>({
|
|||||||
page_no: 1,
|
page_no: 1,
|
||||||
page_size: 10,
|
page_size: 10,
|
||||||
{% for column in columns %}
|
{% for column in columns %}
|
||||||
{% if column.is_query == "1" and column.query_type != "BETWEEN" %}
|
{% if column.is_query == 1 and column.query_type != "BETWEEN" %}
|
||||||
{{ column.python_field }}: undefined,
|
{{ column.python_field }}: undefined,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -1,30 +1,18 @@
|
|||||||
<!--
|
|
||||||
* 基于 wangEditor-next 的富文本编辑器组件二次封装
|
|
||||||
* 版权所有 © 2021-present 有来开源组织
|
|
||||||
*
|
|
||||||
* 开源协议:https://opensource.org/licenses/MIT
|
|
||||||
* 项目地址:https://gitee.com/youlaiorg/vue3-element-admin
|
|
||||||
*
|
|
||||||
* 在使用时,请保留此注释,感谢您对开源的支持!
|
|
||||||
*
|
|
||||||
* 修改:此版本返回纯文本格式,使用 editor.getText() 获取内容
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="z-index: 999; border: 1px solid var(--el-border-color)">
|
<div style="z-index: 999; border: 1px solid var(--el-border-color)">
|
||||||
<!-- 工具栏 -->
|
<!-- 工具栏 -->
|
||||||
<Toolbar
|
<Toolbar
|
||||||
:editor="editorRef"
|
:editor="editorRef"
|
||||||
mode="simple"
|
mode="mode"
|
||||||
:default-config="toolbarConfig"
|
:default-config="toolbarConfig"
|
||||||
style="border-bottom: 1px solid var(--el-border-color)"
|
style="border-bottom: 1px solid var(--el-border-color)"
|
||||||
/>
|
/>
|
||||||
<!-- 编辑器 -->
|
<!-- 编辑器 -->
|
||||||
<Editor
|
<Editor
|
||||||
v-model="modelValue"
|
v-model="modelValue"
|
||||||
:style="{ height: height, overflowY: 'hidden' }"
|
:style="{ minHeight: height, overflowY: 'hidden' }"
|
||||||
:default-config="editorConfig"
|
:default-config="editorConfig"
|
||||||
mode="simple"
|
mode="mode"
|
||||||
@on-created="handleCreated"
|
@on-created="handleCreated"
|
||||||
@on-change="handleChange"
|
@on-change="handleChange"
|
||||||
/>
|
/>
|
||||||
@@ -39,7 +27,7 @@ import { IToolbarConfig, IEditorConfig } from "@wangeditor-next/editor";
|
|||||||
// 上传图片回调函数类型
|
// 上传图片回调函数类型
|
||||||
type InsertFnType = (_url: string, _alt: string, _href: string) => void;
|
type InsertFnType = (_url: string, _alt: string, _href: string) => void;
|
||||||
|
|
||||||
// 模拟文件上传API,根据实际项目结构调整
|
// 模拟文件上传API,根据实际项目进行调整
|
||||||
interface UploadResult {
|
interface UploadResult {
|
||||||
url: string;
|
url: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -56,10 +44,22 @@ const FileAPI = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "300px",
|
default: "200px",
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
autoFocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
scroll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// 双向绑定
|
// 双向绑定
|
||||||
@@ -74,9 +74,12 @@ const editorRef = shallowRef();
|
|||||||
// 工具栏配置
|
// 工具栏配置
|
||||||
const toolbarConfig = ref<Partial<IToolbarConfig>>({});
|
const toolbarConfig = ref<Partial<IToolbarConfig>>({});
|
||||||
|
|
||||||
// 编辑器配置
|
// 编辑器配置 - 根据 props 动态生成配置
|
||||||
const editorConfig = ref<Partial<IEditorConfig>>({
|
const editorConfig = ref<Partial<IEditorConfig>>({
|
||||||
placeholder: "请输入内容...",
|
placeholder: "请输入内容...",
|
||||||
|
readOnly: props.readonly,
|
||||||
|
autoFocus: props.autoFocus,
|
||||||
|
scroll: props.scroll,
|
||||||
MENU_CONF: {
|
MENU_CONF: {
|
||||||
uploadImage: {
|
uploadImage: {
|
||||||
customUpload(file: File, insertFn: InsertFnType) {
|
customUpload(file: File, insertFn: InsertFnType) {
|
||||||
|
|||||||
@@ -856,7 +856,8 @@ defineOptions({
|
|||||||
|
|
||||||
import "codemirror/mode/javascript/javascript.js";
|
import "codemirror/mode/javascript/javascript.js";
|
||||||
import "codemirror/mode/sql/sql.js";
|
import "codemirror/mode/sql/sql.js";
|
||||||
import { ref, reactive, computed, onActivated, onMounted } from "vue";
|
import "codemirror/theme/dracula.css"
|
||||||
|
import { ref, reactive, computed, onActivated, onMounted, watch } from "vue";
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import Codemirror from "codemirror-editor-vue3";
|
import Codemirror from "codemirror-editor-vue3";
|
||||||
@@ -883,6 +884,8 @@ import MenuAPI, { MenuTable } from "@/api/module_system/menu";
|
|||||||
import DictAPI, { DictTable } from "@/api/module_system/dict";
|
import DictAPI, { DictTable } from "@/api/module_system/dict";
|
||||||
import { formatTree } from "@/utils/common";
|
import { formatTree } from "@/utils/common";
|
||||||
import { MenuTypeEnum } from "@/enums";
|
import { MenuTypeEnum } from "@/enums";
|
||||||
|
import { useSettingsStore } from "@/store";
|
||||||
|
import { ThemeMode } from "@/enums/settings/theme.enum";
|
||||||
|
|
||||||
// 表格列配置接口
|
// 表格列配置接口
|
||||||
interface TableColumn {
|
interface TableColumn {
|
||||||
@@ -995,6 +998,27 @@ const tableColumns = ref<TableColumn[]>([
|
|||||||
{ prop: "operation", label: "操作", show: true },
|
{ prop: "operation", label: "操作", show: true },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
|
// 主题计算属性
|
||||||
|
const codeTheme = computed(() =>
|
||||||
|
settingsStore.theme === ThemeMode.DARK ? "dracula" : "default"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听主题变化并更新CodeMirror实例
|
||||||
|
watch(codeTheme, (newTheme) => {
|
||||||
|
// 更新SQL编辑器主题
|
||||||
|
if (sqlRef.value && sqlRef.value.cminstance) {
|
||||||
|
sqlRef.value.cminstance.setOption("theme", newTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新代码预览编辑器主题
|
||||||
|
if (cmRef.value && cmRef.value.cminstance) {
|
||||||
|
cmRef.value.cminstance.setOption("theme", newTheme);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// CodeMirror配置
|
// CodeMirror配置
|
||||||
const cmOptions: EditorConfiguration = {
|
const cmOptions: EditorConfiguration = {
|
||||||
mode: "text/javascript",
|
mode: "text/javascript",
|
||||||
@@ -1002,7 +1026,10 @@ const cmOptions: EditorConfiguration = {
|
|||||||
smartIndent: true,
|
smartIndent: true,
|
||||||
indentUnit: 2,
|
indentUnit: 2,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
readOnly: true,
|
readOnly: false,
|
||||||
|
theme: codeTheme.value,
|
||||||
|
lineWrapping: true,
|
||||||
|
autofocus: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const sqlOptions: EditorConfiguration = {
|
const sqlOptions: EditorConfiguration = {
|
||||||
@@ -1012,8 +1039,9 @@ const sqlOptions: EditorConfiguration = {
|
|||||||
indentUnit: 2,
|
indentUnit: 2,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
theme: "default",
|
theme: codeTheme.value,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
|
autofocus: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 工具函数
|
// 工具函数
|
||||||
|
|||||||
@@ -349,7 +349,7 @@
|
|||||||
>
|
>
|
||||||
<!-- 详情 -->
|
<!-- 详情 -->
|
||||||
<template v-if="dialogVisible.type === 'detail'">
|
<template v-if="dialogVisible.type === 'detail'">
|
||||||
<el-descriptions :column="4" border>
|
<el-descriptions :column="4" border label-width="120px">
|
||||||
<el-descriptions-item label="标题" :span="2">
|
<el-descriptions-item label="标题" :span="2">
|
||||||
{{ detailFormData.notice_title }}
|
{{ detailFormData.notice_title }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
@@ -368,12 +368,12 @@
|
|||||||
{{ detailFormData.status ? "启用" : "停用" }}
|
{{ detailFormData.status ? "启用" : "停用" }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="内容" :span="2">
|
|
||||||
{{ detailFormData.notice_content }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="描述" :span="2">
|
<el-descriptions-item label="描述" :span="2">
|
||||||
{{ detailFormData.description }}
|
{{ detailFormData.description }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="内容" :span="4">
|
||||||
|
<WangEditor v-model="detailFormData.notice_content" :readonly="true" />
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建人" :span="2">
|
<el-descriptions-item label="创建人" :span="2">
|
||||||
{{ detailFormData.creator?.name }}
|
{{ detailFormData.creator?.name }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|||||||
Reference in New Issue
Block a user