refactor(代码生成器): 优化模板文件格式和类型检查逻辑

style: 统一代码格式并移除多余空行
fix(前端): 修复富文本编辑器在详情页的显示问题
feat(前端): 为代码编辑器添加主题切换功能
docs: 更新README中的命令说明
This commit is contained in:
zhangtao
2025-11-19 23:22:13 +08:00
parent fb48b9ea1f
commit 8712831e45
12 changed files with 177 additions and 154 deletions
+4 -5
View File
@@ -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
+4 -5
View File
@@ -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
View File
@@ -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 %}
+22 -19
View File
@@ -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>