一、程式 admin_kind.php
<?php /* 引入檔頭,每支程都會引入 */ require_once 'head.php'; #權限檢查 if(!$_SESSION['isAdmin'])redirect_header("index.php", 3000, "您沒有管理員權限!"); #引入類別物件 include_once WEB_PATH . "/class/ugmKind.php"; #取得主要資料庫 $tbl = "ugm_p_kind"; /* 過濾變數,設定預設值 */ $op = system_CleanVars($_REQUEST, 'op', 'opList', 'string'); $sn = system_CleanVars($_REQUEST, 'sn', '', 'int'); $kind = system_CleanVars($_REQUEST, 'kind', 'prod', 'string'); #foreign key $foreign = array( "prod" => array("title" => "商品類別","stopLevel"=>1) ); #實體化 類別物件 #stopLevel $stopLevel = $foreign[$kind]['stopLevel']; //ugm_tools $ofsn = 0; //(資料表,分類,層數,父層) $ugmKind = new ugmKind($tbl, $kind, $stopLevel, $ofsn); #--------------------------------- #程式流程 switch ($op) { //新增資料 case "opAllInsert": $msg = opAllInsert(); redirect_header($_SESSION['returnUrl'], 3000, $msg); exit; case "opUpdateSort": //更新排序 echo opUpdateSort(); exit; case "opSaveDrag": //移動類別儲存 echo opSaveDrag(); exit; #類別刪除 case "opDelete" : $msg = opDelete($sn); redirect_header($_SESSION['returnUrl'], 3000, $msg); exit; //更新啟用狀態 case "opUpdateEnable": $msg = opUpdateEnable(); redirect_header($_SESSION['returnUrl'], 3, $msg); break; #ajax拖曳排序 case "op_ajax_update_sort": echo op_ajax_update_sort(); exit; break; #新增(Create) case "opInsert": $msg = opInsert(); redirect_header($_SESSION['returnUrl'], 3000, $msg); exit; #更新(Update) case "opUpdate": $msg = opUpdate($sn); redirect_header($_SESSION['returnUrl'], 3000, $msg); exit; break; #顯示單筆(Read) case "op_show": op_show($sn); break; #表單 case "opForm": opForm($sn); break; #讀取(Read) default: $op = "opList"; $_SESSION['returnUrl'] = getCurrentUrl(); opList($kind); break; } /*---- 將變數送至樣版----*/ $smarty->assign("WEB", $WEB); $smarty->assign("op", $op); /*---- 程式結尾-----*/ $smarty->display('theme_admin.tpl'); /*---- 程式結尾-----*/ ########################################################### # 批次編輯資料 ########################################################### function opAllInsert() { global $db, $ugmKind; foreach ($_POST['title'] as $sn => $title) { $title = db_CleanVars($title, "類別名稱");//類別名稱 $sn = db_CleanVars($sn, "sn");//sn $sql = "update `".$ugmKind->get_tbl()."` set `title` = '{$title}' where sn='{$sn}'"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); } return "更新所有類別完成!"; } ########################################### # 自動更新排序 ########################################### function opUpdateSort() { global $db, $ugmKind; $sort = 1; foreach ($_POST['tr'] as $sn) { if (!$sn) { continue; } $sql = "update `{$ugmKind->get_tbl()}` set `sort`='{$sort}' where `sn`='{$sn}'"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); $sort++; } return "排序完成!!"; } ########################################### # 移動類別儲存 ########################################### function opSaveDrag() { global $db,$ugmKind; $ofsn = intval($_POST['ofsn']); //目的 $sn = intval($_POST['sn']); //來源 $kind = $ugmKind->get_kind(); //關鍵字 $tbl = $ugmKind->get_tbl(); //資料表 $stopLevel = $ugmKind->get_stopLevel(); //層次 //$ofsn = $ugmKind->get_ofsn(); //父層 //return $ugmKind->chk_kind_level_down($sn); #檢查類別層次 $thisLevel = $ugmKind->get_thisLevel($sn); $downLevel = $ugmKind->get_downLevel($sn); $ofsnLevel = $ugmKind->get_thisLevel($ofsn); if (!$sn) { #根目錄不可移動 die("根目錄不可移動 (" . date("Y-m-d H:i:s") . ")"); } elseif ($ofsn == $sn) { #自己移至自己 die("不能自己移至自己(" . date("Y-m-d H:i:s") . ")"); } elseif ($ofsnLevel + $downLevel >= $stopLevel) { #自己往底層移動或自己底下層數+目的所在層數 > 類別層數 die("子類別太多,請先將子類別移動!(" . date("Y-m-d H:i:s") . ")"); } $sql = "update `{$tbl}` set `ofsn`='{$ofsn}' where `sn`='{$sn}'"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); return "移動類別完成!"; } ############################### # 刪除類別 ############################### function opDelete($sn){ global $db,$ugmKind; $kind = $ugmKind->get_kind(); //關鍵字 $tbl = $ugmKind->get_tbl(); //資料表 $stopLevel = $ugmKind->get_stopLevel(); //層次 $ofsn = $ugmKind->get_ofsn(); //父層 #檢查類別層次 $downLevel = $ugmKind->get_downLevel($sn); if($downLevel)redirect_header($_SESSION['returnUrl'], 3000, "尚有子類別,無法刪除!"); #刪除商品資料 $sql = "delete from `{$tbl}` where `sn`='{$sn}' "; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); return "刪除成功!"; } ############################################################################### # 更新啟用 ############################################################################### function opUpdateEnable() { global $db,$ugmKind; #過瀘資料 $_GET['sn'] = db_CleanVars($_GET['sn'], "sn"); $_GET['enable'] = db_CleanVars($_GET['enable'], "啟用"); /****************************************************************/ //更新 $sql = "update " . $ugmKind->get_tbl() . " set `enable` = '{$_GET['enable']}' where `sn`='{$_GET['sn']}'"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); return "更新啟用狀態成功!"; } ########################################################### # 新增資料 ########################################################### function opInsert() { global $db, $ugmKind; #驗證token verifyToken($_POST['token']); $kind = $ugmKind->get_kind(); //關鍵字 $tbl = $ugmKind->get_tbl(); //資料表 $stopLevel = $ugmKind->get_stopLevel(); //層次 $ofsn = $ugmKind->get_ofsn(); //父層 $_POST['title'] = db_CleanVars($_POST['title'], "類別名稱");//類別名稱 $_POST['kind'] = db_CleanVars($_POST['kind'], "kind");//分類 $_POST['enable'] = db_CleanVars($_POST['enable'], "啟用");//狀態 $_POST['sn'] = db_CleanVars($_POST['sn'], "");//sn $_POST['ofsn'] = db_CleanVars($_POST['ofsn'], "ofsn");//ofsn //-------------------------------------------------------*/ #取得排序-----------------------------# $sql = "select max(sort) as max_sort from `{$tbl}` where ofsn='{$_POST['ofsn']}' and kind='{$_POST['kind']}'"; $result = $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); list($sort) = $row = $result->fetch_row(); $sort++; #---------寫入------------------------- $sql = "insert into `{$tbl}` (`ofsn` ,`title` , `enable` , `sort`,`kind`) values ('{$_POST['ofsn']}' , '{$_POST['title']}' ,'{$_POST['enable']}' , '{$sort}' , '{$_POST['kind']}')"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); //取得最後新增資料的流水編號 //$_POST['sn'] = $db->insert_id; return "新增類別->{$_POST['title']} 成功!"; } ################################# # 更新資料 ################################# function opUpdate($sn) { global $db,$ugmKind; #驗證token verifyToken($_POST['token']); $kind = $ugmKind->get_kind(); //關鍵字 $tbl = $ugmKind->get_tbl(); //資料表 $stopLevel = $ugmKind->get_stopLevel(); //層次 $ofsn = $ugmKind->get_ofsn(); //父層 #過濾 $_POST['title'] = db_CleanVars($_POST['title'], "類別名稱");//類別名稱 $_POST['kind'] = db_CleanVars($_POST['kind'], "kind");//分類 $_POST['enable'] = db_CleanVars($_POST['enable'], "啟用");//狀態 $_POST['sn'] = db_CleanVars($_POST['sn'], "sn");//sn $_POST['ofsn'] = db_CleanVars($_POST['ofsn'], "ofsn");//ofsn #檢查類別層次 $thisLevel = $ugmKind->get_thisLevel($sn); $downLevel = $ugmKind->get_downLevel($sn); $ofsnLevel = $ugmKind->get_thisLevel($_POST['ofsn']); if($_POST['ofsn'] == $_POST['sn'])redirect_header($_SESSION['returnUrl'], 3000, "不能設定自己為父類別"); if($ofsnLevel + $downLevel >= $stopLevel)redirect_header($_SESSION['returnUrl'], 3000, "子類別太多,請先將子類別移動,再更新!"); $sql = "update `{$tbl}` set `ofsn` = '{$_POST['ofsn']}', `title` = '{$_POST['title']}', `kind` = '{$_POST['kind']}', `enable` = '{$_POST['enable']}' where sn='{$_POST['sn']}'"; $db->query($sql) or redirect_header("", 3000, $db->error."\n".$sql,true); return "編輯類別->{$_POST['title']} 成功!"; } ############################################################################### # 編輯表單 ############################################################################### function opForm($sn = "") { global $db,$smarty,$ugmKind; $kind = $ugmKind->get_kind(); //關鍵字 $tbl = $ugmKind->get_tbl(); //資料表 $stopLevel = $ugmKind->get_stopLevel(); //層次 $ofsn = $ugmKind->get_ofsn(); //父層 //----------------------------------*/ $_GET['ofsn'] = !isset($_GET['ofsn']) ? 0 : intval($_GET['ofsn']); //抓取預設值 if (!empty($sn)) { $row = $ugmKind->get_rowBYsn($sn); $pre = "編輯"; $row['op'] = "opUpdate"; //print_r($row);die(); } else { $row = array(); $pre = "新增"; $row['op'] = "opInsert"; } $row['formTitle'] = $pre . "類別"; $row['stopLevel'] = $stopLevel; //預設值設定 //設定「kind_sn」欄位預設值 $row['sn'] = (!isset($row['sn'])) ? "" : $row['sn']; //設定「ofsn」欄位預設值 $row['ofsn'] = (!isset($row['ofsn'])) ? $_GET['ofsn'] : $row['ofsn']; if ($stopLevel > 1) { $row['ofsnOption'] = $ugmKind->get_ofsnOption($row['ofsn']); } //設定「title」欄位預設值 $row['title'] = (!isset($row['title'])) ? "" : $row['title']; //設定「enable」欄位預設值 $row['enable'] = (!isset($row['enable'])) ? "1" : $row['enable']; //設定「kind」欄位預設值 $row['kind'] = (!isset($row['kind'])) ? $ugmKind->get_kind() : $row['kind']; $smarty->assign('row', $row); #防止偽造表單 $token = getTokenHTML(); $smarty->assign("token", $token); } ################################# # 列表程式 ################################# function opList($kind) { global $db,$smarty,$foreign,$ugmKind; # 預設Foreign key=> system #---- 防呆 if (!in_array($kind, array_keys($foreign))) { $kind = "prod"; } # ----得到foreign key選單 $foreignOption = $ugmKind->get_foreignOption($foreign,$kind); $foreignForm = " <div class='row' style='margin-bottom:10px;'> <div class='col-sm-3'> <select name='kind' id='kind' class='form-control' onchange=\"location.href='?kind='+this.value\"> $foreignOption </select> </div> </div> "; $smarty->assign('foreignForm', $foreignForm); $smarty->assign('kind', $kind); # ----得到陣列 ---------------------------- $list = $ugmKind->get_listArr(); $listTitles = array( "title" => array("content" => "標題", "width" => 9, "align" => "center"), "enable" => array("content" =>"啟用", "width" => 1, "align" => "center"), "function" => array("content" => "功能", "width" => 2, "align" => "center"), ); $smarty->assign("listTitles", $listTitles); #內容---------------------------------------------------------# $listBodys = array( "title" => array("valuetype" => "text", "align" => "left"), "enable" => array("valuetype" => "yesNo", "align" => "center"), "function" => array("valuetype" => "btn", "align" => "center", "btn" => array("edit", "del")), //瀏覽、編輯、刪除 ); $listHtml = $ugmKind->get_listHtml($list, $listBodys); $smarty->assign("listHtml", $listHtml); return; }
二、樣板 admin_kind.tpl
<{if $op=="opList"}> <link href="<{$xoAppUrl}>class/treeTable/stylesheets/jquery.treetable.css" rel="stylesheet"> <link href="<{$xoAppUrl}>class/treeTable/stylesheets/jquery.treetable.theme.default.css" rel="stylesheet"> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script> <script type="text/javascript" src="<{$xoAppUrl}>class/treeTable/javascripts/src/jquery.treetable.js"></script> <script type="text/javascript"> $(function() { //可以展開,預設展開 $('#form_table').treetable({ expandable: true ,initialState: 'expanded' }); // 配置拖動節點 $('#form_table .folder').draggable({ helper: 'clone', opacity: .75, refreshPositions: true, // Performance? revert: 'invalid', revertDuration: 300, scroll: true }); // Configure droppable rows $('#form_table .folder').each(function() { $(this).parents('#form_table tr').droppable({ accept: '.folder', drop: function(e, ui) { var droppedEl = ui.draggable.parents('tr'); console.log(droppedEl[0]); $('#form_table').treetable('move', droppedEl.data('ttId'), $(this).data('ttId')); //alert( droppedEl.data('ttId')); //目地的sn :$(this).data('ttId') //自己的sn:droppedEl.data('ttId') $.ajax({ type: 'POST', url: '?op=opSaveDrag', data: { ofsn: $(this).data('ttId'), sn: droppedEl.data('ttId'),kind :"<{$kind}>" }, success: function(theResponse) { //$('#save_msg').html(theResponse); //警告視窗 swal({ title: theResponse, text: '自動刷新畫面', type: 'success', showCancelButton: false, confirmButtonColor: '#3085d6', confirmButtonText: '確定' }).then(function () { location.href="<{$smarty.session.returnUrl}>"; }); } }); }, hoverClass: 'accept', over: function(e, ui) { var droppedEl = ui.draggable.parents('tr'); if(this != droppedEl[0] && !$(this).is('.expanded')) { $('#form_table').treetable('expandNode', $(this).data('ttId')); } } }); }); //排序 $('#sort').sortable({ opacity: 0.6, cursor: 'move', update: function() { var order = $(this).sortable('serialize') + '&op=opUpdateSort'; $.post('<{$WEB.file_name}>', order, function(theResponse){ //$('#save_msg').html(theResponse);//傳回訊息 //警告視窗 swal({ title: theResponse, text: '自動刷新畫面', type: 'success', showCancelButton: false, confirmButtonColor: '#3085d6', confirmButtonText: '確定' }).then(function () { location.href="<{$smarty.session.returnUrl}>"; }); }); } }); //每行的删除操作注册脚本事件 $(".btnDel").bind("click", function(){ var vbtnDel=$(this);//得到点击的按钮对象 var vTr=vbtnDel.parents("tr");//得到父tr对象; var sn=vTr.attr("sn");//取得 sn var title=$("#title_"+sn).val();//取得 title //警告視窗 swal({ title: '確定要刪除此資料?', text: title, type: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', confirmButtonText: '確定刪除!', cancelButtonText: '取消!' }).then(function () { location.href="admin_kind.php?op=opDelete&sn=" + sn; }) }); }); </script> <div class="panel panel-primary"> <div class="panel-heading"><h3 class="panel-title">類別管理</h3></div> <div class="panel-body"> <div id="save_msg"></div> <form action='<{$WEB.file_name}>' method='post' id='myForm'> <{$foreignForm}> <table id="form_table" class="table table-bordered table-striped table-hover"> <thead> <tr class="active"> <{foreach from=$listTitles item=row key=k}> <th class="col-sm-<{$row.width}> text-<{$row.align}>"><{$row.content}></th> <{/foreach}> </tr> </thead> <!-- 根目錄開始 --> <tr id='tr_0' data-tt-id="0"> <td class="text-left" colspan=<{$listTitles|@count}>> <span class='folder'></span> <i class="fa fa-home" aria-hidden="true"></i>根目錄 <a href="#" class="btn btn-success btn-xs" onclick="jQuery('#form_table').treetable('expandAll'); return false;">展開<i class="fa fa-expand" aria-hidden="true"></i></a> <a href="#" class="btn btn-danger btn-xs" onclick="jQuery('#form_table').treetable('collapseAll'); return false;">闔起<i class="fa fa-compress" aria-hidden="true"></i></a> <a href="#" class="btn btn-warning btn-xs">重整畫面<i class="fa fa-refresh" aria-hidden="true"></i></a> <a href="?op=opForm&kind=<{$kind}>&ofsn=0" class="btn btn-primary btn-xs" ait="在根目錄建立子類別">新增<i class="fa fa-plus" aria-hidden="true"></i></a> </td> </tr> <!-- 根目錄結束 --> <tbody id='sort'> <{$listHtml}> </tbody> <tfoot> <tr> <td colspan=3 class="text-center"> <input type='hidden' name='op' value="opAllInsert"> <input type='hidden' name='kind' value="<{$kind}>"> <button type="submit" class="btn btn-primary">送出</button> </td> </tr> </tfoot> </table> </form> </div> </div> <{/if}> <{if $op=="opForm"}> <div class="panel panel-primary"> <div class="panel-heading"><h3 class="panel-title"><{$row.formTitle}></h3></div> <div class="panel-body"> <form role="form" action="<{$WEB.file_name}>" method="post" id="myForm" enctype="multipart/form-data"> <div class="row"> <div class="col-sm-6"> <div class="form-group"> <label>標題</label> <input type='text' name='title' value='<{$row.title}>' id='title' class="form-control"> </div> </div> <div class="col-sm-2"> <div class="form-group"> <label style="display:block;" >啟用</label> <input type='radio' name='enable' id='enable_1' value='1' <{if $row.enable==1}>checked<{/if}>> <label for='enable_1'>啟用</label> <input type='radio' name='enable' id='enable_0' value='0' <{if $row.enable==0}>checked<{/if}>> <label for='enable_0'>停用</label> </div> </div> <{if $row.stopLevel > 1}> <div class="col-sm-2"> <div class="form-group"> <label>父類別</label> <select name="ofsn" id="ofsn" class="form-control" size="1" > <option value="0">/</option> <{$row.ofsnOption}> </select> </div> </div> <{else}> <input type='hidden' name='ofsn' value='0'> <{/if}> </div> <hr> <div class="form-group text-center"> <button type="submit" class="btn btn-primary">送出</button> <{if !$row.sn}> <button type="reset" class="btn btn-danger">重設</button> <{/if}> <button type="button" class="btn btn-warning" onclick="location.href='<{$smarty.session.returnUrl}>'">返回</button> <input type='hidden' name='op' value='<{$row.op}>'> <input type='hidden' name='sn' value='<{$row.sn}>'> <input type='hidden' name='kind' value='<{$row.kind}>'> <{$token}> </div> </form> </div> </div> <{/if}>
三、使用