diff --git a/app/adminapi/controller/project/ProjectExpenseReimbursementController.php b/app/adminapi/controller/project/ProjectExpenseReimbursementController.php
new file mode 100644
index 000000000..c5fe4d8be
--- /dev/null
+++ b/app/adminapi/controller/project/ProjectExpenseReimbursementController.php
@@ -0,0 +1,108 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+
+namespace app\adminapi\controller\project;
+
+
+use app\adminapi\controller\BaseAdminController;
+use app\adminapi\lists\project\ProjectExpenseReimbursementLists;
+use app\adminapi\logic\project\ProjectExpenseReimbursementLogic;
+use app\adminapi\validate\project\ProjectExpenseReimbursementValidate;
+
+
+/**
+ * 费用报销控制器
+ * Class ProjectExpenseReimbursementController
+ * @package app\adminapi\controller\project
+ */
+class ProjectExpenseReimbursementController extends BaseAdminController
+{
+
+
+    /**
+     * @notes 获取费用报销列表
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists()
+    {
+        return $this->dataLists(new ProjectExpenseReimbursementLists());
+    }
+
+
+    /**
+     * @notes 添加费用报销
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function add()
+    {
+        $params = (new ProjectExpenseReimbursementValidate())->post()->goCheck('add');
+        $result = ProjectExpenseReimbursementLogic::add($params);
+        if (true === $result) {
+            return $this->success('添加成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementLogic::getError());
+    }
+
+
+    /**
+     * @notes 编辑费用报销
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function edit()
+    {
+        $params = (new ProjectExpenseReimbursementValidate())->post()->goCheck('edit');
+        $result = ProjectExpenseReimbursementLogic::edit($params);
+        if (true === $result) {
+            return $this->success('编辑成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementLogic::getError());
+    }
+
+
+    /**
+     * @notes 删除费用报销
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function delete()
+    {
+        $params = (new ProjectExpenseReimbursementValidate())->post()->goCheck('delete');
+        ProjectExpenseReimbursementLogic::delete($params);
+        return $this->success('删除成功', [], 1, 1);
+    }
+
+
+    /**
+     * @notes 获取费用报销详情
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function detail()
+    {
+        $params = (new ProjectExpenseReimbursementValidate())->goCheck('detail');
+        $result = ProjectExpenseReimbursementLogic::detail($params);
+        return $this->data($result);
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/adminapi/controller/project/ProjectExpenseReimbursementDetailController.php b/app/adminapi/controller/project/ProjectExpenseReimbursementDetailController.php
new file mode 100644
index 000000000..01f51695e
--- /dev/null
+++ b/app/adminapi/controller/project/ProjectExpenseReimbursementDetailController.php
@@ -0,0 +1,108 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+
+namespace app\adminapi\controller\project;
+
+
+use app\adminapi\controller\BaseAdminController;
+use app\adminapi\lists\project\ProjectExpenseReimbursementDetailLists;
+use app\adminapi\logic\project\ProjectExpenseReimbursementDetailLogic;
+use app\adminapi\validate\project\ProjectExpenseReimbursementDetailValidate;
+
+
+/**
+ * 报销明细控制器
+ * Class ProjectExpenseReimbursementDetailController
+ * @package app\adminapi\controller\project
+ */
+class ProjectExpenseReimbursementDetailController extends BaseAdminController
+{
+
+
+    /**
+     * @notes 获取报销明细列表
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists()
+    {
+        return $this->dataLists(new ProjectExpenseReimbursementDetailLists());
+    }
+
+
+    /**
+     * @notes 添加报销明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function add()
+    {
+        $params = (new ProjectExpenseReimbursementDetailValidate())->post()->goCheck('add');
+        $result = ProjectExpenseReimbursementDetailLogic::add($params);
+        if (true === $result) {
+            return $this->success('添加成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementDetailLogic::getError());
+    }
+
+
+    /**
+     * @notes 编辑报销明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function edit()
+    {
+        $params = (new ProjectExpenseReimbursementDetailValidate())->post()->goCheck('edit');
+        $result = ProjectExpenseReimbursementDetailLogic::edit($params);
+        if (true === $result) {
+            return $this->success('编辑成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementDetailLogic::getError());
+    }
+
+
+    /**
+     * @notes 删除报销明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function delete()
+    {
+        $params = (new ProjectExpenseReimbursementDetailValidate())->post()->goCheck('delete');
+        ProjectExpenseReimbursementDetailLogic::delete($params);
+        return $this->success('删除成功', [], 1, 1);
+    }
+
+
+    /**
+     * @notes 获取报销明细详情
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function detail()
+    {
+        $params = (new ProjectExpenseReimbursementDetailValidate())->goCheck('detail');
+        $result = ProjectExpenseReimbursementDetailLogic::detail($params);
+        return $this->data($result);
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/adminapi/controller/project/ProjectExpenseReimbursementInvoiceDetailController.php b/app/adminapi/controller/project/ProjectExpenseReimbursementInvoiceDetailController.php
new file mode 100644
index 000000000..11312d59b
--- /dev/null
+++ b/app/adminapi/controller/project/ProjectExpenseReimbursementInvoiceDetailController.php
@@ -0,0 +1,108 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+
+namespace app\adminapi\controller\project;
+
+
+use app\adminapi\controller\BaseAdminController;
+use app\adminapi\lists\project\ProjectExpenseReimbursementInvoiceDetailLists;
+use app\adminapi\logic\project\ProjectExpenseReimbursementInvoiceDetailLogic;
+use app\adminapi\validate\project\ProjectExpenseReimbursementInvoiceDetailValidate;
+
+
+/**
+ * 发票明细控制器
+ * Class ProjectExpenseReimbursementInvoiceDetailController
+ * @package app\adminapi\controller\project
+ */
+class ProjectExpenseReimbursementInvoiceDetailController extends BaseAdminController
+{
+
+
+    /**
+     * @notes 获取发票明细列表
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists()
+    {
+        return $this->dataLists(new ProjectExpenseReimbursementInvoiceDetailLists());
+    }
+
+
+    /**
+     * @notes 添加发票明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function add()
+    {
+        $params = (new ProjectExpenseReimbursementInvoiceDetailValidate())->post()->goCheck('add');
+        $result = ProjectExpenseReimbursementInvoiceDetailLogic::add($params);
+        if (true === $result) {
+            return $this->success('添加成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementInvoiceDetailLogic::getError());
+    }
+
+
+    /**
+     * @notes 编辑发票明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function edit()
+    {
+        $params = (new ProjectExpenseReimbursementInvoiceDetailValidate())->post()->goCheck('edit');
+        $result = ProjectExpenseReimbursementInvoiceDetailLogic::edit($params);
+        if (true === $result) {
+            return $this->success('编辑成功', [], 1, 1);
+        }
+        return $this->fail(ProjectExpenseReimbursementInvoiceDetailLogic::getError());
+    }
+
+
+    /**
+     * @notes 删除发票明细
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function delete()
+    {
+        $params = (new ProjectExpenseReimbursementInvoiceDetailValidate())->post()->goCheck('delete');
+        ProjectExpenseReimbursementInvoiceDetailLogic::delete($params);
+        return $this->success('删除成功', [], 1, 1);
+    }
+
+
+    /**
+     * @notes 获取发票明细详情
+     * @return \think\response\Json
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function detail()
+    {
+        $params = (new ProjectExpenseReimbursementInvoiceDetailValidate())->goCheck('detail');
+        $result = ProjectExpenseReimbursementInvoiceDetailLogic::detail($params);
+        return $this->data($result);
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/adminapi/lists/project/ProjectExpenseReimbursementDetailLists.php b/app/adminapi/lists/project/ProjectExpenseReimbursementDetailLists.php
new file mode 100644
index 000000000..3ecd8f64d
--- /dev/null
+++ b/app/adminapi/lists/project/ProjectExpenseReimbursementDetailLists.php
@@ -0,0 +1,123 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\lists\project;
+
+
+use app\adminapi\lists\BaseAdminDataLists;
+use app\common\model\project\Project;
+use app\common\model\project\ProjectCostTempSet;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\model\project\ProjectExpenseReimbursementDetail;
+use app\common\lists\ListsSearchInterface;
+
+
+/**
+ * 报销明细列表
+ * Class ProjectExpenseReimbursementDetailLists
+ * @package app\adminapi\listsproject
+ */
+class ProjectExpenseReimbursementDetailLists extends BaseAdminDataLists implements ListsSearchInterface
+{
+
+
+    /**
+     * @notes 设置搜索条件
+     * @return \string[][]
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function setSearch(): array
+    {
+        return [
+            '=' => ['expense_reimbursement_id'],
+        ];
+    }
+
+
+    /**
+     * @notes 获取报销明细列表
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists(): array
+    {
+		$params = $this->request->get(['expense_reimbursement_code','project_code','apply_user']);
+		$where = [];
+		if(isset($params['expense_reimbursement_code']) && $params['expense_reimbursement_code'] != ''){
+			$expense_reimbursement_ids = ProjectExpenseReimbursement::where('expense_reimbursement_code','like','%'.$params['expense_reimbursement_code'].'%')->column('id');
+			$where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+		}
+	    if(isset($params['project_code']) && $params['project_code'] != ''){
+			$project_ids = Project::where('project_code','like','%'.$params['project_code'].'%')->column('id');
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('project_id','in',$project_ids)->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+	    if(isset($params['apply_user']) && $params['apply_user'] != ''){
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('apply_user','like','%'.$params['apply_user'].'%')->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+        return ProjectExpenseReimbursementDetail::where($this->searchWhere)->where($where)
+            ->field(['id', 'expense_reimbursement_id', 'project_cost_temp_id', 'amount', 'remark'])
+            ->limit($this->limitOffset, $this->limitLength)
+            ->order(['id' => 'desc'])
+            ->select()->each(function($data){
+		        $expense_reimbursement = ProjectExpenseReimbursement::field('expense_reimbursement_code,project_id,apply_user,apply_date')->where('id',$data['expense_reimbursement_id'])->findOrEmpty();
+				$project = Project::field('name,project_code')->where('id',$expense_reimbursement['project_id'])->findOrEmpty();
+		        $project_cost_temp = ProjectCostTempSet::field('first_level_subject,second_level_subject,third_level_subject')->where('id',$data['project_cost_temp_id'])->findOrEmpty();
+		        $data['expense_reimbursement_code'] = $expense_reimbursement['expense_reimbursement_code'];
+				$data['project_name'] = $project['name'];
+				$data['project_code'] = $project['project_code'];
+		        $data['apply_user'] = $expense_reimbursement['apply_user'];
+		        $data['apply_date'] = $expense_reimbursement['apply_date'];
+		        $data['first_level_subject'] = $project_cost_temp['first_level_subject'];
+		        $data['second_level_subject'] = $project_cost_temp['second_level_subject'];
+		        $data['third_level_subject'] = $project_cost_temp['third_level_subject'];
+				return $data;
+	        })
+            ->toArray();
+    }
+
+
+    /**
+     * @notes 获取报销明细数量
+     * @return int
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function count(): int
+    {
+	    $params = $this->request->get(['expense_reimbursement_code','project_code','apply_user']);
+	    $where = [];
+	    if(isset($params['expense_reimbursement_code']) && $params['expense_reimbursement_code'] != ''){
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('expense_reimbursement_code','like','%'.$params['expense_reimbursement_code'].'%')->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+	    if(isset($params['project_code']) && $params['project_code'] != ''){
+		    $project_ids = Project::where('project_code','like','%'.$params['project_code'].'%')->column('id');
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('project_id','in',$project_ids)->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+	    if(isset($params['apply_user']) && $params['apply_user'] != ''){
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('apply_user','like','%'.$params['apply_user'].'%')->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+        return ProjectExpenseReimbursementDetail::where($this->searchWhere)->where($where)->count();
+    }
+
+}
\ No newline at end of file
diff --git a/app/adminapi/lists/project/ProjectExpenseReimbursementInvoiceDetailLists.php b/app/adminapi/lists/project/ProjectExpenseReimbursementInvoiceDetailLists.php
new file mode 100644
index 000000000..1ff48ccb3
--- /dev/null
+++ b/app/adminapi/lists/project/ProjectExpenseReimbursementInvoiceDetailLists.php
@@ -0,0 +1,114 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\lists\project;
+
+
+use app\adminapi\lists\BaseAdminDataLists;
+use app\common\model\project\Project;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\model\project\ProjectExpenseReimbursementInvoiceDetail;
+use app\common\lists\ListsSearchInterface;
+
+
+/**
+ * 发票明细列表
+ * Class ProjectExpenseReimbursementInvoiceDetailLists
+ * @package app\adminapi\listsproject
+ */
+class ProjectExpenseReimbursementInvoiceDetailLists extends BaseAdminDataLists implements ListsSearchInterface
+{
+
+
+    /**
+     * @notes 设置搜索条件
+     * @return \string[][]
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function setSearch(): array
+    {
+        return [
+            '=' => ['expense_reimbursement_id', 'invoice_type', 'invoice_form'],
+            '%like%' => ['invoice_sn'],
+        ];
+    }
+
+
+    /**
+     * @notes 获取发票明细列表
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists(): array
+    {
+	    $params = $this->request->get(['expense_reimbursement_code','project_code']);
+	    $where = [];
+	    if(isset($params['expense_reimbursement_code']) && $params['expense_reimbursement_code']){
+			$expense_reimbursement_ids = ProjectExpenseReimbursement::where('expense_reimbursement_code','like','%'.$params['expense_reimbursement_code'].'%')->column('id');
+			$where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+	    if(isset($params['project_code']) && $params['project_code']){
+			$project_ids = Project::where('project_code','like','%'.$params['project_code'].'%')->column('id');
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('project_id','in',$project_ids)->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+        return ProjectExpenseReimbursementInvoiceDetail::where($this->searchWhere)->where($where)
+            ->field(['id', 'expense_reimbursement_id', 'invoice_type', 'invoice_sn', 'tax_rate', 'invoice_form', 'invoice_amount', 'tax_amount', 'remark'])
+            ->limit($this->limitOffset, $this->limitLength)
+            ->order(['id' => 'desc'])
+            ->select()->each(function($data){
+		        $expense_reimbursement = ProjectExpenseReimbursement::field('expense_reimbursement_code,project_id,apply_user,apply_date')->where('id',$data['expense_reimbursement_id'])->findOrEmpty();
+				$project = Project::field('name,project_code')->where('id',$expense_reimbursement['project_id'])->findOrEmpty();
+		        $data['expense_reimbursement_code'] = $expense_reimbursement['expense_reimbursement_code'];
+				$data['project_name'] = $project['name'];
+				$data['project_code'] = $project['project_code'];
+		        $data['apply_user'] = $expense_reimbursement['apply_user'];
+		        $data['apply_date'] = $expense_reimbursement['apply_date'];
+		        $data['invoice_type'] = $data->invoice_type_text;
+		        $data['tax_rate'] = $data->tax_rate_text;
+		        $data['invoice_form'] = $data->invoice_form_text;
+				return $data;
+	        })
+            ->toArray();
+    }
+
+
+    /**
+     * @notes 获取发票明细数量
+     * @return int
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function count(): int
+    {
+	    $params = $this->request->get(['expense_reimbursement_code','project_code']);
+	    $where = [];
+	    if(isset($params['expense_reimbursement_code']) && $params['expense_reimbursement_code']){
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('expense_reimbursement_code','like','%'.$params['expense_reimbursement_code'].'%')->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+	    if(isset($params['project_code']) && $params['project_code']){
+		    $project_ids = Project::where('project_code','like','%'.$params['project_code'].'%')->column('id');
+		    $expense_reimbursement_ids = ProjectExpenseReimbursement::where('project_id','in',$project_ids)->column('id');
+		    $where[] = ['expense_reimbursement_id','in',$expense_reimbursement_ids];
+	    }
+        return ProjectExpenseReimbursementInvoiceDetail::where($this->searchWhere)->where($where)->count();
+    }
+
+}
\ No newline at end of file
diff --git a/app/adminapi/lists/project/ProjectExpenseReimbursementLists.php b/app/adminapi/lists/project/ProjectExpenseReimbursementLists.php
new file mode 100644
index 000000000..554e9b6da
--- /dev/null
+++ b/app/adminapi/lists/project/ProjectExpenseReimbursementLists.php
@@ -0,0 +1,93 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\lists\project;
+
+
+use app\adminapi\lists\BaseAdminDataLists;
+use app\common\model\project\Project;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\lists\ListsSearchInterface;
+use app\common\model\project\ProjectExpenseReimbursementDetail;
+use app\common\model\project\ProjectLoanApply;
+
+
+/**
+ * 费用报销列表
+ * Class ProjectExpenseReimbursementLists
+ * @package app\adminapi\listsproject
+ */
+class ProjectExpenseReimbursementLists extends BaseAdminDataLists implements ListsSearchInterface
+{
+
+
+    /**
+     * @notes 设置搜索条件
+     * @return \string[][]
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function setSearch(): array
+    {
+        return [
+            '=' => ['project_id', 'reimbursement_type'],
+            '%like%' => ['expense_reimbursement_code', 'apply_user', 'payee_name'],
+        ];
+    }
+
+
+    /**
+     * @notes 获取费用报销列表
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function lists(): array
+    {
+        return ProjectExpenseReimbursement::where($this->searchWhere)
+            ->field('id,expense_reimbursement_code,project_id,apply_user,apply_date,reimbursement_type,loan_apply_id,offset_loan_amount,remark')
+            ->limit($this->limitOffset, $this->limitLength)
+            ->order(['id' => 'desc'])
+            ->select()->each(function($data){
+		        $project = Project::field('name,project_code')->where('id',$data['project_id'])->findOrEmpty();
+		        $loan_apply = ProjectLoanApply::field('loan_apply_code,loan_amount')->where('id',$data['loan_apply_id'])->findOrEmpty();
+		        $data['project_name'] = $project['name'];
+		        $data['project_code'] = $project['project_code'];
+		        $data['loan_apply_code'] = !$loan_apply->isEmpty() ? $loan_apply['loan_apply_code'] : '---';
+		        $data['loan_amount'] = !$loan_apply->isEmpty() ? $loan_apply['loan_amount'] : '---';
+		        $data['total_amount'] = ProjectExpenseReimbursementDetail::where('expense_reimbursement_id',$data['id'])->sum('amount');
+		        $data['pay_amount'] = $data['total_amount'] - $data['offset_loan_amount'];
+		        $data['reimbursement_type'] = $data->reimbursement_type_text;
+				unset($data['project_id'],$data['loan_apply_id']);
+				return $data;
+	        })
+            ->toArray();
+    }
+
+
+    /**
+     * @notes 获取费用报销数量
+     * @return int
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function count(): int
+    {
+        return ProjectExpenseReimbursement::where($this->searchWhere)->count();
+    }
+
+}
\ No newline at end of file
diff --git a/app/adminapi/logic/project/ProjectExpenseReimbursementDetailLogic.php b/app/adminapi/logic/project/ProjectExpenseReimbursementDetailLogic.php
new file mode 100644
index 000000000..fb3b39864
--- /dev/null
+++ b/app/adminapi/logic/project/ProjectExpenseReimbursementDetailLogic.php
@@ -0,0 +1,120 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\logic\project;
+
+
+use app\common\model\project\ProjectCostTempSet;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\model\project\ProjectExpenseReimbursementDetail;
+use app\common\logic\BaseLogic;
+use think\facade\Db;
+
+
+/**
+ * 报销明细逻辑
+ * Class ProjectExpenseReimbursementDetailLogic
+ * @package app\adminapi\logic\project
+ */
+class ProjectExpenseReimbursementDetailLogic extends BaseLogic
+{
+
+
+    /**
+     * @notes 添加报销明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function add(array $params): bool
+    {
+        Db::startTrans();
+        try {
+            ProjectExpenseReimbursementDetail::create([
+                'expense_reimbursement_id' => $params['expense_reimbursement_id'],
+                'project_cost_temp_id' => $params['project_cost_temp_id'],
+                'amount' => $params['amount'],
+                'remark' => $params['remark'] ?? '',
+            ]);
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 编辑报销明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function edit(array $params): bool
+    {
+        Db::startTrans();
+        try {
+            ProjectExpenseReimbursementDetail::where('id', $params['id'])->update([
+	            'expense_reimbursement_id' => $params['expense_reimbursement_id'],
+	            'project_cost_temp_id' => $params['project_cost_temp_id'],
+	            'amount' => $params['amount'],
+	            'remark' => $params['remark'] ?? '',
+	            'update_time' => time()
+            ]);
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 删除报销明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function delete(array $params): bool
+    {
+        return ProjectExpenseReimbursementDetail::destroy($params['id']);
+    }
+
+
+    /**
+     * @notes 获取报销明细详情
+     * @param $params
+     * @return array
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function detail($params): array
+    {
+		$data = ProjectExpenseReimbursementDetail::field('id,expense_reimbursement_id,project_cost_temp_id,amount,remark')->findOrEmpty($params['id']);
+		$expense_reimbursement = ProjectExpenseReimbursement::field('expense_reimbursement_code')->where('id',$data['expense_reimbursement_id'])->findOrEmpty();
+		$project_cost_temp = ProjectCostTempSet::field('first_level_subject,second_level_subject,third_level_subject')->where('id',$data['project_cost_temp_id'])->findOrEmpty();
+		$data['expense_reimbursement_code'] = $expense_reimbursement['expense_reimbursement_code'];
+		$data['first_level_subject'] = $project_cost_temp['first_level_subject'];
+		$data['second_level_subject'] = $project_cost_temp['second_level_subject'];
+		$data['third_level_subject'] = $project_cost_temp['third_level_subject'];
+        return $data->toArray();
+    }
+}
\ No newline at end of file
diff --git a/app/adminapi/logic/project/ProjectExpenseReimbursementInvoiceDetailLogic.php b/app/adminapi/logic/project/ProjectExpenseReimbursementInvoiceDetailLogic.php
new file mode 100644
index 000000000..77027aeb9
--- /dev/null
+++ b/app/adminapi/logic/project/ProjectExpenseReimbursementInvoiceDetailLogic.php
@@ -0,0 +1,134 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\logic\project;
+
+
+use app\common\model\dict\DictData;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\model\project\ProjectExpenseReimbursementInvoiceDetail;
+use app\common\logic\BaseLogic;
+use think\facade\Db;
+
+
+/**
+ * 发票明细逻辑
+ * Class ProjectExpenseReimbursementInvoiceDetailLogic
+ * @package app\adminapi\logic\project
+ */
+class ProjectExpenseReimbursementInvoiceDetailLogic extends BaseLogic
+{
+
+
+    /**
+     * @notes 添加发票明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function add(array $params): bool
+    {
+	    //获取税率
+	    $tax_rate = DictData::where('type_value','tax_rate')->column('name','value');
+        Db::startTrans();
+        try {
+            ProjectExpenseReimbursementInvoiceDetail::create([
+                'expense_reimbursement_id' => $params['expense_reimbursement_id'],
+                'invoice_type' => $params['invoice_type'],
+                'invoice_sn' => $params['invoice_sn'],
+                'tax_rate' => $params['tax_rate'],
+                'invoice_form' => $params['invoice_form'],
+                'invoice_amount' => $params['invoice_amount'],
+                'tax_amount' => $tax_rate[$params['tax_rate']] / 100 * $params['invoice_amount'],
+                'annex' => $params['annex'] ? json_encode($params['annex']) : null,
+                'remark' => $params['remark'] ?? '',
+            ]);
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 编辑发票明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function edit(array $params): bool
+    {
+	    //获取税率
+	    $tax_rate = DictData::where('type_value','tax_rate')->column('name','value');
+        Db::startTrans();
+        try {
+            ProjectExpenseReimbursementInvoiceDetail::where('id', $params['id'])->update([
+	            'expense_reimbursement_id' => $params['expense_reimbursement_id'],
+	            'invoice_type' => $params['invoice_type'],
+	            'invoice_sn' => $params['invoice_sn'],
+	            'tax_rate' => $params['tax_rate'],
+	            'invoice_form' => $params['invoice_form'],
+	            'invoice_amount' => $params['invoice_amount'],
+	            'tax_amount' => $tax_rate[$params['tax_rate']] / 100 * $params['invoice_amount'],
+	            'annex' => $params['annex'] ? json_encode($params['annex']) : null,
+	            'remark' => $params['remark'] ?? '',
+	            'update_time' => time(),
+            ]);
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 删除发票明细
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function delete(array $params): bool
+    {
+        return ProjectExpenseReimbursementInvoiceDetail::destroy($params['id']);
+    }
+
+
+    /**
+     * @notes 获取发票明细详情
+     * @param $params
+     * @return array
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function detail($params): array
+    {
+		$data = ProjectExpenseReimbursementInvoiceDetail::field('id,expense_reimbursement_id,invoice_type,invoice_sn,tax_rate,invoice_form,invoice_amount,tax_amount,annex,remark')
+			->findOrEmpty($params['id']);
+		$expense_reimbursement = ProjectExpenseReimbursement::field('expense_reimbursement_code')->where('id',$data['expense_reimbursement_id'])->findOrEmpty();
+		$data['expense_reimbursement_code'] = $expense_reimbursement['expense_reimbursement_code'];
+	    $data['invoice_type_text'] = $data->invoice_type_text;
+	    $data['tax_rate_text'] = $data->tax_rate_text;
+	    $data['invoice_form_text'] = $data->invoice_form_text;
+        return $data->toArray();
+    }
+}
\ No newline at end of file
diff --git a/app/adminapi/logic/project/ProjectExpenseReimbursementLogic.php b/app/adminapi/logic/project/ProjectExpenseReimbursementLogic.php
new file mode 100644
index 000000000..88c69f994
--- /dev/null
+++ b/app/adminapi/logic/project/ProjectExpenseReimbursementLogic.php
@@ -0,0 +1,230 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\logic\project;
+
+
+use app\common\model\bank\BankAccount;
+use app\common\model\dict\DictData;
+use app\common\model\project\Project;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\logic\BaseLogic;
+use app\common\model\project\ProjectExpenseReimbursementDetail;
+use app\common\model\project\ProjectExpenseReimbursementInvoiceDetail;
+use app\common\model\project\ProjectLoanApply;
+use think\facade\Db;
+
+
+/**
+ * 费用报销逻辑
+ * Class ProjectExpenseReimbursementLogic
+ * @package app\adminapi\logic\project
+ */
+class ProjectExpenseReimbursementLogic extends BaseLogic
+{
+
+
+    /**
+     * @notes 添加费用报销
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function add(array $params): bool
+    {
+	    //获取税率
+	    $tax_rate = DictData::where('type_value','tax_rate')->column('name','value');
+        Db::startTrans();
+        try {
+            $res = ProjectExpenseReimbursement::create([
+				'expense_reimbursement_code' => data_unique_code('项目费用报销'),
+                'project_id' => $params['project_id'],
+                'apply_user' => $params['apply_user'],
+                'apply_date' => strtotime($params['apply_date']),
+                'reimbursement_type' => $params['reimbursement_type'],
+                'loan_apply_id' => $params['loan_apply_id'] ?? 0,
+                'offset_loan_amount' => $params['offset_loan_amount'] ?? 0,
+                'payee_name' => $params['payee_name'],
+                'payee_bank' => $params['payee_bank'],
+                'payee_account' => $params['payee_account'],
+                'remark' => $params['remark'] ?? '',
+                'annex' => $params['annex'] ? json_encode($params['annex']) : null,
+                'bank_account_id' => $params['bank_account_id'],
+            ]);
+	        foreach($params['reimbursement_detail'] as $item){
+		        ProjectExpenseReimbursementDetail::create([
+			        'expense_reimbursement_id' => $res->id,
+			        'project_cost_temp_id' => $item['project_cost_temp_id'],
+			        'amount' => $item['amount'],
+			        'remark' => $item['remark'] ?? '',
+		        ]);
+	        }
+	        foreach($params['invoice_detail'] as $item){
+		        ProjectExpenseReimbursementInvoiceDetail::create([
+			        'expense_reimbursement_id' => $res->id,
+			        'invoice_type' => $item['invoice_type'],
+			        'invoice_sn' => $item['invoice_sn'],
+			        'tax_rate' => $item['tax_rate'],
+			        'invoice_form' => $item['invoice_form'],
+			        'invoice_amount' => $item['invoice_amount'],
+			        'tax_amount' => $tax_rate[$item['tax_rate']] / 100 * $item['invoice_amount'],
+			        'annex' => $item['annex'] ? json_encode($item['annex']) : null,
+			        'remark' => $item['remark'] ?? '',
+		        ]);
+	        }
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 编辑费用报销
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function edit(array $params): bool
+    {
+	    //获取税率
+	    $tax_rate = DictData::where('type_value','tax_rate')->column('name','value');
+        Db::startTrans();
+        try {
+            ProjectExpenseReimbursement::where('id', $params['id'])->update([
+	            'project_id' => $params['project_id'],
+	            'apply_user' => $params['apply_user'],
+	            'apply_date' => strtotime($params['apply_date']),
+	            'reimbursement_type' => $params['reimbursement_type'],
+	            'loan_apply_id' => $params['loan_apply_id'] ?? 0,
+	            'offset_loan_amount' => $params['offset_loan_amount'] ?? 0,
+	            'payee_name' => $params['payee_name'],
+	            'payee_bank' => $params['payee_bank'],
+	            'payee_account' => $params['payee_account'],
+	            'remark' => $params['remark'] ?? '',
+	            'annex' => $params['annex'] ? json_encode($params['annex']) : null,
+	            'bank_account_id' => $params['bank_account_id'],
+	            'update_time' => time(),
+            ]);
+	        foreach($params['reimbursement_detail'] as $item){
+		        if(isset($item['id']) && $item['id'] != ''){
+			        ProjectExpenseReimbursementDetail::where('id',$item['id'])->update([
+				        'expense_reimbursement_id' => $params['id'],
+				        'project_cost_temp_id' => $item['project_cost_temp_id'],
+				        'amount' => $item['amount'],
+				        'remark' => $item['remark'] ?? '',
+				        'update_time' => time(),
+			        ]);
+		        }else{
+			        ProjectExpenseReimbursementDetail::create([
+				        'expense_reimbursement_id' => $params['id'],
+				        'project_cost_temp_id' => $item['project_cost_temp_id'],
+				        'amount' => $item['amount'],
+				        'remark' => $item['remark'] ?? '',
+			        ]);
+		        }
+	        }
+	        foreach($params['invoice_detail'] as $item){
+		        if(isset($item['id']) && $item['id'] != ''){
+			        ProjectExpenseReimbursementInvoiceDetail::where('id',$item['id'])->update([
+				        'expense_reimbursement_id' => $params['id'],
+				        'invoice_type' => $item['invoice_type'],
+				        'invoice_sn' => $item['invoice_sn'],
+				        'tax_rate' => $item['tax_rate'],
+				        'invoice_form' => $item['invoice_form'],
+				        'invoice_amount' => $item['invoice_amount'],
+				        'tax_amount' => $tax_rate[$item['tax_rate']] / 100 * $item['invoice_amount'],
+				        'annex' => $item['annex'] ? json_encode($item['annex']) : null,
+				        'remark' => $item['remark'] ?? '',
+				        'update_time' => time(),
+			        ]);
+		        }else{
+			        ProjectExpenseReimbursementInvoiceDetail::create([
+				        'expense_reimbursement_id' => $params['id'],
+				        'invoice_type' => $item['invoice_type'],
+				        'invoice_sn' => $item['invoice_sn'],
+				        'tax_rate' => $item['tax_rate'],
+				        'invoice_form' => $item['invoice_form'],
+				        'invoice_amount' => $item['invoice_amount'],
+				        'tax_amount' => $tax_rate[$item['tax_rate']] / 100 * $item['invoice_amount'],
+				        'annex' => $item['annex'] ? json_encode($item['annex']) : null,
+				        'remark' => $item['remark'] ?? '',
+			        ]);
+		        }
+	        }
+            Db::commit();
+            return true;
+        } catch (\Exception $e) {
+            Db::rollback();
+            self::setError($e->getMessage());
+            return false;
+        }
+    }
+
+
+    /**
+     * @notes 删除费用报销
+     * @param array $params
+     * @return bool
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function delete(array $params): bool
+    {
+	    Db::startTrans();
+	    try {
+		    $expense_reimbursement_detail_ids = ProjectExpenseReimbursementDetail::where('expense_reimbursement_id',$params['id'])->column('id');
+		    $expense_reimbursement_invoice_detail_ids = ProjectExpenseReimbursementInvoiceDetail::where('expense_reimbursement_id',$params['id'])->column('id');
+		    ProjectExpenseReimbursement::destroy($params['id']);
+		    ProjectExpenseReimbursementDetail::destroy($expense_reimbursement_detail_ids);
+		    ProjectExpenseReimbursementInvoiceDetail::destroy($expense_reimbursement_invoice_detail_ids);
+		    Db::commit();
+		    return true;
+	    } catch (\Exception $e) {
+		    Db::rollback();
+		    self::setError($e->getMessage());
+		    return false;
+	    }
+    }
+
+
+    /**
+     * @notes 获取费用报销详情
+     * @param $params
+     * @return array
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public static function detail($params): array
+    {
+		$data = ProjectExpenseReimbursement::field('id,expense_reimbursement_code,project_id,apply_user,apply_date,reimbursement_type,loan_apply_id,offset_loan_amount,payee_name,payee_bank,payee_account,remark,annex,bank_account_id')
+			->findOrEmpty($params['id']);
+	    $project = Project::field('name,project_code')->where('id',$data['project_id'])->findOrEmpty();
+	    $loan_apply = ProjectLoanApply::field('loan_apply_code,loan_amount')->where('id',$data['loan_apply_id'])->findOrEmpty();
+	    $data['project_name'] = $project['name'];
+	    $data['project_code'] = $project['project_code'];
+	    $data['loan_apply_code'] = !$loan_apply->isEmpty() ? $loan_apply['loan_apply_code'] : '---';
+	    $data['loan_amount'] = !$loan_apply->isEmpty() ? $loan_apply['loan_amount'] : '---';
+	    $data['total_amount'] = ProjectExpenseReimbursementDetail::where('expense_reimbursement_id',$data['id'])->sum('amount');
+	    $data['pay_amount'] = $data['total_amount'] - $data['offset_loan_amount'];
+	    $data['reimbursement_type_text'] = $data->reimbursement_type_text;
+	    $data['bank_account'] = BankAccount::field('account_sn,deposit_bank,account_name,account')->where('id',$data['bank_account_id'])->findOrEmpty();
+        return $data->toArray();
+    }
+}
\ No newline at end of file
diff --git a/app/adminapi/validate/project/ProjectExpenseReimbursementDetailValidate.php b/app/adminapi/validate/project/ProjectExpenseReimbursementDetailValidate.php
new file mode 100644
index 000000000..f54ad327a
--- /dev/null
+++ b/app/adminapi/validate/project/ProjectExpenseReimbursementDetailValidate.php
@@ -0,0 +1,120 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\validate\project;
+
+
+use app\common\model\project\ProjectCostTempSet;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\validate\BaseValidate;
+
+
+/**
+ * 报销明细验证器
+ * Class ProjectExpenseReimbursementDetailValidate
+ * @package app\adminapi\validate\project
+ */
+class ProjectExpenseReimbursementDetailValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'expense_reimbursement_id' => 'require|checkExpenseReimbursement',
+        'project_cost_temp_id' => 'require|checkProjectCostTemp',
+        'amount' => 'require|float|gt:0',
+    ];
+
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'expense_reimbursement_id' => '费用报销单id',
+        'project_cost_temp_id' => '项目费用模板id',
+        'amount' => '金额',
+    ];
+
+
+    /**
+     * @notes 添加场景
+     * @return ProjectExpenseReimbursementDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneAdd()
+    {
+		return $this->remove('id',true);
+    }
+
+
+    /**
+     * @notes 编辑场景
+     * @return ProjectExpenseReimbursementDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['id','expense_reimbursement_id','project_cost_temp_id','amount']);
+    }
+
+
+    /**
+     * @notes 删除场景
+     * @return ProjectExpenseReimbursementDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDelete()
+    {
+        return $this->only(['id']);
+    }
+
+
+    /**
+     * @notes 详情场景
+     * @return ProjectExpenseReimbursementDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDetail()
+    {
+        return $this->only(['id']);
+    }
+	
+	public function checkExpenseReimbursement($value): bool|string
+	{
+		$data = ProjectExpenseReimbursement::where('id',$value)->findOrEmpty();
+		if($data->isEmpty()){
+			return '费用报销信息不存在';
+		}
+		return true;
+	}
+	
+	public function checkProjectCostTemp($value): bool|string
+	{
+		$data = ProjectCostTempSet::where('id',$value)->findOrEmpty();
+		if($data->isEmpty()){
+			return '项目费用模板信息不存在';
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/app/adminapi/validate/project/ProjectExpenseReimbursementInvoiceDetailValidate.php b/app/adminapi/validate/project/ProjectExpenseReimbursementInvoiceDetailValidate.php
new file mode 100644
index 000000000..ba9c5f9d2
--- /dev/null
+++ b/app/adminapi/validate/project/ProjectExpenseReimbursementInvoiceDetailValidate.php
@@ -0,0 +1,152 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\validate\project;
+
+
+use app\common\model\dict\DictData;
+use app\common\model\project\ProjectExpenseReimbursement;
+use app\common\validate\BaseValidate;
+
+
+/**
+ * 发票明细验证器
+ * Class ProjectExpenseReimbursementInvoiceDetailValidate
+ * @package app\adminapi\validate\project
+ */
+class ProjectExpenseReimbursementInvoiceDetailValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'expense_reimbursement_id' => 'require|checkExpenseReimbursement',
+        'invoice_type' => 'require|checkInvoiceType',
+        'invoice_sn' => 'require',
+        'tax_rate' => 'require|checkTaxRate',
+        'invoice_form' => 'require|checkInvoiceForm',
+        'invoice_amount' => 'require|float|gt:0',
+	    'annex' => 'checkAnnex'
+    ];
+
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'expense_reimbursement_id' => '费用报销单id',
+        'invoice_type' => '发票类型',
+        'invoice_sn' => '发票号',
+        'tax_rate' => '发票税率',
+        'invoice_form' => '发票形式',
+        'invoice_amount' => '发票金额',
+    ];
+
+
+    /**
+     * @notes 添加场景
+     * @return ProjectExpenseReimbursementInvoiceDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneAdd()
+    {
+        return $this->remove('id',true);
+    }
+
+
+    /**
+     * @notes 编辑场景
+     * @return ProjectExpenseReimbursementInvoiceDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneEdit()
+    {}
+
+
+    /**
+     * @notes 删除场景
+     * @return ProjectExpenseReimbursementInvoiceDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDelete()
+    {
+        return $this->only(['id']);
+    }
+
+
+    /**
+     * @notes 详情场景
+     * @return ProjectExpenseReimbursementInvoiceDetailValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDetail()
+    {
+        return $this->only(['id']);
+    }
+	
+	public function checkExpenseReimbursement($value): bool|string
+	{
+		$data = ProjectExpenseReimbursement::where('id',$value)->findOrEmpty();
+		if($data->isEmpty()){
+			return '费用报销信息不存在';
+		}
+		return true;
+	}
+	
+	public function checkInvoiceType($value): bool|string
+	{
+		$dict = DictData::where('type_value','invoice_type')->column('value');
+		if(!in_array($value,$dict)){
+			return '发票类型数据值无效';
+		}
+		return true;
+	}
+	
+	public function checkTaxRate($value): bool|string
+	{
+		$dict = DictData::where('type_value','tax_rate')->column('value');
+		if(!in_array($value,$dict)){
+			return '发票税率数据值无效';
+		}
+		return true;
+	}
+	
+	public function checkInvoiceForm($value){
+		$dict = DictData::where('type_value','invoice_form')->column('value');
+		if(!in_array($value,$dict)){
+			return '发票形式数据值无效';
+		}
+		return true;
+	}
+	
+	public function checkAnnex($value): bool|string
+	{
+		if(!empty($value) && $value != ''){
+			if(!is_array($value)){
+				return '附件格式错误';
+			}
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/app/adminapi/validate/project/ProjectExpenseReimbursementValidate.php b/app/adminapi/validate/project/ProjectExpenseReimbursementValidate.php
new file mode 100644
index 000000000..57ce16a12
--- /dev/null
+++ b/app/adminapi/validate/project/ProjectExpenseReimbursementValidate.php
@@ -0,0 +1,268 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\adminapi\validate\project;
+
+
+use app\common\model\bank\BankAccount;
+use app\common\model\dict\DictData;
+use app\common\model\project\Project;
+use app\common\model\project\ProjectCostTempSet;
+use app\common\model\project\ProjectExpenseReimbursementDetail;
+use app\common\model\project\ProjectExpenseReimbursementInvoiceDetail;
+use app\common\model\project\ProjectLoanApply;
+use app\common\validate\BaseValidate;
+
+
+/**
+ * 费用报销验证器
+ * Class ProjectExpenseReimbursementValidate
+ * @package app\adminapi\validate\project
+ */
+class ProjectExpenseReimbursementValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'project_id' => 'require|checkProject',
+        'apply_user' => 'require',
+        'apply_date' => 'require|dateFormat:Y-m-d',
+        'reimbursement_type' => 'require|checkReimbursementType',
+	    'loan_apply_id' => 'requireCallback:check_require|checkLoanApply',
+	    'offset_loan_amount' => 'requireCallback:check_require|float|egt:0',
+        'payee_name' => 'require',
+        'payee_bank' => 'require',
+        'payee_account' => 'require',
+	    'annex' => 'checkAnnex',
+        'bank_account_id' => 'require|checkBankAccount',
+	    'reimbursement_detail' => 'require|checkReimbursementDetail',
+	    'invoice_detail' => 'require|checkInvoiceDetail',
+    ];
+
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'project_id' => '项目id',
+        'apply_user' => '报销人',
+        'apply_date' => '报销日期',
+        'reimbursement_type' => '报销类型',
+	    'loan_apply_id' => '借款申请id',
+	    'offset_loan_amount' => '冲抵借款金额',
+        'payee_name' => '收款人姓名',
+        'payee_bank' => '收款银行',
+        'payee_account' => '收款账号',
+        'bank_account_id' => '付款银行账户id',
+	    'reimbursement_detail' => '报销明细',
+	    'invoice_detail' => '发票明细',
+    ];
+
+
+    /**
+     * @notes 添加场景
+     * @return ProjectExpenseReimbursementValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneAdd()
+    {
+		return $this->remove('id',true);
+    }
+
+
+    /**
+     * @notes 编辑场景
+     * @return ProjectExpenseReimbursementValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneEdit()
+    {}
+
+
+    /**
+     * @notes 删除场景
+     * @return ProjectExpenseReimbursementValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDelete()
+    {
+        return $this->only(['id']);
+    }
+
+
+    /**
+     * @notes 详情场景
+     * @return ProjectExpenseReimbursementValidate
+     * @author likeadmin
+     * @date 2024/01/19 13:44
+     */
+    public function sceneDetail()
+    {
+        return $this->only(['id']);
+    }
+	
+	public function checkProject($value): bool|string
+	{
+		$data = Project::where('id',$value)->findOrEmpty();
+		if($data->isEmpty()){
+			return '项目信息不存在';
+		}
+		return true;
+	}
+	
+	public function checkReimbursementType($value): bool|string
+	{
+		$data = explode(',',$value);
+		if(empty($data)){
+			return '报销类型数据格式错误';
+		}
+		foreach ($data as $v) {
+			$dict = DictData::where('type_value','reimbursement_type')->column('value');
+			if(!in_array($v,$dict)){
+				return '报销类型数据无效';
+			}
+		}
+		return true;
+	}
+	
+	function check_require($value,$data): bool
+	{
+		$reimbursement_type = explode(',',$data['reimbursement_type']);
+		return in_array(1,$reimbursement_type);
+	}
+	
+	public function checkLoanApply($value): bool|string
+	{
+		$loan_apply_data = ProjectLoanApply::where('id',$value)->findOrEmpty();
+		if($loan_apply_data->isEmpty()){
+			return '借款单信息不存在';
+		}
+		return true;
+	}
+	
+	public function checkAnnex($value): bool|string
+	{
+		if(!empty($value) && $value != ''){
+			if(!is_array($value)){
+				return '附件格式错误';
+			}
+		}
+		return true;
+	}
+	
+	public function checkBankAccount($value): bool|string
+	{
+		$data = BankAccount::where('id',$value)->findOrEmpty();
+		if($data->isEmpty()){
+			return '付款银行账户信息不存在';
+		}
+		return true;
+	}
+	
+	public function checkReimbursementDetail($value): bool|string
+	{
+		if(empty($value) || !is_array($value)){
+			return '报销明细数据格式错误';
+		}
+		foreach($value as $v){
+			if(isset($v['id']) && $v['id'] != ''){
+				$reimbursement_detail = ProjectExpenseReimbursementDetail::where('id',$v['id'])->findOrEmpty();
+				if($reimbursement_detail->isEmpty()){
+					return '报销明细信息不存在';
+				}
+			}
+			if(empty($v['project_cost_temp_id'])){
+				return '请选择项目费用模板';
+			}else{
+				$project_cost_temp = ProjectCostTempSet::where('id',$v['project_cost_temp_id'])->findOrEmpty();
+				if($project_cost_temp->isEmpty()){
+					return '项目费用模板信息不存在';
+				}
+			}
+			if(empty($v['amount'])){
+				return '请填写报销明细金额';
+			}else{
+				if(!is_numeric($v['amount']) || $v['amount'] < 0){
+					return '报销明细金额必须是大于0数字';
+				}
+			}
+		}
+		return true;
+	}
+	
+	public function checkInvoiceDetail($value): bool|string
+	{
+		if(empty($value) || !is_array($value)){
+			return '发票明细数据格式错误';
+		}
+		foreach($value as $v){
+			if(isset($v['id']) && $v['id'] != ''){
+				$invoice_detail = ProjectExpenseReimbursementInvoiceDetail::where('id',$v['id'])->findOrEmpty();
+				if($invoice_detail->isEmpty()){
+					return '发票明细信息不存在';
+				}
+			}
+			if(empty($v['invoice_type'])){
+				return '请选择发票类型';
+			}else{
+				$invoice_type_dict = DictData::where('type_value','invoice_type')->column('value');
+				if(!in_array($v['invoice_type'],$invoice_type_dict)){
+					return '发票类型数据值无效';
+				}
+			}
+			if(empty($v['invoice_sn'])){
+				return '请填写发票号';
+			}
+			if(empty($v['tax_rate'])){
+				return '请选择发票税率';
+			}else{
+				$tax_rate_dict = DictData::where('type_value','tax_rate')->column('value');
+				if(!in_array($v['tax_rate'],$tax_rate_dict)){
+					return '发票税率数据值无效';
+				}
+			}
+			if(empty($v['invoice_form'])){
+				return '请选择发票形式';
+			}else{
+				$invoice_form_dict = DictData::where('type_value','invoice_form')->column('value');
+				if(!in_array($v['invoice_form'],$invoice_form_dict)){
+					return '发票形式数据值无效';
+				}
+			}
+			if(empty($v['invoice_amount'])){
+				return '请填写发票金额';
+			}else{
+				if(!is_numeric($v['invoice_amount']) || $v['invoice_amount'] < 0){
+					return '发票金额必须是大于0的数字';
+				}
+			}
+			if(isset($v['annex']) && $v['annex'] != ''){
+				if(!is_array($v['annex'])){
+					return '发票附件格式错误';
+				}
+			}
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/app/common/model/project/ProjectExpenseReimbursement.php b/app/common/model/project/ProjectExpenseReimbursement.php
new file mode 100644
index 000000000..71d9c5592
--- /dev/null
+++ b/app/common/model/project/ProjectExpenseReimbursement.php
@@ -0,0 +1,46 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\common\model\project;
+
+
+use app\common\model\BaseModel;
+use app\common\model\dict\DictData;
+use think\model\concern\SoftDelete;
+
+
+/**
+ * 费用报销模型
+ * Class ProjectExpenseReimbursement
+ * @package app\common\model\project
+ */
+class ProjectExpenseReimbursement extends BaseModel
+{
+    use SoftDelete;
+    protected $name = 'project_expense_reimbursement';
+    protected $deleteTime = 'delete_time';
+	
+	public function getAnnexAttr($value){
+		return !empty($value) ? json_decode($value,true) : '';
+	}
+	
+	public function getApplyDateAttr($value){
+		return !empty($value) ? date('Y-m-d',$value) : '';
+	}
+	
+	public function getReimbursementTypeTextAttr($value,$data){
+		$dictData = DictData::where('type_value','reimbursement_type')->whereIn('value',$data['reimbursement_type'])->column('name');
+		return  $data['reimbursement_type'] ? implode(',',$dictData) : '';
+	}
+}
\ No newline at end of file
diff --git a/app/common/model/project/ProjectExpenseReimbursementDetail.php b/app/common/model/project/ProjectExpenseReimbursementDetail.php
new file mode 100644
index 000000000..6359bfa84
--- /dev/null
+++ b/app/common/model/project/ProjectExpenseReimbursementDetail.php
@@ -0,0 +1,34 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\common\model\project;
+
+
+use app\common\model\BaseModel;
+use think\model\concern\SoftDelete;
+
+
+/**
+ * 报销明细模型
+ * Class ProjectExpenseReimbursementDetail
+ * @package app\common\model\project
+ */
+class ProjectExpenseReimbursementDetail extends BaseModel
+{
+    use SoftDelete;
+    protected $name = 'project_expense_reimbursement_detail';
+    protected $deleteTime = 'delete_time';
+
+    
+}
\ No newline at end of file
diff --git a/app/common/model/project/ProjectExpenseReimbursementInvoiceDetail.php b/app/common/model/project/ProjectExpenseReimbursementInvoiceDetail.php
new file mode 100644
index 000000000..f4438ec9f
--- /dev/null
+++ b/app/common/model/project/ProjectExpenseReimbursementInvoiceDetail.php
@@ -0,0 +1,52 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeadmin快速开发前后端分离管理后台(PHP版)
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
+// | github下载:https://github.com/likeshop-github/likeadmin
+// | 访问官网:https://www.likeadmin.cn
+// | likeadmin团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeadminTeam
+// +----------------------------------------------------------------------
+
+namespace app\common\model\project;
+
+
+use app\common\model\BaseModel;
+use app\common\model\dict\DictData;
+use think\model\concern\SoftDelete;
+
+
+/**
+ * 发票明细模型
+ * Class ProjectExpenseReimbursementInvoiceDetail
+ * @package app\common\model\project
+ */
+class ProjectExpenseReimbursementInvoiceDetail extends BaseModel
+{
+    use SoftDelete;
+    protected $name = 'project_expense_reimbursement_invoice_detail';
+    protected $deleteTime = 'delete_time';
+	
+	public function getAnnexAttr($value){
+		return !empty($value) ? json_decode($value,true) : '';
+	}
+	
+	public function getInvoiceTypeTextAttr($value,$data){
+		$dict = DictData::where('type_value','invoice_type')->column('name','value');
+		return !empty($data['invoice_type']) ? $dict[$data['invoice_type']] : '';
+	}
+	
+	public function getTaxRateTextAttr($value,$data){
+		$dict = DictData::where('type_value','tax_rate')->column('name','value');
+		return !empty($data['tax_rate']) ? $dict[$data['tax_rate']] : '';
+	}
+	
+	public function getInvoiceFormTextAttr($value,$data){
+		$dict = DictData::where('type_value','invoice_form')->column('name','value');
+		return !empty($data['invoice_form']) ? $dict[$data['invoice_form']] : '';
+	}
+}
\ No newline at end of file