OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,222 @@
@extends($layout)
@section('content')
@php
$showClosedProjects = $showClosedProjects ?? false;
@endphp
<div class="pageheader">
<div class="pageicon"><span class="fa fa-suitcase"></span></div>
<div class="pagetitle">
<h5>{!! __('label.administration') !!}</h5>
<h1>{!! __('headline.all_projects') !!}</h1>
</div>
</div><!--pageheader-->
<div class="maincontent">
<div class="maincontentinner">
{!! $tpl->displayNotification() !!}
<div class="pull-right">
<form action="" method="post">
<input type="hidden" name="hideClosedProjects" value="1" />
<input type="checkbox" name="showClosedProjects" onclick="form.submit();" id="showClosed" @if ($showClosedProjects) checked='checked' @endif />&nbsp;<label for="showClosed" class="pull-right">Show Closed Projects</label>
</form>
</div>
<x-global::forms.button tag="a" link="{{ BASE_URL }}/projects/newProject" contentRole="primary"><i class='fa fa-plus'></i> {!! __('link.new_project') !!}</x-global::forms.button>
{{-- 视图切换:甘特图 / 列表 --}}
<div class="btn-group pull-right" style="margin-left:8px;">
<button type="button" class="btn btn-default active" id="btnViewGantt"><i class="fa fa-chart-gantt"></i> 甘特图</button>
<button type="button" class="btn btn-default" id="btnViewList"><i class="fa fa-list"></i> 列表</button>
</div>
<div class="clearall"></div>
{{-- 甘特图视图(默认显示,页面加载即初始化) --}}
<div id="ganttView" style="margin-top:16px;">
<div class="gantt-wrapper" style="position:relative;min-height:420px;">
<svg id="gantt" style="min-height:420px;min-width:700px;width:100%;display:block;"></svg>
</div>
<div id="ganttError" class="alert alert-danger" style="display:none;margin-top:8px;"></div>
</div>
{{-- 列表视图(默认隐藏) --}}
<div id="listView" style="display:none;">
<table class="table table-bordered" cellpadding="0" cellspacing="0" border="0" id="allProjectsTable">
<colgroup>
<col class="con1"/>
<col class="con0" />
<col class="con1"/>
<col class="con0" />
<col class="con1"/>
<col class="con0"/>
<col class="con0"/>
</colgroup>
<thead>
<tr>
<th class="head0">{!! __('label.project_name') !!}</th>
<th class="head1">{!! __('label.client_product') !!}</th>
<th class="head1">{!! __('label.project_type') !!}</th>
<th class="head0">{!! __('label.project_state') !!}</th>
<th class="head0">{!! __('label.hourly_budget') !!}</th>
<th class="head1">{!! __('label.budget_cost') !!}</th>
<th class="head1" style="width:40px;"></th>
</tr>
</thead>
<tbody>
@foreach ($allProjects as $row)
<tr class='gradeA'>
<td style="padding:6px;">
<a class="" href="{{ BASE_URL }}/projects/showProject/{{ $row['id'] }}">{{ $row['name'] }}</a>
</td>
<td>
<a class="" href="{{ BASE_URL }}/clients/showClient/{{ $row['clientId'] }}">{{ $row['clientName'] }}</a>
</td>
<td> {{ $row['type'] }} </td>
<td>
@if ($row['state'] == -1)
{!! __('label.closed') !!}
@else
{!! __('label.open') !!}
@endif
</td>
<td class="center">{{ $row['hourBudget'] }}</td>
<td class="center">{{ $row['dollarBudget'] }}</td>
<td class="center">
<button type="button" class="btn btn-xs btn-default btnToggleProject" data-project-id="{{ $row['id'] }}">
<i class="fa fa-chevron-down"></i>
</button>
</td>
</tr>
<tr class="projectDetailRow" id="projectDetail-{{ $row['id'] }}" style="display:none;">
<td colspan="7" style="padding:12px;background:#f9f9f9;">
<div style="display:flex;gap:16px;flex-wrap:wrap;">
<div style="flex:1;min-width:220px;">
<h5 style="margin-top:0;"><i class="fa fa-link"></i> 关联主数据</h5>
@if (empty($row['linkedMasters']))
<em class="text-muted">暂无关联主数据</em>
@else
<table class="table table-condensed table-bordered" style="margin-bottom:0;background:#fff;">
<thead>
<tr><th>类型</th><th>编号</th><th>名称</th><th>操作</th></tr>
</thead>
<tbody>
@foreach ($row['linkedMasters'] as $m)
<tr>
<td><span class="label label-info">{{ $m['typeName'] }}</span></td>
<td>{{ $m['bomNo'] ?? '' }}</td>
<td>{{ $m['productName'] ?? '' }}</td>
<td><a class="btn btn-xs btn-default" href="{{ BASE_URL }}/bom/refs/{{ $m['refId'] }}">查看</a></td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
<div style="min-width:180px;">
<h5 style="margin-top:0;"><i class="fa fa-cog"></i> 快捷操作</h5>
<a class="btn btn-xs btn-primary" href="{{ BASE_URL }}/projects/showProject/{{ $row['id'] }}#masterdata">
<i class="fa fa-link"></i> 关联主数据
</a>
</div>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>{{-- /#listView --}}
</div>
</div>
@once @push('scripts')
<script type="text/javascript">
jQuery(document).ready(function() {
leantime.projectsController.initProjectTable();
// 点击展开按钮,切换项目关联主数据详情行
jQuery('.btnToggleProject').on('click', function () {
var projectId = jQuery(this).data('project-id');
var row = jQuery('#projectDetail-' + projectId);
var icon = jQuery(this).find('i');
if (row.is(':visible')) {
row.hide();
icon.removeClass('fa-chevron-up').addClass('fa-chevron-down');
} else {
row.show();
icon.removeClass('fa-chevron-down').addClass('fa-chevron-up');
}
});
// ---- 甘特图 / 列表 视图切换(甘特图默认显示,加载即初始化) ----
var ganttTasks = {!! json_encode($ganttTasks ?? [], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) !!};
function renderGantt() {
if (!ganttTasks || !ganttTasks.length) {
jQuery('#gantt').html('<div class="alert alert-info" style="margin:20px;">暂无项目数据</div>');
return;
}
try {
if (typeof Gantt === 'undefined') {
jQuery('#ganttError').text('甘特图组件未加载Gantt undefined请强制刷新 Ctrl+Shift+R').show();
return;
}
new Gantt('#gantt', ganttTasks, {
readonlyGantt: true,
resizing: false,
progress: false,
is_draggable: false,
view_modes: ['Day', 'Week', 'Month'],
view_mode: 'Month',
bar_height: 40,
header_height: 55,
column_width: 30,
step: 24,
padding: 20,
bar_corner_radius: 10,
arrow_curve: 10,
language: 'en'
});
} catch (e) {
jQuery('#ganttError').text('甘特图渲染失败:' + e.message).show();
}
}
// 甘特图组件是 defer 加载,用 load 事件确保已就绪后再渲染
if (document.readyState === 'complete') {
renderGantt();
} else {
window.addEventListener('load', renderGantt);
}
jQuery('#btnViewGantt').on('click', function () {
jQuery('#ganttView').show();
jQuery('#listView').hide();
jQuery('#btnViewGantt').addClass('active');
jQuery('#btnViewList').removeClass('active');
});
jQuery('#btnViewList').on('click', function () {
jQuery('#ganttView').hide();
jQuery('#listView').show();
jQuery('#btnViewList').addClass('active');
jQuery('#btnViewGantt').removeClass('active');
});
});
</script>
@endpush @endonce
@endsection