add backend source code

This commit is contained in:
2026-02-28 15:06:52 +08:00
parent 1bc330e20c
commit 2c37aa9064
67 changed files with 11654 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
"""添加指标模板表
Revision ID: 002_template
Revises: initial
Create Date: 2024-01-02 00:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = '002_template'
down_revision: Union[str, None] = 'initial'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# 创建指标模板表
op.create_table(
'indicator_templates',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('template_name', sa.String(length=200), nullable=False, comment='模板名称'),
sa.Column('template_code', sa.String(length=50), nullable=False, comment='模板编码'),
sa.Column('template_type', sa.String(length=30), nullable=False, comment='模板类型'),
sa.Column('description', sa.Text(), nullable=True, comment='模板描述'),
sa.Column('dimension_weights', sa.Text(), nullable=True, comment='维度权重 (JSON)'),
sa.Column('assessment_cycle', sa.String(length=20), nullable=True, comment='考核周期'),
sa.Column('is_active', sa.Boolean(), nullable=True, comment='是否启用'),
sa.Column('created_at', sa.DateTime(), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), nullable=True, comment='更新时间'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('template_code')
)
op.create_index('idx_template_type', 'indicator_templates', ['template_type'])
op.create_index('idx_template_active', 'indicator_templates', ['is_active'])
# 创建模板指标关联表
op.create_table(
'template_indicators',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('template_id', sa.Integer(), nullable=False, comment='模板 ID'),
sa.Column('indicator_id', sa.Integer(), nullable=False, comment='指标 ID'),
sa.Column('category', sa.String(length=100), nullable=True, comment='指标分类'),
sa.Column('target_value', sa.Numeric(precision=10, scale=2), nullable=True, comment='目标值'),
sa.Column('target_unit', sa.String(length=50), nullable=True, comment='目标值单位'),
sa.Column('weight', sa.Numeric(precision=5, scale=2), nullable=True, comment='权重'),
sa.Column('scoring_method', sa.String(length=50), nullable=True, comment='评分方法'),
sa.Column('scoring_params', sa.Text(), nullable=True, comment='评分参数 (JSON)'),
sa.Column('sort_order', sa.Integer(), nullable=True, comment='排序'),
sa.Column('remark', sa.Text(), nullable=True, comment='备注'),
sa.Column('created_at', sa.DateTime(), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['template_id'], ['indicator_templates.id']),
sa.ForeignKeyConstraint(['indicator_id'], ['indicators.id']),
sa.PrimaryKeyConstraint('id')
)
op.create_index('idx_ti_template', 'template_indicators', ['template_id'])
op.create_index('idx_ti_indicator', 'template_indicators', ['indicator_id'])
op.create_index('idx_ti_unique', 'template_indicators', ['template_id', 'indicator_id'], unique=True)
# 为指标表添加 BSC 维度字段(如果不存在)
# 注意:在 PostgreSQL 中,如果字段已存在会报错,需要检查
conn = op.get_bind()
inspector = sa.inspect(conn)
columns = [col['name'] for col in inspector.get_columns('indicators')]
if 'bs_dimension' not in columns:
op.add_column('indicators', sa.Column('bs_dimension', sa.String(length=30), nullable=True, comment='平衡计分卡维度'))
if 'target_unit' not in columns:
op.add_column('indicators', sa.Column('target_unit', sa.String(length=50), nullable=True, comment='目标值单位'))
if 'assessment_method' not in columns:
op.add_column('indicators', sa.Column('assessment_method', sa.Text(), nullable=True, comment='考核方法'))
if 'deduction_standard' not in columns:
op.add_column('indicators', sa.Column('deduction_standard', sa.Text(), nullable=True, comment='扣分标准'))
if 'data_source' not in columns:
op.add_column('indicators', sa.Column('data_source', sa.String(length=100), nullable=True, comment='数据来源'))
if 'applicable_dept_types' not in columns:
op.add_column('indicators', sa.Column('applicable_dept_types', sa.Text(), nullable=True, comment='适用科室类型'))
if 'is_veto' not in columns:
op.add_column('indicators', sa.Column('is_veto', sa.Boolean(), nullable=True, default=False, comment='是否一票否决指标'))
def downgrade() -> None:
op.drop_table('template_indicators')
op.drop_table('indicator_templates')