21 Commits

Author SHA1 Message Date
insistence
e34a493b3e docs: 更新README文档 2025-03-19 15:55:10 +08:00
insistence
a9df9ea56a chore: 升级版本至1.6.2 2025-03-19 15:54:12 +08:00
insistence
d89c0df425 perf: 优化代码生成vue模板 #23 2025-03-19 15:46:28 +08:00
insistence
d0730e7993 fix: 修复用户导出缺失部门名称的问题 2025-03-18 16:55:16 +08:00
insistence
5fe376f978 perf: pagination更换成flex布局 2025-03-18 08:28:46 +08:00
insistence
dd5b1c55c9 feat: 文件上传组件新增类型 2025-03-18 08:12:13 +08:00
insistence
7645c6d9fd feat: 文件上传组件新增disabled属性 2025-03-18 08:11:18 +08:00
insistence
61073970fa fix: 修复代码生成模板时间查询问题 #28 2025-03-17 16:32:46 +08:00
insistence
9ae2ac02eb perf: 优化代码生成新增和编辑字段显示和渲染 2025-03-17 09:51:05 +08:00
insistence
6622c329fc fix: 修复修改字典类型时字典数据更新时间异常的问题 2025-03-17 08:27:39 +08:00
insistence
b66d545985 fix: 修复修改字典类型时获取dict_code异常的问题 2025-03-17 08:25:39 +08:00
insistence
1789cb5a9b fix: 修复定时任务状态暂停时执行单次任务会触发cron表达式的问题 #31 2025-03-15 21:59:28 +08:00
insistence
ee376c477d fix: 修复日志管理时间查询报错 #27 2025-03-09 18:43:57 +08:00
jiangbaihe
2b6f0905a9 chore: 调整.gitignore策略 2025-03-04 14:58:04 +08:00
insistence
c953754bed chore: pg依赖文件新增sqlglot依赖 2025-03-03 17:13:37 +08:00
insistence
b708d86eff docs: 更新README文档 2025-03-03 16:44:31 +08:00
insistence
28aab8c7d4 chore: 升级版本至1.6.1 2025-03-03 16:43:47 +08:00
insistence
9412e3f344 fix: 修复代码生成主子表vo模板可能缺失NotBlank的问题 2025-02-28 10:46:45 +08:00
insistence
b4d5619b1b fix: 引入泛型修复as_query和as_form装饰模型文档丢失的问题 2025-02-28 10:36:29 +08:00
insistence
8ce598ad54 fix: 修复代码生成字段唯一性校验dao层模板判断异常的问题 2025-02-26 09:00:35 +08:00
insistence
ca641055e0 fix: 引入sqlglot修复sql语句解析异常的问题 2025-02-21 15:40:47 +08:00
29 changed files with 322 additions and 150 deletions

7
.gitignore vendored
View File

@@ -136,3 +136,10 @@ dmypy.json
# Cython debug symbols
cython_debug/
# PyCharm
.idea/
# VSCode
.vscode/

View File

@@ -1,12 +1,12 @@
<p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi-Vue3-FastAPI v1.6.0</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi-Vue3-FastAPI v1.6.2</h1>
<h4 align="center">基于RuoYi-Vue3+FastAPI前后端分离的快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/stargazers"><img src="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/badge/star.svg?theme=dark"></a>
<a href="https://github.com/insistence/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/github/stars/insistence/RuoYi-Vue3-FastAPI?style=social"></a>
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/badge/RuoYiVue3FastAPI-v1.6.0-brightgreen.svg"></a>
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/badge/RuoYiVue3FastAPI-v1.6.2-brightgreen.svg"></a>
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
<img src="https://img.shields.io/badge/python-≥3.9-blue">
<img src="https://img.shields.io/badge/MySQL-≥5.7-blue">

View File

@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
APP_VERSION= '1.6.0'
APP_VERSION= '1.6.2'
# 应用是否开启热重载
APP_RELOAD = true
# 应用是否开启IP归属区域查询

View File

@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
APP_VERSION= '1.6.0'
APP_VERSION= '1.6.2'
# 应用是否开启热重载
APP_RELOAD = false
# 应用是否开启IP归属区域查询

View File

@@ -252,6 +252,8 @@ class GenConstant:
'double',
'decimal',
]
COLUMNNAME_NOT_ADD_SHOW = ['create_by', 'create_time']
COLUMNNAME_NOT_EDIT_SHOW = ['update_by', 'update_time']
COLUMNNAME_NOT_EDIT = ['id', 'create_by', 'create_time', 'del_flag']
COLUMNNAME_NOT_LIST = ['id', 'create_by', 'create_time', 'del_flag', 'update_by', 'update_time']
COLUMNNAME_NOT_QUERY = ['id', 'create_by', 'create_time', 'del_flag', 'update_by', 'update_time', 'remark']

View File

