Files
time-tracking-system/templates/projects.html
bf1942 8938ce2708 refactor(api): 重构数据库访问为SQLAlchemy绑定的session
- 统一移除手动创建的数据库session,统一使用models模块中的db.session
- 修正项目创建接口,增加开始和结束日期的格式验证与处理
- 更新导入项目接口,使用枚举类型校验项目类型并优化异常处理
- 更新统计接口,避免多次查询假期数据,优化日期字符串处理
- 删除回滚前多余的session关闭调用,改为使用db.session.rollback()
- app.py中重构数据库初始化:统一配置SQLAlchemy,动态创建数据库路径和表
- 项目模型新增开始日期和结束日期字段支持
- 添加导入批次历史记录模型支持
- 优化工具函数中日期类型提示,移除无用导入
- 更新requirements.txt依赖版本回退,确保兼容性
- 前端菜单添加导入历史导航入口,实现页面访问路由绑定
2025-09-04 18:12:24 +08:00

224 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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')">&times;</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')">&times;</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')">&times;</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>