refactor(api): 重构数据库访问为SQLAlchemy绑定的session
- 统一移除手动创建的数据库session,统一使用models模块中的db.session - 修正项目创建接口,增加开始和结束日期的格式验证与处理 - 更新导入项目接口,使用枚举类型校验项目类型并优化异常处理 - 更新统计接口,避免多次查询假期数据,优化日期字符串处理 - 删除回滚前多余的session关闭调用,改为使用db.session.rollback() - app.py中重构数据库初始化:统一配置SQLAlchemy,动态创建数据库路径和表 - 项目模型新增开始日期和结束日期字段支持 - 添加导入批次历史记录模型支持 - 优化工具函数中日期类型提示,移除无用导入 - 更新requirements.txt依赖版本回退,确保兼容性 - 前端菜单添加导入历史导航入口,实现页面访问路由绑定
This commit is contained in:
224
templates/projects.html
Normal file
224
templates/projects.html
Normal file
@@ -0,0 +1,224 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>项目管理 - 个人工时记录系统</title>
|
||||
<link rel="stylesheet" href="/static/css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="nav-container">
|
||||
<div class="nav-brand">
|
||||
<h1>个人工时记录系统</h1>
|
||||
</div>
|
||||
<ul class="nav-menu">
|
||||
<li><a href="/" class="nav-link">首页</a></li>
|
||||
<li><a href="/projects" class="nav-link active">项目管理</a></li>
|
||||
<li><a href="/timerecords" class="nav-link">工时记录</a></li>
|
||||
<li><a href="/statistics" class="nav-link">统计分析</a></li>
|
||||
<li><a href="/import" class="nav-link">导入历史</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="main-content">
|
||||
<div class="container">
|
||||
<div class="page-header">
|
||||
<h2>项目管理</h2>
|
||||
<div class="page-actions">
|
||||
<button class="btn btn-primary" onclick="showCreateProjectModal()">新建项目</button>
|
||||
<button class="btn btn-secondary" onclick="showImportModal()">导入项目</button>
|
||||
<select id="project-type-filter" class="form-control" onchange="filterProjects()">
|
||||
<option value="">全部项目类型</option>
|
||||
<option value="traditional">传统项目</option>
|
||||
<option value="psi">PSI项目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目统计 -->
|
||||
<div class="stats-row">
|
||||
<div class="stat-card">
|
||||
<div class="stat-value" id="total-projects-count">0</div>
|
||||
<div class="stat-label">总项目数</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-value" id="traditional-projects-count">0</div>
|
||||
<div class="stat-label">传统项目</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-value" id="psi-projects-count">0</div>
|
||||
<div class="stat-label">PSI项目</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目列表表格 -->
|
||||
<div class="table-container">
|
||||
<table class="data-table" id="projects-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>项目名称</th>
|
||||
<th>项目类型</th>
|
||||
<th>客户名</th>
|
||||
<th>标识码</th>
|
||||
<th>状态</th>
|
||||
<th>项目开始时间</th>
|
||||
<th>创建时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="projects-tbody">
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">加载中...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 新建项目模态框 -->
|
||||
<div id="create-project-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 id="modal-title">新建项目</h3>
|
||||
<button class="close-btn" onclick="closeModal('create-project-modal')">×</button>
|
||||
</div>
|
||||
<form id="project-form">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="project_name">项目名称 *</label>
|
||||
<input type="text" id="project_name" name="project_name" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="customer_name">客户名 *</label>
|
||||
<input type="text" id="customer_name" name="customer_name" class="form-control"
|
||||
placeholder="如:NexChip" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="project_type">项目类型 *</label>
|
||||
<select id="project_type" name="project_type" class="form-control"
|
||||
onchange="toggleProjectFields()" required>
|
||||
<option value="">请选择项目类型</option>
|
||||
<option value="traditional">传统项目</option>
|
||||
<option value="psi">PSI项目</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 传统项目字段 -->
|
||||
<div id="traditional-fields" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label for="project_code">项目代码 *</label>
|
||||
<input type="text" id="project_code" name="project_code"
|
||||
class="form-control" placeholder="如:02C-FBV">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PSI项目字段 -->
|
||||
<div id="psi-fields" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label for="contract_number">合同号 *</label>
|
||||
<input type="text" id="contract_number" name="contract_number"
|
||||
class="form-control" placeholder="如:ID00462761">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>项目代码</label>
|
||||
<input type="text" value="PSI-PROJ" class="form-control" readonly disabled>
|
||||
<small class="form-text">PSI项目统一使用代码 PSI-PROJ</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">描述</label>
|
||||
<textarea id="description" name="description" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="start_date">项目开始时间</label>
|
||||
<input type="date" id="start_date" name="start_date" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="end_date">项目结束时间</label>
|
||||
<input type="date" id="end_date" name="end_date" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal('create-project-modal')">取消</button>
|
||||
<button type="submit" class="btn btn-primary">保存</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 导入项目模态框 -->
|
||||
<div id="import-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>导入项目</h3>
|
||||
<button class="close-btn" onclick="closeModal('import-modal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="import-instructions">
|
||||
<h4>CSV文件格式要求:</h4>
|
||||
<p>请确保CSV文件包含以下列(按顺序):</p>
|
||||
<ul>
|
||||
<li><strong>项目名称</strong> - 必填</li>
|
||||
<li><strong>项目类型</strong> - 必填(traditional 或 psi)</li>
|
||||
<li><strong>客户名</strong> - 必填</li>
|
||||
<li><strong>项目代码</strong> - 传统项目必填,PSI项目可忽略</li>
|
||||
<li><strong>合同号</strong> - PSI项目必填,传统项目可为空</li>
|
||||
<li><strong>描述</strong> - 可选</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="import-file">选择CSV文件</label>
|
||||
<input type="file" id="import-file" accept=".csv" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="sample-templates">
|
||||
<h4>示例模板:</h4>
|
||||
<div class="template-buttons">
|
||||
<button type="button" class="btn btn-outline" onclick="downloadTemplate('traditional')">
|
||||
下载传统项目模板
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline" onclick="downloadTemplate('psi')">
|
||||
下载PSI项目模板
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline" onclick="downloadTemplate('mixed')">
|
||||
下载混合项目模板
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal('import-modal')">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="importProjects()">导入</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 导入结果模态框 -->
|
||||
<div id="import-result-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>导入结果</h3>
|
||||
<button class="close-btn" onclick="closeModal('import-result-modal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="import-result-content"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" onclick="closeModal('import-result-modal')">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/common.js"></script>
|
||||
<script src="/static/js/projects.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user