someone-oa/pc/project-start.html
2025-12-11 19:04:46 +08:00

460 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>项目启动 - OA系统</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 统一布局样式 -->
<link rel="stylesheet" href="unified-layout.css">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
background: #f0f2f5;
overflow: hidden;
}
.layout-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.navbar {
height: 50px;
background: #fff;
border-bottom: 1px solid #e6e6e6;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
}
.navbar-left {
display: flex;
align-items: center;
}
.logo {
font-size: 20px;
font-weight: bold;
color: #409EFF;
}
.nav-menu { display: flex; gap: 8px; }
.nav-item { padding: 8px 16px; cursor: pointer; border-radius: 4px; }
.nav-item:hover {
background: #ecf5ff;
color: #409EFF;
}
 background: #409EFF; }
.navbar-right {
display: flex;
align-items: center;
gap: 20px;
}
.main-container {
flex: 1;
display: flex;
overflow: hidden;
}
.app-main {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
background: #f0f2f5;
}
.sidebar {
width: 210px;
background: #fff;
border-right: 1px solid #e6e6e6;
overflow-y: auto;
}
.el-menu {
border-right: none;
}
.menu-item { padding: 12px 24px; cursor: pointer; }
.menu-item.active {
background: #409EFF;
color: #fff;
}
.content {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #fff;
margin: 10px;
border-radius: 4px;
}
.page-header { margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid #f0f0f0; }
.page-title { font-size: 20px; font-weight: 500; }
.form-card { background: white; border-radius: 4px; padding: 24px; }
.form-section { margin-bottom: 24px; }
.form-section-title { font-size: 16px; font-weight: 500; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
.form-row { display: flex; gap: 16px; margin-bottom: 16px; }
.form-item { flex: 1; }
.form-label { display: block; margin-bottom: 8px; color: #333; font-size: 14px; }
.form-label .required { color: #ff4d4f; }
.form-input, .form-select { width: 100%; padding: 8px 12px; border: 1px solid #d9d9d9; border-radius: 4px; }
.staff-table { width: 100%; border-collapse: collapse; margin-top: 16px; }
.staff-table th, .staff-table td { padding: 12px; text-align: left; border: 1px solid #f0f0f0; }
.staff-table th { background: #fafafa; }
.btn { padding: 8px 24px; border: none; border-radius: 4px; cursor: pointer; }
.btn-primary { background: #409EFF; color: white; }
.btn-default { background: white; color: #333; border: 1px solid #d9d9d9; }
.form-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 24px; padding-top: 24px; border-top: 1px solid #f0f0f0; }
.fee-calculation { background: #f5f7fa; padding: 16px; border-radius: 4px; margin-top: 16px; }
.fee-formula { font-size: 12px; color: #666; margin-top: 8px; }
.formula-note { background: #fff7e6; padding: 12px; border-radius: 4px; margin-top: 16px; font-size: 12px; color: #d46b08; }
.formula-note-title { font-weight: 500; margin-bottom: 8px; }
</style>
<!-- Vue.js -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- Element UI JS -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<div class="layout-container">
<div class="navbar">
<div class="navbar-left">
<div class="logo">OA系统</div>
<div class="nav-menu">
<div class="nav-item" onclick="window.location.href='project-initiation.html'">商机管理</div>
<div class="nav-item active">过程管理</div>
<div class="nav-item" onclick="window.location.href='finance-invoice.html'">财务管理</div>
<div class="nav-item" onclick="window.location.href='report-project-detail.html'">报表管理</div>
</div>
</div>
<div class="navbar-right">
<span style="color: #303133;">张三</span><span style="color: #909399; margin: 0 8px;">|</span>
<a href="profile.html" style="color: #409EFF; text-decoration: none;">个人中心</a>
<span>|</span>
<a href="login.html" style="color: #409EFF; text-decoration: none;">退出</a>
</div>
</div>
<div class="main-container">
<div class="sidebar">
<div class="menu-item active">启动申请</div>
<div class="menu-item" onclick="window.location.href='output-submit.html'">成果提交</div>
<div class="menu-item" onclick="window.location.href='progress-query.html'">进度查询</div>
</div>
<div class="content">
<div class="page-header">
<div class="page-title">项目启动申请</div>
</div>
<div class="form-card">
<form id="startForm">
<div class="form-section">
<div class="form-section-title">关联项目</div>
<div class="form-row">
<div class="form-item">
<label class="form-label">
<span class="required">*</span>关联立项项目
</label>
<select id="projectSelect" class="form-select" required onchange="onProjectChange()">
<option value="">请选择项目</option>
<option value="25-1" data-type="工程咨询" data-count="0">25-1 - XX工程项目工程咨询</option>
<option value="25-2" data-type="跟踪审计" data-count="1">25-2 - YY工程项目跟踪审计</option>
<option value="25-3" data-type="结算审计、概算编制及审核、清单控制价编制及审核" data-count="0">25-3 - ZZ工程项目结算审计</option>
</select>
</div>
<div class="form-item">
<label class="form-label">启动编号</label>
<input type="text" id="startNumber" class="form-input" value="" readonly placeholder="选择项目后自动生成">
<div style="font-size: 12px; color: #999; margin-top: 4px;">规则:立项编号+项目类型数字+启动序号</div>
</div>
</div>
</div>
<div class="form-section">
<div class="form-section-title">费用计算</div>
<div class="fee-calculation">
<div class="form-row">
<div class="form-item">
<label class="form-label">基础金额(元)</label>
<input type="number" id="baseAmount" class="form-input" placeholder="根据文件计算的基础金额" oninput="calculateFee()">
</div>
<div class="form-item">
<label class="form-label">折扣率</label>
<input type="number" id="discountRate" class="form-input" placeholder="0-1之间的小数" min="0" max="1" step="0.01" value="1" oninput="calculateFee()">
</div>
</div>
<div id="adjustmentFactors" style="display: none;">
<div class="form-row">
<div class="form-item">
<label class="form-label">专业调整系数</label>
<input type="number" id="professionalFactor" class="form-input" placeholder="专业调整系数" min="0" step="0.01" value="1" oninput="calculateFee()">
</div>
<div class="form-item">
<label class="form-label">工程复杂程度调整系数</label>
<input type="number" id="complexityFactor" class="form-input" placeholder="工程复杂程度调整系数" min="0" step="0.01" value="1" oninput="calculateFee()">
</div>
<div class="form-item">
<label class="form-label">高程调整系数</label>
<input type="number" id="elevationFactor" class="form-input" placeholder="高程调整系数" min="0" step="0.01" value="1" oninput="calculateFee()">
</div>
</div>
</div>
<div class="form-row">
<div class="form-item">
<label class="form-label">最终费用(元)</label>
<input type="text" id="finalFee" class="form-input" value="0" readonly style="background: #f5f5f5; font-weight: 500; color: #409EFF; font-size: 16px;">
</div>
</div>
<div id="formulaNote" class="formula-note" style="display: none;">
<div class="formula-note-title">计算公式说明:</div>
<div id="formulaText"></div>
</div>
</div>
</div>
<div class="form-section">
<div class="form-section-title">人员分工</div>
<table class="staff-table">
<thead>
<tr>
<th>执业工程师</th>
<th>工作内容</th>
<th>操作</th>
</tr>
</thead>
<tbody id="staffTableBody">
<tr>
<td>
<select class="form-select">
<option>张三</option>
<option>李四</option>
<option>王五</option>
</select>
</td>
<td>
<select id="workContent0" class="form-select work-content-select" multiple style="height: 60px;">
<option>请先选择关联项目</option>
</select>
</td>
<td>
<button type="button" class="btn btn-default" onclick="removeStaff(this)">删除</button>
</td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-default" onclick="addStaff()" style="margin-top: 12px;">+ 添加人员</button>
</div>
<div class="form-actions">
<button type="button" class="btn btn-default" onclick="resetForm()">重置</button>
<button type="submit" class="btn btn-primary">提交审核</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="common.js"></script>
<script src="unified-layout.js"></script>
<script>
initUnifiedLayout('process');
// 项目类型数字映射
const projectTypeMap = {
'结算审计、概算编制及审核、清单控制价编制及审核': '1',
'工程咨询': '2',
'跟踪审计': '3',
'项目管理': '4',
'工程监理': '5'
};
// 工作内容映射
const workContentMap = {
'结算审计、概算编制及审核、清单控制价编制及审核': ['计量', '计价', '对账', '出报告'],
'工程咨询': ['文本', '估算', '出报告'],
'跟踪审计': ['现场跟踪', '进度款审核'],
'项目管理': ['项目协助甲方报批报建', '项目实施过程中管控'],
'工程监理': ['现场跟踪', '进度审核']
};
// 计算公式说明
const formulaMap = {
'工程咨询': '依据鄂价房字[2001]107号文计算 × 折扣率',
'工程造价': '依据鄂价工服规[2012]149号文计算 × 折扣率',
'工程监理': '依据发改价格[2007]670号文计算 × 专业调整系数 × 工程复杂程度调整系数 × 高程调整系数 × 折扣率',
'工程设计': '依据计价格[2002]10号文计算 × 折扣率',
'工程代建': '依据财建[2016]504号文计算 × 折扣率',
'招标代理': '依据鄂建文202335号文计算 × 折扣率'
};
// 项目选择变化事件
function onProjectChange() {
const select = document.getElementById('projectSelect');
const selectedOption = select.options[select.selectedIndex];
if (!selectedOption.value) {
document.getElementById('startNumber').value = '';
updateWorkContentOptions(null);
return;
}
const projectNumber = selectedOption.value;
const serviceType = selectedOption.getAttribute('data-type');
const startCount = parseInt(selectedOption.getAttribute('data-count') || '0');
// 生成启动编号
const typeNum = projectTypeMap[serviceType] || '0';
const nextStartNum = startCount + 1;
const startNumber = `${projectNumber}-${typeNum}-${nextStartNum}`;
document.getElementById('startNumber').value = startNumber;
// 更新工作内容选项
updateWorkContentOptions(serviceType);
// 更新费用计算公式
updateFeeFormula(serviceType);
}
// 更新工作内容选项
function updateWorkContentOptions(serviceType) {
const workContentSelects = document.querySelectorAll('.work-content-select');
const options = serviceType ? workContentMap[serviceType] : [];
workContentSelects.forEach(select => {
select.innerHTML = '';
if (options.length > 0) {
options.forEach(option => {
const opt = document.createElement('option');
opt.value = option;
opt.textContent = option;
select.appendChild(opt);
});
} else {
const opt = document.createElement('option');
opt.textContent = '请先选择关联项目';
select.appendChild(opt);
}
});
}
// 更新费用计算公式
function updateFeeFormula(serviceType) {
const formulaNote = document.getElementById('formulaNote');
const formulaText = document.getElementById('formulaText');
const adjustmentFactors = document.getElementById('adjustmentFactors');
if (serviceType === '工程监理') {
adjustmentFactors.style.display = 'block';
formulaText.textContent = formulaMap['工程监理'] || '';
} else {
adjustmentFactors.style.display = 'none';
// 根据服务类型匹配公式
let formula = '';
if (serviceType === '工程咨询') {
formula = formulaMap['工程咨询'];
} else if (serviceType.includes('结算') || serviceType.includes('概算') || serviceType.includes('清单')) {
formula = formulaMap['工程造价'];
} else {
formula = '请选择服务类型查看计算公式';
}
formulaText.textContent = formula;
}
if (formulaText.textContent) {
formulaNote.style.display = 'block';
} else {
formulaNote.style.display = 'none';
}
// 重新计算费用
calculateFee();
}
// 计算费用
function calculateFee() {
const baseAmount = parseFloat(document.getElementById('baseAmount').value) || 0;
const discountRate = parseFloat(document.getElementById('discountRate').value) || 1;
const select = document.getElementById('projectSelect');
const selectedOption = select.options[select.selectedIndex];
const serviceType = selectedOption ? selectedOption.getAttribute('data-type') : '';
let finalFee = 0;
if (baseAmount > 0) {
if (serviceType === '工程监理') {
const professionalFactor = parseFloat(document.getElementById('professionalFactor').value) || 1;
const complexityFactor = parseFloat(document.getElementById('complexityFactor').value) || 1;
const elevationFactor = parseFloat(document.getElementById('elevationFactor').value) || 1;
finalFee = baseAmount * professionalFactor * complexityFactor * elevationFactor * discountRate;
} else {
finalFee = baseAmount * discountRate;
}
}
document.getElementById('finalFee').value = finalFee.toLocaleString('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
// 添加人员
let staffCount = 1;
function addStaff() {
const tbody = document.getElementById('staffTableBody');
const row = document.createElement('tr');
const select = document.getElementById('projectSelect');
const selectedOption = select.options[select.selectedIndex];
const serviceType = selectedOption ? selectedOption.getAttribute('data-type') : '';
const options = serviceType ? workContentMap[serviceType] : [];
let workContentOptions = '';
if (options.length > 0) {
options.forEach(option => {
workContentOptions += `<option value="${option}">${option}</option>`;
});
} else {
workContentOptions = '<option>请先选择关联项目</option>';
}
row.innerHTML = `
<td>
<select class="form-select">
<option>张三</option>
<option>李四</option>
<option>王五</option>
</select>
</td>
<td>
<select id="workContent${staffCount}" class="form-select work-content-select" multiple style="height: 60px;">
${workContentOptions}
</select>
</td>
<td>
<button type="button" class="btn btn-default" onclick="removeStaff(this)">删除</button>
</td>
`;
tbody.appendChild(row);
staffCount++;
}
function removeStaff(btn) {
btn.closest('tr').remove();
}
function resetForm() {
CommonUtils.confirm('确认重置表单?', () => {
document.getElementById('startForm').reset();
document.getElementById('startNumber').value = '';
document.getElementById('finalFee').value = '0';
document.getElementById('formulaNote').style.display = 'none';
document.getElementById('adjustmentFactors').style.display = 'none';
updateWorkContentOptions(null);
});
}
document.getElementById('startForm').addEventListener('submit', function(e) {
e.preventDefault();
CommonUtils.confirm('确认提交启动申请?', () => {
CommonUtils.showMessage('提交成功!等待审核');
setTimeout(() => window.location.href = 'progress-query.html', 1000);
});
});
// initUnifiedLayout('process'); // 已在上面调用
</script>
</div>
</body>
</html>