PHP如何输出合并单元格的表

https://mp.weixin.qq.com/s/ChPIKIv9tqmuqGyfc9Zi7Q

合并单元格的表,很多地方可以见到,比如购物车,订单合并等,今天给大家讲解一下,如何操作,虽然我用的laravel,但是都是PHP。以下只做参考!

 

部分效果图如下

路由文件

 Route::get('admin/allots/index', ['as'=> 'admin.allots.index', 'uses' => 'AllotController@index']); 

控制器文件:AllotController.php

/**
     * Display a listing of the Allot.
     *
     * @param Request $request
     * @return Response
     */
    public function index(Request $request)
    {
        $param  = $request->all();
        $params  = [
            'orderBy' => ['allot_id', 'desc'],
            'groupBy' => 'allot_sn'
        ];


        $params['left_join'][] = ['allot_detail','allot.allot_id','=','allot_detail.allot_id'];
        $params['left_join'][] = ['goods_sku','allot_detail.sku_id','=','goods_sku.sku_id'];
        $params['left_join'][] = ['goods','goods_sku.goods_id','=','goods.goods_id'];

        $params['select']   = [
            'allot.*',
            'allot_detail.sku_id',
            'goods_sku.sku_id',
            'goods_sku.goods_id',
            'goods.goods_id',
            'goods.goods_name'
        ];

        if(!empty($param['goods_name'])){
            $params['where'] = $this->entryWareRepository->getLikeGoods(trim($param['goods_name']));
            $search_sku_id = $this->entryWareRepository->getLikeSkuID(trim($param['goods_name']));
        }

        //用户所属对应仓库的信息
        $admin_ware = $this->allotRepository->getAdminWare();
        if($admin_ware > 0){
            $params['whereIn'] = ['allot.from_ware_id', $admin_ware];
        }

        $this->allotRepository->pushCriteria(new RequestCriteria($request));
        $allots = $this->allotRepository->paginate(config('config.pagesize'),[
            'detail.sku.goods','out_ware','entry_ware'
        ],$params);

        $allots->each(function($item,$key){
            $item->is_out_ware = count($this->allotRepository->out_ware($item->allot_sn));
            $item->is_entry_ware = count($this->allotRepository->entry_ware($item->allot_sn));
        });

        foreach ($allots as $val){
            $val->detail->each(function($vo,$k){
                $vo->change_sku = $vo->sku->getShowSku();
            });
        }
        //dd($allots);

        return view('admin.allots.index', compact('allots','admin_ware','param'));

    }

model文件:Allot.php

class Allot extends Model
{

    public $table = 'allot';

    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';


    protected $primaryKey = 'allot_id';

    public $fillable = [
        'allot_sn',
        'remark',
        'status',
        'from_ware_id',
        'to_ware_id',
        'create_admin_id',
        'create_admin_name',
        'examine_admin_id',
        'examine_admin_name',
        'entry_ware_status',
        'out_ware_status',
        'confirm_admin_id',
        'confirm_admin_name'
    ];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        'allot_id' => 'integer',
        'allot_sn' => 'string',
        'remark' => 'string',
        'status' => 'integer',
        'from_ware_id' => 'integer',
        'to_ware_id' => 'integer',
        'create_admin_id' => 'integer',
        'create_admin_name' => 'string',
        'examine_admin_id' => 'integer',
        'examine_admin_name' => 'string',
        'confirm_admin_id' => 'integer',
        'confirm_admin_name' => 'string',
        'entry_ware_status' =>'integer',
        'out_ware_status' => 'integer',
    ];

    /**
     * Validation rules
     *
     * @var array
     */
    public static $rules = [

    ];

容器文件:AllotRepository.php

<?php

namespace App\Repository;

use App\Model\Allot;
use App\Model\AllotDetail;
use App\Model\AllotSkuBatch;
use App\Repository\CommonRepository;


class AllotRepository extends CommonRepository
{
    /**
     * @var array
     */
    protected $fieldSearchable = [
        'allot_id',
    ];

    /**
     * Configure the Model
     **/
    public function model()
    {
        return Allot::class;
    }

    public function search($param = [])
    {

        $model = $this->model();
        $model = new $model;

        $rs = $model;
        if (!empty($param['goods_name'])) {
            $rs = $model->where('goods_name', '=', $param['goods_name']);
        }

        //创建时间开始
        if (!empty($param['add_time_start'])) {
            $rs = $rs->where('created_at', '>=', $param['created_at'] . ' 00:00:00');
        }
        //创建时间结束
        if (!empty($param['add_time_end'])) {
            $rs = $rs->where('created_at', '<=', $param['created_at'] . ' 23:59:59');
        }

        return $rs;
    }

