Bladeren bron

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	app/Service/StatisticService.php
gogs 1 maand geleden
bovenliggende
commit
ce8eec4e59
56 gewijzigde bestanden met toevoegingen van 2495 en 360 verwijderingen
  1. 103 0
      app/Exports/CompanyRdActivityExport.php
  2. 101 0
      app/Exports/ProjectStaffExport.php
  3. 26 0
      app/Exports/ResearchProjectDetailMultiExport.php
  4. 182 0
      app/Exports/ResearchProjectDetailSheetExport.php
  5. 103 0
      app/Exports/TechnicalStaffExport.php
  6. 11 0
      app/Http/Controllers/Api/LoginController.php
  7. 154 0
      app/Http/Controllers/Api/MiddleGroundController.php
  8. 62 0
      app/Http/Controllers/Api/PriorityController.php
  9. 38 0
      app/Http/Controllers/Api/StatisticController.php
  10. 186 1
      app/Http/Controllers/Api/TestController.php
  11. 1 0
      app/Http/Kernel.php
  12. 33 0
      app/Http/Middleware/CheckCenterLogin.php
  13. 11 4
      app/Http/Middleware/CheckLogin.php
  14. 1 1
      app/Model/Archive.php
  15. 20 1
      app/Model/DataScopeBaseModel.php
  16. 13 5
      app/Model/Employee.php
  17. 1 1
      app/Model/ExpenseClaims.php
  18. 1 0
      app/Model/Item.php
  19. 32 0
      app/Model/Priority.php
  20. 9 0
      app/Model/SysMenu.php
  21. 10 0
      app/Providers/RouteServiceProvider.php
  22. 48 0
      app/Service/AuxiliaryAccountService.php
  23. 0 1
      app/Service/BIService.php
  24. 1 1
      app/Service/DeviceService.php
  25. 17 161
      app/Service/DeviceWorkService.php
  26. 15 24
      app/Service/EmployeeService.php
  27. 6 5
      app/Service/ExpenseClaimsService.php
  28. 156 7
      app/Service/ExportFileService.php
  29. 147 0
      app/Service/ImportService.php
  30. 9 9
      app/Service/ItemService.php
  31. 81 18
      app/Service/LoginService.php
  32. 520 0
      app/Service/MiddleGroundService.php
  33. 1 1
      app/Service/PLeaveOverService.php
  34. 31 13
      app/Service/PersonWorkService.php
  35. 152 0
      app/Service/PriorityService.php
  36. 55 78
      app/Service/SysMenuService.php
  37. 1 1
      config/cors.php
  38. 1 1
      config/excel/RDOrder.php
  39. 1 1
      config/excel/dailyDwOrder.php
  40. 1 1
      config/excel/dailyPwOrder.php
  41. 2 2
      config/excel/depart.php
  42. 5 5
      config/excel/device.php
  43. 14 3
      config/excel/employee.php
  44. 2 2
      config/excel/fee.php
  45. 1 1
      config/excel/feeOrder.php
  46. 3 3
      config/excel/item.php
  47. 1 1
      config/excel/leaveOrder.php
  48. 1 1
      config/excel/monthDdOrder.php
  49. 1 1
      config/excel/monthDwOrder.php
  50. 1 1
      config/excel/monthPsOrder.php
  51. 1 1
      config/excel/monthPwOrder.php
  52. 1 1
      config/excel/overtimeOrder.php
  53. 61 0
      config/excel/priority.php
  54. 1 1
      config/excel/ruleSet.php
  55. 21 2
      routes/api.php
  56. 38 0
      routes/c_api.php

+ 103 - 0
app/Exports/CompanyRdActivityExport.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace App\Exports;
+
+use Maatwebsite\Excel\Concerns\WithEvents;
+use Maatwebsite\Excel\Concerns\WithTitle;
+use Maatwebsite\Excel\Events\AfterSheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+
+class CompanyRdActivityExport implements WithEvents, WithTitle
+{
+    protected $data; // 存放传入的列表数据
+
+    public function __construct(array $data) {
+        $this->data = $data;
+    }
+
+    public function title(): string {
+        return '研发活动汇总';
+    }
+
+    public function registerEvents(): array {
+        return [
+            AfterSheet::class => function (AfterSheet $event) {
+                $sheet = $event->sheet->getDelegate();
+                $lastCol = 'H';
+                $dataCount = count($this->data);
+                $lastRow = 3 + $dataCount; // 数据从第4行开始填充
+
+                // --- 1. 第一行:主标题 ---
+                $sheet->mergeCells('A1:H1');
+                $sheet->setCellValue('A1', "企业研究开发活动汇总表");
+
+                // --- 2. 第二行:单位说明 ---
+                $sheet->mergeCells('A2:H2');
+                $sheet->setCellValue('A2', "单位:元  "); // 末尾加空格防止贴边
+
+                // --- 3. 第三行:表头标题 ---
+                $headers = [
+                    'A'=>'序号','B'=>'研发活动名称','C'=>'起止时间',
+                    'D'=>'技术来源','E'=>'研发预算','F'=>'实际支出',
+                    'G'=>'技术领域','H'=>'备注'
+                ];
+                foreach ($headers as $col => $title) {
+                    $sheet->setCellValue("{$col}3", $title);
+                }
+
+                // --- 4. 填充数据 (从第4行开始) ---
+                $currentRow = 4;
+                foreach ($this->data as $index => $row) {
+                    $sheet->fromArray([
+                        $index + 1,                 // A 序号
+                        $row['activity_name']??'',  // B 研发活动名称
+                        $row['time_range']??'',     // C 起止时间
+                        $row['from'],                  // D 技术来源
+                        $row['budget']??0,          // E 研发预算
+                        $row['actual_spending']??0, // F 实际支出
+                        $row['tech_area']??'',      // G 技术领域
+                        $row['remark']??'',         // H 备注
+                    ], null, "A{$currentRow}");
+                    $currentRow++;
+                }
+
+                // --- 5. 样式全局精修 ---
+                $fullRange = "A1:{$lastCol}{$lastRow}";
+
+                // 统一设置:垂直居中、水平居中、自动换行
+                $sheet->getStyle($fullRange)->getAlignment()->applyFromArray([
+                    'vertical' => Alignment::VERTICAL_CENTER,
+                    'horizontal' => Alignment::HORIZONTAL_CENTER,
+                    'wrapText' => true,
+                ]);
+
+                // --- 【关键修正】第二行:单位说明 强制右对齐 ---
+                // 必须在全局居中设置之后执行,否则会被覆盖
+                $sheet->getStyle('A2:H2')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT);
+
+                // 表头 (第1行和第3行) 字体加粗
+                $sheet->getStyle('A1:H1')->getFont()->setBold(true)->setSize(14);
+                $sheet->getStyle('A3:H3')->getFont()->setBold(true);
+
+                // --- 6. 调整行高与列宽 ---
+                $sheet->getRowDimension(1)->setRowHeight(35); // 主标题行
+                $sheet->getRowDimension(2)->setRowHeight(20); // 单位行
+                $sheet->getRowDimension(3)->setRowHeight(25); // 表头行
+
+                // 设置列宽
+                $sheet->getColumnDimension('A')->setWidth(8);
+                $sheet->getColumnDimension('B')->setWidth(30);
+                $sheet->getColumnDimension('C')->setWidth(18);
+                $sheet->getColumnDimension('D')->setWidth(15);
+                $sheet->getColumnDimension('E')->setWidth(13);
+                $sheet->getColumnDimension('F')->setWidth(13);
+                $sheet->getColumnDimension('G')->setWidth(15);
+                $sheet->getColumnDimension('H')->setWidth(25);
+
+                // --- 7. 全表加细边框 ---
+                $sheet->getStyle("A3:{$lastCol}{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
+            },
+        ];
+    }
+}

+ 101 - 0
app/Exports/ProjectStaffExport.php

