Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c33bc05f2 | ||
|
|
153835b184 | ||
|
|
9de0a63be2 | ||
|
|
2f759b42cd | ||
|
|
f3c94c57d6 | ||
|
|
9db627770b | ||
|
|
75b988c77a | ||
|
|
2b7f67436e | ||
|
|
ed5455f309 | ||
|
|
452d410843 | ||
|
|
c95373b85e | ||
|
|
6be10481d5 | ||
|
|
4ce0e66d90 | ||
|
|
0f9e1b6cf2 | ||
|
|
dc8d3d59d2 | ||
|
|
1e5c5b5706 | ||
|
|
b68144ebb0 | ||
|
|
3cae1d85cf | ||
|
|
ca0cd9eab1 | ||
|
|
2bdc0e0779 | ||
|
|
93dca56c3f | ||
|
|
8c4f50fc52 | ||
|
|
13864f1968 | ||
|
|
d11e8f9313 | ||
|
|
02a12a208c | ||
|
|
b977627895 | ||
|
|
edf8e6179c | ||
|
|
3148af05b3 | ||
|
|
4029933ada | ||
|
|
95d3f9809c | ||
|
|
8b040489e2 | ||
|
|
db9700c8ee | ||
|
|
11e30f33b9 | ||
|
|
95f52b61d0 | ||
|
|
a4012f2189 | ||
|
|
e1c5e65c1e | ||
|
|
a3d78b3ca0 | ||
|
|
9dc5631574 | ||
|
|
c5a59508d2 | ||
|
|
ab1d57492c | ||
|
|
9a81a30feb | ||
|
|
d6d21b03dd | ||
|
|
b9a05e8732 | ||
|
|
440707e19a | ||
|
|
e0dc1a56b2 | ||
|
|
f45afd954d | ||
|
|
664da22329 | ||
|
|
73a6ac126c | ||
|
|
878e26d4ca | ||
|
|
e12ed0936b | ||
|
|
8edb74f173 | ||
|
|
1a42c6e6f3 | ||
|
|
d21497bce3 | ||
|
|
574e3c5700 | ||
|
|
c70293b447 | ||
|
|
adeff08827 | ||
|
|
8bd40de41d | ||
|
|
ac6eacea82 | ||
|
|
83c2a5ca94 | ||
|
|
fbd2290d29 | ||
|
|
97fcf88c61 | ||
|
|
a01afef599 | ||
|
|
28fa244fe5 | ||
|
|
ad3885e0be | ||
|
|
0fb7ee2992 | ||
|
|
f6792cad39 | ||
|
|
bed6e9192a | ||
|
|
aaa213a765 | ||
|
|
207629a9bb |
@@ -53,3 +53,4 @@ curl http://127.0.0.1:5177/api/health
|
|||||||
- 产品:慰心斋产品路线图中的 5 个产品版本
|
- 产品:慰心斋产品路线图中的 5 个产品版本
|
||||||
- 财务:首版财务样例和原财务 manager 合并方向
|
- 财务:首版财务样例和原财务 manager 合并方向
|
||||||
|
|
||||||
|
# test trigger
|
||||||
|
|||||||
@@ -718,7 +718,7 @@ window.planEditSignMonth = (event, pfId) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.switchPlanTab = (tab) => {
|
window.switchPlanTab = (tab) => {
|
||||||
document.querySelectorAll(".plan-tab").forEach(b => b.classList.toggle("active", b.dataset.tab === tab));
|
document.querySelectorAll("#planModal .finance-tab").forEach(b => b.classList.toggle("active", b.dataset.tab === tab));
|
||||||
document.querySelector("#plan_financeTabInfo").classList.toggle("hidden", tab !== "info");
|
document.querySelector("#plan_financeTabInfo").classList.toggle("hidden", tab !== "info");
|
||||||
document.querySelector("#plan_financeTabRevpay").classList.toggle("hidden", tab !== "revpay");
|
document.querySelector("#plan_financeTabRevpay").classList.toggle("hidden", tab !== "revpay");
|
||||||
document.querySelector("#plan_financeTabCost").classList.toggle("hidden", tab !== "cost");
|
document.querySelector("#plan_financeTabCost").classList.toggle("hidden", tab !== "cost");
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ function renderPlanExpense() {
|
|||||||
|
|
||||||
var modal = '<div id="planExpenseModal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40" onclick="closePlanExpModal()"><div class="bg-white rounded-2xl shadow-2xl w-full max-w-lg mx-4" onclick="event.stopPropagation()"><div class="sticky top-0 z-10 bg-white/95 backdrop-blur border-b border-slate-100 px-6 py-4 flex items-center justify-between"><h3 class="text-lg font-bold text-slate-800" id="planExpenseModalTitle">新增费用</h3><div class="flex items-center gap-2"><button class="btn btn-ghost btn-sm text-red-600 hidden" id="planExpDeleteBtn" onclick="deletePlanExpItem()">删除</button><button class="btn btn-ghost btn-sm rounded-full w-8 h-8 p-0" onclick="closePlanExpModal()"><i data-lucide="x"></i></button></div></div><form onsubmit="savePlanExpense(event)" class="p-6 grid gap-4" novalidate><input type="hidden" name="expense_id" value=""><div class="grid grid-cols-2 gap-3"><label class="block"><span class="text-sm text-slate-500 mb-1 block">费用类型 <span class="text-red-500">*</span></span><select name="expense_type" required class="form-ctrl bg-white"><option value="">请选择</option>';
|
var modal = '<div id="planExpenseModal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40" onclick="closePlanExpModal()"><div class="bg-white rounded-2xl shadow-2xl w-full max-w-lg mx-4" onclick="event.stopPropagation()"><div class="sticky top-0 z-10 bg-white/95 backdrop-blur border-b border-slate-100 px-6 py-4 flex items-center justify-between"><h3 class="text-lg font-bold text-slate-800" id="planExpenseModalTitle">新增费用</h3><div class="flex items-center gap-2"><button class="btn btn-ghost btn-sm text-red-600 hidden" id="planExpDeleteBtn" onclick="deletePlanExpItem()">删除</button><button class="btn btn-ghost btn-sm rounded-full w-8 h-8 p-0" onclick="closePlanExpModal()"><i data-lucide="x"></i></button></div></div><form onsubmit="savePlanExpense(event)" class="p-6 grid gap-4" novalidate><input type="hidden" name="expense_id" value=""><div class="grid grid-cols-2 gap-3"><label class="block"><span class="text-sm text-slate-500 mb-1 block">费用类型 <span class="text-red-500">*</span></span><select name="expense_type" required class="form-ctrl bg-white"><option value="">请选择</option>';
|
||||||
EXPENSE_TYPES.forEach(function(t) { modal += '<option>' + t + '</option>'; });
|
EXPENSE_TYPES.forEach(function(t) { modal += '<option>' + t + '</option>'; });
|
||||||
modal += '</select></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">月份 <span class="text-red-500">*</span></span><select name="expense_month" required class="form-ctrl bg-white">' + modalMonthOpts + '</select></label></div><div class="grid grid-cols-2 gap-3"><label class="block"><span class="text-sm text-slate-500 mb-1 block">金额(元)</span><input name="amount" type="number" step="0.01" class="form-ctrl" placeholder="0.00"></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">已发生金额(元)</span><input name="incurred_amount" type="number" step="0.01" class="form-ctrl" placeholder="0.00"></label></div><label class="block"><span class="text-sm text-slate-500 mb-1 block">状态</span><select name="status" class="form-ctrl bg-white">' + statusOpts + '</select></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">费用说明</span><textarea name="notes" class="form-ctrl" rows="3" placeholder="备注信息"></textarea></label><div class="flex justify-end gap-3 pt-2"><button type="button" class="btn btn-ghost btn-sm px-6" onclick="closePlanExpModal()">取消</button><button type="submit" class="btn btn-primary btn-sm px-8">保存</button></div></form></div></div>';
|
modal += '</select></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">月份 <span class="text-red-500">*</span></span><select name="expense_month" required class="form-ctrl bg-white">' + modalMonthOpts + '</select></label></div><div class="grid grid-cols-2 gap-3"><label class="block"><span class="text-sm text-slate-500 mb-1 block">费用计提(元)</span><input name="amount" type="number" step="0.01" class="form-ctrl" placeholder="0.00"></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">已发生费用计提(元)</span><input name="incurred_amount" type="number" step="0.01" class="form-ctrl" placeholder="0.00"></label></div><label class="block"><span class="text-sm text-slate-500 mb-1 block">状态</span><select name="status" class="form-ctrl bg-white">' + statusOpts + '</select></label><label class="block"><span class="text-sm text-slate-500 mb-1 block">费用说明</span><textarea name="notes" class="form-ctrl" rows="3" placeholder="备注信息"></textarea></label><div class="flex justify-end gap-3 pt-2"><button type="button" class="btn btn-ghost btn-sm px-6" onclick="closePlanExpModal()">取消</button><button type="submit" class="btn btn-primary btn-sm px-8">保存</button></div></form></div></div>';
|
||||||
|
|
||||||
var target = document.querySelector("#planExpenseModule") || document.querySelector("#planExpenseModule") || document.querySelector("#planExpenseContent");
|
var target = document.querySelector("#planExpenseModule") || document.querySelector("#planExpenseModule") || document.querySelector("#planExpenseContent");
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
@@ -123,10 +123,10 @@ function renderPlanExpense() {
|
|||||||
'<div class="grid grid-cols-3 gap-3">' +
|
'<div class="grid grid-cols-3 gap-3">' +
|
||||||
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">费用记录</span><strong class="mt-2 block text-xl">' + filtered.length + '</strong></div>' +
|
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">费用记录</span><strong class="mt-2 block text-xl">' + filtered.length + '</strong></div>' +
|
||||||
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">总费用</span><strong class="mt-2 block text-xl">' + money(totalAmount) + '</strong></div>' +
|
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">总费用</span><strong class="mt-2 block text-xl">' + money(totalAmount) + '</strong></div>' +
|
||||||
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">已发生金额</span><strong class="mt-2 block text-xl">' + money(totalIncurred) + '</strong></div>' +
|
'<div class="metric-card p-3"><span class="flex items-center gap-2 text-sm text-slate-500">现金支出</span><strong class="mt-2 block text-xl">' + money(totalIncurred) + '</strong></div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
modal +
|
modal +
|
||||||
'<div class="card p-4"><div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="bg-slate-50 border-b border-slate-200"><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'expense_month\')">月份' + sortArrow('expense_month') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'expense_type\')">费用类型' + sortArrow('expense_type') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'status\')">状态' + sortArrow('status') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'amount\')">金额' + sortArrow('amount') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'incurred_amount\')">已发生金额' + sortArrow('incurred_amount') + '</th><th class="p-2 text-center font-semibold">费用说明</th></tr></thead><tbody>' + tableRows + '</tbody></table></div></div>' +
|
'<div class="card p-4"><div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="bg-slate-50 border-b border-slate-200"><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'expense_month\')">月份' + sortArrow('expense_month') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'expense_type\')">费用类型' + sortArrow('expense_type') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'status\')">状态' + sortArrow('status') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'amount\')">金额' + sortArrow('amount') + '</th><th class="p-2 text-center font-semibold cursor-pointer select-none" onclick="togglePlanExpSort(\'incurred_amount\')">现金支出' + sortArrow('incurred_amount') + '</th><th class="p-2 text-center font-semibold">费用说明</th></tr></thead><tbody>' + tableRows + '</tbody></table></div></div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
if (window.lucide) window.lucide.createIcons();
|
if (window.lucide) window.lucide.createIcons();
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ function renderTable(headers, rows, rowClicks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _loadingSteps = [
|
var _loadingSteps = [
|
||||||
{ fn: 'renderHome', label: '正在加载首页仪表盘(指标卡片+图表)', skip: function() { return state.tenant !== '总览' && state.active !== 'home'; } },
|
{ fn: 'renderHome', label: '正在加载首页仪表盘(指标卡片+图表)', skip: function() { return state.tenant !== '总览'; } },
|
||||||
{ fn: 'renderProjects', label: '正在加载业务机会列表' },
|
{ fn: 'renderProjects', label: '正在加载业务机会列表' },
|
||||||
{ fn: 'renderProposals', label: '正在加载业务方案列表' },
|
{ fn: 'renderProposals', label: '正在加载业务方案列表' },
|
||||||
{ fn: 'renderProducts', label: '正在加载产品迭代列表' },
|
{ fn: 'renderProducts', label: '正在加载产品迭代列表' },
|
||||||
@@ -224,7 +224,7 @@ function updateSidebarTabs() {
|
|||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
if (!state.data) return;
|
if (!state.data) return;
|
||||||
if (state.tenant === '总览' || state.active === 'home') renderHome();
|
if (state.tenant === '总览') renderHome();
|
||||||
renderProjects();
|
renderProjects();
|
||||||
renderProposals();
|
renderProposals();
|
||||||
renderProducts();
|
renderProducts();
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
<header class="topbar border-b border-slate-200 bg-white px-8 py-5">
|
<header class="topbar border-b border-slate-200 bg-white px-8 py-5">
|
||||||
<div class="flex items-center gap-3 w-full">
|
<div class="flex items-center gap-3 w-full">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<p class="eyebrow text-xs font-semibold uppercase tracking-[0.18em] text-blue-700">OPC Manager <span class="ml-2 text-xs font-normal text-slate-400 tracking-normal">v1.0.0.40</span></p>
|
<p class="eyebrow text-xs font-semibold uppercase tracking-[0.18em] text-blue-700">OPC Manager <span class="ml-2 text-xs font-normal text-slate-400 tracking-normal">v1.2.0.3</span></p>
|
||||||
<div class="flex items-center gap-4 mt-1">
|
<div class="flex items-center gap-4 mt-1">
|
||||||
<h1 class="text-2xl font-semibold" id="workspaceTitle">科普 OPC 工作台</h1>
|
<h1 class="text-2xl font-semibold" id="workspaceTitle">科普 OPC 工作台</h1>
|
||||||
<div class="hidden sm:flex items-center gap-1.5 bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-100 rounded-full px-4 py-1.5">
|
<div class="hidden sm:flex items-center gap-1.5 bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-100 rounded-full px-4 py-1.5">
|
||||||
|
|||||||
Reference in New Issue
Block a user