@@ -3,6 +3,7 @@ import os
import sys
from dotenv import load_dotenv
from functools import lru_cache
from pydantic import computed_field
from pydantic_settings import BaseSettings
from typing import Literal
@@ -51,6 +52,13 @@ class DataBaseSettings(BaseSettings):
db_pool_recycle: int = 3600
db_pool_timeout: int = 30
@computed_field
@property
def sqlglot_parse_dialect(self) -> str:
if self.db_type == 'postgresql':
return 'postgres'
return self.db_type
class RedisSettings(BaseSettings):
"""

View File

@@ -201,9 +201,12 @@ class SchedulerUtil:
job_executor = job_info.job_executor
if iscoroutinefunction(job_func):
job_executor = 'default'
job_trigger = DateTrigger()
if job_info.status == '0':
job_trigger = OrTrigger(triggers=[DateTrigger(), MyCronTrigger.from_crontab(job_info.cron_expression)])
scheduler.add_job(
func=eval(job_info.invoke_target),
trigger=OrTrigger(triggers=[DateTrigger(), MyCronTrigger.from_crontab(job_info.cron_expression)]),
trigger=job_trigger,
args=job_info.job_args.split(',') if job_info.job_args else None,
kwargs=json.loads(job_info.job_kwargs) if job_info.job_kwargs else None,
id=str(job_info.job_id),

View File

@@ -2,10 +2,13 @@ import inspect
from fastapi import Form, Query
from pydantic import BaseModel
from pydantic.fields import FieldInfo
from typing import Type
from typing import Type, TypeVar
def as_query(cls: Type[BaseModel]):
BaseModelVar = TypeVar('BaseModelVar', bound=BaseModel)
def as_query(cls: Type[BaseModelVar]) -> Type[BaseModelVar]:
"""
pydantic模型查询参数装饰器将pydantic模型用于接收查询参数
"""
@@ -43,7 +46,7 @@ def as_query(cls: Type[BaseModel]):
return cls
def as_form(cls: Type[BaseModel]):
def as_form(cls: Type[BaseModelVar]) -> Type[BaseModelVar]:
"""
pydantic模型表单参数装饰器将pydantic模型用于接收表单参数
"""

View File

@@ -5,6 +5,7 @@ from module_admin.entity.do.log_do import SysLogininfor, SysOperLog
from module_admin.entity.vo.log_vo import LogininforModel, LoginLogPageQueryModel, OperLogModel, OperLogPageQueryModel
from utils.common_util import SnakeCaseUtil
from utils.page_util import PageUtil
from utils.time_format_util import TimeFormatUtil
class OperationLogDao:
@@ -38,8 +39,8 @@ class OperationLogDao:
SysOperLog.business_type == query_object.business_type if query_object.business_type else True,
SysOperLog.status == query_object.status if query_object.status else True,
SysOperLog.oper_time.between(
datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)),
datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)),
datetime.combine(TimeFormatUtil.parse_date(query_object.begin_time), time(00, 00, 00)),
datetime.combine(TimeFormatUtil.parse_date(query_object.end_time), time(23, 59, 59)),
)
if query_object.begin_time and query_object.end_time
else True,
@@ -120,8 +121,8 @@ class LoginLogDao:
SysLogininfor.user_name.like(f'%{query_object.user_name}%') if query_object.user_name else True,
SysLogininfor.status == query_object.status if query_object.status else True,
SysLogininfor.login_time.between(
datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)),
datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)),
datetime.combine(TimeFormatUtil.parse_date(query_object.begin_time), time(00, 00, 00)),
datetime.combine(TimeFormatUtil.parse_date(query_object.end_time), time(23, 59, 59)),
)
if query_object.begin_time and query_object.end_time
else True,

View File

@@ -103,9 +103,10 @@ class DictTypeService:
if dict_type_info.dict_type != page_object.dict_type:
for dict_data in dict_data_list:
edit_dict_data = DictDataModel(
dictCode=dict_data.dict_code,
dictCode=dict_data.get('dict_code'),
dictType=page_object.dict_type,
updateBy=page_object.update_by,
updateTime=page_object.update_time,
).model_dump(exclude_unset=True)
await DictDataDao.edit_dict_data_dao(query_db, edit_dict_data)
await DictTypeDao.edit_dict_type_dao(query_db, edit_dict_type)

View File

@@ -494,6 +494,7 @@ class UserService:
}
for item in user_list:
item['deptName'] = item.get('dept').get('deptName')
if item.get('status') == '0':
item['status'] = '正常'
else:

View File

@@ -2,6 +2,7 @@ from datetime import datetime, time
from sqlalchemy import delete, func, select, text, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from sqlglot.expressions import Expression
from typing import List
from config.env import DataBaseConfig
from module_generator.entity.do.gen_do import GenTable, GenTableColumn
@@ -75,15 +76,17 @@ class GenTableDao:
return gen_table_all
@classmethod
async def create_table_by_sql_dao(cls, db: AsyncSession, sql: str):
async def create_table_by_sql_dao(cls, db: AsyncSession, sql_statements: List[Expression]):
"""
根据sql语句创建表结构
:param db: orm对象
:param sql: sql语句
:param sql_statements: sql语句的ast列表
:return:
"""
await db.execute(text(sql))
for sql_statement in sql_statements:
sql = sql_statement.sql(dialect=DataBaseConfig.sqlglot_parse_dialect)
await db.execute(text(sql))
@classmethod
async def get_gen_table_list(cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False):

View File

@@ -1,13 +1,14 @@
import io
import json
import os
import re
import zipfile
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession
from sqlglot import parse as sqlglot_parse
from sqlglot.expressions import Add, Alter, Create, Delete, Drop, Expression, Insert, Table, TruncateTable, Update
from typing import List
from config.constant import GenConstant
from config.env import GenConfig
from config.env import DataBaseConfig, GenConfig
from exceptions.exception import ServiceException
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_admin.entity.vo.user_vo import CurrentUserModel
@@ -197,10 +198,11 @@ class GenTableService:
:param current_user: 当前用户信息对象
:return: 创建表结构结果
"""
if cls.__is_valid_create_table(sql):
sql_statements = sqlglot_parse(sql, dialect=DataBaseConfig.sqlglot_parse_dialect)
if cls.__is_valid_create_table(sql_statements):
try:
table_names = re.findall(r'create\s+table\s+(\w+)', sql, re.IGNORECASE)
await GenTableDao.create_table_by_sql_dao(query_db, sql)
table_names = cls.__get_table_names(sql_statements)
await GenTableDao.create_table_by_sql_dao(query_db, sql_statements)
gen_table_list = await cls.get_gen_db_table_list_by_name_services(query_db, table_names)
await cls.import_gen_table_services(query_db, gen_table_list, current_user)
@@ -211,22 +213,39 @@ class GenTableService:
raise ServiceException(message='建表语句不合法')
@classmethod
def __is_valid_create_table(cls, sql: str):
def __is_valid_create_table(cls, sql_statements: List[Expression]):
"""
校验sql语句是否为合法的建表语句
:param sql: sql语句
:param sql_statements: sql语句的ast列表
:return: 校验结果
"""
create_table_pattern = r'^\s*CREATE\s+TABLE\s+'
if not re.search(create_table_pattern, sql, re.IGNORECASE):
validate_create = [isinstance(sql_statement, Create) for sql_statement in sql_statements]
validate_forbidden_keywords = [
isinstance(
sql_statement,
(Add, Alter, Delete, Drop, Insert, TruncateTable, Update),
)
for sql_statement in sql_statements
]
if not any(validate_create) or any(validate_forbidden_keywords):
return False
forbidden_keywords = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'ALTER', 'TRUNCATE']
for keyword in forbidden_keywords:
if re.search(rf'\b{keyword}\b', sql, re.IGNORECASE):
return False
return True
@classmethod
def __get_table_names(cls, sql_statements: List[Expression]):
"""
获取sql语句中所有的建表表名
:param sql_statements: sql语句的ast列表
:return: 建表表名列表
"""
table_names = []
for sql_statement in sql_statements:
if isinstance(sql_statement, Create):
table_names.append(sql_statement.find(Table).name)
return table_names
@classmethod
async def preview_code_services(cls, query_db: AsyncSession, table_id: int):
"""

View File

@@ -70,7 +70,7 @@ class {{ BusinessName }}Dao:
await db.execute(
select({{ ClassName }}).where(
{% for column in columns %}
{% if column.required %}
{% if column.unique %}
{{ ClassName }}.{{ column.python_field | camel_to_snake }} == {{ businessName }}.{{ column.python_field | camel_to_snake }} if {{ businessName }}.{{ column.python_field | camel_to_snake }} else True,
{% endif %}
{% endfor %}
@@ -118,12 +118,12 @@ class {{ BusinessName }}Dao:
{{ ClassName }}.{{ field }} <= query_object.{{ field }} if query_object.{{ field }} else True,
{% elif column.query_type == "LIKE" %}
{{ ClassName }}.{{ field }}.like(f'%{% raw %}{{% endraw %}query_object.{{ field }}{% raw %}}{% endraw %}%') if query_object.{{ field }} else True,
{% elif column.query_type == "BETWEEN" %}
{% elif column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{{ ClassName }}.{{ field }}.between(
datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)),
datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)),
datetime.combine(datetime.strptime(query_object.begin_{{ column.column_name }}, '%Y-%m-%d'), time(00, 00, 00)),
datetime.combine(datetime.strptime(query_object.end_{{ column.column_name }}, '%Y-%m-%d'), time(23, 59, 59)),
)
if query_object.begin_time and query_object.end_time
if query_object.begin_{{ column.column_name }} and query_object.end_{{ column.column_name }}
else True,
{% endif %}
{% endif %}
@@ -145,7 +145,7 @@ class {{ BusinessName }}Dao:
:param {{ businessName }}: {{ functionName }}对象
:return:
"""
db_{{ businessName }} = {{ ClassName }}(**{{ businessName }}.model_dump(exclude={% raw %}{{% endraw %}{% if table.sub %}'{{ subclassName }}_list', {% endif %}{% for column in columns %}{% if not column.insert %}'{{ column.python_field | camel_to_snake }}'{% if not loop.last %}, {% endif %}{% endif %}{% endfor %}{% raw %}}{% endraw %}))
db_{{ businessName }} = {{ ClassName }}(**{{ businessName }}.model_dump(exclude={% raw %}{{% endraw %}{% if table.sub %}'{{ subclassName }}_list', {% endif %}{% for column in columns %}{% if not column.insert and column.column_name not in column_not_add_show + column_not_edit_show %}'{{ column.python_field | camel_to_snake }}'{% if not loop.last %}, {% endif %}{% endif %}{% endfor %}{% raw %}}{% endraw %}))
db.add(db_{{ businessName }})
await db.flush()