@@ -0,0 +1,101 @@
+<?php
+
+namespace App\Exports;
+
+use Maatwebsite\Excel\Concerns\WithEvents;
+use Maatwebsite\Excel\Concerns\WithTitle;
+use Maatwebsite\Excel\Events\AfterSheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Style\Color;
+
+class ProjectStaffExport implements WithEvents, WithTitle
+{
+    protected $data;
+
+    public function __construct(array $data)
+    {
+        $this->data = $data;
+    }
+
+    public function title(): string
+    {
+        return '项目研发人员情况';
+    }
+
+    public function registerEvents(): array
+    {
+        return [
+            AfterSheet::class => function (AfterSheet $event) {
+                $sheet = $event->sheet->getDelegate();
+                $lastCol = 'I';
+                $dataCount = count($this->data);
+                $lastRow = 2 + $dataCount;
+
+                // --- 1. 第一行:主标题(包含红色提示文字) ---
+                $sheet->mergeCells('A1:I1');
+                $sheet->setCellValue('A1', "项目研发活动人员情况表");
+                $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
+
+                // --- 2. 第二行:表头设置 ---
+                $headers = [
+                    'A' => '序号',
+                    'B' => '姓名',
+                    'C' => '学历',
+                    'D' => '专业',
+                    'E' => '职称',
+                    'F' => "项目", // 提示列
+                    'G' => '项目角色',
+                    'H' => '部门',
+                    'I' => '承担职责'
+                ];
+                foreach ($headers as $col => $title) {
+                    $sheet->setCellValue("{$col}2", $title);
+                }
+
+                // 设置表头中 F2 单元格“项目角色”下方文字为红色
+                $sheet->getStyle('F2')->getFont()->getColor()->setARGB(Color::COLOR_RED);
+                $sheet->getStyle('A2:I2')->getFont()->setBold(true);
+
+                // --- 3. 填充数据 ---
+                $currentRow = 3;
+                foreach ($this->data as $index => $row) {
+                    $sheet->fromArray([
+                        $index + 1,
+                        $row['title'] ?? '',
+                        $row['education'] ?? '',
+                        $row['major'] ?? '',
+                        $row['p_title'] ?? '',
+                        $row['item_title'] ?? '',
+                        $row['item_role'] ?? '',
+                        $row['depart_title'] ?? '',
+                        $row['duty'] ?? '',
+                    ], null, "A{$currentRow}");
+                    $currentRow++;
+                }
+
+                // --- 4. 全局样式 ---
+                $fullRange = "A1:{$lastCol}{$lastRow}";
+                $sheet->getStyle($fullRange)->getAlignment()->applyFromArray([
+                    'vertical' => Alignment::VERTICAL_CENTER,
+                    'horizontal' => Alignment::HORIZONTAL_CENTER,
+                    'wrapText' => true,
+                ]);
+
+                // --- 5. 行高与列宽 ---
+                $sheet->getRowDimension(1)->setRowHeight(35);
+                $sheet->getRowDimension(2)->setRowHeight(45); // 表头双行文字
+
+                $sheet->getColumnDimension('A')->setWidth(8);
+                $sheet->getColumnDimension('B')->setWidth(12);
+                $sheet->getColumnDimension('F')->setWidth(20); // 角色定义列
+                $sheet->getColumnDimension('G')->setWidth(15);
+                $sheet->getColumnDimension('H')->setWidth(15);
+                $sheet->getColumnDimension('I')->setWidth(25); // 职责列
+
+                // --- 6. 边框 ---
+                $sheet->getStyle("A2:{$lastCol}{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
+            },
+        ];
+    }
+}

+ 26 - 0
app/Exports/ResearchProjectDetailMultiExport.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Exports;
+
+use Maatwebsite\Excel\Concerns\WithMultipleSheets;
+
+class ResearchProjectDetailMultiExport implements WithMultipleSheets
+{
+    protected $year;
+    protected $projects;
+    protected $taxInfo;
+
+    public function __construct($year, array $projects, array $taxInfo) {
+        $this->year = $year;
+        $this->projects = $projects;
+        $this->taxInfo = $taxInfo;
+    }
+
+    public function sheets(): array {
+        $sheets = [];
+        foreach ($this->projects as $project) {
+            $sheets[] = new ResearchProjectDetailSheetExport($this->year, $project, $this->taxInfo);
+        }
+        return $sheets;
+    }
+}

+ 182 - 0
app/Exports/ResearchProjectDetailSheetExport.php

@@ -0,0 +1,182 @@
+<?php
+
+namespace App\Exports;
+
+use Maatwebsite\Excel\Concerns\WithEvents;
+use Maatwebsite\Excel\Concerns\WithTitle;
+use Maatwebsite\Excel\Events\AfterSheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+
+class ResearchProjectDetailSheetExport implements WithEvents, WithTitle
+{
+    protected $project;
+    protected $year;
+    protected $taxInfo;
+
+    public function __construct($year, array $project, array $taxInfo = []) {
+        $this->year = $year;
+        $this->project = $project;
+        $this->taxInfo = $taxInfo;
+    }
+
+    public function title(): string {
+        return $this->project['project_no'] ?? '项目明细';
+    }
+
+    public function registerEvents(): array {
+        return [
+            AfterSheet::class => function (AfterSheet $event) {
+                $sheet = $event->sheet->getDelegate();
+                $lastCol = 'AO';
+                $dataCount = count($this->project['details']);
+                $lastRow = 7 + $dataCount;
+
+                // --- 1. 第一行:基础信息行 ---
+                $sheet->mergeCells('A1:D1');
+                $sheet->setCellValue('A1', "加计扣除年度:{$this->year}年");
+                $sheet->mergeCells('E1:L1');
+                $sheet->setCellValue('E1', "纳税人识别号:" . ($this->taxInfo['tax_id'] ?? ''));
+                $sheet->mergeCells('M1:AD1');
+                $sheet->setCellValue('M1', "纳税人名称(盖章):" . ($this->taxInfo['tax_name'] ?? ''));
+                $sheet->mergeCells('AE1:AO1');
+                $sheet->setCellValue('AE1', "金额单位:元(列至角分)");
+
+                // --- 2. 绘制全量表头 (第2-7行) ---
+                $this->drawCorrectHeaders($sheet);
+
+                // --- 3. 填充数据 (从第8行开始) ---
+                $currentRow = 8;
+                foreach ($this->project['details'] as $row) {
+                    $sheet->fromArray($this->mapRowData($row), null, "A{$currentRow}");
+                    $currentRow++;
+                }
+
+                // --- 4. 样式全局精修 ---
+                $fullRange = "A1:{$lastCol}{$lastRow}";
+                $sheet->getStyle($fullRange)->getFont()->setBold(false);
+                $sheet->getStyle($fullRange)->getAlignment()->applyFromArray([
+                    'vertical' => Alignment::VERTICAL_CENTER,
+                    'horizontal' => Alignment::HORIZONTAL_CENTER,
+                    'wrapText' => true,
+                ]);
+
+                // 信息行特殊处理:靠左
+                $sheet->getStyle('A1:AO1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
+
+                // --- 5. A列数据区特殊处理:合并单元格并纵向排列文字 ---
+                if ($dataCount > 0) {
+                    $dataStartRow = 8;
+                    $sheet->mergeCells("A{$dataStartRow}:A{$lastRow}");
+                    $sheet->setCellValue("A{$dataStartRow}", "项目明细\n(填写项目贷方发生额)");
+                    // 设置文字竖排/换行对齐
+                    $sheet->getStyle("A{$dataStartRow}")->getAlignment()->setWrapText(true);
+                }
+
+                // --- 6. 设置行高与列宽 ---
+                $sheet->getRowDimension(1)->setRowHeight(30);
+                for ($i = 2; $i <= 6; $i++) {
+                    $sheet->getRowDimension($i)->setRowHeight(40);
+                }
+                $sheet->getRowDimension(7)->setRowHeight(30); // 编号行
+
+                $wideCols = ['A', 'H', 'R', 'S', 'U', 'V', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO'];
+                foreach (range('A', 'AO') as $col) {
+                    $width = in_array($col, $wideCols) ? 25 : 12;
+                    $sheet->getColumnDimension($col)->setWidth($width);
+                }
+
+                // --- 7. 全表框线 ---
+                $sheet->getStyle("A2:{$lastCol}{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
+            },
+        ];
+    }
+
+    private function drawCorrectHeaders($sheet) {
+        // A列特殊:2-6行合并为“项目”,7行填“行次、序号”
+        $sheet->mergeCells("A2:A6");
+        $sheet->setCellValue("A2", "项目");
+        $sheet->setCellValue("A7", "行次、序号");
+
+        // B-K: 其他基础项目 (垂直合并 2-7行)
+        $headers = [
+            'B'=>'序号','C'=>'项目名称','D'=>'项目编号','E'=>'研发形式',
+            'F'=>'资本化、费用化支出选项','G'=>'项目实施状态选项',
+            'H'=>'委托方与受托方是否存在关联关系选项','I'=>'是否委托境外选项','J'=>'研发成果','K'=>'研发成果证书号'
+        ];
+        foreach ($headers as $col => $title) {
+            $sheet->mergeCells("{$col}2:{$col}7");
+            $sheet->setCellValue("{$col}2", $title);
+        }
+
+        // 一、人员人工
+        $sheet->mergeCells('L2:N3'); $sheet->setCellValue('L2', '一、人员人工费用');
+        $sheet->mergeCells('L4:M4'); $sheet->setCellValue('L4', '直接从事研发活动人员');
+        $sheet->mergeCells('L5:L6'); $sheet->setCellValue('L5', '工资薪金'); $sheet->setCellValue('L7', '1.1');
+        $sheet->mergeCells('M5:M6'); $sheet->setCellValue('M5', '五险一金'); $sheet->setCellValue('M7', '1.2');
+        $sheet->mergeCells('N4:N6'); $sheet->setCellValue('N4', "外聘研发人员的\n劳务费用"); $sheet->setCellValue('N7', '1.3');
+
+        // 二、直接投入
+        $sheet->mergeCells('O2:V3'); $sheet->setCellValue('O2', '二、直接投入费用');
+        $sheet->mergeCells('O4:Q4'); $sheet->setCellValue('O4', '研发活动直接消耗');
+        $sheet->mergeCells('O5:O6'); $sheet->setCellValue('O5', '材料'); $sheet->setCellValue('O7', '2.1');
+        $sheet->mergeCells('P5:P6'); $sheet->setCellValue('P5', '燃料'); $sheet->setCellValue('P7', '2.2');
+        $sheet->mergeCells('Q5:Q6'); $sheet->setCellValue('Q5', '动力费用'); $sheet->setCellValue('Q7', '2.3');
+        $sheet->mergeCells('R4:R6'); $sheet->setCellValue('R4', "用于中间试验和产品试制的模具、工艺装备开发及制造费"); $sheet->setCellValue('R7', '2.4');
+        $sheet->mergeCells('S4:S6'); $sheet->setCellValue('S4', "用于不构成固定资产的样品、样机及一般测试手段购置费"); $sheet->setCellValue('S7', '2.5');
+        $sheet->mergeCells('T4:T6'); $sheet->setCellValue('T4', '用于试制产品的检验验收费'); $sheet->setCellValue('T7', '2.6');
+        $sheet->mergeCells('U4:U6'); $sheet->setCellValue('U4', "用于研发活动的仪器、设备的运行维护、调整、检验、维修等费用"); $sheet->setCellValue('U7', '2.7');
+        $sheet->mergeCells('V4:V6'); $sheet->setCellValue('V4', "通过经营租赁方式租入的用于研发活动的仪器、设备租赁费"); $sheet->setCellValue('V7', '2.8');
+
+        // 三、折旧
+        $sheet->mergeCells('W2:X4'); $sheet->setCellValue('W2', '三、折旧费用');
+        $sheet->mergeCells('W5:W6'); $sheet->setCellValue('W5', '用于研发活动的仪器、设备的折旧费'); $sheet->setCellValue('W7', '3.1');
+        $sheet->mergeCells('X5:X6'); $sheet->setCellValue('X5', '用于研发活动的建筑物的折旧费'); $sheet->setCellValue('X7', '3.2');
+
+        // 四、无形资产摊销
+        $sheet->mergeCells('Y2:AA4'); $sheet->setCellValue('Y2', '四、无形资产摊销');
+        $sheet->mergeCells('Y5:Y6'); $sheet->setCellValue('Y5', '用于研发活动的软件的摊销费用'); $sheet->setCellValue('Y7', '4.1');
+        $sheet->mergeCells('Z5:Z6'); $sheet->setCellValue('Z5', '用于研发活动的专利权的摊销费用'); $sheet->setCellValue('Z7', '4.2');
+        $sheet->mergeCells('AA5:AA6'); $sheet->setCellValue('AA5', "用于研发活动的非专利技术(包括许可证、专有技术、设计和计算方法等)的摊销费用"); $sheet->setCellValue('AA7', '4.3');
+
+        // 五、新产品设计费
+        $sheet->mergeCells('AB2:AE4'); $sheet->setCellValue('AB2', '五、新产品设计费等');
+        $sheet->mergeCells('AB5:AB6'); $sheet->setCellValue('AB5', '新产品设计费'); $sheet->setCellValue('AB7', '5.1');
+        $sheet->mergeCells('AC5:AC6'); $sheet->setCellValue('AC5', '新工艺规程制定费'); $sheet->setCellValue('AC7', '5.2');
+        $sheet->mergeCells('AD5:AD6'); $sheet->setCellValue('AD5', '新药研制的临床试验费'); $sheet->setCellValue('AD7', '5.3');
+        $sheet->mergeCells('AE5:AE6'); $sheet->setCellValue('AE5', '勘探开发技术的现场试验费'); $sheet->setCellValue('AE7', '5.4');
+
+        // 六、其他相关费用
+        $sheet->mergeCells('AF2:AJ4'); $sheet->setCellValue('AF2', '六、其他相关费用');
+        $sheet->mergeCells('AF5:AF6'); $sheet->setCellValue('AF5', '技术图书资料费、资料翻译费等'); $sheet->setCellValue('AF7', '6.1');
+        $sheet->mergeCells('AG5:AG6'); $sheet->setCellValue('AG5', '研发成果的检索、分析、评议等'); $sheet->setCellValue('AG7', '6.2');
+        $sheet->mergeCells('AH5:AH6'); $sheet->setCellValue('AH5', '知识产权的申请费、注册费等'); $sheet->setCellValue('AH7', '6.3');
+        $sheet->mergeCells('AI5:AI6'); $sheet->setCellValue('AI5', '职工福利费、补充养老保险费等'); $sheet->setCellValue('AI7', '6.4');
+        $sheet->mergeCells('AJ5:AJ6'); $sheet->setCellValue('AJ5', '差旅费、会议费'); $sheet->setCellValue('AJ7', '6.5');
+
+        // 七、委托外部
+        $sheet->mergeCells('AK2:AK6'); $sheet->setCellValue('AK2', "七、委托外部机构或个人进行研发活动所发生的费用"); $sheet->setCellValue('AK7', '7');
+        $sheet->mergeCells('AL2:AL6'); $sheet->setCellValue('AL2', "其中:委托境外进行研发活动所发生的费用(包括存在关联关系的委托研发"); $sheet->setCellValue('AL7', '7.1');
+
+        // 八、九 汇总
+        $sheet->mergeCells('AM2:AM6'); $sheet->setCellValue('AM2', "八、允许加计扣除的研发费用中的第1至5类费用合计"); $sheet->setCellValue('AM7', '8');
+        $sheet->mergeCells('AN2:AN6'); $sheet->setCellValue('AN2', "其他相关费用限额=序号8×10%/(1-10%)"); $sheet->setCellValue('AN7', '8.1');
+        $sheet->mergeCells('AO2:AO6'); $sheet->setCellValue('AO2', "九、当期费用化支出可加计扣除总额"); $sheet->setCellValue('AO7', '9');
+    }
+
+    private function mapRowData($row) {
+        // A列在 registerEvents 中通过 mergeCells 统一填充了,所以这里返回时第一个位置留空
+        return [
+            '', $row['id']??'', $row['rd_name']??'', $row['rd_code']??'', $row['form']??'',
+            $row['opt']??'', $row['status']??'', $row['rel']??'', $row['os']??'', $row['res']??'', $row['res_no']??'',
+            $row['v1_1']??0, $row['v1_2']??0, $row['v1_3']??0,
+            $row['v2_1']??0, $row['v2_2']??0, $row['v2_3']??0, $row['v2_4']??0, $row['v2_5']??0, $row['v2_6']??0, $row['v2_7']??0, $row['v2_8']??0,
+            $row['v3_1']??0, $row['v3_2']??0,
+            $row['v4_1']??0, $row['v4_2']??0, $row['v4_3']??0,
+            $row['v5_1']??0, $row['v5_2']??0, $row['v5_3']??0, $row['v5_4']??0,
+            $row['v6_1']??0, $row['v6_2']??0, $row['v6_3']??0, $row['v6_4']??0, $row['v6_5']??0,
+            $row['v7']??0, $row['v7_1']??0,
+            $row['v8']??0, $row['v8_1']??0, $row['v9']??0
+        ];
+    }
+}

+ 103 - 0
app/Exports/TechnicalStaffExport.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace App\Exports;
+
+use Maatwebsite\Excel\Concerns\WithEvents;
+use Maatwebsite\Excel\Concerns\WithTitle;
+use Maatwebsite\Excel\Events\AfterSheet;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Cell\DataType;
+
+class TechnicalStaffExport implements WithEvents, WithTitle
+{
+    protected $data;
+
+    public function __construct(array $data)
+    {
+        $this->data = $data;
+    }
+
+    public function title(): string
+    {
+        return '科技人员情况表';
+    }
+
+    public function registerEvents(): array
+    {
+        return [
+            AfterSheet::class => function (AfterSheet $event) {
+                $sheet = $event->sheet->getDelegate();
+                $lastCol = 'H';
+                $dataCount = count($this->data);
+                $lastRow = 2 + $dataCount;
+
+                // --- 1. 第一行:主标题 ---
+                $sheet->mergeCells('A1:H1');
+                $sheet->setCellValue('A1', "企业研究开发科技人员情况表");
+                $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
+
+                // --- 2. 第二行:表头 ---
+                $headers = [
+                    'A' => '序号',
+                    'B' => '姓名',
+                    'C' => '身份证号码',
+                    'D' => '学历',
+                    'E' => '专业',
+                    'F' => '职称/职业资格',
+                    'G' => '部门/岗位',
+                    'H' => '聘用类型',
+                ];
+                foreach ($headers as $col => $title) {
+                    $sheet->setCellValue("{$col}2", $title);
+                }
+                $sheet->getStyle('A2:H2')->getFont()->setBold(true);
+
+                // --- 3. 填充数据 (解决科学计数法关键) ---
+                $currentRow = 3;
+                foreach ($this->data as $index => $row) {
+                    // 序号、姓名正常填充
+                    $sheet->setCellValue("A{$currentRow}", $index + 1);
+                    $sheet->setCellValue("B{$currentRow}", $row['name'] ?? '');
+
+                    // 【关键点】显式设置身份证列为文本格式 (Explicitly set as String)
+                    $idCard = $row['id_card'] ?? '';
+                    $sheet->setCellValueExplicit("C{$currentRow}", $idCard, DataType::TYPE_STRING);
+
+                    // 其他字段
+                    $sheet->setCellValue("D{$currentRow}", $row['education'] ?? '');
+                    $sheet->setCellValue("E{$currentRow}", $row['major'] ?? '');
+                    $sheet->setCellValue("F{$currentRow}", $row['title_level'] ?? '');
+                    $sheet->setCellValue("G{$currentRow}", $row['department_job'] ?? '');
+                    $sheet->setCellValue("H{$currentRow}", $row['employment_type'] ?? '');
+
+                    $currentRow++;
+                }
+
+                // --- 4. 样式全局精修 ---
+                $fullRange = "A1:{$lastCol}{$lastRow}";
+                $sheet->getStyle($fullRange)->getAlignment()->applyFromArray([
+                    'vertical' => Alignment::VERTICAL_CENTER,
+                    'horizontal' => Alignment::HORIZONTAL_CENTER,
+                    'wrapText' => true,
+                ]);
+
+                // --- 5. 设置行高与列宽 ---
+                $sheet->getRowDimension(1)->setRowHeight(40);
+                $sheet->getRowDimension(2)->setRowHeight(30);
+
+                $sheet->getColumnDimension('A')->setWidth(8);
+                $sheet->getColumnDimension('B')->setWidth(12);
+                $sheet->getColumnDimension('C')->setWidth(30); // 身份证列加宽
+                $sheet->getColumnDimension('D')->setWidth(12);
+                $sheet->getColumnDimension('E')->setWidth(15);
+                $sheet->getColumnDimension('F')->setWidth(25);
+                $sheet->getColumnDimension('G')->setWidth(25);
+                $sheet->getColumnDimension('H')->setWidth(18);
+
+                // --- 6. 全表加细边框 ---
+                $sheet->getStyle("A1:{$lastCol}{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
+            },
+        ];
+    }
+}

+ 11 - 0
app/Http/Controllers/Api/LoginController.php

@@ -16,4 +16,15 @@ class LoginController extends BaseController
             return $this->json_return(201, $data);
         }
     }
+
+    public function cLogin(Request $request){
+        $service = new LoginService();
+        list($status,$data) = $service->cLogin($request->all());
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201, $data);
+        }
+    }
 }

+ 154 - 0
app/Http/Controllers/Api/MiddleGroundController.php