    /**
     * Function:自动生成入单号
     * User:wucy
     * @return string
     */
    public function createAllotSn()
    {
        $model = $this->model();
        $allot_id = $model::max('allot_id');
        $date = date('Ymd',time());
        $allot_id = $allot_id +1;
        $allot_sn = 'A' .$date. str_repeat('0', 8 - strlen($allot_id)) . $allot_id;
        $sn_list = $model::where('allot_sn','like','%'.$allot_id.'%')->where('allot_id','<>',$allot_id)->get()->toArray();
        if (in_array($allot_sn, $sn_list))
        {
            $max = pow(10, strlen($sn_list[0]) - strlen($allot_sn) + 1) - 1;
            $new_sn = $allot_sn . mt_rand(0, $max);
            while (in_array($new_sn, $sn_list))
            {
                $new_sn = $allot_sn . mt_rand(0, $max);
            }
            $allot_sn = $new_sn;
        }

        return $allot_sn;
    }

模板文件table.blade.php

<div class="box" style="overflow-x:scroll;">
    <div class="box-body">
        <table class="table table-bordered table-hover lastTd" id="allots-table" style="font-size:12px;">
            <thead>
                <tr class="nowrap">
                    <th>调拨单号</th>
                    <th>制单时间</th>
                    <th>调出仓库</th>

                    <th>商品SKU</th>
                    <th>商品名称</th>
                    <th>商品属性</th>
                    <th>单位</th>
                    <th>调拨数量</th>

                    <th>调入仓库</th>
                    <th>调拨备注</th>
                    <th>审核状态</th>
                    <th>审核人</th>
                    <th>是否出库</th>
                    <th>是否入库</th>
                    <th style="width:135px;min-width:135px;">操作</th>
                </tr>
            </thead>
            <tbody>
            @foreach($allots as $allot)
                <?php
                    if(isset($param['goods_name']) && !empty($param['goods_name'])){
                        $detail = $allot->detail->whereInLoose('sku_id',$search_sku_id);
                    }else{
                        $detail = $allot->detail;
                    }

                    $count = count($detail);
                    $rowspan = $count == 1 ? '' : "rowspan='{$count}'";   //单元格合并
                    $first_detail = $detail->shift();

                    $admin_id = Auth::id();

                    if(($admin_ware > 0 && in_array( $allot->from_ware_id,$admin_ware))
                        || $admin_ware==0){
                         $from_admin_ware =1;
                    }else{
                         $from_admin_ware =0;
                    }

                    if(($admin_ware > 0 && in_array( $allot->to_ware_id,$admin_ware))
                    || $admin_ware==0){
                        $to_admin_ware =1;
                    }else{
                        $to_admin_ware =0;
                    }

                    //dd($from_admin_ware);

                ?>
                <tr>
                    <td {!! $rowspan !!}>{!! $allot->allot_sn !!}</td>
                    <td {!! $rowspan !!}>{!! $allot->created_at !!}</td>
                    <td {!! $rowspan !!}>{!! $allot['out_ware']['name'] !!}</td>

                    <td>{!! !empty($first_detail) ? $first_detail->change_sku : '--' !!}</td>
                    <td>{!! !empty($first_detail) ? $first_detail->sku->goods->goods_name : '--' !!}</td>
                    <td>{!! !empty($first_detail) ? $first_detail->sku->value_name : '--' !!}</td>
                    <td>{!! !empty($first_detail) ? $first_detail->sku->goods->goods_unit : '--' !!}</td>
                    <td>{!! !empty($first_detail) ? $first_detail->send_number : '--' !!}</td>

                    <td {!! $rowspan !!}>{!! $allot['entry_ware']['name'] !!}</td>
                    <td {!! $rowspan !!}>{!! $allot->remark !!}</td>
                    <td {!! $rowspan !!}>
                        <small class="label pull-left bg-blue">{!! config('const.ware.entry_status')[$allot->status] !!}</small>
                    </td>
                    <td {!! $rowspan !!}>{!! $allot->confirm_admin_name ? $allot->confirm_admin_name : '--'!!}</td>
                    <td {!! $rowspan !!}>{!! config('const.ware.entry_or_out_ware')[$allot->out_ware_status] !!}</td>
                    <td {!! $rowspan !!}>{!! config('const.ware.entry_or_out_ware')[$allot->entry_ware_status] !!}</td>
                    <td {!! $rowspan !!}>
                        {!! Form::open(['route' => ['admin.allots.destroy', $allot->getKey()], 'method' => 'delete']) !!}
                        <div class='btn-group'>
                            <a href="@if($allot->status==1) javascript:; @else {!! route('admin.allots.edit', [$allot->getKey()]) !!} @endif"
                               class='btn btn-default btn-xs' @if($allot->status==1) disabled="disabled" @endif title="编辑" alt="编辑"><i class="fa fa-edit"></i></a>
                            <a href="@if($allot->status==1) javascript:; @else{!! route('admin.allots.examine', [$allot->getKey()]) !!} @endif"
                               class='btn btn-default btn-xs' @if($allot->status==1) disabled="disabled" @endif title="审核" alt="审核"><i class="fa fa-user"></i></a>