View File

@@ -103,7 +103,7 @@ class {{ BusinessName }}Service:
:param page_object: 编辑{{ functionName }}对象
:return: 编辑{{ functionName }}校验结果
"""
edit_{{ businessName }} = page_object.model_dump(exclude_unset=True, exclude={% raw %}{{% endraw %}{% if table.sub %}'{{ subclassName }}_list', {% endif %}{% for column in columns %}{% if not column.edit and not column.pk %}'{{ column.python_field | camel_to_snake }}'{% if not loop.last %}, {% endif %}{% endif %}{% endfor %}{% raw %}}{% endraw %})
edit_{{ businessName }} = page_object.model_dump(exclude_unset=True, exclude={% raw %}{{% endraw %}{% if table.sub %}'{{ subclassName }}_list', {% endif %}{% for column in columns %}{% if not column.edit and not column.pk and column.column_name not in column_not_edit_show %}'{{ column.python_field | camel_to_snake }}'{% if not loop.last %}, {% endif %}{% endif %}{% endfor %}{% raw %}}{% endraw %})
{{ businessName }}_info = await cls.{{ businessName }}_detail_services(query_db, page_object.{{ pk_field }})
if {{ businessName }}_info.{{ pk_field }}:
{% for column in columns %}

View File

@@ -3,13 +3,17 @@
{% set pkParentheseIndex = pkColumn.column_comment.find("") %}
{% set pk_field_comment = pkColumn.column_comment[:pkParentheseIndex] if pkParentheseIndex != -1 else pkColumn.column_comment %}
{% set vo_field_required = namespace(has_required=False) %}
{% set vo_field_daterange = namespace(has_daterange=False) %}
{% for column in columns %}
{% if column.required %}
{% set vo_field_required.has_required = True %}
{% endif %}
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{% set vo_field_daterange.has_daterange = True %}
{% endif %}
{% endfor %}
{% if table.sub %}
{% set sub_vo_field_required = namespace(has_required=False) %}
{% if table.sub %}
{% for sub_column in subTable.columns %}
{% if sub_column.required %}
{% set sub_vo_field_required.has_required = True %}
@@ -21,7 +25,7 @@
{% endfor %}
from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel
{% if vo_field_required.has_required %}
{% if vo_field_required.has_required or sub_vo_field_required.has_required %}
from pydantic_validation_decorator import NotBlank
{% endif %}
{% if table.sub %}
@@ -142,9 +146,16 @@ class {{ BusinessName }}QueryModel({% if table.sub %}{{ BusinessName }}BaseModel
"""
{{ functionName }}不分页查询模型
"""
begin_time: Optional[str] = Field(default=None, description='开始时间')
end_time: Optional[str] = Field(default=None, description='结束时间')
{% if vo_field_daterange.has_daterange %}
{% for column in columns %}
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
begin_{{ column.column_name }}: Optional[str] = Field(default=None, description='开始{{ column.column_comment }}')
end_{{ column.column_name }}: Optional[str] = Field(default=None, description='结束{{ column.column_comment }}')
{% endif %}
{% endfor %}
{% else %}
pass
{% endif %}
@as_query

View File

@@ -35,12 +35,13 @@
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-date-picker clearable
<el-date-picker
v-model="queryParams.{{ column.python_field }}"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择{{ comment }}">
</el-date-picker>
placeholder="请选择{{ comment }}"
clearable
/>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type == "BETWEEN" %}
<el-form-item label="{{ comment }}">
@@ -52,7 +53,7 @@
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
/>
</el-form-item>
{% endif %}
{% endif %}
@@ -161,33 +162,33 @@
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
{% for column in columns %}
{% set field = column.python_field %}
{% if column.insert and not column.pk %}
{% if (column.insert or column.edit) and not column.pk and column.column_name not in column_not_add_show + column_not_edit_show %}
{% if column.usable_column or not column.super_column %}
{% set parentheseIndex = column.column_comment.find("") %}
{% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %}
{% set dictType = column.dict_type %}
{% if treeParentCode and column.python_field == treeParentCode %}
<el-form-item label="{{ comment }}" prop="{{ treeParentCode }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ treeParentCode }}">
<treeselect v-model="form.{{ treeParentCode }}" :options="{{ businessName }}Options" :normalizer="normalizer" placeholder="请选择{{ comment }}" />
</el-form-item>
{% elif column.html_type == "input" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" placeholder="请输入{{ comment }}" />
</el-form-item>
{% elif column.html_type == "imageUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<image-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "fileUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<file-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "editor" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<editor v-model="form.{{ field }}" :min-height="192"/>
</el-form-item>
{% elif column.html_type == "select" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option
v-for="dict in dict.type.{{ dictType }}"
@@ -202,13 +203,13 @@
</el-select>
</el-form-item>
{% elif column.html_type == "select" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "checkbox" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox
v-for="dict in dict.type.{{ dictType }}"
@@ -219,13 +220,13 @@
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "checkbox" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "radio" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio
v-for="dict in dict.type.{{ dictType }}"
@@ -240,13 +241,13 @@
</el-radio-group>
</el-form-item>
{% elif column.html_type == "radio" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio label="请选择字典生成" value="" />
</el-radio-group>
</el-form-item>
{% elif column.html_type == "datetime" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-date-picker clearable
v-model="form.{{ field }}"
type="date"
@@ -255,7 +256,7 @@
</el-date-picker>
</el-form-item>
{% elif column.html_type == "textarea" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" type="textarea" placeholder="请输入内容" />
</el-form-item>
{% endif %}
@@ -351,8 +352,8 @@ export default {
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{% set AttrName = column.python_field[0] | upper + column.python_field[1:] %}
if (null != this.daterange{{ AttrName }} && '' != this.daterange{{ AttrName }}) {
this.queryParams.params["begin{{ AttrName }}"] = this.daterange{{ AttrName }}[0];
this.queryParams.params["end{{ AttrName }}"] = this.daterange{{ AttrName }}[1];
this.queryParams.begin{{ AttrName }} = this.daterange{{ AttrName }}[0];
this.queryParams.end{{ AttrName }} = this.daterange{{ AttrName }}[1];
}
{% endif %}
{% endfor %}
@@ -485,6 +486,10 @@ export default {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 是否渲染字段 */
renderField(insert, edit) {
return this.form.{{ pkColumn.python_field }} == null ? insert : edit;
}
},
};

View File

@@ -35,12 +35,13 @@
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-date-picker clearable
<el-date-picker
v-model="queryParams.{{ column.python_field }}"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择{{ comment }}">
</el-date-picker>
placeholder="请选择{{ comment }}"
clearable
/>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type == "BETWEEN" %}
<el-form-item label="{{ comment }}">
@@ -52,7 +53,7 @@
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
/>
</el-form-item>
{% endif %}
{% endif %}
@@ -173,29 +174,29 @@
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
{% for column in columns %}
{% set field = column.python_field %}
{% if column.insert and not column.pk %}
{% if (column.insert or column.edit) and not column.pk and column.column_name not in column_not_add_show + column_not_edit_show %}
{% if column.usable_column or not column.super_column %}
{% set parentheseIndex = column.column_comment.find("") %}
{% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %}
{% set dictType = column.dict_type %}
{% if column.html_type == "input" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" placeholder="请输入{{ comment }}" />
</el-form-item>
{% elif column.html_type == "imageUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<image-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "fileUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<file-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "editor" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<editor v-model="form.{{ field }}" :min-height="192"/>
</el-form-item>
{% elif column.html_type == "select" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option
v-for="dict in dict.type.{{ dictType }}"
@@ -210,13 +211,13 @@
</el-select>
</el-form-item>
{% elif column.html_type == "select" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "checkbox" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox
v-for="dict in dict.type.{{ dictType }}"
@@ -227,13 +228,13 @@
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "checkbox" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "radio" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio
v-for="dict in dict.type.{{ dictType }}"
@@ -248,13 +249,13 @@
</el-radio-group>
</el-form-item>
{% elif column.html_type == "radio" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio label="请选择字典生成" value="" />
</el-radio-group>
</el-form-item>
{% elif column.html_type == "datetime" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-date-picker clearable
v-model="form.{{ field }}"
type="date"
@@ -263,7 +264,7 @@
</el-date-picker>
</el-form-item>
{% elif column.html_type == "textarea" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" type="textarea" placeholder="请输入内容" />
</el-form-item>
{% endif %}
@@ -426,8 +427,8 @@ export default {
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{% set AttrName = column.python_field[0] | upper + column.python_field[1:] %}
if (null != this.daterange{{ AttrName }} && '' != this.daterange{{ AttrName }}) {
this.queryParams.params["begin{{ AttrName }}"] = this.daterange{{ AttrName }}[0];
this.queryParams.params["end{{ AttrName }}"] = this.daterange{{ AttrName }}[1];
this.queryParams.begin{{ AttrName }} = this.daterange{{ AttrName }}[0];
this.queryParams.end{{ AttrName }} = this.daterange{{ AttrName }}[1];
}
{% endif %}
{% endfor %}
@@ -580,6 +581,10 @@ export default {
this.download('{{ moduleName }}/{{ businessName }}/export', {
...this.queryParams
}, `{{ businessName }}_${new Date().getTime()}.xlsx`);
},
/** 是否渲染字段 */
renderField(insert, edit) {
return this.form.{{ pkColumn.python_field }} == null ? insert : edit;
}
},
};

View File

@@ -13,12 +13,13 @@
v-model="queryParams.{{ column.python_field }}"
placeholder="请输入{{ comment }}"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
{% elif (column.html_type == "select" or column.html_type == "radio") and dictType %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable style="width: 240px">
<el-option
v-for="dict in {{ dictType }}"
:key="dict.value"
@@ -29,18 +30,20 @@
</el-form-item>
{% elif (column.html_type == "select" or column.html_type == "radio") and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable style="width: 240px">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-date-picker clearable
<el-date-picker
v-model="queryParams.{{ column.python_field }}"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择{{ comment }}">
</el-date-picker>
placeholder="请选择{{ comment }}"
clearable
style="width: 240px"
/>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type == "BETWEEN" %}
<el-form-item label="{{ comment }}" style="width: 308px">
@@ -51,7 +54,8 @@
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
style="width: 240px"
/>
</el-form-item>
{% endif %}
{% endif %}
@@ -136,13 +140,13 @@
<el-form ref="{{ businessName }}Ref" :model="form" :rules="rules" label-width="80px">
{% for column in columns %}
{% set field = column.python_field %}
{% if column.insert and not column.pk %}
{% if (column.insert or column.edit) and not column.pk and column.column_name not in column_not_add_show + column_not_edit_show %}
{% if column.usable_column or not column.super_column %}
{% set parentheseIndex = column.column_comment.find("") %}
{% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %}
{% set dictType = column.dict_type %}
{% if treeParentCode and column.python_field == treeParentCode %}
<el-form-item label="{{ comment }}" prop="{{ treeParentCode }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ treeParentCode }}">
<el-tree-select
v-model="form.{{ treeParentCode }}"
:data="{{ businessName }}Options"
@@ -153,23 +157,23 @@
/>
</el-form-item>
{% elif column.html_type == "input" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" placeholder="请输入{{ comment }}" />
</el-form-item>
{% elif column.html_type == "imageUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<image-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "fileUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<file-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "editor" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<editor v-model="form.{{ field }}" :min-height="192"/>
</el-form-item>
{% elif column.html_type == "select" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option
v-for="dict in {{ dictType }}"
@@ -184,13 +188,13 @@
</el-select>
</el-form-item>
{% elif column.html_type == "select" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "checkbox" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox
v-for="dict in {{ dictType }}"
@@ -201,13 +205,13 @@
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "checkbox" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "radio" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio
v-for="dict in {{ dictType }}"
@@ -222,13 +226,13 @@
</el-radio-group>
</el-form-item>
{% elif column.html_type == "radio" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio label="请选择字典生成" value="" />
</el-radio-group>
</el-form-item>
{% elif column.html_type == "datetime" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-date-picker clearable
v-model="form.{{ field }}"
type="date"
@@ -237,7 +241,7 @@
</el-date-picker>
</el-form-item>
{% elif column.html_type == "textarea" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" type="textarea" placeholder="请输入内容" />
</el-form-item>
{% endif %}
@@ -315,8 +319,8 @@ function getList() {
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{% set AttrName = column.python_field[0] | upper + column.python_field[1:] %}
if (null != daterange{{ AttrName }} && '' != daterange{{ AttrName }}) {
queryParams.value.params["begin{{ AttrName }}"] = daterange{{ AttrName }}.value[0];
queryParams.value.params["end{{ AttrName }}"] = daterange{{ AttrName }}.value[1];
queryParams.value.begin{{ AttrName }} = daterange{{ AttrName }}.value[0];
queryParams.value.end{{ AttrName }} = daterange{{ AttrName }}.value[1];
}
{% endif %}
{% endfor %}
@@ -450,5 +454,10 @@ function handleDelete(row) {
}).catch(() => {});
}
/** 是否渲染字段 */
function renderField(insert, edit) {
return form.value.{{ pkColumn.python_field }} == null ? insert : edit;
}
getList();
</script>

View File

@@ -13,12 +13,13 @@
v-model="queryParams.{{ column.python_field }}"
placeholder="请输入{{ comment }}"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
{% elif (column.html_type == "select" or column.html_type == "radio") and dictType %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable style="width: 240px">
<el-option
v-for="dict in {{ dictType }}"
:key="dict.value"
@@ -29,18 +30,20 @@
</el-form-item>
{% elif (column.html_type == "select" or column.html_type == "radio") and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable>
<el-select v-model="queryParams.{{ column.python_field }}" placeholder="请选择{{ comment }}" clearable style="width: 240px">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type != "BETWEEN" %}
<el-form-item label="{{ comment }}" prop="{{ column.python_field }}">
<el-date-picker clearable
<el-date-picker
v-model="queryParams.{{ column.python_field }}"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择{{ comment }}">
</el-date-picker>
placeholder="请选择{{ comment }}"
clearable
style="width: 240px"
/>
</el-form-item>
{% elif column.html_type == "datetime" and column.query_type == "BETWEEN" %}
<el-form-item label="{{ comment }}" style="width: 308px">
@@ -51,7 +54,8 @@
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
style="width: 240px"
/>
</el-form-item>
{% endif %}
{% endif %}
@@ -159,29 +163,29 @@
<el-form ref="{{ businessName }}Ref" :model="form" :rules="rules" label-width="80px">
{% for column in columns %}
{% set field = column.python_field %}
{% if column.insert and not column.pk %}
{% if (column.insert or column.edit) and not column.pk and column.column_name not in column_not_add_show + column_not_edit_show %}
{% if column.usable_column or not column.super_column %}
{% set parentheseIndex = column.column_comment.find("") %}
{% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %}
{% set dictType = column.dict_type %}
{% if column.html_type == "input" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" placeholder="请输入{{ comment }}" />
</el-form-item>
{% elif column.html_type == "imageUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<image-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "fileUpload" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<file-upload v-model="form.{{ field }}"/>
</el-form-item>
{% elif column.html_type == "editor" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<editor v-model="form.{{ field }}" :min-height="192"/>
</el-form-item>
{% elif column.html_type == "select" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option
v-for="dict in {{ dictType }}"
@@ -196,13 +200,13 @@
</el-select>
</el-form-item>
{% elif column.html_type == "select" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-select v-model="form.{{ field }}" placeholder="请选择{{ comment }}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
{% elif column.html_type == "checkbox" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox
v-for="dict in {{ dictType }}"
@@ -213,13 +217,13 @@
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "checkbox" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-checkbox-group v-model="form.{{ field }}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
{% elif column.html_type == "radio" and dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio
v-for="dict in {{ dictType }}"
@@ -234,13 +238,13 @@
</el-radio-group>
</el-form-item>
{% elif column.html_type == "radio" and not dictType %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-radio-group v-model="form.{{ field }}">
<el-radio label="请选择字典生成" value="" />
</el-radio-group>
</el-form-item>
{% elif column.html_type == "datetime" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-date-picker clearable
v-model="form.{{ field }}"
type="date"
@@ -249,7 +253,7 @@
</el-date-picker>
</el-form-item>
{% elif column.html_type == "textarea" %}
<el-form-item label="{{ comment }}" prop="{{ field }}">
<el-form-item v-if="renderField({{ column.insert | lower }}, {{ column.edit | lower }})" label="{{ comment }}" prop="{{ field }}">
<el-input v-model="form.{{ field }}" type="textarea" placeholder="请输入内容" />
</el-form-item>
{% endif %}
@@ -397,8 +401,8 @@ function getList() {
{% if column.html_type == "datetime" and column.query_type == "BETWEEN" %}
{% set AttrName = column.python_field[0] | upper + column.python_field[1:] %}
if (null != daterange{{ AttrName }} && '' != daterange{{ AttrName }}) {
queryParams.value.params["begin{{ AttrName }}"] = daterange{{ AttrName }}.value[0];
queryParams.value.params["end{{ AttrName }}"] = daterange{{ AttrName }}.value[1];
queryParams.value.begin{{ AttrName }} = daterange{{ AttrName }}.value[0];
queryParams.value.end{{ AttrName }} = daterange{{ AttrName }}.value[1];
}
{% endif %}
{% endfor %}
@@ -567,5 +571,10 @@ function handleExport() {
}, `{{ businessName }}_${new Date().getTime()}.xlsx`);
}
/** 是否渲染字段 */
function renderField(insert, edit) {
return form.value.{{ pkColumn.python_field }} == null ? insert : edit;
}
getList();
</script>

View File

@@ -14,4 +14,5 @@ psycopg2==2.9.10
redis==5.2.1
requests==2.32.3
SQLAlchemy[asyncio]==2.0.38
sqlglot[rs]==26.6.0
user-agents==2.2.0

View File

@@ -14,4 +14,5 @@ PyMySQL==1.1.1
redis==5.2.1
requests==2.32.3
SQLAlchemy[asyncio]==2.0.38
sqlglot[rs]==26.6.0
user-agents==2.2.0

View File

@@ -91,6 +91,8 @@ class TemplateUtils:
'table': gen_table,
'dicts': cls.get_dicts(gen_table),
'dbType': DataBaseConfig.db_type,
'column_not_add_show': GenConstant.COLUMNNAME_NOT_ADD_SHOW,
'column_not_edit_show': GenConstant.COLUMNNAME_NOT_EDIT_SHOW,
}
# 设置菜单、树形结构、子表的上下文

View File

@@ -1,4 +1,7 @@
import datetime
from copy import deepcopy
from datetime import datetime
from dateutil.parser import parse
from typing import Dict, List, Union
def object_format_datetime(obj):
@@ -8,7 +11,7 @@ def object_format_datetime(obj):
"""
for attr in dir(obj):
value = getattr(obj, attr)
if isinstance(value, datetime.datetime):
if isinstance(value, datetime):
setattr(obj, attr, value.strftime('%Y-%m-%d %H:%M:%S'))
return obj
@@ -21,7 +24,7 @@ def list_format_datetime(lst):
for obj in lst:
for attr in dir(obj):
value = getattr(obj, attr)
if isinstance(value, datetime.datetime):
if isinstance(value, datetime):
setattr(obj, attr, value.strftime('%Y-%m-%d %H:%M:%S'))
return lst
@@ -41,7 +44,7 @@ def format_datetime_dict_list(dicts):
if isinstance(v, dict):
# 递归遍历子字典
new_item[k] = format_datetime_dict_list([v])[0]
elif isinstance(v, datetime.datetime):
elif isinstance(v, datetime):
# 如果值是 datetime 类型,则格式化为字符串
new_item[k] = v.strftime('%Y-%m-%d %H:%M:%S')
else:
@@ -50,3 +53,89 @@ def format_datetime_dict_list(dicts):
result.append(new_item)
return result
class TimeFormatUtil:
"""
时间格式化工具类
"""
@classmethod
def format_time(cls, time_info: Union[str, datetime], format: str = '%Y-%m-%d %H:%M:%S'):
"""
格式化时间字符串或datetime对象为指定格式
:param time_info: 时间字符串或datetime对象
:param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S'
:return: 格式化后的时间字符串
"""
if isinstance(time_info, datetime):
format_date = time_info.strftime(format)
else:
try:
date = parse(time_info)
format_date = date.strftime(format)
except Exception:
format_date = time_info
return format_date
@classmethod
def parse_date(cls, time_str: str):
"""
解析时间字符串提取日期部分
:param time_str: 时间字符串
:return: 日期部分
"""
try:
dt = parse(time_str)
return dt.date()
except Exception:
return time_str
@classmethod
def format_time_dict(cls, time_dict: Dict, format: str = '%Y-%m-%d %H:%M:%S'):
"""
格式化时间字典
:param time_dict: 时间字典
:param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S'
:return: 格式化后的时间字典
"""
copy_time_dict = deepcopy(time_dict)
for k, v in copy_time_dict.items():
if isinstance(v, (str, datetime)):
copy_time_dict[k] = cls.format_time(v, format)
elif isinstance(v, dict):
copy_time_dict[k] = cls.format_time_dict(v, format)
elif isinstance(v, list):
copy_time_dict[k] = cls.format_time_list(v, format)
else:
copy_time_dict[k] = v
return copy_time_dict
@classmethod
def format_time_list(cls, time_list: List, format: str = '%Y-%m-%d %H:%M:%S'):
"""
格式化时间列表
:param time_list: 时间列表
:param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S'
:return: 格式化后的时间列表
"""
format_time_list = []
for item in time_list:
if isinstance(item, (str, datetime)):
format_item = cls.format_time(item, format)
elif isinstance(item, dict):
format_item = cls.format_time_dict(item, format)
elif isinstance(item, list):
format_item = cls.format_time_list(item, format)
else:
format_item = item
format_time_list.append(format_item)
return format_time_list

