PHP项目怎么实现报废管理?

wen java案例 2

本文目录导读:

PHP项目怎么实现报废管理?

  1. 数据库设计(核心表)
  2. 后端PHP核心逻辑
  3. 前端页面(以Vue为例,仅示意)
  4. 权限控制建议
  5. 扩展功能(根据需求)
  6. 安全问题注意

在PHP项目中实现一套完整的报废管理功能,通常需要覆盖申请、审批、执行、归档这几个核心环节,下面是一个通用的设计思路和核心代码实现示例,你可以根据自己的业务逻辑进行调整。


数据库设计(核心表)

至少需要两张表:一张报废申请表,一张报废明细表(如果是单条物品报废,也可以合并)。

-- 1. 报废主表
CREATE TABLE `scrap_orders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(64) NOT NULL COMMENT '报废单号',
  `dept_id` int(11) NOT NULL COMMENT '申请部门',
  `applicant_id` int(11) NOT NULL COMMENT '申请人',
  `total_amount` decimal(10,2) DEFAULT '0.00' COMMENT '报废总价值',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0-待审批, 1-审批通过, 2-已驳回, 3-已完成',
  `remark` text COMMENT '备注',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 2. 报废明细表
CREATE TABLE `scrap_order_items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL COMMENT '关联主表ID',
  `asset_id` int(11) NOT NULL COMMENT '资产编号',
  `asset_name` varchar(255) NOT NULL COMMENT '资产名称',
  `spec` varchar(255) DEFAULT NULL COMMENT '规格型号',
  `quantity` int(11) NOT NULL DEFAULT '1' COMMENT '报废数量',
  `unit_price` decimal(10,2) DEFAULT '0.00' COMMENT '原值',
  `scrap_reason` varchar(500) DEFAULT NULL COMMENT '报废原因',
  `disposal_method` tinyint(4) DEFAULT '0' COMMENT '处置方式:0-销毁, 1-变卖, 2-回收',
  PRIMARY KEY (`id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

后端PHP核心逻辑

建议使用 MVC 结构,这里以 ThinkPHP / Laravel 风格为例,显示核心业务逻辑:

报废单申请(创建)

// ScrapService.php
public function createScrapOrder($data, $items)
{
    // 开启事务
    DB::beginTransaction();
    try {
        // 生成单号:日期 + 随机数
        $orderNo = 'SCRAP-' . date('Ymd') . '-' . mt_rand(1000, 9999);
        // 1. 写入主表
        $order = new ScrapOrder();
        $order->order_no = $orderNo;
        $order->dept_id = $data['dept_id'];
        $order->applicant_id = auth()->id();
        $order->total_amount = array_sum(array_column($items, 'unit_price'));
        $order->status = 0; // 待审批
        $order->remark = $data['remark'] ?? '';
        $order->save();
        // 2. 写入明细表
        foreach ($items as $item) {
            $orderItem = new ScrapOrderItem();
            $orderItem->order_id = $order->id;
            $orderItem->asset_id = $item['asset_id'];
            $orderItem->asset_name = $item['asset_name'];
            $orderItem->spec = $item['spec'] ?? '';
            $orderItem->quantity = $item['quantity'];
            $orderItem->unit_price = $item['unit_price'];
            $orderItem->scrap_reason = $item['scrap_reason'];
            $orderItem->disposal_method = $item['disposal_method'] ?? 0;
            $orderItem->save();
            // 可选:锁定对应的资产,防止重复报废
            // Asset::where('id', $item['asset_id'])->update(['status' => 'scrap_pending']);
        }
        DB::commit();
        return ['code' => 1, 'msg' => '申请成功', 'order_id' => $order->id];
    } catch (\Exception $e) {
        DB::rollBack();
        return ['code' => 0, 'msg' => '申请失败: ' . $e->getMessage()];
    }
}

审批流程(简单版)

// ScrapService.php
public function approveOrder($orderId, $approveResult, $approveRemark = '')
{
    $order = ScrapOrder::find($orderId);
    if (!$order) {
        return ['code' => 0, 'msg' => '单据不存在'];
    }
    if ($order->status != 0) {
        return ['code' => 0, 'msg' => '当前状态不可审批'];
    }
    DB::beginTransaction();
    try {
        if ($approveResult == 1) { // 通过
            $order->status = 1; // 审批通过
            // 处理资产状态:将资产标记为“已报废”
            foreach ($order->items as $item) {
                Asset::where('id', $item->asset_id)->update(['status' => 'scrapped']);
            }
        } else { // 驳回
            $order->status = 2;
            // 解冻资产状态(如果有锁定)
            foreach ($order->items as $item) {
                Asset::where('id', $item->asset_id)->update(['status' => 'normal']);
            }
        }
        $order->approve_remark = $approveRemark;
        $order->approver_id = auth()->id();
        $order->approved_at = now();
        $order->save();
        DB::commit();
        return ['code' => 1, 'msg' => '操作成功'];
    } catch (\Exception $e) {
        DB::rollBack();
        return ['code' => 0, 'msg' => '操作失败: ' . $e->getMessage()];
    }
}

资产列表查询(供选择报废资产)

// 获取可报废的资产列表(未被报废、未被借出等)
public function getScrappableAssets($params)
{
    $query = Asset::where('status', 'normal')
                  ->where('use_status', 'idle'); // 闲置状态
    if (!empty($params['keyword'])) {
        $query->where(function($q) use ($params) {
            $q->where('asset_name', 'like', '%'.$params['keyword'].'%')
              ->orWhere('asset_no', 'like', '%'.$params['keyword'].'%');
        });
    }
    return $query->paginate($params['per_page'] ?? 20);
}

前端页面(以Vue为例,仅示意)

通常你需要以下页面:

页面 功能
scrap/create.blade.php 选择资产 -> 填写原因 -> 提交申请
scrap/list.blade.php 我的申请 / 待我审批 / 全部记录
scrap/detail.blade.php 查看详情 + 审批按钮(根据角色)

核心交互逻辑(Vue + Element UI 示例):

// 1. 申请页面:多选资产提交
async submitScrap() {
    if (this.selectedAssets.length === 0) {
        this.$message.warning('请选择至少一项资产');
        return;
    }
    const items = this.selectedAssets.map(asset => ({
        asset_id: asset.id,
        asset_name: asset.name,
        spec: asset.spec,
        quantity: 1,
        unit_price: asset.price,
        scrap_reason: this.reason,
        disposal_method: this.disposalMethod
    }));
    const res = await axios.post('/api/scrap/create', {
        dept_id: this.deptId,
        remark: this.remark,
        items: items
    });
    if (res.data.code == 1) {
        this.$message.success('提交成功');
        this.$router.push('/scrap/list');
    }
}

权限控制建议

  • 普通用户:只能查看自己的申请,只能操作“待审批”状态的单据(不能修改已审批的)。
  • 审批人:可以查看所有待审批单据,进行“通过”或“驳回”。
  • 管理员:可以查看/导出所有记录,进行最终归档操作。

在控制器中检查权限:

// 在审批方法前
$this->authorize('approve_scrap'); // 使用Laravel Policy或自定义中间件

扩展功能(根据需求)

  1. 报废单打印:使用 dompdfTCPDF 生成PDF。
  2. 资产残值回收:如果报废后需要变卖,增加“回收金额”、“买家信息”字段。
  3. 流程审批流:支持多级审批(部门主管 -> 财务 -> 总经理),可以使用审批流表 + 状态机实现。
  4. Excel导出:使用 PhpSpreadsheet 导出所有申请明细。
  5. 通知机制:提交申请后,通过邮件/钉钉/企业微信通知审批人。

安全问题注意

  • 报废操作涉及资产状态变更,必须使用事务保证数据一致性。
  • 禁止前端直接传资产ID修改资产状态,所有变更应在后端校验。
  • 对于批量操作,注意 SQL注入越权 问题(尤其是 IDOR,即不安全的直接对象引用)。

如果你使用的是 ThinkPHP 5/6/8Laravel 框架,我可以根据你的具体框架提供更贴合框架语法的代码示例,如果你们的业务包含 多级审批工作流引擎,实现会更复杂一些,需要结合 审批节点表审批记录表 来做状态推进。

抱歉,评论功能暂时关闭!