                            <a href="@if($allot->is_out_ware == 1 || $from_admin_ware ==0)javascript:; @else {!! route('admin.allots.out_ware', [$allot->getKey()]) !!} @endif"
                               class='btn btn-default btn-xs' @if($allot->is_out_ware==1 ||$allot->status==0 || $from_admin_ware ==0) disabled="disabled" @endif title="办理出库" alt="办理出库"><i class="fa fa-share"></i></a>

                            <a href="@if($allot->entry_ware_status == 1 || $allot->out_ware_status==0 || $allot->is_entry_ware==1 || $to_admin_ware == 0) javascript:; @else {!! route('admin.allots.entry_ware', [$allot->getKey()]) !!} @endif"
                               class='btn btn-default btn-xs' @if($allot->entry_ware_status==1 || $allot->out_ware_status==0 ||$allot->is_entry_ware==1 || $to_admin_ware == 0) disabled="disabled" @endif title="办理入库" alt="办理入库"><i class="fa fa-reply"></i></a>

                            <a @if($allot->status > 0) disabled="disabled" @endif href="{!! route('admin.allots.destroy', [$allot->getKey()]) !!}" title="删除" alt="删除" class='btn btn-default btn-xs'><i class="fa fa-trash"></i></a>
                        </div>
                        {!! Form::close() !!}
                    </td>
                </tr>

                @if($rowspan != '')
                    @foreach($detail as $row)
                <tr>
                    <td>{{ $row->change_sku }}</td>
                    <td>{{ $row->sku->goods->goods_name }}</td>
                    <td>{{ $row->sku->value_name }}</td>
                    <td>{{ $row->sku->goods->goods_unit }}</td>
                    <td>{{ $row->send_number }}</td>
                </tr>
                    @endforeach
                @endif
            @endforeach
            </tbody>
        </table>
    </div>
</div>

一个功能模块包括增删改查,贴出来的代码会很多!这里只贴出列表的功能,有问题的可以留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
:首先是要分组,因为如果不分组,想合并的列与其它列会自动打印。这样,只能使用FR自带的隐藏重复数据的功能,但很多类似报都是要求合并行居中的,这点FR就不能自动实现了。 2:要全并的列放在分组脚中,其它放在分组数据BAND中,这样,打印完分组数据BAND后,动态改变分组脚中要合并列的TOP和HEIGHT就可以了。而且这样打印,因为要合并的行实际上只打印了一遍,因此应该效率更高。所以这就需要在打印分组数据BAND后有一个可记录此分组已打印高度的功能。 3:代码解释 procedure MCOnAfterData(Sender: TfrxComponent); begin if =1 then MC.Tag:=Int(MC.Height) else MC.Tag:=MC.Tag+Int(MC.Height); end; 因为FR的在每次分组后重新计数,使用MC.Tag保存现在数据BAND上的所有不合并行的总高度。当然也可以使用一个变量,但放着这么多TAG不用,多浪费呀。况且使用TAG的语法也比使用变量简单,使用变量使程序看上去很难懂。 if >=1 then 这样的写法看起来多痛苦呀。 procedure MBBOnAfterData(Sender: TfrxComponent); begin MBB.Tag:=GetStandHeight(MBB.CalcHeight); //这一句是为了保持行高的一致性,如果不需要直接 MBB.Tag:=MBB.CalcHeight; //这样可能计算的行高不是标准行高的整数倍。 MBB.Visible:=False; end; procedure MD1OnBeforePrint(Sender: TfrxComponent); begin if =1 then MBB.Visible:=True; end; 上二句只是为了不多次统计CalcHeight,但不能直接设可视性为假,否则不会触发MBBOnAfterData事件。 计算此例中可能会很高的列的计算高度,这是在宽度已经确定的情况下计算的。 因为此例中的第二列单行高度可能大于其它列的总高度。如果没有此例中的特殊情况,可以省略。 4:如果此例中没有第二列单行高度可能大于其它列的总高度的话,MBB是不需要的。 5:如果不是要求空行为多行多列显示的话,GFOnBeforePrint也是不需要的,只需要在GF上放二个MEMOVIEW,宽高和左边距分别与上方的二个相同,调用我例子中注释掉的代码改变它们的TOP和HEIGHT即可。 6:TAG是所有Tcomponent的属性呀,这是我最常使用的一个属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lxw1844912514

你的打赏就是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值