diff --git a/backend/alembic/versions/062_system_variable.py b/backend/alembic/versions/062_system_variable.py new file mode 100644 index 000000000..561404a9d --- /dev/null +++ b/backend/alembic/versions/062_system_variable.py @@ -0,0 +1,82 @@ +"""062_system_variable + +Revision ID: ed947895d470 +Revises: 547df942eb90 +Create Date: 2026-01-26 10:16:59.877303 + +""" +import sqlalchemy as sa +import sqlmodel.sql.sqltypes +from alembic import op +from sqlalchemy import String, BigInteger, DateTime +from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.sql import table, column + +# revision identifiers, used by Alembic. +revision = 'ed947895d470' +down_revision = '547df942eb90' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('system_variable', + sa.Column('id', sa.BigInteger(), sa.Identity(always=True), nullable=False), + sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False), + sa.Column('var_type', sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False), + sa.Column('type', sqlmodel.sql.sqltypes.AutoString(length=128), nullable=False), + sa.Column('value', postgresql.JSONB(astext_type=sa.Text()), nullable=True), + sa.Column('create_time', sa.DateTime(), nullable=True), + sa.Column('create_by', sa.BigInteger(), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + + variable_table = table( + "system_variable", + column("id", BigInteger), + column("name", String), + column("var_type", String), + column("type", String), + column("value", JSONB), + column("create_time", DateTime), + column("create_by", BigInteger), + ) + + op.bulk_insert( + variable_table, + [ + { + "name": "i18n_variable.name", + "var_type": "text", + "type": "system", + "value": ["name"], + "create_time": None, + "create_by": None + }, + { + "name": "i18n_variable.account", + "var_type": "text", + "type": "system", + "value": ["account"], + "create_time": None, + "create_by": None + }, + { + "name": "i18n_variable.email", + "var_type": "text", + "type": "system", + "value": ["email"], + "create_time": None, + "create_by": None + } + ] + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('system_variable') + # ### end Alembic commands ### diff --git a/backend/alembic/versions/063_user_bind_var.py b/backend/alembic/versions/063_user_bind_var.py new file mode 100644 index 000000000..140198960 --- /dev/null +++ b/backend/alembic/versions/063_user_bind_var.py @@ -0,0 +1,29 @@ +"""063_user + +Revision ID: 8ff90df7871d +Revises: ed947895d470 +Create Date: 2026-01-26 15:30:11.348083 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel.sql.sqltypes +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '8ff90df7871d' +down_revision = 'ed947895d470' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('sys_user', sa.Column('system_variables', postgresql.JSONB(astext_type=sa.Text()), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('sys_user', 'system_variables') + # ### end Alembic commands ### diff --git a/backend/apps/api.py b/backend/apps/api.py index 27d5f9890..ec5a4209f 100644 --- a/backend/apps/api.py +++ b/backend/apps/api.py @@ -5,7 +5,7 @@ from apps.data_training.api import data_training from apps.datasource.api import datasource, table_relation, recommended_problem from apps.mcp import mcp -from apps.system.api import login, user, aimodel, workspace, assistant, parameter, apikey +from apps.system.api import login, user, aimodel, workspace, assistant, parameter, apikey, variable_api from apps.terminology.api import terminology from apps.settings.api import base #from audit.api import audit_api @@ -30,4 +30,6 @@ api_router.include_router(recommended_problem.router) +api_router.include_router(variable_api.router) + #api_router.include_router(audit_api.router) diff --git a/backend/apps/datasource/crud/permission.py b/backend/apps/datasource/crud/permission.py index 870718121..8c9cc29ec 100644 --- a/backend/apps/datasource/crud/permission.py +++ b/backend/apps/datasource/crud/permission.py @@ -40,7 +40,7 @@ def get_row_permission_filters(session: SessionDep, current_user: CurrentUser, d break if flag: res.append(transRecord2DTO(session, permission)) - where_str = transFilterTree(session, res, ds) + where_str = transFilterTree(session, current_user, res, ds) filters.append({"table": table.table_name, "filter": where_str}) return filters diff --git a/backend/apps/datasource/crud/row_permission.py b/backend/apps/datasource/crud/row_permission.py index 16f97971c..52fdc44e6 100644 --- a/backend/apps/datasource/crud/row_permission.py +++ b/backend/apps/datasource/crud/row_permission.py @@ -4,10 +4,12 @@ from typing import List, Dict from apps.datasource.models.datasource import CoreField, CoreDatasource from apps.db.constant import DB -from common.core.deps import SessionDep +from apps.system.models.system_variable_model import SystemVariable +from common.core.deps import SessionDep, CurrentUser -def transFilterTree(session: SessionDep, tree_list: List[any], ds: CoreDatasource) -> str | None: +def transFilterTree(session: SessionDep, current_user: CurrentUser, tree_list: List[any], + ds: CoreDatasource) -> str | None: if tree_list is None: return None res: List[str] = [] @@ -15,13 +17,13 @@ def transFilterTree(session: SessionDep, tree_list: List[any], ds: CoreDatasourc tree = dto.tree if tree is None: continue - tree_exp = transTreeToWhere(session, tree, ds) + tree_exp = transTreeToWhere(session, current_user, tree, ds) if tree_exp is not None: res.append(tree_exp) return " AND ".join(res) -def transTreeToWhere(session: SessionDep, tree: any, ds: CoreDatasource) -> str | None: +def transTreeToWhere(session: SessionDep, current_user: CurrentUser, tree: any, ds: CoreDatasource) -> str | None: if tree is None: return None logic = tree['logic'] @@ -32,16 +34,16 @@ def transTreeToWhere(session: SessionDep, tree: any, ds: CoreDatasource) -> str for item in items: exp: str = None if item['type'] == 'item': - exp = transTreeItem(session, item, ds) + exp = transTreeItem(session, current_user, item, ds) elif item['type'] == 'tree': - exp = transTreeToWhere(session, item['sub_tree'], ds) + exp = transTreeToWhere(session, current_user, item['sub_tree'], ds) if exp is not None: list.append(exp) return '(' + f' {logic} '.join(list) + ')' if len(list) > 0 else None -def transTreeItem(session: SessionDep, item: Dict, ds: CoreDatasource) -> str | None: +def transTreeItem(session: SessionDep, current_user: CurrentUser, item: Dict, ds: CoreDatasource) -> str | None: res: str = None field = session.query(CoreField).filter(CoreField.id == int(item['field_id'])).first() if field is None: @@ -49,6 +51,8 @@ def transTreeItem(session: SessionDep, item: Dict, ds: CoreDatasource) -> str | db = DB.get_db(ds.type) whereName = db.prefix + field.field_name + db.suffix + whereTerm = transFilterTerm(item['term']) + if item['filter_type'] == 'enum': if len(item['enum_value']) > 0: if ds['type'] == 'sqlServer' and ( @@ -57,38 +61,113 @@ def transTreeItem(session: SessionDep, item: Dict, ds: CoreDatasource) -> str | else: res = "(" + whereName + " IN ('" + "','".join(item['enum_value']) + "'))" else: - value = item['value'] - whereTerm = transFilterTerm(item['term']) - whereValue = '' + # if system variable, do check and get value + # new field: value_type(variable or normal), variable_id + value_type = item.get('value_type') + if value_type and value_type == 'variable': + # get system variable + variable_id = item.get('variable_id') + if variable_id is not None: + sys_variable = session.query(SystemVariable).filter(SystemVariable.id == variable_id).first() + # do inner system variable + if sys_variable.type == 'system': + res = whereName + whereTerm + getSysVariableValue(sys_variable, current_user) + else: + # check user variable + user_variables = current_user.system_variables + if user_variables is None or len(user_variables) == 0 or not userHaveVariable(user_variables, + sys_variable): + return None + else: + # get user variable + u_variable = None + for u in user_variables: + if u.get('variableId') == sys_variable.id: + u_variable = u + break + if u_variable is None: + return None - if item['term'] == 'null': - whereValue = '' - elif item['term'] == 'not_null': - whereValue = '' - elif item['term'] == 'empty': - whereValue = "''" - elif item['term'] == 'not_empty': - whereValue = "''" - elif item['term'] == 'in' or item['term'] == 'not in': - if ds.type == 'sqlServer' and ( - field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): - whereValue = "(N'" + "', N'".join(value.split(",")) + "')" - else: - whereValue = "('" + "', '".join(value.split(",")) + "')" - elif item['term'] == 'like' or item['term'] == 'not like': - if ds.type == 'sqlServer' and ( - field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): - whereValue = f"N'%{value}%'" + # check value + values = u_variable.get('variableValues') + if sys_variable.var_type == 'text': + set_sys = set(sys_variable.value) + values = [x for x in values if x in set_sys] + if values is None or len(values) == 0: + return None + elif sys_variable.var_type == 'number': + if (sys_variable.value[0] is not None and values[0] < sys_variable.value[0]) or ( + sys_variable.value[1] is not None and values[0] > sys_variable.value[1]): + return None + elif sys_variable.var_type == 'datetime': + if (sys_variable.value[0] is not None and values[0] < sys_variable.value[0]) or ( + sys_variable.value[1] is not None and values[0] > sys_variable.value[1]): + return None + + # build exp + whereValue = '' + if item['term'] == 'null': + whereValue = '' + elif item['term'] == 'not_null': + whereValue = '' + elif item['term'] == 'empty': + whereValue = "''" + elif item['term'] == 'not_empty': + whereValue = "''" + elif item['term'] == 'in' or item['term'] == 'not in': + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = "(N'" + "', N'".join(values) + "')" + else: + whereValue = "('" + "', '".join(values) + "')" + elif item['term'] == 'like' or item['term'] == 'not like': + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = f"N'%{values[0]}%'" + else: + whereValue = f"'%{values[0]}%'" + else: + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = f"N'{values[0]}'" + else: + whereValue = f"'{values[0]}'" + + res = whereName + whereTerm + whereValue else: - whereValue = f"'%{value}%'" + return None else: - if ds.type == 'sqlServer' and ( - field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): - whereValue = f"N'{value}'" + value = item['value'] + whereValue = '' + + if item['term'] == 'null': + whereValue = '' + elif item['term'] == 'not_null': + whereValue = '' + elif item['term'] == 'empty': + whereValue = "''" + elif item['term'] == 'not_empty': + whereValue = "''" + elif item['term'] == 'in' or item['term'] == 'not in': + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = "(N'" + "', N'".join(value.split(",")) + "')" + else: + whereValue = "('" + "', '".join(value.split(",")) + "')" + elif item['term'] == 'like' or item['term'] == 'not like': + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = f"N'%{value}%'" + else: + whereValue = f"'%{value}%'" else: - whereValue = f"'{value}'" + if ds.type == 'sqlServer' and ( + field.field_type == 'nchar' or field.field_type == 'NCHAR' or field.field_type == 'nvarchar' or field.field_type == 'NVARCHAR'): + whereValue = f"N'{value}'" + else: + whereValue = f"'{value}'" - res = whereName + whereTerm + whereValue + res = whereName + whereTerm + whereValue return res @@ -124,3 +203,19 @@ def transFilterTerm(term: str) -> str: if term == "between": return " BETWEEN " return "" + + +def userHaveVariable(user_variables: List, sys_variable: SystemVariable): + for u in user_variables: + if sys_variable.id == u.get('variableId'): + return True + return False + + +def getSysVariableValue(sys_variable: SystemVariable, current_user: CurrentUser): + if sys_variable.value[0] == 'name': + return current_user.name + if sys_variable.value[0] == 'account': + return current_user.account + if sys_variable.value[0] == 'email': + return current_user.email diff --git a/backend/apps/swagger/i18n.py b/backend/apps/swagger/i18n.py index c0ed7a746..39a6aa71e 100644 --- a/backend/apps/swagger/i18n.py +++ b/backend/apps/swagger/i18n.py @@ -107,6 +107,10 @@ def load_translation(lang: str) -> Dict[str, str]: { "name": "Audit", "description": f"{PLACEHOLDER_PREFIX}audit_api" + }, + { + "name": "System_variable", + "description": f"{PLACEHOLDER_PREFIX}variable_api" } ] diff --git a/backend/apps/swagger/locales/en.json b/backend/apps/swagger/locales/en.json index f4499c9a9..05ddb02ef 100644 --- a/backend/apps/swagger/locales/en.json +++ b/backend/apps/swagger/locales/en.json @@ -188,5 +188,11 @@ "delete_resource_api": "Delete Resource", "create_canvas_api": "Create Dashboard", "update_canvas_api": "Update Dashboard", - "check_name_api": "Name Validation" + "check_name_api": "Name Validation", + + "variable_api": "System Variable", + "variable_save": "Save", + "variable_delete": "Delete", + "variable_list": "List", + "variable_page": "Pager" } \ No newline at end of file diff --git a/backend/apps/swagger/locales/zh.json b/backend/apps/swagger/locales/zh.json index 443dd4731..b6e7609df 100644 --- a/backend/apps/swagger/locales/zh.json +++ b/backend/apps/swagger/locales/zh.json @@ -188,5 +188,11 @@ "delete_resource_api": "删除资源", "create_canvas_api": "新建仪表板", "update_canvas_api": "更新仪表板", - "check_name_api": "名称校验" + "check_name_api": "名称校验", + + "variable_api": "系统变量", + "variable_save": "保存变量", + "variable_delete": "删除变量", + "variable_list": "获取变量", + "variable_page": "获取变量分页" } diff --git a/backend/apps/system/api/variable_api.py b/backend/apps/system/api/variable_api.py new file mode 100644 index 000000000..751462391 --- /dev/null +++ b/backend/apps/system/api/variable_api.py @@ -0,0 +1,34 @@ +# Author: Junjun +# Date: 2026/1/26 +from typing import List +from fastapi import APIRouter + +from apps.swagger.i18n import PLACEHOLDER_PREFIX +from apps.system.crud.system_variable import save, delete, list_all, list_page +from apps.system.models.system_variable_model import SystemVariable +from common.core.config import settings +from common.core.deps import SessionDep, CurrentUser, Trans + +router = APIRouter(tags=["System_variable"], prefix="/sys_variable") +path = settings.EXCEL_PATH + + +@router.post("/save", response_model=None, summary=f"{PLACEHOLDER_PREFIX}variable_save") +async def save_variable(session: SessionDep, user: CurrentUser, trans: Trans, variable: SystemVariable): + return save(session, user, trans, variable) + + +@router.post("/delete",response_model=None, summary=f"{PLACEHOLDER_PREFIX}variable_delete") +async def delete_variable(session: SessionDep, ids: List[int]): + return delete(session, ids) + + +@router.post("/listAll",response_model=None, summary=f"{PLACEHOLDER_PREFIX}variable_list") +async def list_all_data(session: SessionDep, trans: Trans, variable: SystemVariable = None): + return list_all(session, trans, variable) + + +@router.post("/listPage/{pageNum}/{pageSize}",response_model=None, summary=f"{PLACEHOLDER_PREFIX}variable_page") +async def pager(session: SessionDep, trans: Trans, pageNum: int, pageSize: int, + variable: SystemVariable = None): + return await list_page(session, trans, pageNum, pageSize, variable) diff --git a/backend/apps/system/crud/system_variable.py b/backend/apps/system/crud/system_variable.py new file mode 100644 index 000000000..50ebe490e --- /dev/null +++ b/backend/apps/system/crud/system_variable.py @@ -0,0 +1,98 @@ +# Author: Junjun +# Date: 2026/1/26 +import datetime + +from typing import List +from fastapi import HTTPException +from sqlalchemy import and_ +from sqlmodel import select + +from apps.system.models.system_variable_model import SystemVariable +from common.core.deps import SessionDep, CurrentUser, Trans +from common.core.pagination import Paginator +from common.core.schemas import PaginationParams + + +def save(session: SessionDep, user: CurrentUser, trans: Trans, variable: SystemVariable): + checkName(session, trans, variable) + variable.type = 'custom' + if variable.id is None: + variable.create_time = datetime.datetime.now() + variable.create_by = user.id + session.add(variable) + session.commit() + else: + record = session.query(SystemVariable).filter(SystemVariable.id == variable.id).first() + update_data = variable.model_dump(exclude_unset=True) + for field, value in update_data.items(): + setattr(record, field, value) + session.add(record) + session.commit() + return True + + +def delete(session: SessionDep, ids: List[int]): + session.query(SystemVariable).filter(SystemVariable.id.in_(ids)).delete() + + +def list_all(session: SessionDep, trans: Trans, variable: SystemVariable): + if variable.name is None: + records = session.query(SystemVariable).order_by(SystemVariable.type.desc()).all() + else: + records = session.query(SystemVariable).filter( + and_(SystemVariable.name.like(f'%{variable.name}%'), SystemVariable.type != 'system')).order_by( + SystemVariable.type.desc()).all() + + res = [] + for r in records: + data = SystemVariable(**r.__dict__) + if data.type == 'system': + data.name = trans(data.name) + res.append(data) + return res + + +async def list_page(session: SessionDep, trans: Trans, pageNum: int, pageSize: int, variable: SystemVariable): + pagination = PaginationParams(page=pageNum, size=pageSize) + paginator = Paginator(session) + filters = {} + + if variable.name is None: + stmt = select(SystemVariable).order_by(SystemVariable.type.desc()) + else: + stmt = select(SystemVariable).where( + and_(SystemVariable.name.like(f'%{variable.name}%'), SystemVariable.type != 'system')).order_by( + SystemVariable.type.desc()) + + variable_page = await paginator.get_paginated_response( + stmt=stmt, + pagination=pagination, + **filters) + + res = [] + for r in variable_page.items: + data = SystemVariable(**r) + if data.type == 'system': + data.name = trans(data.name) + res.append(data) + + return {"items": res, "page": variable_page.page, "size": variable_page.size, "total": variable_page.total, + "total_pages": variable_page.total_pages} + + +def checkName(session: SessionDep, trans: Trans, variable: SystemVariable): + if variable.id is None: + records = session.query(SystemVariable).filter(SystemVariable.name == variable.name).all() + if records and len(records) > 0: + raise HTTPException(status_code=500, detail=trans('i18n_variable.name_exist')) + else: + records = session.query(SystemVariable).filter( + and_(SystemVariable.name == variable.name, SystemVariable.id != variable.id)).all() + if records and len(records) > 0: + raise HTTPException(status_code=500, detail=trans('i18n_variable.name_exist')) + + +def checkValue(session: SessionDep, trans: Trans, values:List): + # values: [{"variableId":1,"variableValues":["a","b"]}] + + pass \ No newline at end of file diff --git a/backend/apps/system/models/system_variable_model.py b/backend/apps/system/models/system_variable_model.py new file mode 100644 index 000000000..896868984 --- /dev/null +++ b/backend/apps/system/models/system_variable_model.py @@ -0,0 +1,20 @@ +# Author: Junjun +# Date: 2026/1/26 + +from datetime import datetime +from typing import List + +from sqlalchemy import Column, BigInteger, Identity, DateTime +from sqlalchemy.dialects.postgresql import JSONB +from sqlmodel import SQLModel, Field + + +class SystemVariable(SQLModel, table=True): + __tablename__ = "system_variable" + id: int = Field(sa_column=Column(BigInteger, Identity(always=True), nullable=False, primary_key=True)) + name: str = Field(max_length=128, nullable=False) + var_type: str = Field(max_length=128, nullable=False) + type: str = Field(max_length=128, nullable=False) + value: List = Field(sa_column=Column(JSONB, nullable=True)) + create_time: datetime = Field(sa_column=Column(DateTime(timezone=False), nullable=True)) + create_by: int = Field(sa_column=Column(BigInteger())) \ No newline at end of file diff --git a/backend/apps/system/models/user.py b/backend/apps/system/models/user.py index a6ed524f6..e5ae8794e 100644 --- a/backend/apps/system/models/user.py +++ b/backend/apps/system/models/user.py @@ -1,13 +1,14 @@ +from typing import List -from typing import Optional -from sqlmodel import BigInteger, SQLModel, Field +from sqlalchemy import Column, BigInteger +from sqlalchemy.dialects.postgresql import JSONB +from sqlmodel import SQLModel, Field from common.core.models import SnowflakeBase from common.core.security import default_md5_pwd from common.utils.time import get_timestamp - class BaseUserPO(SQLModel): account: str = Field(max_length=255, unique=True) oid: int = Field(nullable=False, sa_type=BigInteger(), default=0) @@ -18,17 +19,18 @@ class BaseUserPO(SQLModel): origin: int = Field(nullable=False, default=0) create_time: int = Field(default_factory=get_timestamp, sa_type=BigInteger(), nullable=False) language: str = Field(max_length=255, default="zh-CN") - + system_variables: List = Field(sa_column=Column(JSONB, nullable=True)) + + class UserModel(SnowflakeBase, BaseUserPO, table=True): __tablename__ = "sys_user" - + class UserPlatformBase(SQLModel): uid: int = Field(nullable=False, sa_type=BigInteger()) origin: int = Field(nullable=False, default=0) platform_uid: str = Field(max_length=255, nullable=False) - + + class UserPlatformModel(SnowflakeBase, UserPlatformBase, table=True): __tablename__ = "sys_user_platform" - - diff --git a/backend/apps/system/schemas/system_schema.py b/backend/apps/system/schemas/system_schema.py index 08d0d7509..cfa3d0351 100644 --- a/backend/apps/system/schemas/system_schema.py +++ b/backend/apps/system/schemas/system_schema.py @@ -1,5 +1,5 @@ import re -from typing import Optional +from typing import Optional,List from pydantic import BaseModel, Field, field_validator @@ -58,6 +58,7 @@ class UserCreator(BaseUser): status: int = Field(default=1, description=f"{PLACEHOLDER_PREFIX}status") origin: Optional[int] = Field(default=0, description=f"{PLACEHOLDER_PREFIX}origin") oid_list: Optional[list[int]] = Field(default=None, description=f"{PLACEHOLDER_PREFIX}oid") + system_variables: Optional[List] = Field(default=None) """ @field_validator("email") def validate_email(cls, lang: str) -> str: diff --git a/backend/locales/en.json b/backend/locales/en.json index fb9e1ad8a..d7f165558 100644 --- a/backend/locales/en.json +++ b/backend/locales/en.json @@ -184,5 +184,11 @@ "update_status": "Update Status", "update_table_relation": "Change Table Relation" }, - "i18n_table_not_exist": "Table not exist" + "i18n_table_not_exist": "Table not exist", + "i18n_variable": { + "name_exist": "Name exist", + "name": "Name", + "account": "Account", + "email": "Email" + } } \ No newline at end of file diff --git a/backend/locales/ko-KR.json b/backend/locales/ko-KR.json index 4d5cdd764..9f55d385c 100644 --- a/backend/locales/ko-KR.json +++ b/backend/locales/ko-KR.json @@ -184,5 +184,11 @@ "update_status": "상태 업데이트", "update_table_relation": "테이블 관계 변경" }, - "i18n_table_not_exist": "현재 테이블이 존재하지 않습니다" + "i18n_table_not_exist": "현재 테이블이 존재하지 않습니다", + "i18n_variable": { + "name_exist": "변수 이름이 이미 존재합니다", + "name": "이름", + "account": "계정", + "email": "이메일" + } } \ No newline at end of file diff --git a/backend/locales/zh-CN.json b/backend/locales/zh-CN.json index 8fe37bcf7..16e191103 100644 --- a/backend/locales/zh-CN.json +++ b/backend/locales/zh-CN.json @@ -184,5 +184,11 @@ "update_status": "更新状态", "update_table_relation": "变更表关系" }, - "i18n_table_not_exist": "当前表不存在" + "i18n_table_not_exist": "当前表不存在", + "i18n_variable": { + "name_exist": "变量名称已存在", + "name": "姓名", + "account": "账号", + "email": "邮箱" + } } \ No newline at end of file diff --git a/frontend/src/api/variables.ts b/frontend/src/api/variables.ts new file mode 100644 index 000000000..61ac0df1e --- /dev/null +++ b/frontend/src/api/variables.ts @@ -0,0 +1,9 @@ +import { request } from '@/utils/request' + +export const variablesApi = { + save: (data: any) => request.post('/sys_variable/save', data), + listAll: () => request.post('/sys_variable/listAll', {}), + listPage: (pageNum: any, pageSize: any, data: any) => + request.post(`/sys_variable/listPage/${pageNum}/${pageSize}`, data), + delete: (data: any) => request.post(`/sys_variable/delete`, data), +} diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 16f89f718..6c803d75f 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -7,6 +7,29 @@ "AI Model Configuration": "AI Model Config", "Details": "Details" }, + "variables": { + "built_in": "Built-in", + "normal_value": "Normal value", + "​​cannot_be_empty": "Variable values ​​cannot be empty.", + "1_to_100": "{name}, the numerical range is {min} to {max}.", + "1_to_100_de": "{name}, the date range is {min} to {max}.", + "system_variables": "System Variables", + "variables": "Variables", + "system": "System", + "search_variables": "Search Variables", + "add_variable": "Add Variable", + "variable_name": "Variable Name", + "variable_type": "Variable Type", + "variable_value": "Variable Value", + "edit_variable": "Edit Variable", + "no_variables_yet": "No Variables Yet", + "please_enter_value": "Please Enter Value", + "date": "Date", + "start_date": "Start Date", + "end_date": "End Date", + "enter_variable_name": "Please Enter Variable Name", + "enter_variable_value": "Please Enter Variable Value" + }, "parameter": { "export_notes": "Export notes", "import_notes": "Import notes", @@ -868,4 +891,4 @@ "to_doc": "View API", "trigger_limit": "Supports up to {0} API Keys" } -} +} \ No newline at end of file diff --git a/frontend/src/i18n/ko-KR.json b/frontend/src/i18n/ko-KR.json index 2dae6eacf..d542eb9d1 100644 --- a/frontend/src/i18n/ko-KR.json +++ b/frontend/src/i18n/ko-KR.json @@ -7,6 +7,29 @@ "AI Model Configuration": "모델 구성", "Details": "세부" }, + "variables": { + "built_in": "내장형", + "normal_value": "정상값", + "​​cannot_be_empty": "변수 값은 비어 있을 수 없습니다.", + "1_to_100": "{name}, 숫자 범위는 {min}부터 {max}까지입니다.", + "1_to_100_de": "{name}, 날짜 범위는 {min}부터 {max}까지입니다.", + "system_variables": "시스템 변수", + "variables": "변수", + "system": "체계", + "search_variables": "변수 검색", + "add_variable": "변수 추가", + "variable_name": "변수 이름", + "variable_type": "변수 유형", + "variable_value": "변수 값", + "edit_variable": "변수 편집", + "no_variables_yet": "아직 변수가 없습니다", + "please_enter_value": "값을 입력하세요", + "date": "날짜", + "start_date": "시작일", + "end_date": "종료일", + "enter_variable_name": "변수 이름을 입력하세요", + "enter_variable_value": "변수 값을 입력하세요" + }, "parameter": { "export_notes": "수출 참고사항", "import_notes": "수입 참고사항", @@ -868,4 +891,4 @@ "to_doc": "API 보기", "trigger_limit": "최대 {0}개의 API 키 생성 지원" } -} +} \ No newline at end of file diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json index 5996ee944..60186da09 100644 --- a/frontend/src/i18n/zh-CN.json +++ b/frontend/src/i18n/zh-CN.json @@ -7,6 +7,29 @@ "AI Model Configuration": "模型配置", "Details": "详情" }, + "variables": { + "built_in": "已内置", + "normal_value": "常规值", + "​​cannot_be_empty": "变量值不能为空", + "1_to_100": "{name}数值范围 {min}~{max}", + "1_to_100_de": "{name}日期范围 {min}~{max}", + "system_variables": "系统变量", + "variables": "变量", + "system": "系统", + "search_variables": "搜索变量", + "add_variable": "添加变量", + "variable_name": "变量名称", + "variable_type": "变量类型", + "variable_value": "变量值", + "edit_variable": "编辑变量", + "no_variables_yet": "暂无变量", + "please_enter_value": "请输入数值", + "date": "日期", + "start_date": "开始日期", + "end_date": "结束日期", + "enter_variable_name": "请输入变量名称", + "enter_variable_value": "请输入变量值" + }, "parameter": { "export_notes": "导出备注", "import_notes": "导入备注", @@ -868,4 +891,4 @@ "to_doc": "查看 API", "trigger_limit": "最多支持创建 {0} 个 API Key" } -} +} \ No newline at end of file diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index f7b8d38d5..b1c266752 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -12,6 +12,7 @@ import Model from '@/views/system/model/Model.vue' // import Embedded from '@/views/system/embedded/index.vue' // import SetAssistant from '@/views/system/embedded/iframe.vue' import SystemEmbedded from '@/views/system/embedded/Page.vue' +import Variables from '@/views/system/variables/index.vue' import assistantTest from '@/views/system/embedded/Test.vue' import assistant from '@/views/embedded/index.vue' @@ -219,6 +220,12 @@ export const routes = [ component: Parameter, meta: { title: t('parameter.parameter_configuration') }, }, + { + path: 'variables', + name: 'variables', + component: Variables, + meta: { title: t('variables.system_variables') }, + }, { path: 'authentication', name: 'authentication', diff --git a/frontend/src/views/chat/QuickQuestion.vue b/frontend/src/views/chat/QuickQuestion.vue index 140354a03..c4e42d2e6 100644 --- a/frontend/src/views/chat/QuickQuestion.vue +++ b/frontend/src/views/chat/QuickQuestion.vue @@ -149,7 +149,7 @@ const props = withDefaults( cursor: pointer; margin-left: 8px; &:hover { - color: #189e7a; + color: var(--ed-color-primary-15-d, #189e7a); background: #1f23291a; } } diff --git a/frontend/src/views/system/permission/auth-tree/AuthTree.vue b/frontend/src/views/system/permission/auth-tree/AuthTree.vue index f27d8c200..9fd2ddfa5 100644 --- a/frontend/src/views/system/permission/auth-tree/AuthTree.vue +++ b/frontend/src/views/system/permission/auth-tree/AuthTree.vue @@ -71,6 +71,8 @@ const add = (type: any, child: any, logic: any) => { term: '', filter_type: 'logic', name: '', + value_type: 'normal', + variable_id: undefined, } : { child: [], logic } ) diff --git a/frontend/src/views/system/permission/auth-tree/FilterFiled.vue b/frontend/src/views/system/permission/auth-tree/FilterFiled.vue index c10686775..1b335eb89 100644 --- a/frontend/src/views/system/permission/auth-tree/FilterFiled.vue +++ b/frontend/src/views/system/permission/auth-tree/FilterFiled.vue @@ -1,6 +1,7 @@ + + + + +