• fastadmin 实现标签的多选研究---基于fa的test案例,已经CMS中的标签写法


    官方文档

    动态下拉组件
    https://doc.fastadmin.net/doc/178.html

    首先生成控制器和菜单看下fa_test的多选效果

    多选效果如下



    使用多选的两种方式(chekbox是最简单的,那中多选就不算了)

    1.input里使用多选(官网中,以分类id的多选为例,因为ui的逼格比较高,所以我使用这个。)
    view

    <div class="form-group">
            <label class="control-label col-xs-12 col-sm-2">{:__('Category_ids')}:</label>
            <div class="col-xs-12 col-sm-8">
                <input id="c-category_ids" data-rule="required" data-source="category/selectpage" data-params='{"custom[type]":"test"}' data-multiple="true" class="form-control selectpage" name="row[category_ids]" type="text" value="">
            </div>
        </div>
    

    2.select里使用多选(官网中,以状态的多选为例子)
    view

      <div class="form-group">
            <label class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
            <div class="col-xs-12 col-sm-8">
                            
                <select  id="c-flag" data-rule="required" class="form-control selectpicker" multiple="" name="row[flag][]">
                    {foreach name="flagList" item="vo"}
                        <option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option>
                    {/foreach}
                </select>
    
            </div>
        </div>
    

    具体的方式,大家,看相关的test控制器和js,以及模型

    控制器中直接引入一个方法

      /**
         * Selectpage搜索
         *
         * @internal
         */
        public function selectpage()
        {
            return parent::selectpage();
        }
    }
    

    如何,让多选项是树状效果呢?

    注释掉父类的方法,重写自己的方法,最后不需要重写
    直接在input里增加一个参数

    1.data-params='{"isTree":1}'
    同时,可以使用
    2.data-params='{"custom[type]":"test"}',来限制返回的字段
    
       /**
         * Selectpage搜索
         *
         * @internal
         */
        public function selectpage()
        {
            // return parent::selectpage();
            // 注释掉继承的,下面是重写的
    
             //  获取标签列表,渲染成右侧的树形,记得引入use fast/tree 这个命名空间
            $wenzhang_tags_right=collection(db::name("cms_exams_tags")->select())->toArray();
            $tree = Tree::instance();
            $tree->init($wenzhang_tags_right, 'parent');
            $this->tagsListRight = $tree->getTreeList($tree->getTreeArray(0), 'text');
            
             //对请求进行判断,并返回json数据,
            if ($this->request->isAjax()) {
               
                //构造父类select列表选项数据
               
                $list = $this->tagsListRight;
              
                $list = array_values($list);
              
            //   下面这个,是设置pid的,不设置,就会成undefine,前端的展开隐藏,靠这个pid
                foreach ($list as $k => &$v) {
                    $v['pid'] = $v['parent'];
                 
                }
                $total = count($list);
                $result = array("total" => $total, "rows" => $list);
    
                return json($result);
            }
            
        }
        
    

    接下来,就是多个tag如何存储的问题,以及如何读取的问题了

    1.存储,要操作tag表
    参考官方的tags.php控制器
    并研究官方的selectpage函数代码

    protected function selectpage()
        {
            //设置过滤方法
            $this->request->filter(['strip_tags', 'htmlspecialchars']);
    
            //搜索关键词,客户端输入以空格分开,这里接收为数组
            $word = (array)$this->request->request("q_word/a");
            //当前页
            $page = $this->request->request("pageNumber");
            //分页大小
            $pagesize = $this->request->request("pageSize");
            //搜索条件
            $andor = $this->request->request("andOr", "and", "strtoupper");
            //排序方式
            $orderby = (array)$this->request->request("orderBy/a");
            //显示的字段
            $field = $this->request->request("showField");
            //主键
            $primarykey = $this->request->request("keyField");
            //主键值
            $primaryvalue = $this->request->request("keyValue");
            //搜索字段
            $searchfield = (array)$this->request->request("searchField/a");
            //自定义搜索条件
            $custom = (array)$this->request->request("custom/a");
            //是否返回树形结构
            $istree = $this->request->request("isTree", 0);
            $ishtml = $this->request->request("isHtml", 0);
            if ($istree) {
                $word = [];
                $pagesize = 99999;
            }
            $order = [];
            foreach ($orderby as $k => $v) {
                $order[$v[0]] = $v[1];
            }
            $field = $field ? $field : 'name';
    
            //如果有primaryvalue,说明当前是初始化传值
            if ($primaryvalue !== null) {
                $where = [$primarykey => ['in', $primaryvalue]];
                $pagesize = 99999;
            } else {
                $where = function ($query) use ($word, $andor, $field, $searchfield, $custom) {
                    $logic = $andor == 'AND' ? '&' : '|';
                    $searchfield = is_array($searchfield) ? implode($logic, $searchfield) : $searchfield;
                    foreach ($word as $k => $v) {
                        $query->where(str_replace(',', $logic, $searchfield), "like", "%{$v}%");
                    }
                    if ($custom && is_array($custom)) {
                        foreach ($custom as $k => $v) {
                            if (is_array($v) && 2 == count($v)) {
                                $query->where($k, trim($v[0]), $v[1]);
                            } else {
                                $query->where($k, '=', $v);
                            }
                        }
                    }
                };
            }
            $adminIds = $this->getDataLimitAdminIds();
            if (is_array($adminIds)) {
                $this->model->where($this->dataLimitField, 'in', $adminIds);
            }
            $list = [];
            $total = $this->model->where($where)->count();
            if ($total > 0) {
                if (is_array($adminIds)) {
                    $this->model->where($this->dataLimitField, 'in', $adminIds);
                }
                $datalist = $this->model->where($where)
                    ->order($order)
                    ->page($page, $pagesize)
                    ->field($this->selectpageFields)
                    ->select();
                foreach ($datalist as $index => $item) {
                    unset($item['password'], $item['salt']);
                    $list[] = [
                        $primarykey => isset($item[$primarykey]) ? $item[$primarykey] : '',
                        $field      => isset($item[$field]) ? $item[$field] : '',
                        'pid'       => isset($item['pid']) ? $item['pid'] : 0
                    ];
                }
                if ($istree && !$primaryvalue) {
                    $tree = Tree::instance();
                    $tree->init(collection($list)->toArray(), 'pid');
                    $list = $tree->getTreeList($tree->getTreeArray(0), $field);
                    if (!$ishtml) {
                        foreach ($list as &$item) {
                            $item = str_replace('&nbsp;', ' ', $item);
                        }
                        unset($item);
                    }
                }
            }
            //这里一定要返回有list这个字段,total是可选的,如果total<=list的数量,则会隐藏分页按钮
            return json(['list' => $list, 'total' => $total]);
        }
    

    archives模型init中的更新tags的代码

      self::afterWrite(function ($row) use ($config) {
                if (isset($row['channel_id'])) {
                    //在更新成功后刷新副表、TAGS表数据、栏目表
                    $channel = Channel::get($row->channel_id);
                    if ($channel) {
                        $model = Modelx::get($channel['model_id']);
                        if ($model && isset($row['content'])) {
                            $values = array_intersect_key($row->getData(), array_flip($model->fields));
                            $values['id'] = $row['id'];
                            $values['content'] = $row['content'];
                            db($model['table'])->insert($values, true);
                        }
                    }
                }
                if (isset($row['tags'])) {
                    $tags = array_filter(explode(',', $row['tags']));
                    if ($tags) {
                        $tagslist = Tags::where('name', 'in', $tags)->select();
                        foreach ($tagslist as $k => $v) {
                            $archives = explode(',', $v['archives']);
                            if (!in_array($row['id'], $archives)) {
                                $archives[] = $row['id'];
                                $v->archives = implode(',', $archives);
                                $v->nums++;
                                $v->save();
                            }
                            $tags = array_udiff($tags, [$v['name']], 'strcasecmp');
                        }
                        $list = [];
                        foreach ($tags as $k => $v) {
                            $list[] = ['name' => $v, 'archives' => $row['id'], 'nums' => 1];
                        }
                        if ($list) {
                            (new Tags())->saveAll($list);
                        }
                    }
                }
                $changedData = $row->getChangedData();
                if (isset($changedData['status']) && $changedData['status'] == 'normal') {
                    //增加积分
                    User::score($config['score']['postarchives'], $row['user_id'], '发布文章');
                    //推送到熊掌号和百度站长
                    if ($config['baidupush']) {
                        $urls = [$row->fullurl];
                        	hinkHook::listen("baidupush", $urls);
                    }
                }
                if ($config['searchtype'] == 'xunsearch') {
                    //更新全文搜索
                    FulltextSearch::update($row->id);
                }
            });
    

    这里我抄袭tags表的更新方法,修改自己的examstags表的tag数据

     // 新增tag分组,不能新增,只能选择,所以,不需要对比,直接插入新的tags
                
                  if (isset($row['tags_ids'])) {
                    $mytags = array_filter(explode(',', $row['tags_ids']));
                    if ($mytags) {
                        // 获取数据表里的tags数据
                        $mytagslist = Examstags::where('id', 'in', $mytags)->select();
                        foreach ($mytagslist as $k => $v) {
                            $archives = explode(',', $v['archive_id']);
                        // 如果当前的id,不在数据表的archives,那么就新增一下
                            if (!in_array($row['id'], $archives)) {
                                $archives[] = $row['id'];
                                $v->archive_id = implode(',', $archives);
                                // 忘记设置nums了,这里也去掉
                                // $v->nums++;
                                $v->save();
                            }
                        // 再看看,有没有新增标签,因为我们展示不支持新增,所以,暂时不用这个
                        //   $tags = array_udiff($tags, [$v['name']], 'strcasecmp');
                        }
                        // $list = [];
                        // foreach ($tags as $k => $v) {
                        //     $list[] = ['name' => $v, 'archives' => $row['id'], 'nums' => 1];
                        // }
                        // if ($list) {
                        //     (new Tags())->saveAll($list);
                        // }
                    }
                }
    

    2.读取,也要操作tag表,并且,view视图里,如何写,也是个问题

    //在新增页面,新增树状结构的tag下拉选项
     <div class="form-group">
                                    <label class="control-label col-xs-12 col-sm-3">{:__('标签(多选)')}:</label>
                                    <div class="col-xs-12 col-sm-8">
    //默认的字段为name,可以显示出中文,如果字段不是name,那么使用data-field="xxx",来显示tag的中文
                                        <input id="c-tags_ids" data-rule="required" data-source="cms/examstags/selectpage" data-field="text"  data-multiple="true" class="form-control selectpage" name="row[tags_ids]" type="text" value="">
                                    </div>
                                </div>
    
     //在编辑页面获取当前的,多选的tag
     <div class="form-group">
            <label class="control-label col-xs-12 col-sm-2">{:__('tags_ids')}:</label>
            <div class="col-xs-12 col-sm-8">
    //默认的字段为name,可以显示出中文,如果字段不是name,那么使用data-field="xxx",来显示tag的中文
                <input id="c-tags_ids" data-rule="required" data-source="cms/examstags/selectpage" data-field="text" data-multiple="true" class="form-control selectpage" name="row[tags_ids]" type="text" value="{$row.tags_ids|htmlentities}">
            </div>
        </div>
    
    默认情况下,是显示所有的tag,id。但是编辑页面,要显示当前的tags,id
    对主键值进行判断。为什么要进行这样的判断呢?
     if ($istree&& !$primaryvalue) {
                
                    $list = $this->tagsListRight;
                    $list = array_values($list);
                      
                    //   下面这个,是设置pid的,不设置,就会成undefine,前端的展开隐藏,靠这个pid
                        foreach ($list as $k => &$v) {
                            $v['pid'] = $v['parent'];
                        }
                  
                  
                    if (!$ishtml) {
                        foreach ($list as &$item) {
                            $item = str_replace('&nbsp;', ' ', $item);
                        }
                        unset($item);
                    }
                }
    

    3.如何搜索
    4.如何批量录入

  • 相关阅读:
    Win10 .Net Framework 3.5 安装错误 0x800F0954
    论如何去掌握一门新技术
    SpringBoot入门(二):日志及自定义属性
    SpringBoot入门(一):从HelloWorld开始
    【总结】Java面试题
    【SpringBoot-创建项目】一.通过Idea创建SpringBoot项目
    130道 Java多线程面试题汇总
    100道精选Redis面试题,最新Java面试题
    最新Redis面试题,附答案
    Little定律
  • 原文地址:https://www.cnblogs.com/cn-oldboy/p/13070125.html
Copyright © 2020-2023  润新知