@@ -0,0 +1,154 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\MiddleGroundService;
+use Illuminate\Http\Request;
+
+class MiddleGroundController extends BaseController
+{
+    public function initializationCompany(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->initializationCompany($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function initializationCompanyList(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->initializationCompanyList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function roleEdit(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleEdit($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function roleAdd(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleAdd($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function roleDel(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleDel($request->all(), $user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function roleList(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function roleMenu(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleMenu($request->all());
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function roleDetail(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->roleDetail($request->all());
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function menuList(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->menuList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function employeeList(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->employeeList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function employeeEdit(Request $request)
+    {
+        $service = new MiddleGroundService();
+        $user = $request->userData;
+        list($status,$data) = $service->employeeEdit($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 62 - 0
app/Http/Controllers/Api/PriorityController.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\PriorityService;
+use Illuminate\Http\Request;
+
+class PriorityController extends BaseController
+{
+    public function priorityEdit(Request $request)
+    {
+        $service = new PriorityService();
+        $user = $request->userData;
+        list($status,$data) = $service->priorityEdit($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function priorityAdd(Request $request)
+    {
+        $service = new PriorityService();
+        $user = $request->userData;
+        list($status,$data) = $service->priorityAdd($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function priorityDel(Request $request)
+    {
+        $service = new PriorityService();
+        $user = $request->userData;
+        list($status,$data) = $service->priorityDel($request->all(), $user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function priorityList(Request $request)
+    {
+        $service = new PriorityService();
+        $user = $request->userData;
+        list($status,$data) = $service->priorityList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 38 - 0
app/Http/Controllers/Api/StatisticController.php

@@ -106,5 +106,43 @@ class StatisticController extends BaseController
     }
 
 
+    public function enterpriseRdStatistic(Request $request)
+    {
+        $service = new StatisticService();
+        $user = $request->userData;
+        list($status,$data) = $service->enterpriseRdStatistic($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function enterpriseRdManStatistic(Request $request)
+    {
+        $service = new StatisticService();
+        $user = $request->userData;
+        list($status,$data) = $service->enterpriseRdManStatistic($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function enterpriseRdItemStatistic(Request $request)
+    {
+        $service = new StatisticService();
+        $user = $request->userData;
+        list($status,$data) = $service->enterpriseRdItemStatistic($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
 
 }

+ 186 - 1
app/Http/Controllers/Api/TestController.php

@@ -2,13 +2,17 @@
 
 namespace App\Http\Controllers\Api;
 
+use App\Exports\CompanyRdActivityExport;
 use App\Exports\ItemSalaryFTMultipleSheetExport;
 use App\Exports\ItemSalarySheetExport;
 use App\Exports\ManActivityTimeCardMultipleSheetExport;
 use App\Exports\ManMonthlyWorkHourMultipleSheetExport;
 use App\Exports\ProjectDepreciationMultipleSheetExport;
+use App\Exports\ProjectStaffExport;
 use App\Exports\ResearchExpenseMultipleSheetExport;
 use App\Exports\ResearchExpenseSummaryMultipleSheetExport;
+use App\Exports\ResearchProjectDetailMultiExport;
+use App\Exports\TechnicalStaffExport;
 use Maatwebsite\Excel\Facades\Excel;
 use PhpMqtt\Client\MqttClient;
 // --- 必须引入以下两个 MQTT 相关的类 ---
@@ -17,7 +21,7 @@ use PhpMqtt\Client\ConnectionSettings;
 class TestController extends BaseController
 {
     public function aa(){
-//         return $this->exportSummary();
+         return $this->testExport();
         $mqtt = new MqttClient('47.111.77.194', 1883, 'web_publisher');
         $mqtt->connect((new ConnectionSettings)->setUsername('yonglidev1')->setPassword('tZjUw0kQ'));
         $mqtt->publish('/wy/119/RealtimeData/DT5/yonglidev1', json_encode(['cmd' => 'reset']), 0);
@@ -326,4 +330,185 @@ class TestController extends BaseController
 
         return $filename;
     }
+
+    //最长的报表
+    public function rdB(){
+        // 示例数据准备 (通常从数据库查询得出)
+        $year = 2026;
+
+        $taxInfo = [
+            'tax_id'   => '91330101MA28XXXXXX',
+            'tax_name' => '杭州青艾科技有限公司'
+        ];
+        $projects = [
+            [
+                'project_no' => 'RD01',
+                'details' => [
+                    [
+                        // A-J (10个)
+                        'p_name'=>'AI项目', 'id'=>1, 'rd_name'=>'智能识别', 'rd_code'=>'RD01',
+                        'form'=>'自主研发', 'opt'=>'费用化', 'status'=>'已完成', 'rel'=>'否', 'os'=>'否', 'res'=>'软著',
+                        'res_no' => '2026SR123456',
+                        // K-M (3个)
+                        'v1_1'=>8000, 'v1_2'=>1200, 'v1_3'=>0,
+                        // N-U (8个)
+                        'v2_1'=>1500, 'v2_2'=>100, 'v2_3'=>50, 'v2_4'=>0, 'v2_5'=>0, 'v2_6'=>200, 'v2_7'=>0, 'v2_8'=>0,
+                        // V-W (2个)
+                        'v3_1'=>400, 'v3_2'=>0,
+                        // X-Z (3个)
+                        'v4_1'=>300, 'v4_2'=>0, 'v4_3'=>0,
+                        // AA-AD (4个)
+                        'v5_1'=>500, 'v5_2'=>0, 'v5_3'=>0, 'v5_4'=>0,
+                        // AE-AI (5个)
+                        'v6_1'=>100, 'v6_2'=>0, 'v6_3'=>200, 'v6_4'=>0, 'v6_5'=>150,
+                        // AJ-AN (汇总)
+                        'v7'=>0, 'v7_1'=>0,
+                        'v8'=>10200,    // 栏次 8:前五项合计
+                        'v8_1'=>1133.33, // 栏次 8.1:限额
+                        'v9' => 11333.33   // 九、总额
+                    ]
+                ]
+            ]
+        ];
+
+        $file_name = "研发支出汇总表_" . date("YmdHis");
+        $filename =  $file_name . '.xlsx';
+
+        // 传入 $dynamicHeaders 到构造函数
+        Excel::store(
+            new ResearchProjectDetailMultiExport($year, $projects, $taxInfo),
+            "public/export/{$filename}"
+        );
+
+        return $filename;
+    }
+
+    //企业研究开发活动汇总表
+    public function exportRdSummary() {
+
+        // 模拟从数据库获取的研发活动列表数据
+        $rdData = [
+            [
+                'activity_name' => '智能AI图像识别算法研发项目',
+                'time_range' => '2025.01-2025.12',
+                'budget' => 500000.00,
+                'actual_spending' => 485000.50,
+                'tech_area' => '人工智能',
+                'remark' => '核心算法已申请软著',
+            ],
+            [
+                'activity_name' => '高并发云原生架构优化',
+                'time_range' => '2025.03-2025.10',
+                'budget' => 300000.00,
+                'actual_spending' => 310000.00,
+                'tech_area' => '云计算',
+                'remark' => '超出预算部分已通过审批',
+            ],
+        ];
+
+        $file_name = "企业研发活动汇总表_" . date("YmdHis");
+        $filename =  $file_name . '.xlsx';
+
+        // 触发导出
+         Excel::store(
+            new CompanyRdActivityExport($rdData),
+             "public/export/{$filename}"
+        );
+
+         return $filename;
+    }
+
+    // 企业研究开发科技人员情况表
+    public function exportTechnicalStaff()
+    {
+        // 模拟测试数据,对应图片中的示例内容
+        $testData = [
+            [
+                'name' => '张三',
+                'id_card' => '33010119900101XXXX',
+                'education' => '本科',
+                'major' => '计算机科学',
+                'title_level' => '高级工程师',
+                'department_job' => "技术部/\n系统集成工程师",
+                'employment_type' => '在职',
+            ],
+            [
+                'name' => '李四',
+                'id_card' => '33010119920202XXXX',
+                'education' => '硕士',
+                'major' => '机械工程',
+                'title_level' => "工程师/\n注册电气工程师",
+                'department_job' => "生产部/\n模具制作师",
+                'employment_type' => '在职',
+            ],
+            [
+                'name' => '王五',
+                'id_card' => '33010119950505XXXX',
+                'education' => '大专',
+                'major' => '自动化',
+                'title_level' => '助理工程师',
+                'department_job' => "生产部/\n产品试制研发辅助员",
+                'employment_type' => '临聘',
+            ],
+            [
+                'name' => '赵六',
+                'id_card' => '33010119800808XXXX',
+                'education' => '博士',
+                'major' => '电子工程',
+                'title_level' => '教授/电工证',
+                'department_job' => '研发部/技术顾问',
+                'employment_type' => '兼职',
+            ]
+        ];
+
+        $filename = '企业研究开发科技人员情况表_' . date('Ymd') . '.xlsx';
+
+         Excel::store(new TechnicalStaffExport($testData), "public/export/{$filename}");
+
+         return $filename;
+    }
+
+    //项目研发活动人员情况表
+    public function testExport()
+    {
+        // 模拟数据:对应图片中的角色定义示例
+        $data = [
+            [
+                'name' => '张技术',
+                'education' => '本科',
+                'major' => '机械设计',
+                'title' => '高级工程师',
+                'role_desc' => '项目负责人',
+                'role_name' => '总指挥',
+                'dept' => '研发部',
+                'duty' => '负责项目整体进度把控与技术架构设计',
+            ],
+            [
+                'name' => '李研发',
+                'education' => '硕士',
+                'major' => '自动化',
+                'title' => '工程师',
+                'role_desc' => '技术负责人',
+                'role_name' => '核心研发',
+                'dept' => '技术部',
+                'duty' => '负责核心算法编写与系统集成',
+            ],
+            [
+                'name' => '王测试',
+                'education' => '大专',
+                'major' => '电子信息',
+                'title' => '助工',
+                'role_desc' => '测试工程师',
+                'role_name' => '质量检测',
+                'dept' => '质检部',
+                'duty' => '负责产品试制阶段的可靠性测试',
+            ]
+        ];
+
+        $filename = '项目研发活动人员情况表' . date('Ymd') . '.xlsx';
+
+        Excel::store(new ProjectStaffExport($data), "public/export/{$filename}");
+
+        return $filename;
+    }
 }

+ 1 - 0
app/Http/Kernel.php

@@ -64,6 +64,7 @@ class Kernel extends HttpKernel
         'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
         'checkLogin' => \App\Http\Middleware\CheckLogin::class,
+        'checkCenterLogin' => \App\Http\Middleware\CheckCenterLogin::class,
         'OssFileDeal' => \App\Http\Middleware\OssFileDeal::class,
     ];
 

+ 33 - 0
app/Http/Middleware/CheckCenterLogin.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Service\MiddleGroundService;
+use Closure;
+use App\Service\TokenService;
+
+class CheckCenterLogin
+{
+    public function handle($request, Closure $next)
+    {
+        $token = $request->header('Authorization');
+        if (empty($token)) return response()->json(['code' => 1,'msg' => '缺少登录凭证','data' => null]);
+
+        //校验token
+        list($bool, $return) = TokenService::verifyToken($token);
+        if(! $bool) return response()->json(['code' => 1,'msg' => $return,'data' => null]);
+
+        //人员在jwt里的信息
+        $e_array = $return;
+
+        //校验人员
+        $checkResult = MiddleGroundService::checkCenterUser($e_array);
+        list($state, $msg) = $checkResult;
+        if(! $state) return response()->json(['code' => 1,'msg' => $msg,'data' => null]);
+        $employee = $msg;
+        $employee['top_depart_id'] = 0;
+        $request->userData = $employee;
+
+        return $next($request);
+    }
+}

+ 11 - 4
app/Http/Middleware/CheckLogin.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Middleware;
 
+use App\Model\SysMenu;
 use App\Service\LoginService;
 use Closure;
 use App\Service\TokenService;
@@ -13,6 +14,10 @@ class CheckLogin
         $token = $request->header('Authorization');
         if (empty($token)) return response()->json(['code' => 1,'msg' => '缺少登录凭证','data' => null]);
 
+        $tree_type = $request->header('TreeType');
+        if (! isset(SysMenu::tree[$tree_type])) return response()->json(['code' => 1,'msg' => '缺少参数或参数错误','data' => null]);
+        $title = SysMenu::tree[$tree_type];
+
         //校验token
         list($bool, $return) = TokenService::verifyToken($token);
         if(! $bool) return response()->json(['code' => 1,'msg' => $return,'data' => null]);
@@ -20,6 +25,10 @@ class CheckLogin
         //人员在jwt里的信息
         $e_array = $return;
 
+        //校验是否越权拿菜单数据
+        $bool = LoginService::hasPersonRoleForSysMenuList($e_array['employee_id'], $tree_type);
+        if(! $bool) return response()->json(['code' => 1,'msg' => '无系统' . $title . '权限','data' => null]);
+
         //校验人员
         $checkResult = LoginService::checkUser($e_array);
         list($state, $msg) = $checkResult;
@@ -35,10 +44,8 @@ class CheckLogin
         //人员角色 菜单权限
         $employee = array_merge($employee, LoginService::getPersonRoleAndPermissions($employee));
 
-        //校验是否有路由权限
-//        list($state, $msg) = LoginService::checkRoute($employee,$request);
-//        if(! $state) return response()->json(['code' => 201,'msg' => $msg,'data' => null]);
-
+        //当前选择的系统菜单
+        $employee['select_tree_type'] = $tree_type;
         $request->userData = $employee;
 
         return $next($request);

+ 1 - 1
app/Model/Archive.php

@@ -12,5 +12,5 @@ class Archive extends DataScopeBaseModel
     const UPDATED_AT = 'upd_time';
     protected $dateFormat = 'U';
 
-    public static $field = ['month','id','crt_id','time'];
+    public static $field = ['month','id','crt_id','crt_time'];
 }

+ 20 - 1
app/Model/DataScopeBaseModel.php

@@ -17,6 +17,23 @@ class DataScopeBaseModel extends Model
     //根据公司过滤
     public function scopeTopClear($query, $user, $search)
     {
+        $top_depart_id = "top_depart_id";
+
+        // 获取当前查询的表名或别名(这样无论你起什么别名 i 还是 item_details 都能自适应)
+        $table = $query->getQuery()->from;
+
+        // 如果 $table 里包含 " as ",说明有别名,截取别名部分
+        if (strpos($table, ' as ') !== false) {
+            $segments = explode(' as ', $table);
+            $table = trim(end($segments));
+
+            $top_depart_id = $table . '.top_depart_id';
+        }
+
+        $query->where($top_depart_id, $user['top_depart_id']);
+
+        return $query;
+
         $query->where('top_depart_id', $user['top_depart_id']);
 
         return $query;
@@ -41,6 +58,8 @@ class DataScopeBaseModel extends Model
 
     //最高权限
     private function makeModel(&$query, $auth_type, $user, $depart_range, $column){
+        $query->where('top_depart_id', $user['top_depart_id']);
+
         if(empty($column)) return;
 
         if($auth_type == Employee::AUTH_ONE){
@@ -63,7 +82,7 @@ class DataScopeBaseModel extends Model
 
     public function getQx($data, $user){
         if(empty($data['menu_id'])) return Employee::AUTH_ONE; // 我的
-        if($user['top_depart_id'] == Employee::IS_ADMIN_TWO) return Employee::AUTH_THREE; // 全部
+        if($user['is_admin'] == Employee::IS_ADMIN_TWO) return Employee::AUTH_THREE; // 全部
         if(! empty($user['menu_permissions'][$data['menu_id']])) {
             //指定菜单 显示对应权限
             return $user['menu_permissions'][$data['menu_id']];

+ 13 - 5
app/Model/Employee.php

@@ -11,13 +11,14 @@ class Employee extends DataScopeBaseModel
     const CREATED_AT = 'crt_time';
     const UPDATED_AT = 'upd_time';
     protected $dateFormat = 'U';
-    public static $field = ['number','mobile','title','id','is_admin', 'account', 'crt_time', 'state', 'education', 'major', 'id_card','p_title','sex', 'entrust_type', 'man_type', 'position'];
-    const SPECIAL_ADMIN = 1;
+    public static $field = ['number','mobile','title','id','is_admin', 'account', 'crt_time', 'state', 'education', 'major', 'id_card','p_title','sex', 'entrust_type', 'man_type', 'position','employee_type'];
+    public static $report_field = ['title','id', 'employee_type', 'education', 'major', 'id_card','p_title', 'position'];
     const USE = 1;
     const NOT_USE = 2;
     const IS_ADMIN_ZERO = 0;
     const IS_ADMIN_ONE = 1;
     const IS_ADMIN_TWO = 2;
+    const IS_ADMIN_THREE = 3; // 中台管理员
     const IS_ADMIN_TITLE_SIMPLE = [
         self::IS_ADMIN_ZERO => '普通账号',
         self::IS_ADMIN_ONE => '后台用户',
@@ -25,7 +26,7 @@ class Employee extends DataScopeBaseModel
     const IS_ADMIN_TITLE = [
         self::IS_ADMIN_ZERO => '普通账号(限制后台登录)',
         self::IS_ADMIN_ONE => '后台用户',
-        self::IS_ADMIN_TWO => '管理员',
+        self::IS_ADMIN_TWO => '后台管理员',
     ];
 
     const AUTH_ONE = 1; // 我的
@@ -51,11 +52,18 @@ class Employee extends DataScopeBaseModel
 
     const TYPE_ONE = 1; // 在职
     const TYPE_TWO = 2; // 离职
-    const TYPE_THREE = 3; // 休假
     const State_Type = [
         self::TYPE_ONE => '在职',
         self::TYPE_TWO => '离职',
-        self::TYPE_THREE => '休假',
+    ];
+
+    const E_TYPE_ONE = 1;
+    const E_TYPE_TWO = 2;
+    const E_TYPE_THREE = 3;
+    const E_State_Type = [
+        self::E_TYPE_ONE => '全职',
+        self::E_TYPE_TWO => '兼职',
+        self::E_TYPE_THREE => '外聘',
     ];
 
     //是否技术研究人员

+ 1 - 1
app/Model/ExpenseClaims.php

@@ -4,7 +4,7 @@ namespace App\Model;
 
 class ExpenseClaims extends DataScopeBaseModel
 {
-    //设备日工时单
+    //项目费用
     protected $table = "expense_claims"; //指定表
     const CREATED_AT = 'crt_time';
     const UPDATED_AT = 'upd_time';

+ 1 - 0
app/Model/Item.php

@@ -13,6 +13,7 @@ class Item extends DataScopeBaseModel
     const employee_column = "crt_id";
 
     public static $field = ['title','id','code','start_time','end_time','mark','crt_id','crt_time','state','budget','charge_id','item_attribute','field'];
+    public static $report_field_1 = ['title','id','code','start_time','end_time','mark','budget','field'];
 
     const TYPE_ONE = 1;
     const TYPE_TWO = 2;

+ 32 - 0
app/Model/Priority.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Priority extends DataScopeBaseModel
+{
+    protected $guarded = [];
+    protected $table = "priority"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+
+    public static $field = ['title','id','code','sort','type'];
+
+    const TYPE_ONE = 1;
+    const TYPE_TWO = 2;
+    const TYPE_THREE = 3;
+    const TYPE_TITLE = [
+        self::TYPE_ONE => '项目',
+        self::TYPE_TWO => '节点',
+        self::TYPE_THREE => '任务',
+    ];
+
+    const IS_USE_ZERO = 0;
+    const IS_USE_ONE = 1;
+    const IS_USE = [
+        self::IS_USE_ZERO => '否',
+        self::IS_USE_ONE => '是',
+    ];
+}

+ 9 - 0
app/Model/SysMenu.php

@@ -12,4 +12,13 @@ class SysMenu extends Model
     const UPDATED_AT = 'upd_time';
     protected $dateFormat = 'U';
 
+    const type_zero = 0; // 正常用户菜单
+    const type_one = 1; // 中台菜单
+
+    const tree_type_zero = 0; // 工时菜单
+    const tree_type_one = 1; // 项目管理
+    const tree = [
+        self::tree_type_zero => '工时菜单',
+        self::tree_type_one => '项目管理',
+    ];
 }

+ 10 - 0
app/Providers/RouteServiceProvider.php

@@ -43,6 +43,8 @@ class RouteServiceProvider extends ServiceProvider
     public function map()
     {
         $this->mapApiRoutes();
+
+        $this->mapCApiRoutes();
     }
 
     /**
@@ -59,4 +61,12 @@ class RouteServiceProvider extends ServiceProvider
              ->namespace($this->namespace)
              ->group(base_path('routes/api.php'));
     }
+
+    protected function mapCApiRoutes()
+    {
+        Route::prefix('cApi')
+            ->middleware('api')
+            ->namespace($this->namespace)
+            ->group(base_path('routes/c_api.php'));
+    }
 }

+ 48 - 0
app/Service/AuxiliaryAccountService.php

@@ -83,6 +83,54 @@ class AuxiliaryAccountService extends Service
     }
 
     private  function employeeMonthAmount($month,$user,$monthStart,$monthEnd){
+        $data['top_depart_id'] = $user['top_depart_id'];
+        $month_ps_order = MonthlyPsOrder::Clear($user,$data);
+        $month_ps_order_id = $month_ps_order->where('del_time',0)->where("month",$monthStart)->first();
+        if(empty($month_ps_order_id)){
+            return [false,"请补充对应月份人员月度工资信息"];
+        }else{
+            $month_ps_order_id = $month_ps_order_id->id;
+        }
+        $model = MonthlyPsOrderDetails::Clear($user,$data);
+        $totals = $model->where('main_id', $month_ps_order_id)
+            ->where('del_time', 0)
+            ->selectRaw('
+        employee_id, 
+        SUM(
+            IFNULL(base_salary, 0) + 
+            IFNULL(other, 0) + 
+            IFNULL(performance_salary, 0) + 
+            IFNULL(bonus, 0)
+        ) as total
+    ')
+            ->groupBy('employee_id')
+            ->pluck('total' , 'employee_id')
+            ->toArray();
+
+        $entrust_type_map = Employee::whereIn('id', array_keys($totals))
+            ->pluck('entrust_type', 'id')
+            ->toArray();
+        $total_amount = $entrust_in_amount = $entrust_out_amount = 0;
+        foreach ($totals as $employee_id => $amount){
+            $total_amount = bcadd($amount, $total_amount, 2);
+            if(! empty($entrust_type_map[$employee_id])){
+                $tmp = $entrust_type_map[$employee_id];
+                if($tmp == Employee::WT_TYPE_ONE){
+                    $entrust_in_amount = bcadd($amount, $entrust_in_amount, 2);
+                }elseif($tmp == Employee::WT_TYPE_TWO){
+                    $entrust_out_amount = bcadd($amount, $entrust_out_amount, 2);
+                }
+            }
+        }
+
+        return [true,[
+            "total_amount" => $total_amount,
+            "entrust_in_amount" => $entrust_in_amount,
+            "entrust_out_amount" => $entrust_out_amount,
+        ]];
+    }
+
+    private  function employeeMonthAmount1($month,$user,$monthStart,$monthEnd){
         $data['top_depart_id'] = $user['top_depart_id'];
         $month_ps_order = MonthlyPsOrder::Clear($user,$data);
         $month_ps_order_id = $month_ps_order->where('del_time',0)->where("month",$monthStart)->first();

+ 0 - 1
app/Service/BIService.php

@@ -14,7 +14,6 @@ use App\Model\MonthlyPsOrder;
 use App\Model\MonthlyPsOrderDetails;
 use App\Model\PLeaveOverOrder;
 use App\Model\PLeaveOverOrderDetails;
-use Illuminate\Support\Facades\DB;
 
 class BIService extends Service
 {

+ 1 - 1
app/Service/DeviceService.php

@@ -148,7 +148,7 @@ class DeviceService extends Service
             if(! $res['valid']) return [false,'原始价值:' . $res['error']];
         }
         $res = $this->checkNumber($data['initial_value'],0,'positive');
-        if(! $res['valid']) return [false,'期初值:' . $res['error']];
+        if(! $res['valid']) return [false,'期初值:' . $res['error']];
         $data['top_depart_id'] = $user['top_depart_id'];
 
         if($is_add){

+ 17 - 161
app/Service/DeviceWorkService.php

@@ -620,6 +620,8 @@ class DeviceWorkService extends Service
         $internalOverlap = [];
 
         foreach ($data['details'] as $key => $value){
+            $line = $key + 1;
+            $t = "第" . $line . "行";
             $empId = $value['device_id'] ?? 0;
             if(empty($empId)) return [false, '设备不能为空'];
 
@@ -627,23 +629,29 @@ class DeviceWorkService extends Service
 
             // 校验数字有效性
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}开始点:" . $res['error']];
-            if($value['start_time_hour'] > 23) return [false, false, "设备{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "设备{$empName}开始点:" . $res['error']];
+            if($value['start_time_hour'] > 23) return [false, false, $t . "设备{$empName}开始点不合法"];
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}开始分:" . $res['error']];
-            if($value['start_time_min'] > 60) return [false, false, "设备{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}开始分:" . $res['error']];
+            if($value['start_time_min'] > 60) return [false, false, $t . "设备{$empName}开始点不合法"];
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}结束点:" . $res['error']];
-            if($value['end_time_hour'] > 24) return [false, false, "设备{$empName}结束点不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}结束点:" . $res['error']];
+            if($value['end_time_hour'] > 24) return [false, false, $t . "设备{$empName}结束点不合法"];
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "设备{$empName}结束分:" . $res['error']];
-            if($value['end_time_min'] > 60) return [false, false, "设备{$empName}结束分不合法"];
+            if(!$res['valid']) return [false, $t ."设备{$empName}结束分:" . $res['error']];
+            if($value['end_time_min'] > 60) return [false, false, $t . "设备{$empName}结束分不合法"];
 
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
 
             if ($currentStart >= $currentEnd) {
-                return [false, "设备{$empName}:开始时间必须早于结束时间"];
+                return [false, $t . "设备{$empName}:开始时间必须早于结束时间"];
+            }
+
+            // --- 新增:总分钟数校验 ---
+            $calculatedTotal = $currentEnd - $currentStart;
+            if (!isset($value['total_work_min']) || intval($value['total_work_min']) !== $calculatedTotal) {
+                return [false, $t . "设备{$empName}:工时计算有误,应为 {$calculatedTotal} 分钟"];
             }
 
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---
@@ -1046,158 +1054,6 @@ class DeviceWorkService extends Service
         ]];
     }
 
-    private function calculateDailyDeviceAllocation1($monthStart, $topDepartId, $user)
-    {
-        // 加载月度设备明细
-        $monthlyOrder = DB::table('monthly_dw_order_details as d')
-            ->join('monthly_dw_order as m', 'm.id', '=', 'd.main_id')
-            ->where('m.month', $monthStart)
-            ->where('m.top_depart_id', $topDepartId)
-            ->where('m.del_time', 0)
-            ->where('d.del_time', 0)
-            ->select('d.*')
-            ->get();
-
-        if ($monthlyOrder->isEmpty()) return ['status' => false, 'msg' => '未找到设备月度工时明细'];
-
-        $usedDeviceIds = $monthlyOrder->pluck('device_id')->unique()->toArray();
-
-        // 【优化点】按需查询设备名称
-        $deviceMap = DB::table('device')
-        ->whereIn('id', $usedDeviceIds)
-            ->pluck('title', 'id')
-            ->toArray();
-
-        // 加载分配规则
-        $ruleSet = DB::table('rule_set_details as rd')
-            ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
-            ->where('r.month', $monthStart)
-            ->where('rd.type', RuleSetDetails::type_two) // 设备类型
-            ->where('rd.top_depart_id', $topDepartId)
-            ->where('r.del_time', 0)
-            ->where('rd.del_time', 0)
-            ->select('rd.*')
-            ->get();
-
-        // 【优化点】按需查询项目名称
-        $usedItemIds = $ruleSet->pluck('item_id')->unique()->toArray();
-        $itemMap = DB::table('item')
-            ->whereIn('id', $usedItemIds)
-            ->pluck('title', 'id')
-            ->toArray();
-
-        $ruleSetGrouped = $ruleSet->groupBy('data_id'); // 按 device_id 分组
-
-        // 标准班次 & 日历 (逻辑同前)
-        $standardWorkRanges = DB::table('work_range_details')
-            ->where('top_depart_id', $topDepartId)
-            ->where('del_time', 0)
-            ->get();
-        $dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
-
-        $workDays = DB::table('calendar_details')
-            ->where('top_depart_id', $topDepartId)
-            ->where('month', $monthStart)
-            ->where('is_work', 1)
-            ->where('del_time', 0)
-            ->orderBy('time', 'asc')->get();
-
-        if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
-
-        // --- 2. 阶段一:计算每天每台设备分配的项目分钟数 ---
-        $finalAlloc = [];
-        foreach ($monthlyOrder as $mDetail) {
-            $deviceId = $mDetail->device_id;
-            $deviceRules = $ruleSetGrouped->get($deviceId);
-            if (!$deviceRules) continue;
-
-            $remainingMin = (int)round((float)$mDetail->rd_total_hours * 60);
-            if ($remainingMin <= 0) continue;
-
-            foreach ($workDays as $dayInfo) {
-                if ($remainingMin <= 0) break;
-
-                $canAllocToday = min($remainingMin, $dayMaxAvail);
-                $allocatedInDay = 0;
-                $ruleCount = count($deviceRules);
-
-                foreach ($deviceRules as $index => $rule) {
-                    $rate = (float)$rule->rate / 100;
-                    if ($index === $ruleCount - 1) {
-                        $projectMin = $canAllocToday - $allocatedInDay;
-                    } else {
-                        $projectMin = (int)round($canAllocToday * $rate);
-                    }
-
-                    if ($projectMin > 0) {
-                        $finalAlloc[$dayInfo->time][$rule->item_id][$deviceId] = $projectMin;
-                        $allocatedInDay += $projectMin;
-                    }
-                }
-                $remainingMin -= $canAllocToday;
-            }
-        }
-
-        // --- 3. 阶段二:生成预览行 ---
-        $previewList = [];
-        $dailyDevicePools = [];
-        $tempMainIdCounter = 1;
-
-        foreach ($finalAlloc as $dayTs => $projects) {
-            foreach ($projects as $itemId => $devices) {
-
-                $currentTempMainId = $tempMainIdCounter++;
-                $itemTitle = $itemMap[$itemId] ?? '未知项目';
-
-                foreach ($devices as $deviceId => $toAllocMin) {
-                    if (!isset($dailyDevicePools[$dayTs][$deviceId])) {
-                        $pool = [];
-                        foreach ($standardWorkRanges as $swr) {
-                            $pool[] = [
-                                's' => (int)($swr->start_time_hour * 60 + $swr->start_time_min),
-                                'e' => (int)($swr->end_time_hour * 60 + $swr->end_time_min)
-                            ];
-                        }
-                        $dailyDevicePools[$dayTs][$deviceId] = $pool;
-                    }
-
-                    $tempRem = (int)$toAllocMin;
-                    foreach ($dailyDevicePools[$dayTs][$deviceId] as &$p) {
-                        if ($tempRem <= 0) break;
-                        $pMax = $p['e'] - $p['s'];
-                        if ($pMax <= 0) continue;
-
-                        $take = min($tempRem, $pMax);
-                        $start = (int)$p['s'];
-                        $end = $start + $take;
-
-                        $previewList[] = [
-                            'temp_main_id'    => $currentTempMainId,
-                            'order_time'      => date('Y-m-d', $dayTs),
-                            'order_timestamp' => $dayTs,
-                            'item_id'         => $itemId,
-                            'item_title'      => $itemTitle,
-                            'device_id'       => $deviceId,
-                            'device_title'    => $deviceMap[$deviceId] ?? '未知设备',
-                            'start_time'      => sprintf('%02d:%02d', floor($start / 60), $start % 60),
-                            'end_time'        => sprintf('%02d:%02d', floor($end / 60), $end % 60),
-                            'start_hour'      => (int)floor($start / 60),
-                            'start_min'       => (int)($start % 60),
-                            'end_hour'        => (int)floor($end / 60),
-                            'end_min'         => (int)($end % 60),
-                            'total_work_min'  => $take,
-                        ];
-
-                        $tempRem -= $take;
-                        $p['s'] = $end;
-                    }
-                }
-            }
-        }
-
-        return ['status' => true, 'data' => $previewList];
-    }
-
     private function calculateDailyDeviceAllocation($monthStart, $topDepartId, $user)
     {
         // 加载月度设备明细

+ 15 - 24
app/Service/EmployeeService.php

@@ -72,6 +72,7 @@ class EmployeeService extends Service
             $model->position = $data['position'] ?? "";
             $model->p_title = $data['p_title'] ?? "";
             $model->state = $data['state'] ?? 0;
+            $model->employee_type = $data['employee_type'] ?? 0;
             $model->is_admin = $data['is_admin'] ?? 0;
             $model->entrust_type = $data['entrust_type'] ?? 0;
             $model->man_type = $data['man_type'] ?? 0;
@@ -176,6 +177,7 @@ class EmployeeService extends Service
             $model->position = $data['position'] ?? "";
             $model->p_title = $data['p_title'] ?? "";
             $model->state = $data['state'] ?? 0;
+            $model->employee_type = $data['employee_type'] ?? 0;
             $model->crt_id = $user['id'];
             $model->is_admin = $data['is_admin'] ?? 0;
             $model->account = $data['account'] ?? "";
@@ -316,7 +318,7 @@ class EmployeeService extends Service
 
         $model = Employee::TopClear($user,$data);
         $model = $model->where('del_time',0)
-            ->where('is_admin', '<>', Employee::IS_ADMIN_TWO)
+            ->where('is_admin', '<=', Employee::IS_ADMIN_ONE)
             ->select($field)
             ->orderBy('id','desc');
 
@@ -385,6 +387,7 @@ class EmployeeService extends Service
             // 业务状态字段
             $item['is_admin_title'] = Employee::IS_ADMIN_TITLE[$item['is_admin']] ?? "";
             $item['state_title'] = Employee::State_Type[$item['state']] ?? "";
+            $item['employee_type_title'] = Employee::E_State_Type[$item['employee_type']] ?? "";
             $item['sex_title'] = Employee::SEX_TYPE[$item['sex']] ?? "";
             $item['man_type_title'] = Employee::Man_Type[$item['man_type']] ?? "";
             $item['entrust_type_title'] = Employee::WT_Type[$item['entrust_type']] ?? "";
@@ -568,6 +571,7 @@ class EmployeeService extends Service
         $sexMap   = Employee::SEX_TYPE;
         $eduMap   = Employee::Education;
         $stateMap = Employee::State_Type;
+        $eMap = Employee::E_State_Type;
 
         foreach ($dataArray as $main) {
             $empId = $main['id'];
@@ -578,6 +582,7 @@ class EmployeeService extends Service
             $mainInfo['sex_title']       = $sexMap[$main['sex']] ?? '';
             $mainInfo['education_title'] = $eduMap[$main['education']] ?? '';
             $mainInfo['state_title']     = $stateMap[$main['state']] ?? '';
+            $mainInfo['employee_type_title']   = $eMap[$main['employee_type']] ?? '';
 
             if (empty($details)) {
                 // 如果没部门,保底出一行
@@ -634,20 +639,22 @@ class EmployeeService extends Service
         if(! empty($data['sex']) && ! isset(Employee::SEX_TYPE[$data['sex']])) return [false, '性别不存在'];
         if(empty($data['mobile'])) return [false,'联系电话不能为空'];
 //        if(! $this->isValidPhone($data['mobile'])) return [false, '手机号码格式错误'];
-        if(empty($data['major'])) return [false, '专业领域不能为空'];
+//        if(empty($data['major'])) return [false, '专业领域不能为空'];
         if(! empty($data['education']) && ! isset(Employee::Education[$data['education']])) return [false, '学历不存在'];
         if(empty($data['id_card'])) return [false, '身份证号不能为空'];
         if(empty($data['depart'])) return [false,'部门不能为空'];
         if(empty($data['state'])) return [false,'状态不能为空'];
         if(! isset(Employee::State_Type[$data['state']])) return [false,'状态不存在'];
+        if(empty($data['employee_type'])) return [false,'聘用类型不能为空'];
+        if(! isset(Employee::E_State_Type[$data['employee_type']])) return [false,'聘用类型不存在'];
         if(! empty($data['is_admin'])){
             if(! isset(Employee::IS_ADMIN_TITLE_SIMPLE[$data['is_admin']])) return [false, 'is_admin类型不存在'];
             if(empty($data['password'])) return [false, '密码不能为空'];
             if(mb_strlen($data['password']) < 6) return [false, '密码长度不得小于6位长度'];
             if(empty($data['role'])) return [false, '角色不能为空'];
         }
-        if(empty($data['man_type'])) return [false,'是否技术研究人员不能为空'];
-        if(! isset(Employee::Man_Type[$data['man_type']])) return [false,'是否技术研究人员不存在'];
+        if(empty($data['man_type'])) return [false,'是否技术人员不能为空'];
+        if(! isset(Employee::Man_Type[$data['man_type']])) return [false,'是否技术人员不存在'];
         if(! isset($data['entrust_type'])) return [false,'委托方式不能为空'];
         if(! isset(Employee::WT_Type[$data['entrust_type']])) return [false,'委托方式不存在'];
         $data['top_depart_id'] = $user['top_depart_id'];
@@ -854,7 +861,10 @@ class EmployeeService extends Service
 
         $update = $msg['data'][0];
         $model = new Depart();
-        $model->where('id',$data['id'])->update($update);
+        $model->where('id',$data['id'])->update([
+            'title' => $update['title'],
+            'code' => $update['code'],
+        ]);
 
         return [true, ''];
     }
@@ -989,7 +999,6 @@ class EmployeeService extends Service
 
         foreach ($data['data'] as $key => $value){
             $top_depart_id = $user['top_depart_id'];
-            $parent_id = $value['parent_id'];
             if(empty($value['parent_id'])) {
                 $parent_id = $top_depart_id;
                 $data['data'][$key]['parent_id'] = $parent_id;
@@ -1055,22 +1064,4 @@ class EmployeeService extends Service
             ->pluck('title', 'id')
             ->toArray();
     }
-
-    public static function fillMenu2($menu_id, &$user){
-        // 直接查询匹配的菜单
-        $menuItem = SysMenu::where('del_time',0)
-            ->where('id', $menu_id)
-            ->first();
-
-        $func = $menuItem ? $menuItem->export_file_func : "";
-        $funcName = $menuItem ? $menuItem->title : "";
-
-        $header_default = config("excel." . $func) ?? [];
-//        $header_f = "extra_" . $menu_id;
-//        $service = new TableHeadService();
-//        if(method_exists($service,$header_f)) $service->$header_f($header_default);
-        $user['e_header_default'] = $header_default;
-
-        return [$func, $funcName];
-    }
 }

+ 6 - 5
app/Service/ExpenseClaimsService.php

@@ -101,7 +101,8 @@ class ExpenseClaimsService extends Service
                     'employee_id' => $value['employee_id'] ?? "",
                     'fee_id' => $value['fee_id'] ?? 0,
                     'amount' => $value['amount'] ?? 0,
-                    'entrust_amount' => $value['entrust_amount'] ?? 0,
+                    'entrust1_amount' => $value['entrust1_amount'] ?? 0,
+                    'entrust2_amount' => $value['entrust2_amount'] ?? 0,
                     'remark' => $value['remark'] ?? "",
                     'claim_date' => strtotime($value['claim_date']),
                     'entrust_type' => $value['entrust_type'] ?? 0,
@@ -161,12 +162,12 @@ class ExpenseClaimsService extends Service
             if(! isset(ExpenseClaimsDetails::State_Type[$item['entrust_type']])) return [false, "第" . ($index + 1) . "委托类型不存在"];
             $title = ExpenseClaimsDetails::State_Type[$item['entrust_type']];
 
-            if(! isset($item['entrust1_amount'])) return [false, "第" . ($index + 1) . "行{$title}金额不能存在"];
+            if(! isset($item['entrust1_amount'])) return [false, "第" . ($index + 1) . "行境内委托金额不存在"];
             $res = $this->checkNumber($item['entrust1_amount'], 2, 'non-negative');
-            if (!$res['valid']) return [false, "第" . ($index + 1) . "行{$title}金额". $res['error']];
-            if(! isset($item['entrust2_amount'])) return [false, "第" . ($index + 1) . "行{$title}金额不能存在"];
+            if (!$res['valid']) return [false, "第" . ($index + 1) . "行境内委托金额". $res['error']];
+            if(! isset($item['entrust2_amount'])) return [false, "第" . ($index + 1) . "行境外委托金额不存在"];
             $res = $this->checkNumber($item['entrust2_amount'], 2, 'non-negative');
-            if (!$res['valid']) return [false, "第" . ($index + 1) . "行{$title}金额". $res['error']];
+            if (!$res['valid']) return [false, "第" . ($index + 1) . "行境外委托金额". $res['error']];
             $tmp = bcadd($item['entrust1_amount'], $item['entrust2_amount'],2);
             if(floatval($tmp) > $item['amount']) return [false, "第" . ($index + 1) . "行委托金额总和不能超过费用金额"];
         }

+ 156 - 7
app/Service/ExportFileService.php

@@ -8,9 +8,13 @@ use App\Exports\ItemSalarySheetExport;
 use App\Exports\ManMonthlyWorkHourMultipleSheetExport;
 use App\Exports\MultiSheetExport;
 use App\Exports\ProjectDepreciationMultipleSheetExport;
+use App\Exports\ProjectStaffExport;
 use App\Exports\ResearchExpenseMultipleSheetExport;
 use App\Model\Depart;
+use App\Model\Employee;
+use App\Model\Fee;
 use App\Model\PLeaveOverOrder;
+use Illuminate\Support\Carbon;
 use Maatwebsite\Excel\Facades\Excel;
 
 class ExportFileService extends Service
@@ -401,6 +405,31 @@ class ExportFileService extends Service
         return [true, $this->saveExportData($return, $header)];
     }
 
+    //优先级
+    public function priority($ergs, $user)
+    {
+        // 导出配置
+        $return = [];
+        $header_default = $user['e_header_default'];
+        $column = array_column($header_default, 'export');
+        $header = array_column($header_default, 'value');
+
+        $service = new PriorityService();
+        $model = $service->priorityCommon($ergs, $user);
+
+        $model->chunk(500, function ($data) use (&$return, $service, $column, $user) {
+            $data = $data->toArray();
+            $list['data'] = $data;
+
+            //订单数据
+            $list = $service->fillPriorityList($list, $user, true);
+            //返回数据
+            $this->fillData($list['data'], $column, $return);
+        });
+
+        return [true, $this->saveExportData($return, $header)];
+    }
+
     // 项目工资统计表
     public function exportEmployeeSalary($data, $user)
     {
@@ -797,9 +826,8 @@ class ExportFileService extends Service
                 // 填充到动态科目列
                 $rowValues[] = $amount;
 
-                // --- 费用归集逻辑修正 ---
                 // 1. 累加其他相关费用合计 (7.1)
-                $val7_1 += $amount;
+                if(! empty($feeData['is_other']) && $feeData['is_other'] == Fee::IS_OTHER_ONE) $val7_1 += $amount;
 
                 // 2. 累加委托费用 (8.1 和 8.3)
                 $val8_1 += (float)($feeData['entrust1_amount'] ?? 0);
@@ -812,15 +840,16 @@ class ExportFileService extends Service
                 'status' => (($v['state'] ?? '') == "完结" ? 3 : 2),
                 'type'   => $v['expense_type'] ?? '费用化支出',
                 'values' => $rowValues,
-                'val7_1' => $val7_1, // 修正:此处为 total_amount 累加之和
-                'val8_1' => $val8_1, // 修正:此处为 entrust1_amount 累加之和
-                'val8_3' => $val8_3, // 修正:此处为 entrust2_amount 累加之和
+                'val7_1' => $val7_1,
+                'val8_1' => $val8_1,
+                'val8_3' => $val8_3,
             ];
         }
 
         // 年份获取逻辑
-        $timeSource = $data['month_start'] ?? ($data['month_end'] ?? 'now');
-        $year = is_numeric($timeSource) ? date('Y', $timeSource) : date('Y', strtotime($timeSource));
+        $year = Carbon::parse($data['year'])
+            ->setTimezone(config('app.timezone')) // 转换为 Laravel 配置的时区
+            ->format('Y');
 
         // 3. 组织多 Sheet 格式数据
         $monthsData = [
@@ -948,6 +977,126 @@ class ExportFileService extends Service
         return [true, $filename];
     }
 
+    //业研究开发活动汇总表
+    public function exportEnterpriseRdStatistic(array $data, $user)
+    {
+        $service = new StatisticService();
+        list($status, $result) = $service->enterpriseRdStatistic($data, $user);
+        if (!$status) return [false, '获取统计数据失败'];
+
+        $exportData = [];
+        $totalBudget = 0;   // 预算总计累加器
+        $totalActual = 0;   // 支出总计累加器
+        foreach ($result as $row) {
+            $budget = (float)($row['budget'] ?? 0);
+            $actual = (float)($row['actual_expenditure'] ?? 0);
+
+            $totalBudget = bcadd($totalBudget, $budget, 2);
+            $totalActual = bcadd($totalActual, $actual, 2);
+
+            $exportData[] = [
+                'activity_name'   => $row['title'] ?? '',           // 研发活动名称
+                'time_range'      => $row['time_range'] ?? '',      // 起止时间
+                'from'      => $row['from'] ?? '自有技术',      // 起止时间
+                'budget'          => $budget,  // 研发预算
+                'actual_spending' => $actual, // 实际支出
+                'tech_area'       => $row['field'] ?? '',      // 技术领域
+                'remark'          => $row['mark'] ?? '',          // 备注
+            ];
+        }
+        $exportData[] = [
+            'activity_name'   => '',
+            'time_range'      => '',
+            'from'      => '',
+            'budget'          => $totalBudget,
+            'actual_spending' => $totalActual,
+            'tech_area'       => '',
+            'remark'          => '',
+        ];
+
+        $file_name = "企业研究开发活动汇总表_" . date("YmdHis");
+        $filename = $file_name . '.xlsx';
+        $relative_path = "public/export/{$filename}";
+
+        \Maatwebsite\Excel\Facades\Excel::store(
+            new \App\Exports\CompanyRdActivityExport($exportData),
+            $relative_path
+        );
+
+        return [true, $filename];
+    }
+
+    //企业研究开发科技人员情况表
+    public function exportEnterpriseRdManStatistic(array $data, $user)
+    {
+        $service = new StatisticService();
+        list($status, $result) = $service->enterpriseRdManStatistic($data, $user);
+
+        if (!$status) return [false, '获取人员统计数据失败'];
+
+        // 2. 映射数据到导出类需要的字段格式
+        $exportData = [];
+        foreach ($result as $row) {
+            $exportData[] = [
+                'name'            => $row['title'] ?? '',          // 姓名 (对应模型里的 title 字段)
+                'id_card'         => $row['id_card'] ?? '',        // 身份证号码
+                'education'       => Employee::Education[$row['education']] ?? "", // 学历
+                'major'           => $row['major'] ?? '',          // 专业
+                'title_level'     => $row['p_title'] ?? '',    // 职称/职业资格
+                'department_job'  => $row['position_new'] ?? '',       // 部门/岗位
+                'employment_type' => $row['employee_type_title'] ?? "", // 聘用类型
+            ];
+        }
+
+        // 3. 定义文件名和路径
+        $file_name = "企业研究开发科技人员情况表_" . date("YmdHis");
+        $filename = $file_name . '.xlsx';
+        $relative_path = "public/export/{$filename}";
+
+        \Maatwebsite\Excel\Facades\Excel::store(
+            new \App\Exports\TechnicalStaffExport($exportData),
+            $relative_path
+        );
+
+        return [true, $filename];
+    }
+
+    //项目研发活动人员情况表
+    public function exportEnterpriseRdItemStatistic(array $data, $user)
+    {
+        $service = new StatisticService();
+        list($status, $result) = $service->enterpriseRdItemStatistic($data, $user);
+
+        if (!$status) return [false, '获取统计数据失败'];
+
+        // 2. 映射数据到导出类需要的字段格式
+        $exportData = [];
+        foreach ($result as $row) {
+            $exportData[] = [
+                'title'            => $row['title'] ?? '',          // 姓名 (对应模型里的 title 字段)
+                'education'       => Employee::Education[$row['education']] ?? "", // 学历
+                'major'           => $row['major'] ?? '',          // 专业
+                'p_title'     => $row['p_title'] ?? '',    // 职称/职业资格
+                'item_title'  => $row['item_title'] ?? '',       // 项目
+                'item_role'  => $row['item_role'] ?? '',       // 项目角色
+                'depart_title'  => $row['depart_title'] ?? '',       // 部门
+                'duty' => $row['duty'] ?? "", // 职责
+            ];
+        }
+
+        // 3. 定义文件名和路径
+        $file_name = "项目研发活动人员情况表_" . date("YmdHis");
+        $filename = $file_name . '.xlsx';
+        $relative_path = "public/export/{$filename}";
+
+        \Maatwebsite\Excel\Facades\Excel::store(
+            new \App\Exports\ProjectStaffExport($exportData),
+            $relative_path
+        );
+
+        return [true, $filename];
+    }
+
     public function saveExportData($data, $headers, $type = 'default',$file_name = ''){
         if(empty($file_name)) $file_name = self::$filename . "_". date("Y-m-d") . "_". rand(1000,9999);
         $filename =  $file_name . '.' . 'xlsx';

+ 147 - 0
app/Service/ImportService.php

@@ -18,6 +18,7 @@ use App\Model\MonthlyDdOrder;
 use App\Model\MonthlyPsOrder;
 use App\Model\MonthlyPwOrder;
 use App\Model\PLeaveOverOrder;
+use App\Model\Priority;
 use App\Model\RuleSet;
 use App\Model\RuleSetDetails;
 use Illuminate\Support\Facades\DB;
@@ -45,6 +46,7 @@ class ImportService extends Service
         'overtimeOrder', // 加班单
         'feeOrder', // 费用项目单
         'RDOrder', // 研发支出辅助帐
+        'priority', // 优先级
     ];
 
     public function getTableTitleXls($data,$user){
@@ -301,6 +303,7 @@ class ImportService extends Service
         $manIdx = array_search('man_type', $keys);
         $entrustIdx = array_search('entrust_type', $keys);
         $depIdx = array_search('depart_code', $keys);
+        $employeeTypeIdx = array_search('employee_type', $keys);
 
         $code_map = $this->getEmployeeList($array, $user, $codeIdx);
         $dep_map = $this->getEDataList($array, $user, $depIdx);
@@ -315,6 +318,7 @@ class ImportService extends Service
         $state_map = array_flip(Employee::State_Type);
         $man_map = array_flip(Employee::Man_Type);
         $wt_map = array_flip(Employee::WT_Type);
+        $employeeT_map = array_flip(Employee::E_State_Type);
 
         // 获取所有标记为 is_main 的列索引,用于一致性对比
         $mainColIndices = [];
@@ -374,6 +378,13 @@ class ImportService extends Service
             } else {
                 $array[$rowIndex][$stateIdx] = $state_map[$state_text];
             }
+            // 外聘类型
+            $e_text = trim($rowValue[$employeeTypeIdx] ?? '');
+            if (!isset($employeeT_map[$e_text])) {
+                $errors[] = "第{$displayLine}行:外聘类型[{$e_text}]无效";
+            } else {
+                $array[$rowIndex][$employeeTypeIdx] = $employeeT_map[$e_text];
+            }
 
             //人员类别
             $man_text = trim($rowValue[$manIdx] ?? '');
@@ -3958,6 +3969,142 @@ class ImportService extends Service
         return [!empty($errors) ? implode('|', $errors) : "", $update_map, $maps];
     }
 
+    // 优先级
+    public function priorityImport($array, $user, $other_param)
+    {
+        $upload = $array[0];
+        list($status, $msg) = $this->compareTableAndReturn($upload, $other_param);
+        if (!$status) return [false, $msg];
+        $table_config = $msg;
+
+        unset($array[0]);
+        if (empty($array)) return [false, '导入数据不能为空'];
+
+        // 基础格式校验
+        list($array, $error) = $this->checkCommon($array, $table_config);
+        if (!empty($error)) return [0, $error];
+
+        // 2. 业务逻辑校验
+        list($error, $update_map) = $this->priorityCheck($array, $user, $table_config);
+        if (!empty($error)) return [0, $error];
+
+        $time = time();
+        $insert = [];
+        $update = [];
+
+        foreach ($array as $key => $value) {
+            $main_tmp = [];
+            foreach ($value as $k => $val){
+                if(!empty($table_config[$k]['is_main'])){
+                    $main_tmp[$table_config[$k]['key']] = $val;
+                }
+            }
+
+            if (isset($update_map[$key])) {
+                // 更新逻辑
+                $update[] = array_merge($main_tmp, [
+                    'id' => $update_map[$key],
+                ]);
+            } else {
+                // 新增逻辑
+                $main_tmp['top_depart_id'] = $user['top_depart_id'];
+                $main_tmp['crt_time'] = $time;
+                $insert[] = $main_tmp;
+            }
+        }
+
+        DB::beginTransaction();
+        try {
+            if (!empty($insert)) {
+                foreach (array_chunk($insert, 500) as $chunk) {
+                    Priority::insert($chunk);
+                }
+            }
+
+            if (!empty($update)) {
+                foreach ($update as $item) {
+                    $uId = $item['id'];
+                    unset($item['id']);
+                    Priority::where('id', $uId)->update($item);
+                }
+            }
+
+            DB::commit();
+        } catch (\Exception $e) {
+            DB::rollBack();
+            return [false, "导入失败:" . $e->getMessage()];
+        }
+        return [true, ''];
+    }
+
+    private function priorityCheck(&$array, $user, $table_config)
+    {
+        $keys = array_column($table_config, 'key');
+        $codeIdx = array_search('code', $keys);
+        $sortIdx = array_search('sort', $keys);
+        $typeIdx = array_search('type', $keys);
+        $isUseIdx = array_search('is_use', $keys);
+
+        $type_map = array_flip(Priority::TYPE_TITLE);
+        $isUse_map = array_flip(Priority::IS_USE);
+
+        // 获取当前企业下已存在的优先级,用于判断是新增还是更新
+        $dbMap = Priority::where('del_time', 0)
+            ->where('top_depart_id', $user['top_depart_id'])
+            ->get()
+            ->keyBy('code')
+            ->toArray();
+
+        $errors = [];
+        $update = [];
+        $excelCodes = [];
+
+        foreach ($array as $rowIndex => $value) {
+            $displayLine = $rowIndex + 1;
+            $valCode = trim($value[$codeIdx] ?? '');
+
+            if ($valCode === '') {
+                $errors[] = "第{$displayLine}行:编码不能为空";
+                continue;
+            }
+
+            // 校验 Excel 内部是否重复
+            if (isset($excelCodes[$valCode])) {
+                $errors[] = "第{$displayLine}行:编码[{$valCode}]在文件中重复出现";
+                continue;
+            }
+            $excelCodes[$valCode] = true;
+
+            // 类型
+            $e_text = $value[$typeIdx] ?? '';
+            if (!isset($type_map[$e_text])) {
+                $errors[] = "第{$displayLine}行:类型[{$e_text}]无效";
+            } else {
+                $array[$rowIndex][$typeIdx] = $type_map[$e_text];
+            }
+
+            // 是否启用
+            $e_text = $value[$isUseIdx] ?? '';
+            if (!isset($isUse_map[$e_text])) {
+                $errors[] = "第{$displayLine}行:是否启用[{$e_text}]无效";
+            } else {
+                $array[$rowIndex][$isUseIdx] = $isUse_map[$e_text];
+            }
+
+            // 数字格式校验
+            $sort = $value[$sortIdx];
+            if (filter_var($sort, FILTER_VALIDATE_INT) === false) return [false, "第{$displayLine}行排序字段排序字段必须是整数且不能含有小数点"];
+
+            // 如果数据库已存在,记录为更新操作
+            if (isset($dbMap[$valCode])) {
+                $update[$rowIndex] = $dbMap[$valCode]['id'];
+            }
+        }
+
+        $error_string = !empty($errors) ? implode('|', $errors) : "";
+        return [$error_string, $update];
+    }
+
     /**
      * 解析并校验时间
      */

+ 9 - 9
app/Service/ItemService.php

@@ -26,7 +26,7 @@ class ItemService extends Service
             $model->state = $data['state'] ?? 0;
             $model->budget = $data['budget'] ?? 0;
             $model->charge_id = $data['charge_id'] ?? 0;
-            $model->field = $data['field'] ?? 0;
+            $model->field = $data['field'] ?? "";
             $model->item_attribute = $data['item_attribute'] ?? 0;
             $model->save();
 
@@ -61,7 +61,7 @@ class ItemService extends Service
             $model->state = $data['state'] ?? 0;
             $model->budget = $data['budget'] ?? 0;
             $model->charge_id = $data['charge_id'] ?? 0;
-            $model->field = $data['field'] ?? 0;
+            $model->field = $data['field'] ?? "";
             $model->item_attribute = $data['item_attribute'] ?? 0;
             $model->crt_id = $user['id'];
             $model->top_depart_id = $data['top_depart_id'];
@@ -69,11 +69,11 @@ class ItemService extends Service
 
             $this->saveDetail($model->id, time(), $data);
 
-            list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id,$data,$user);
-            if (!$status) {
-                DB::rollBack();
-                return [false, $msg];
-            }
+//            list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id,$data,$user);
+//            if (!$status) {
+//                DB::rollBack();
+//                return [false, $msg];
+//            }
 
             DB::commit();
         }catch (\Exception $exception){
@@ -413,11 +413,11 @@ class ItemService extends Service
             if ($item->type == ItemDetails::type_one) {
                 $emp = $empMap[$item->data_id] ?? null;
                 $detailRow['code_2'] = $emp ? $emp->number : '';
-                $detailRow['title']  = $emp ? $emp->title : '';
+                $detailRow['title_2']  = $emp ? $emp->title : '';
             } else {
                 $dev = $devMap[$item->data_id] ?? null;
                 $detailRow['code_2'] = $dev ? $dev->code : '';
-                $detailRow['title']  = $dev ? $dev->title : '';
+                $detailRow['title_2']  = $dev ? $dev->title : '';
             }
 
             // 归档到对应的主表 ID 下

+ 81 - 18
app/Service/LoginService.php

@@ -26,19 +26,90 @@ class LoginService extends Service
         $employee = $employee->toArray();
 
         if(! Hash::check($password, $employee['password'])) return [false,'密码错误'];
-        if($employee['is_admin'] == Employee::IS_ADMIN_ZERO) return [false, '账号限制登录'];
+        if($employee['is_admin'] == Employee::IS_ADMIN_ZERO || $employee['is_admin'] == Employee::IS_ADMIN_THREE) return [false, '账号限制登录'];
 
         //生成token
         list($status, $jwtToken) = TokenService::getToken($employee);
         if(! $status) return [false, $jwtToken];
 
+        //获取人员所有的所有的顶级菜单
+        $sysMenu = $this->getPersonRoleForSysMenuList($employee['id']);
+        if(empty($sysMenu)) return [false, '账户未设置菜单功能'];
+
         return [true, [
             'token' => $jwtToken,
             'employee_id' => $employee['id'],
             'title' => $employee['title'],
+            'sys_menu' => $sysMenu,
         ]];
     }
 
+    public function clogin($data){
+        if(empty($data['account'])) return [false, '账号不能为空'];
+        if(empty($data['password'])) return [false, '密码不能为空'];
+
+        $account = $data['account'];
+        $password = $data['password'];
+        $employee = Employee::where('del_time',0)
+            ->where('account', $account)
+            ->first();
+        if(empty($employee)) return [false,'账号不存在或已被删除'];
+        $employee = $employee->toArray();
+
+        if(! Hash::check($password, $employee['password'])) return [false,'密码错误'];
+        if($employee['is_admin'] != Employee::IS_ADMIN_THREE) return [false, '账号限制登录'];
+
+        //生成token
+        list($status, $jwtToken) = TokenService::getToken($employee);
+        if(! $status) return [false, $jwtToken];
+
+        return [true, [
+            'token' => $jwtToken,
+            'employee_id' => $employee['id'],
+            'title' => $employee['title'],
+        ]];
+    }
+
+    private function getPersonRoleForSysMenuList($employee_id) {
+        $sysMenu = SysMenu::where('del_time',0)
+            ->where('type', SysMenu::type_zero)
+            ->where('parent_id', 0)
+            ->select('id','title', 'tree_type', 'uri')
+            ->get()->toArray();
+
+        $role_menu_id = EmployeeRole::from('employee_role as a')
+            ->join('role_menu as b', 'b.role_id', '=', 'a.role_id')
+            ->where('a.del_time', 0)
+            ->where('b.del_time', 0)
+            ->whereIn('b.menu_id', array_column($sysMenu,'id'))
+            ->where('a.employee_id',$employee_id)
+            ->pluck('b.menu_id')
+            ->toArray();
+
+        foreach ($sysMenu as $key => $value){
+            if(! in_array($value['id'], $role_menu_id)) unset($sysMenu[$key]);
+        }
+
+        return array_values($sysMenu);
+    }
+
+    public static function hasPersonRoleForSysMenuList($employee_id, $tree_type) {
+        $sysMenu = SysMenu::where('del_time',0)
+            ->where('type', SysMenu::type_zero)
+            ->where('parent_id', 0)
+            ->where('tree_type', $tree_type)
+            ->pluck('id')
+            ->toArray();
+
+        return EmployeeRole::from('employee_role as a')
+            ->join('role_menu as b', 'b.role_id', '=', 'a.role_id')
+            ->where('a.del_time', 0)
+            ->where('b.del_time', 0)
+            ->where('b.menu_id', $sysMenu)
+            ->where('a.employee_id',$employee_id)
+            ->exists();
+    }
+
     public static function checkUser($employee){
         if(empty($employee['employee_id'])) return [false, 'token错误'];
         if(! isset($employee['p_version'])) return [false, 'token错误'];
@@ -47,15 +118,13 @@ class LoginService extends Service
             ->first();
         if(empty($result)) return [false, '账号不存在或已被删除'];
         $result = $result->toArray();
-        if($result['is_admin'] == Employee::IS_ADMIN_ZERO) return [false, '账号限制登录'];
+        if($result['is_admin'] == Employee::IS_ADMIN_ZERO || $result['is_admin'] == Employee::IS_ADMIN_THREE) return [false, '账号限制登录'];
         if($result['p_version'] != $employee['p_version']) return [false, '请重新登录'];
 
         return [true, $result];
     }
 
     public static function checkCompany($employee){
-        $employee_id = $employee['id'];
-//        if ($employee_id == Employee::SPECIAL_ADMIN) return [true, ''];
         $top_depart_id = $employee['top_depart_id'];
         if(empty($top_depart_id)) return [false, '公司信息不存在'];
 
@@ -115,26 +184,20 @@ class LoginService extends Service
     }
 
     public static function getPersonRoleAndPermissions($employee) {
-        // 1. 初始化返回结构
+        // 初始化返回结构
         $result = [
             'role_ids'    => [],
             'menu_permissions' => []
         ];
 
-        // 2. 是管理员账户
-        if ($employee['is_admin'] == Employee::IS_ADMIN_TWO) {
-            return $result;
-        }
+//        // 2. 是管理员账户
+//        if ($employee['is_admin'] == Employee::IS_ADMIN_TWO) {
+//            return $result;
+//        }
 
-        $role_ids = EmployeeRole::from('employee_role as a')
-            ->join('role as b', 'b.id', '=', 'a.role_id')
-            ->where('a.del_time', 0)
-            ->where('b.top_depart_id', $employee['top_depart_id'])
-            ->where('a.employee_id', $employee['id'])
-            ->pluck('a.role_id')
-            ->unique()
-            ->sort()
-            ->values()
+        $role_ids = EmployeeRole::where('del_time', 0)
+            ->where('employee_id', $employee['id'])
+            ->pluck('role_id')
             ->toArray();
 
         if (empty($role_ids)) return $result;

+ 520 - 0
app/Service/MiddleGroundService.php

@@ -0,0 +1,520 @@
+<?php
+
+namespace App\Service;
+
+use App\Model\Depart;
+use App\Model\Employee;
+use App\Model\EmployeeDepartPermission;
+use App\Model\EmployeeRole;
+use App\Model\Role;
+use App\Model\RoleMenu;
+use App\Model\RoleMenuButton;
+use App\Model\SysMenu;
+use App\Model\SysMenuButton;
+use App\Model\WorkRangeDetails;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Hash;
+
+class MiddleGroundService extends Service
+{
+    // 角色 ---------------------------------------
+    public function roleEdit($data,$user){
+        list($status,$msg) = $this->roleRule($data,$user, false);
+        if(!$status) return [$status,$msg];
+
+        $model = new Role();
+        $model = $model->where('id',$data['id'])->first();
+        $model->title = $data['title'];
+        $model->save();
+
+        return [true,''];
+    }
+
+    public function roleAdd($data,$user){
+        list($status,$msg) = $this->roleRule($data,$user);
+        if(!$status) return [$status,$msg];
+
+        $model = new Role();
+        $model->title = $data['title'] ;
+        $model->top_depart_id = $user['top_depart_id'];
+        $model->save();
+
+        return [true,''];
+    }
+
+    public function roleDel($data, $user){
+        if($this->isEmpty($data,'id')) return [false,'ID必须!'];
+
+        $bool = EmployeeRole::where('del_time',0)
+            ->whereIn('role_id',$data['id'])
+            ->exists();
+        if($bool) return [false,'角色已绑定人员'];
+
+        try {
+            DB::beginTransaction();
+            $time = time();
+
+            Role::where('id',$data['id'])->update([
+                'del_time' => $time
+            ]);
+
+            RoleMenu::where('del_time',0)->where('role_id',$data['id'])->update([
+                'del_time' => $time
+            ]);
+
+            RoleMenuButton::where('del_time',0)->where('role_id',$data['id'])->update([
+                'del_time' => $time
+            ]);
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false,$exception->getMessage()];
+        }
+
+        return [true, ''];
+    }
+
+    public function roleList($data,$user){
+        $model = Role::TopClear($user,$data);
+        $model = $model->where('del_time',0)
+            ->select('title','crt_time','id','upd_time')
+            ->orderBy('id','desc');
+        if(! empty($data['title'])) $model->where('title', 'LIKE', '%' . $data['title'] . '%');
+
+        $list = $this->limit($model,'',$data);
+
+        return [true, $list];
+    }
+
+    public function roleRule(&$data,$user, $is_check = true){
+        if($this->isEmpty($data,'title')) return [false,'名称不能为空'];
+
+        if($is_check){
+            $bool = Role::where('title',$data['title'])
+                ->where('top_depart_id', $user['top_depart_id'])
+                ->where('del_time',0)
+                ->exists();
+            if($bool) return [false,'角色名称已存在'];
+        }else{
+            if($this->isEmpty($data,'id')) return [false,'ID不能为空'];
+            $top_depart_id = Role::where('id',$data['id'])->value('top_depart_id');
+            $bool = Role::where('title',$data['title'])
+                ->where('top_depart_id',$top_depart_id)
+                ->where('id','<>',$data['id'])
+                ->where('del_time',0)
+                ->exists();
+            if($bool) return [false,'角色名称已存在'];
+        }
+
+        return [true, ''];
+    }
+
+    public function roleMenu($data){
+        if(empty($data['role_id']))  return [false,'角色不能为空!'];
+        if(empty($data['menu'])) return [false,'菜单数据不能为空!'];
+
+        DB::beginTransaction();
+        try {
+            RoleMenu::where('del_time',0)->where('role_id',$data['role_id'])->update(['del_time' => time()]);
+            RoleMenuButton::where('del_time',0)->where('role_id',$data['role_id'])->update(['del_time' => time()]);
+
+            $insert = $insert2 = [];
+            foreach ($data['menu'] as $t){
+                $insert[] = [
+                    'role_id' => $data['role_id'],
+                    'menu_id' => $t['menu_id'],
+                    'type' => $t['type'],
+                    'crt_time' => time()
+                ];
+                if(! empty($t['button'])){
+                    foreach ($t['button'] as $b){
+                        $insert2[] = [
+                            'role_id' => $data['role_id'],
+                            'menu_id' => $t['menu_id'],
+                            'button_id' => $b,
+                            'crt_time' => time()
+                        ];
+                    }
+                RoleMenuButton::insert($insert2);
+                }
+            }
+            RoleMenu::insert($insert);
+
+            DB::commit();
+        }catch (\Throwable $exception){
+            DB::rollBack();
+            return [false,$exception->getMessage()];
+        }
+
+        return [true, ''];
+    }
+
+    public function roleDetail($data){
+        if(empty($data['role_id'])) return [false,'请选择角色'];
+
+        $role = Role::where('id',$data['role_id'])
+            ->where('del_time',0)
+            ->select('id','title')
+            ->first();
+        if(empty($role)) return [false,'角色不存在或已被删除'];
+        $role = $role->toArray();
+
+        $menu = RoleMenu::where('role_id',$data['role_id'])
+            ->where('del_time',0)
+            ->select('menu_id','type')
+            ->get()->toArray();
+        $button = $this->fillRoleButton([$data['role_id']]);
+        foreach ($menu as $key => $value){
+            $menu[$key]['button'] = $button[$value['menu_id']] ?? [];
+        }
+        $role['menu'] = $menu;
+
+        return [true, $role];
+    }
+
+    public function fillRoleButton($role_id){
+        $button = RoleMenuButton::whereIn('role_id',$role_id)
+            ->where('del_time',0)
+            ->select('menu_id','button_id')
+            ->get()->toArray();
+        $button_map = [];
+        foreach ($button as $value){
+            if(! isset($button_map[$value['menu_id']])){
+                $button_map[$value['menu_id']][] = $value['button_id'];
+            }else{
+                if(! in_array($value['button_id'], $button_map[$value['menu_id']])) $button_map[$value['menu_id']][] = $value['button_id'];
+            }
+        }
+
+        return $button_map;
+    }
+
+    public function initializationCompanyList($data, $user){
+        $model = Depart::where('del_time',0)
+            ->where('parent_id', 0)
+            ->select('*')
+            ->orderby('id', 'desc');
+
+        if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
+        if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
+
+        $list = $this->limit($model,'',$data);
+
+        return [true, $list];
+    }
+
+    // 公司初始化 返回 公司后台管理员账户 密码
+    public function initializationCompany($data, $user){
+        if(empty($data['title'])) return [false, '公司名称不能为空'];
+        if(empty($data['code'])) return [false, '公司代码不能为空'];
+
+        // ^[A-Za-z]+$  表示从头到尾只能是英文字母(不区分大小写)
+        if (! preg_match('/^[A-Za-z]+$/', $data['code']) || mb_strlen($data['code']) < 4) return [false, "公司代码必须全为英文且长度需大于等于 4 位"];
+
+        $exists = Depart::where('parent_id', 0)
+            ->where('del_time', 0)
+            ->where(function($query) use ($data) {
+                $query->where('title', $data['title'])
+                    ->orWhere('code', $data['code']);
+            })
+            ->exists();
+        if($exists) return [false, '公司名称或公司代码已存在,新增失败'];
+
+        $account = $data['code'] . "_" . 'admin';
+        $exists = Employee::where('del_time', 0)
+            ->where('account', $account)
+            ->exists();
+        if($exists) return [false, '创建账号已存在,新增失败'];
+
+        try {
+            DB::beginTransaction();
+
+            //创建公司
+            $model = new Depart();
+            $model->parent_id = 0;
+            $model->title = $data['title'];
+            $model->code = $data['code'];
+            $model->top_depart_id = 0;
+            $model->save();
+            //公司ID
+            $top_depart_id = $model->id;
+
+            $password = $this->generateAt8CharPassword();
+            //创建账号
+            $model_2 = new Employee();
+            $model_2->title = $data['title'];
+            $model_2->account = $account;
+            $model_2->password = Hash::make($password);
+            $model_2->is_admin = Employee::IS_ADMIN_TWO;
+            $model_2->top_depart_id = $top_depart_id;
+            $model_2->state = Employee::TYPE_ONE;
+            $model_2->save();
+            $employee_id = $model_2->id;
+
+            //关联人员的部门初始信息
+            $model_3 = new EmployeeDepartPermission();
+            $model_3->employee_id = $employee_id;
+            $model_3->depart_id = 0;
+            $model_3->top_depart_id = $top_depart_id;
+            $model_3->save();
+
+            //公司上班时段
+            $work_range[] = [
+                'top_depart_id' => $top_depart_id,
+                'start_time_hour' => 9,
+                'start_time_min' => 0,
+                'end_time_hour' => 12,
+                'end_time_min' => 0,
+                'total_work_min' => 180,
+            ];
+            $work_range[] = [
+                'top_depart_id' => $top_depart_id,
+                'start_time_hour' => 13,
+                'start_time_min' => 0,
+                'end_time_hour' => 18,
+                'end_time_min' => 0,
+                'total_work_min' => 300,
+            ];
+            WorkRangeDetails::insert($work_range);
+
+            DB::commit();
+        }catch (\Throwable $exception){
+            DB::rollBack();
+            return [false, $exception->getMessage()];
+        }
+
+        return [true, ['account' => $account, 'password' => $password]];
+    }
+
+    function generateAt8CharPassword() {
+        $lettersNumbers = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
+
+        $password = '@'; // 1. 先把固定的 @ 放进去
+
+        // 2. 随机抽取 6 位英文或数字
+        for ($i = 0; $i < 6; $i++) {
+            $password .= $lettersNumbers[random_int(0, strlen($lettersNumbers) - 1)];
+        }
+
+        // 3. 打乱顺序,让 @ 的位置不固定
+        return str_shuffle($password);
+    }
+
+    // 菜单
+    public function menuList($data, $user){
+        $type = $data['type'] ?? "";
+
+        if(empty($type)){
+            //权限
+            $sysList = SysMenu::where('del_time',0)
+                ->where('type', SysMenu::type_zero)
+                ->select('title','icon','uri','parent_id','sort','id','is_authority', 'state')
+                ->orderBy('sort','desc')
+                ->get()
+                ->toArray();
+            $button = SysMenuButton::where('del_time',0)
+                ->select('id','title','sort','func','menu_id')
+                ->get()->toArray();
+
+            $return = $this->fillMenuButton($button,$sysList, $user);
+        }elseif($type == "all"){
+            $sysList = SysMenu::where('del_time',0)
+                ->where('type', SysMenu::type_one)
+                ->select('title','icon','uri','parent_id','sort','id','is_authority', 'state')
+                ->orderBy('sort','desc')
+                ->get()
+                ->toArray();
+            //侧边栏
+            $return = $this->returnTwo($sysList, $user);
+
+            $return = [
+                'one' => $sysList,
+                'two' => $return,
+            ];
+        }
+
+
+        return [true, $return];
+    }
+
+    private function returnTwo($sysList, $user){
+        foreach ($sysList as $key => $value){
+            if($value['state'] <= 0) unset($sysList[$key]);
+        }
+        $list = array_values($sysList);
+        $return = $this->makeTree(0,$list);
+
+        return $this->set_sort_circle($return);;
+    }
+
+    public function fillMenuButton($button, $menu, $user)
+    {
+        // 1. 预处理所有按钮池(合并配置中的特殊按钮)
+        $allButtons = collect($button)->concat(config('specialButton') ?? [])->groupBy('menu_id');
+
+        // 2. 获取权限基础数据
+        $isSuper = ($user['is_admin'] == Employee::IS_ADMIN_THREE);
+
+        $result = [];
+
+        foreach ($menu as $m) {
+            $menuId = $m['id'];
+
+            // 权限过滤:非超管
+            if (!$isSuper) continue;
+
+            // 计算当前菜单拥有的按钮
+            $btns = $allButtons->get($menuId) ?? [];
+
+            $m['button'] = $btns;
+
+            $result[] = $m;
+        }
+
+        return $result;
+    }
+
+    // 管理员
+    public function employeeCommon($data,$user){
+        $model = Employee::where('del_time',0)
+            ->where('is_admin', Employee::IS_ADMIN_TWO)
+            ->select('id', 'account', 'crt_time', 'top_depart_id','title')
+            ->orderBy('id','desc');
+
+        if(! empty($data['id'])) $model->whereIn('id', $data['id']);
+        if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
+        if(! empty($data['mobile'])) $model->where('mobile', 'LIKE', '%'.$data['mobile'].'%');
+        if(! empty($data['role'])) {
+            $emp = EmployeeRole::where('role_id',$data['role'])
+                ->where('del_time',0)
+                ->select('employee_id')->get()->toArray();
+            $model->whereIn('id',array_column($emp,'employee_id'));
+        }
+
+        return $model;
+    }
+
+    public function employeeList($data,$user){
+        $model = $this->employeeCommon($data, $user);
+        $list = $this->limit($model,'',$data);
+        $list = $this->organizationEmployeeData($list, $data, $user);
+
+        return [true, $list];
+    }
+
+    public function organizationEmployeeData($data, $ergs, $user)
+    {
+        if (empty($data['data'])) return $data;
+
+        // 获取员工ID并查询扩展数据
+        $employee_ids = array_column($data['data'], 'id');
+        list($status, $extraMap) = $this->getEmployee($employee_ids);
+
+        $depart_map = Depart::whereIn('id', array_unique(array_column($data['data'],'top_depart_id')))
+            ->pluck('title', 'id')
+            ->toArray();
+        foreach ($data['data'] as &$item) {
+            $id = $item['id'];
+            $extra = $extraMap[$id] ?? null;
+
+            $item['role'] = $extra['role_ids'] ?? [];
+            $item['role_name'] = isset($extra['role_names']) ? implode(',', $extra['role_names']) : '';
+            $item['top_depart_title'] = $depart_map[$item['top_depart_id']];
+
+            $item['crt_time'] = !empty($item['crt_time']) ? date("Y-m-d", $item['crt_time']) : "";
+        }
+
+        return $data;
+    }
+
+    public function getEmployee(array $employee_ids)
+    {
+        if (empty($employee_ids)) return [false, []];
+
+        // 1. 一次性获取所有角色
+        $roles = DB::table('employee_role as a')
+            ->join('role as b', 'a.role_id', '=', 'b.id')
+            ->where('a.del_time', 0)
+            ->where('b.del_time', 0)
+            ->whereIn("a.employee_id", $employee_ids)
+            ->select('a.employee_id', 'b.title', 'b.id')
+            ->get();
+        $resultMap = [];
+
+        foreach ($roles as $r) {
+            $resultMap[$r->employee_id]['role_ids'][] = $r->id;
+            $resultMap[$r->employee_id]['role_names'][] = $r->title;
+        }
+
+        return [true, $resultMap];
+    }
+
+    public function employeeEdit($data,$user){
+        list($status,$msg) = $this->employeeRule($data,$user,false);
+        if(!$status) return [$status,$msg];
+
+        try {
+            DB::beginTransaction();
+            $model = new Employee();
+            $model = $model->where('id',$data['id'])->first();
+            if($model->is_admin && $data['password'] !== '******') {
+                $model->password = Hash::make($data['password']);
+                $model->p_version = $model->p_version + 1;
+            }
+            $model->save();
+
+            $time = time();
+
+            EmployeeRole::where('employee_id',$data['id'])->update([
+                'del_time' => $time
+            ]);
+
+            if(! empty($data['role'])){
+                $insert = [];
+                foreach ($data['role'] as $value){
+                    $insert[] = [
+                        'employee_id' => $model->id,
+                        'role_id' => $value,
+                        'crt_time' => $time,
+                    ];
+                }
+                EmployeeRole::insert($insert);
+            }
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false, $exception->getMessage()];
+        }
+
+        return [true, ''];
+    }
+
+    public function employeeRule(&$data, $user, $is_add = true){
+        if(empty($data['id'])) return [false, '管理员ID不能为空'];
+        $bool = Employee::where('del_time',0)
+            ->where('id', $data['id'])
+            ->exists();
+        if(! $bool) return [false, '管理员账户不存在或已被删除'];
+
+        if(empty($data['password'])) return [false, '密码不能为空'];
+        if(mb_strlen($data['password']) < 6) return [false, '密码长度不得小于6位长度'];
+
+        return [true, ''];
+    }
+
+    public static function checkCenterUser($employee){
+        if(empty($employee['employee_id'])) return [false, 'token错误'];
+        if(! isset($employee['p_version'])) return [false, 'token错误'];
+        $result = Employee::where('id', $employee['employee_id'])
+            ->where('del_time',0)
+            ->first();
+        if(empty($result)) return [false, '账号不存在或已被删除'];
+        $result = $result->toArray();
+        if($result['is_admin'] != Employee::IS_ADMIN_THREE) return [false, '账号限制登录'];
+        if($result['p_version'] != $employee['p_version']) return [false, '请重新登录'];
+
+        return [true, $result];
+    }
+}

+ 1 - 1
app/Service/PLeaveOverService.php

@@ -393,7 +393,7 @@ class PLeaveOverService extends Service
         if(empty($data['data'])) return $data;
 
         $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'crt_id')));
-        $map = ArchiveService::fillIsArchive(array_unique(array_column($data['data'],'month')), $user);
+        $map = ArchiveService::fillIsArchive(array_unique(array_column($data['data'],'order_time')), $user);
 
         foreach ($data['data'] as $key => $value){
             $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';

+ 31 - 13
app/Service/PersonWorkService.php

@@ -164,6 +164,8 @@ class PersonWorkService extends Service
         $customer = $customer->toArray();
         $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
         $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
+        $map = ArchiveService::fillIsArchive($customer['month'], $user);
+        $customer['is_archive'] = $map[$customer['month']] ?? false;
         $customer['month'] = $customer['month'] ? date("Y-m",$customer['month']): '';
 
         $details = $this->getDetail($data['id']);
@@ -199,7 +201,7 @@ class PersonWorkService extends Service
     public function monthlyPwOrderList($data,$user){
         $model = $this->monthlyPwOrderCommon($data, $user);
         $list = $this->limit($model,'',$data);
-        $list = $this->fillData($list);
+        $list = $this->fillData($list, $user);
 
         return [true, $list];
     }
@@ -289,14 +291,17 @@ class PersonWorkService extends Service
         return [true, ''];
     }
 
-    public function fillData($data){
+    public function fillData($data, $user){
         if(empty($data['data'])) return $data;
 
         $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'crt_id')));
+        $map = ArchiveService::fillIsArchive(array_unique(array_column($data['data'],'month')), $user);
+
         foreach ($data['data'] as $key => $value){
             $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
             $data['data'][$key]['month'] = $value['month'] ? date('Y-m',$value['month']) : '';
             $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
+            $data['data'][$key]['is_archive'] = $map[$value['month']] ?? false;
         }
 
         return $data;
@@ -526,6 +531,8 @@ class PersonWorkService extends Service
         $item = Item::where('id', $customer['item_id'])->first();
         $customer['item_title'] = $item->title;
         $customer['item_code'] = $item->code;
+        $map = ArchiveService::fillIsArchive($customer['order_time'], $user);
+        $customer['is_archive'] = $map[$customer['order_time']] ?? false;
         $customer['order_time'] = $customer['order_time'] ? date("Y-m-d",$customer['order_time']): '';
 
         $details = $this->getDetailDaily($data['id']);
@@ -569,7 +576,7 @@ class PersonWorkService extends Service
     public function dailyPwOrderList($data,$user){
         $model = $this->dailyPwOrderCommon($data, $user);
         $list = $this->limit($model,'',$data);
-        $list = $this->fillDataDaily($list);
+        $list = $this->fillDataDaily($list, $user);
 
         return [true, $list];
     }
@@ -605,29 +612,38 @@ class PersonWorkService extends Service
         $internalOverlap = [];
 
         foreach ($data['details'] as $key => $value){
+            $line = $key + 1;
+            $t = "第" . $line . "行";
+
             $empId = $value['employee_id'] ?? 0;
             if(empty($empId)) return [false, '人员不能为空'];
 
             $empName = $empDisplayMap[$empId] ?? "ID:{$empId}";
 
             $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}开始点:" . $res['error']];
-            if($value['start_time_hour'] > 23) return [false, false, "人员{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}开始点:" . $res['error']];
+            if($value['start_time_hour'] > 23) return [false, false, $t . "人员{$empName}开始点不合法"];
             $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}开始分:" . $res['error']];
-            if($value['start_time_min'] > 60) return [false, false, "人员{$empName}开始点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}开始分:" . $res['error']];
+            if($value['start_time_min'] > 60) return [false, false, $t . "人员{$empName}开始点不合法"];
             $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}结束点:" . $res['error']];
-            if($value['end_time_hour'] > 24) return [false, false, "人员{$empName}结束点不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}结束点:" . $res['error']];
+            if($value['end_time_hour'] > 24) return [false, false, $t . "人员{$empName}结束点不合法"];
             $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
-            if(!$res['valid']) return [false, "人员{$empName}结束分:" . $res['error']];
-            if($value['end_time_min'] > 60) return [false, false, "人员{$empName}结束分不合法"];
+            if(!$res['valid']) return [false, $t . "人员{$empName}结束分:" . $res['error']];
+            if($value['end_time_min'] > 60) return [false, false, $t .  "人员{$empName}结束分不合法"];
 
             $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
             $currentEnd   = $value['end_time_hour'] * 60 + $value['end_time_min'];
 
             if ($currentStart >= $currentEnd) {
-                return [false, "人员{$empName}:开始时间必须早于结束时间"];
+                return [false, $t . "人员{$empName}:开始时间必须早于结束时间"];
+            }
+
+            // --- 新增:总分钟数校验 ---
+            $calculatedTotal = $currentEnd - $currentStart;
+            if (!isset($value['total_work_min']) || intval($value['total_work_min']) !== $calculatedTotal) {
+                return [false, $t . "人员{$empName}:总工时计算有误,应为 {$calculatedTotal} 分钟"];
             }
 
             // --- 3. 内部重叠校验(防止一次提交多行重复) ---
@@ -679,11 +695,12 @@ class PersonWorkService extends Service
         return [true, ''];
     }
 
-    public function fillDataDaily($data){
+    public function fillDataDaily($data, $user){
         if(empty($data['data'])) return $data;
 
         $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'crt_id')));
         $item = (new ItemService())->getItemMap(array_unique(array_column($data['data'],'item_id')));
+        $map = ArchiveService::fillIsArchive(array_unique(array_column($data['data'],'order_time')), $user);
         foreach ($data['data'] as $key => $value){
             $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
             $data['data'][$key]['order_time'] = $value['order_time'] ? date('Y-m-d',$value['order_time']) : '';
@@ -691,6 +708,7 @@ class PersonWorkService extends Service
             $item_tmp = $item[$value['item_id']] ?? [];
             $data['data'][$key]['item_title'] = $item_tmp['title'] ?? '';
             $data['data'][$key]['item_code'] = $item_tmp['code'] ?? '';
+            $data['data'][$key]['is_archive'] = $map[$value['order_time']] ?? false;
         }
 
         return $data;

+ 152 - 0
app/Service/PriorityService.php

@@ -0,0 +1,152 @@
+<?php
+
+namespace App\Service;
+
+use App\Model\Priority;
+use Illuminate\Support\Facades\DB;
+
+class PriorityService extends Service
+{
+    public function priorityEdit($data, $user){
+        list($status,$msg) = $this->priorityRule($data,$user,false);
+        if(!$status) return [$status, $msg];
+
+        try {
+            DB::beginTransaction();
+
+            $update = $msg['data'][0];
+            $model = new Priority();
+            $model->where('id',$data['id'])->update($update);
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false,$exception->getMessage()];
+        }
+
+        return [true,''];
+    }
+
+    public function priorityAdd($data,$user){
+        list($status,$msg) = $this->priorityRule($data,$user);
+        if(!$status) return [$status,$msg];
+
+        try {
+            DB::beginTransaction();
+
+            foreach ($msg['data'] as $value){
+                $model = new Priority();
+                $model->title = $value['title'];
+                $model->code = $value['code'];
+                $model->type = $value['type'];
+                $model->sort = $value['sort'];
+                $model->top_depart_id = $value['top_depart_id'];
+                $model->save();
+            }
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false,$exception->getMessage()];
+        }
+
+        return [true,''];
+    }
+
+    public function priorityDel($data, $user){
+        if(empty($data['id'])) return [false, 'ID不能为空'];
+
+        Priority::whereIn('id',$data['id'])->update([
+            'del_time'=>time()
+        ]);
+
+        return [true,''];
+    }
+
+    public function priorityCommon($data,$user, $field = []){
+        if(empty($field)) $field = Priority::$field;
+
+        $model = Priority::TopClear($user,$data);
+        $model = $model->where('del_time',0)
+            ->select($field)
+            ->orderby('id', 'asc');
+
+        if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
+        if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
+
+        return $model;
+    }
+
+    public function priorityList($data, $user){
+        $model = $this->priorityCommon($data, $user);
+
+        $list = $model->get()->toArray();
+        $list = $this->fillPriorityList($list, $user);
+
+        return [true, $list];
+    }
+
+    public function fillPriorityList($list, $user, $is_export = false){
+        if(empty($list)) return $list;
+
+        if($is_export){
+            foreach ($list['data'] as $key => $value){
+                $list['data'][$key]['type_title'] = Priority::TYPE_TITLE[$value['type']] ?? "";
+            }
+        }
+
+        return $list;
+    }
+
+    public function priorityRule($data,$user, $is_check = true){
+        if(empty($data['data'])) return [false,'数据不能为空!'];
+
+        $code = array_column($data['data'],'code');
+        $title = array_column($data['data'],'title');
+        $code = array_map(function($val) {
+            return $val !== null ? $val : 0;
+        }, $code);
+        $title = array_map(function($val) {
+            return $val !== null ? $val : 0;
+        }, $title);
+        $code_count = array_count_values($code);
+        $title_count = array_count_values($title);
+        foreach ($code as $value){
+            if(empty($value)) return [false,'编码不能为空!'];
+            if($code_count[$value] > 1) return [false,'编码不能重复'];
+        }
+        foreach ($title as $value){
+            if(empty($value)) return [false,'名称不能为空!'];
+            if($title_count[$value] > 1) return [false,'名称不能重复'];
+        }
+
+        foreach ($data['data'] as $key => $value){
+            $top_depart_id = $user['top_depart_id'];
+
+            $data['data'][$key]['top_depart_id'] = $top_depart_id;
+            $data['data'][$key]['upd_time'] = time();
+
+            if(! isset($value['sort'])) return [false, '排序字段sort不存在'];
+            if (filter_var($value['sort'], FILTER_VALIDATE_INT) === false) return [false, '排序字段sort必须是整数且不能含有小数点'];
+
+            if(! isset(Priority::TYPE_TITLE[$value['type']])) return [false, 'type错误'];
+            if($is_check){
+                $data['data'][$key]['crt_time'] = time();
+                $bool = Priority::whereRaw("binary code = '{$value['code']}'")
+                    ->where('top_depart_id', $top_depart_id)
+                    ->where('del_time',0)
+                    ->exists();
+            }else{
+                if($this->isEmpty($data,'id')) return [false,'id不能为空!'];
+                $bool = Priority::whereRaw("binary code = '{$value['code']}'")
+                    ->where('top_depart_id', $top_depart_id)
+                    ->where('id','<>',$data['id'])
+                    ->where('del_time',0)
+                    ->exists();
+            }
+            if($bool) return [false,'编码已存在'];
+        }
+
+        return [true, $data];
+    }
+}

+ 55 - 78
app/Service/SysMenuService.php

@@ -146,12 +146,16 @@ class SysMenuService extends Service
     public function menuList($data, $user){
         $return = [];
         $type = $data['type'] ?? "";
+        $tree_type = $user['select_tree_type'];
 
         $sysList = SysMenu::where('del_time',0)
+            ->where('type', SysMenu::type_zero)
+            ->where('tree_type', $tree_type)
             ->select('title','icon','uri','parent_id','sort','id','is_authority', 'state')
             ->orderBy('sort','desc')
             ->get()
             ->toArray();
+
         $button = SysMenuButton::where('del_time',0)
             ->select('id','title','sort','func','menu_id')
             ->get()->toArray();
@@ -260,12 +264,12 @@ class SysMenuService extends Service
         return [true,''];
     }
 
-    public function fillMenuButton($button, $menu, $user, $type = 1)
+    public function fillMenuButton1($button, $menu, $user, $type = 1)
     {
         // 1. 预处理所有按钮池(合并配置中的特殊按钮)
         $allButtons = collect($button)->concat(config('specialButton') ?? [])->groupBy('menu_id');
 
-        // 2. 获取权限基础数据(如果是超管,这两个值为空,逻辑依然兼容)
+        // 2. 获取权限基础数据
         $isSuper = ($user['is_admin'] == Employee::IS_ADMIN_TWO);
         $roleButtons = $isSuper ? [] : (new EmployeeService())->fillRoleButton($user['role_ids'] ?? []);
         $allowedMenuIds = $isSuper ? [] : $this->getMenuIDByRoleInList($user);
@@ -306,85 +310,58 @@ class SysMenuService extends Service
         return $result;
     }
 
-    public function fillMenuButton1($button, $menu, $user, $type = 1){
-        $button_map = [];
-        $special_button = config('specialButton') ?? [];
-        foreach ($special_button as $value){
-            $button[] = $value;
-        }
-        foreach ($button as $value){
-            $button_map[$value['menu_id']][] = $value;
-        }
+    public function fillMenuButton($button, $menu, $user, $type = 1)
+    {
+        // 1. 预处理所有按钮池(合并配置中的特殊按钮)
+        $allButtons = collect($button)->concat(config('specialButton') ?? [])->groupBy('menu_id');
 
-        if($type == 1){
-            if($user['is_admin'] == Employee::IS_ADMIN_TWO){
-                //管理员
-                foreach ($menu as $key => $value){
-                    $menu[$key]['button'] = $button_map[$value['id']] ?? [];
-                }
-                return $menu;
-            }else{
-                //人员所拥有的菜单ID
-                $menu_id = $this->getMenuIDByRoleInList($user);
-                //角色
-                $role_id = $user['role_ids'] ?? [];
-                //角色下拥有的菜单里按钮
-                $role_button = (new EmployeeService())->fillRoleButton($role_id);
-                foreach ($menu as $key => $value){
-                    $result = [];
-                    if(! in_array($value['id'], $menu_id)) {
-                        unset($menu[$key]);
-                        continue;
-                    }
-                    $bt = $role_button[$value['id']] ?? [];
-                    $button_tmp = $button_map[$value['id']] ?? [];
-                    foreach ($bt as $b){
-                        if(isset($button_tmp[$b])) $result[] = $button_tmp[$b];
-                    }
-                    $menu[$key]['button'] = $result;
-                }
-                return array_values($menu);
-            }
-        }else{
-            $object = [];
-
-            if($user['is_admin'] == Employee::IS_ADMIN_TWO){
-                //管理员
-                foreach ($menu as $value){
-                    $object[] = [
-                        'id' => $value['id'],
-                        'uri' => $value['uri'],
-                        'button' => $button_map[$value['id']] ?? [],
-                    ];
-                }
-            }else{
-                //人员所拥有的菜单数据
-                $role_menu = $this->getMenuDataByRoleInList($user);
-                if(empty($role_menu)) return $object;
-                $menu_map = array_column($menu,'uri','id');
-                //角色
-                $role_id = $user['role_ids'] ?? [];
-                //角色下拥有的菜单里按钮
-                $role_button = (new EmployeeService())->fillRoleButton($role_id);
-                foreach ($role_menu as $value){
-                    $result = [];
-                    $bt = $role_button[$value['menu_id']] ?? [];
-                    $button_tmp = $button_map[$value['menu_id']] ?? [];
-                    $button_tmp = array_column($button_tmp,null,'id');
-                    foreach ($bt as $b){
-                        if(isset($button_tmp[$b])) $result[] = $button_tmp[$b];
-                    }
-
-                    $object[] = [
-                        'id' => $value['menu_id'],
-                        'uri' => $menu_map[$value['menu_id']] ?? '',
-                        'button' => $result,
-                    ];
-                }
+        // 2. 获取权限基础数据
+        $roleButtons = (new EmployeeService())->fillRoleButton($user['role_ids'] ?? []);
+        $allowedMenuIds = $this->getMenuIDByRoleInList($user);
+
+        $result = [];
+
+        foreach ($menu as $m) {
+            $menuId = $m['id'];
+
+            // 权限过滤:不在权限内,跳过
+            if (!in_array($menuId, $allowedMenuIds)) continue;
+
+            // 计算当前菜单拥有的按钮
+            // 只返回该角色拥有的按钮数据
+            $myBtnIds = $roleButtons[$menuId] ?? [];
+            $btnPool = collect($allButtons->get($menuId))->keyBy('id');
+            $btns = collect($myBtnIds)->map(fn($id) => $btnPool->get($id))->filter()->values();
+
+            // 3. 根据 type 返回不同的数据结构
+            if ($type == 1) {
+                // 完整模式:保留原菜单所有字段
+                $m['button'] = $btns;
+                $result[] = $m;
+            } else {
+                // 精简模式:只给前端路由用的字段
+                $result[] = [
+                    'id'     => $menuId,
+                    'uri'    => $m['uri'] ?? '',
+                    'button' => $btns,
+                ];
             }
+        }
+
+        return $result;
+    }
+
+    private function returnTwo1($sysList, $user){
+        //人员所拥有的菜单
+        $menu = $this->getMenuIDByRoleInList($user);
 
-            return $object;
+        foreach ($sysList as $key => $value){
+            if($value['state'] <= 0) unset($sysList[$key]);
+            if($user['is_admin'] != Employee::IS_ADMIN_TWO && ! in_array($value['id'], $menu)) unset($sysList[$key]);
         }
+        $list = array_values($sysList);
+        $return = $this->makeTree(0,$list);
+        return $this->set_sort_circle($return);;
     }
 
     private function returnTwo($sysList, $user){
@@ -393,7 +370,7 @@ class SysMenuService extends Service
 
         foreach ($sysList as $key => $value){
             if($value['state'] <= 0) unset($sysList[$key]);
-            if($user['is_admin'] != Employee::IS_ADMIN_TWO && ! in_array($value['id'], $menu)) unset($sysList[$key]);
+            if(! in_array($value['id'], $menu)) unset($sysList[$key]);
         }
         $list = array_values($sysList);
         $return = $this->makeTree(0,$list);

+ 1 - 1
config/cors.php

@@ -21,7 +21,7 @@ return [
      * You can enable CORS for 1 or multiple paths.
      * Example: ['api/*']
      */
-    'paths' => ['api/*','assetapi/*','maycur/*'],
+    'paths' => ['api/*','cApi/*'],
 
     /*
     * Matches the request method. `[*]` allows all methods.

+ 1 - 1
config/excel/RDOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 1 - 1
config/excel/dailyDwOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'order_time',

+ 1 - 1
config/excel/dailyPwOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'order_time',

+ 2 - 2
config/excel/depart.php

@@ -5,7 +5,7 @@ return [
         [
             'key' =>'code',
             'export' =>'code',
-            'value' => '编码',
+            'value' => '部门编码',
             'required' => true,
             'is_main' => true,
             'default' => "",
@@ -16,7 +16,7 @@ return [
         [
             'key' =>'title',
             'export' =>'title',
-            'value' => '名称',
+            'value' => '部门名称',
             'required' => true,
             'is_main' => true,
             'default' => "",

+ 5 - 5
config/excel/device.php

@@ -5,7 +5,7 @@ return [
         [
             'key' =>'code',
             'export' =>'code',
-            'value' => '固定资产编码',
+            'value' => '资产编码',
             'required' => true,
             'is_main' => true,
             'default' => "",
@@ -27,7 +27,7 @@ return [
         [
             'key' =>'type',
             'export' =>'type_title',
-            'value' => '固定资产类别',
+            'value' => '类别',
             'required' => true,
             'is_main' => true,
             'default' => 0,
@@ -47,7 +47,7 @@ return [
         [
             'key' =>'size',
             'export' =>'size',
-            'value' => '规格型号',
+            'value' => '设备型号',
             'required' => false,
             'is_main' => true,
             'unique' => false,
@@ -56,7 +56,7 @@ return [
         [
             'key' =>'position',
             'export' =>'position',
-            'value' => '位置',
+            'value' => '设备位置',
             'required' => false,
             'is_main' => true,
             'unique' => false,
@@ -83,7 +83,7 @@ return [
         [
             'key' =>'initial_value',
             'export' =>'initial_value',
-            'value' => '期初值',
+            'value' => '期初值',
             'required' => true,
             'default' => 0,
             'unique' => false,

+ 14 - 3
config/excel/employee.php

@@ -61,12 +61,12 @@ return [
             'key' =>'major',
             'export' =>'major',
             'value' => '专业领域',
-            'required' => true,
+            'required' => false,
             'is_main' => true,
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '必填'
+            'comments' => ''
         ],
         [
             'key' =>'position',
@@ -104,7 +104,7 @@ return [
         [
             'key' =>'man_type',
             'export' =>'man_type_title',
-            'value' => '是否技术研究人员',
+            'value' => '是否技术人员',
             'required' => true,
             'is_main' => true,
             'unique' => false,
@@ -123,6 +123,17 @@ return [
             'default' => \App\Model\Employee::WT_TYPE_ZERO,
             'comments' => "必填"
         ],
+        [
+            'key' =>'employee_type',
+            'export' =>'employee_type_title',
+            'value' => '聘用类型',
+            'required' => true,
+            'is_main' => true,
+            'unique' => false,
+            'enums' => array_values(\App\Model\Employee::E_State_Type),
+            'default' => \App\Model\Employee::E_TYPE_ONE,
+            'comments' => '必填'
+        ],
         [
             'key' =>'state',
             'export' =>'state_title',

+ 2 - 2
config/excel/fee.php

@@ -5,7 +5,7 @@ return [
         [
             'key' =>'code',
             'export' =>'code',
-            'value' => '编码',
+            'value' => '费用类型编码',
             'required' => true,
             'is_main' => true,
             'default' => "",
@@ -16,7 +16,7 @@ return [
         [
             'key' =>'title',
             'export' =>'title',
-            'value' => '名称',
+            'value' => '费用类型名称',
             'required' => true,
             'is_main' => true,
             'default' => "",

+ 1 - 1
config/excel/feeOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 3 - 3
config/excel/item.php

@@ -115,7 +115,7 @@ return [
         [
             'key' =>'mark',
             'export' =>'mark',
-            'value' => '项目说明',
+            'value' => '项目备注',
             'required' => false,
             'is_main' => true,
             'unique' => false,
@@ -146,8 +146,8 @@ return [
             'comments' => '必填(人员的工号或设备的资产编码)'
         ],
         [
-            'key' =>'title',
-            'export' =>'title',
+            'key' =>'title_2',
+            'export' =>'title_2',
             'value' => '名称',
             'required' => false,
             'is_main' => false,

+ 1 - 1
config/excel/leaveOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'order_time',

+ 1 - 1
config/excel/monthDdOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 1 - 1
config/excel/monthDwOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 1 - 1
config/excel/monthPsOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 1 - 1
config/excel/monthPwOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 1 - 1
config/excel/overtimeOrder.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'order_time',

+ 61 - 0
config/excel/priority.php

@@ -0,0 +1,61 @@
+<?php
+return [
+    "name" => "优先级",
+    "array" => [
+        [
+            'key' =>'code',
+            'export' =>'code',
+            'value' => '编码',
+            'required' => true,
+            'is_main' => true,
+            'default' => "",
+            'unique' => false,
+            'enums' => [],
+            'comments' => '必填'
+        ],
+        [
+            'key' =>'title',
+            'export' =>'title',
+            'value' => '名称',
+            'required' => true,
+            'is_main' => true,
+            'default' => "",
+            'unique' => false,
+            'enums' => [],
+            'comments' => '必填'
+        ],
+        [
+            'key' =>'type',
+            'export' =>'type_title',
+            'value' => '类型',
+            'required' => true,
+            'is_main' => true,
+            'default' => 0,
+            'unique' => false,
+            'enums' => array_values(\App\Model\Priority::TYPE_TITLE),
+            'comments' => '必填'
+        ],
+        [
+            'key' =>'is_use',
+            'export' =>'is_use_title',
+            'value' => '是否启用',
+            'required' => true,
+            'is_main' => true,
+            'default' => 0,
+            'unique' => false,
+            'enums' => array_values(\App\Model\Priority::IS_USE),
+            'comments' => '必填'
+        ],
+        [
+            'key' =>'sort',
+            'export' =>'sort',
+            'value' => '排序字段',
+            'required' => true,
+            'is_main' => true,
+            'default' => 0,
+            'unique' => false,
+            'enums' => [],
+            'comments' => '必填'
+        ]
+    ]
+];

+ 1 - 1
config/excel/ruleSet.php

@@ -11,7 +11,7 @@ return [
             'default' => "",
             'unique' => false,
             'enums' => [],
-            'comments' => '(如果填写则是编辑)'
+            'comments' => '新增则不需要填写,如果填写则是编辑'
         ],
         [
             'key' =>'month',

+ 21 - 2
routes/api.php

@@ -92,6 +92,21 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('itemDel', 'Api\ItemController@itemDel');
     $route->any('itemDetail', 'Api\ItemController@itemDetail');
 
+    //中台新建角色 以及分配菜单权限
+    $route->any('roleMiddleGroundAdd', 'Api\RoleMiddleGroudController@roleAdd');
+    $route->any('roleMiddleGroundEdit', 'Api\RoleMiddleGroudController@roleEdit');
+    $route->any('roleMiddleGroundDel', 'Api\RoleMiddleGroudController@roleDel');
+    $route->any('roleMiddleGroundList', 'Api\RoleMiddleGroudController@roleList');
+    $route->any('roleMiddleGroundDetail', 'Api\RoleMiddleGroudController@roleDetail');
+    $route->any('roleMiddleGroundMenu', 'Api\RoleMiddleGroudController@roleMenu');
+
+    //优先级
+    $route->any('priorityList', 'Api\PriorityController@priorityList');
+    $route->any('priorityEdit', 'Api\PriorityController@priorityEdit');
+    $route->any('priorityAdd', 'Api\PriorityController@priorityAdd');
+    $route->any('priorityDel', 'Api\PriorityController@priorityDel');
+    $route->any('priorityDetail', 'Api\PriorityController@priorityDetail');
+
     //费用类型
     $route->any('feeAdd', 'Api\FeeController@feeAdd')->name('fee.add');
     $route->any('feeEdit', 'Api\FeeController@feeEdit')->name('fee.edit');
@@ -168,8 +183,6 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('archiveAdd', 'Api\ArchiveController@archiveAdd');
     $route->any('archiveDel', 'Api\ArchiveController@archiveDel');
 
-    //工时设置 暂时后台写死数据 toDo
-
     //请假单 加班单
     $route->any('pLeaveOverOrderList', 'Api\PLeaveOverController@pLeaveOverList');
     $route->any('pLeaveOverEdit', 'Api\PLeaveOverController@pLeaveOverEdit');
@@ -214,6 +227,12 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('employeeAttendanceMonthStatistic', 'Api\StatisticController@employeeAttendanceMonthStatistic');
     ///年度研发支出辅助账汇总表(年)
     $route->any('auxiliaryStatistic', 'Api\StatisticController@auxiliaryStatistic');
+    //企业研发开发活动汇总表
+    $route->any('enterpriseRdStatistic', 'Api\StatisticController@enterpriseRdStatistic');
+    //企业研究开发科技人员情况表
+    $route->any('enterpriseRdManStatistic', 'Api\StatisticController@enterpriseRdManStatistic');
+    //企业研发开发活动汇总表
+    $route->any('enterpriseRdItemStatistic', 'Api\StatisticController@enterpriseRdItemStatistic');
 
 
     //首页BI数据

+ 38 - 0
routes/c_api.php

@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Http\Request;
+
+/*
+|--------------------------------------------------------------------------
+| API Routes
+|--------------------------------------------------------------------------
+|
+| Here is where you can register API routes for your application. These
+| routes are loaded by the RouteServiceProvider within a group which
+| is assigned the "api" middleware group. Enjoy building your API!
+|
+*/
+
+//伪中台路由
+Route::any('login', 'Api\LoginController@cLogin');
+Route::group(['middleware'=> ['checkCenterLogin']],function ($route){
+    $route->any('roleAdd', 'Api\MiddleGroundController@roleAdd');
+    $route->any('roleEdit', 'Api\MiddleGroundController@roleEdit');
+    $route->any('roleDel', 'Api\MiddleGroundController@roleDel');
+    $route->any('roleList', 'Api\MiddleGroundController@roleList');
+    $route->any('roleDetail', 'Api\MiddleGroundController@roleDetail');
+    $route->any('roleMenu', 'Api\MiddleGroundController@roleMenu');
+
+    //创建公司账号 工时设置 初始化
+    $route->any('initializationCompany', 'Api\MiddleGroundController@initializationCompany');
+    //公司列表
+    $route->any('initializationCompanyList', 'Api\MiddleGroundController@initializationCompanyList');
+
+    //菜单列表 为了设置角色权限用的
+    $route->any('menuList', 'Api\MiddleGroundController@menuList');
+
+    //管理员
+    $route->any('employeeList', 'Api\MiddleGroundController@employeeList');
+    $route->any('employeeEdit', 'Api\MiddleGroundController@employeeEdit');
+});
+