View File

@@ -1,6 +1,6 @@
{
"name": "vfadmin",
"version": "1.6.0",
"version": "1.6.2",
"description": "vfadmin管理系统",
"author": "insistence",
"license": "MIT",

View File

@@ -131,10 +131,6 @@ aside {
position: relative;
}
.pagination-container {
margin-top: 30px;
}
.text-center {
text-align: center
}

View File

@@ -102,21 +102,12 @@
/** 表格布局 **/
.pagination-container {
position: relative;
height: 25px;
margin-bottom: 10px;
margin-top: 15px;
padding: 10px 20px !important;
display: flex;
justify-content: flex-end;
margin-top: 20px;
background-color: transparent !important;
}
/* 分页器定位 */
.pagination-container .el-pagination {
position: absolute;
right: 0;
top: 0;
}
/* 弹窗中的分页器 */
.el-dialog .pagination-container {
position: static !important;

View File

@@ -13,12 +13,13 @@
:headers="headers"
class="upload-file-uploader"
ref="fileUpload"
v-if="!disabled"
>
<!-- 上传按钮 -->
<el-button type="primary">选取文件</el-button>
</el-upload>
<!-- 上传提示 -->
<div class="el-upload__tip" v-if="showTip">
<div class="el-upload__tip" v-if="showTip && !disabled">
请上传
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
@@ -31,7 +32,7 @@
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
<el-link :underline="false" @click="handleDelete(index)" type="danger" v-if="!disabled">删除</el-link>
</div>
</li>
</transition-group>
@@ -46,22 +47,27 @@ const props = defineProps({
// 数量限制
limit: {
type: Number,
default: 5,
default: 5
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 5,
default: 5
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"]
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
},
// 禁用组件(仅查看文件)
disabled: {
type: Boolean,
default: false
}
});

View File

@@ -97,7 +97,6 @@ function handleCurrentChange(val) {
<style scoped>
.pagination-container {
background: #fff;
padding: 32px 16px;
}
.pagination-container.hidden {
display: none;