liuhairui 2 settimane fa
parent
commit
1e4ea6471a

+ 182 - 3
application/admin/controller/Procuremen.php

@@ -40,21 +40,181 @@ class Procuremen extends Backend
     protected $pickHiddenScydgySetCache = null;
     protected $pickHiddenScydgySetCache = null;
 
 
     /**
     /**
+     * 采购子接口均走菜单规则鉴权;下列方法在方法内用 hasProcuremenPerm 做别名校验。
      * @var array
      * @var array
      */
      */
     protected $noNeedRight = [
     protected $noNeedRight = [
-        'review', 'reviewCompanies', 'outward_detail', 'export_month_outward', 'snapshotToProcure',
-        'pick', 'audit', 'confirm', 'pickreview', 'picksubmit', 'pickadd', 'auditissue', 'auditsubmit',
-        'auditresendsms', 'auditabandon', 'archiveabandon', 'auditresendemail', 'purchaseconfirmpick', 'purchaseapprovalreject', 'add', 'pickdelete', 'completeDirectly', 'rfqlist', 'details',
+        'pickreview', 'review', 'reviewcompanies',
     ];
     ];
 
 
     public function _initialize()
     public function _initialize()
     {
     {
         parent::_initialize();
         parent::_initialize();
         $this->model = new \app\admin\model\Procuremen;
         $this->model = new \app\admin\model\Procuremen;
+        $this->assignProcuremenAuthConfig();
 
 
     }
     }
 
 
+    /**
+     * 是否拥有采购子权限(支持 procuremen/pickreview 与 procuremen/pickreview/index 等写法)
+     *
+     * @param string[] $actions 如 pickreview、procuremen/picksubmit
+     */
+    protected function hasProcuremenPerm(array $actions): bool
+    {
+        foreach ($actions as $action) {
+            $action = strtolower(trim((string)$action));
+            if ($action === '') {
+                continue;
+            }
+            if (strpos($action, 'procuremen/') !== 0) {
+                $action = 'procuremen/' . $action;
+            }
+            if ($this->auth->check($action)) {
+                return true;
+            }
+        }
+        $suffixes = [];
+        foreach ($actions as $action) {
+            $action = strtolower(trim((string)$action));
+            $action = preg_replace('#^procuremen/#', '', $action);
+            if ($action !== '') {
+                $suffixes[$action] = true;
+            }
+        }
+        if ($suffixes === []) {
+            return false;
+        }
+        try {
+            foreach ($this->auth->getRuleList() as $rule) {
+                $rule = strtolower((string)$rule);
+                if (strpos($rule, 'procuremen/') !== 0) {
+                    continue;
+                }
+                foreach (array_keys($suffixes) as $suffix) {
+                    if ($rule === 'procuremen/' . $suffix || strpos($rule, 'procuremen/' . $suffix . '/') === 0) {
+                        return true;
+                    }
+                }
+            }
+        } catch (\Throwable $e) {
+        }
+
+        return false;
+    }
+
+    /**
+     * 仅精确匹配规则名(删除/完结等敏感操作,避免模糊匹配误放行)
+     *
+     * @param string[] $actions
+     */
+    protected function hasProcuremenPermStrict(array $actions): bool
+    {
+        foreach ($actions as $action) {
+            $action = strtolower(trim((string)$action));
+            if ($action === '') {
+                continue;
+            }
+            if (strpos($action, 'procuremen/') !== 0) {
+                $action = 'procuremen/' . $action;
+            }
+            if ($this->auth->check($action)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 当前角色已勾选的菜单规则中,是否包含指定标题(与「删除按钮」「完结按钮」等中文节点对应)
+     *
+     * @param string[] $titles
+     */
+    protected function authHasAssignedRuleTitle(array $titles): bool
+    {
+        $titles = array_values(array_filter(array_map('trim', $titles)));
+        if ($titles === []) {
+            return false;
+        }
+        try {
+            $ids = $this->auth->getRuleIds();
+            if (in_array('*', $ids, true)) {
+                return true;
+            }
+            if ($ids === []) {
+                return false;
+            }
+            $rows = Db::name('auth_rule')
+                ->where('status', 'normal')
+                ->whereIn('id', $ids)
+                ->column('title');
+            foreach ($rows as $title) {
+                $t = trim((string)$title);
+                if ($t !== '' && in_array($t, $titles, true)) {
+                    return true;
+                }
+            }
+        } catch (\Throwable $e) {
+        }
+
+        return false;
+    }
+
+    protected function procuremenCanPickDelete(): bool
+    {
+        if ($this->hasProcuremenPermStrict(['pickdelete'])) {
+            return true;
+        }
+
+        return $this->authHasAssignedRuleTitle(['删除按钮', '删除']);
+    }
+
+    protected function procuremenCanComplete(): bool
+    {
+        if ($this->hasProcuremenPermStrict(['completedirectly', 'completeDirectly'])) {
+            return true;
+        }
+
+        return $this->authHasAssignedRuleTitle(['完结按钮', '完结']);
+    }
+
+    protected function procuremenCanDispatch(): bool
+    {
+        return $this->hasProcuremenPerm(['pickreview', 'picksubmit', 'review']);
+    }
+
+    /**
+     * 前端按钮显隐(Config.procuremenAuth)
+     */
+    protected function assignProcuremenAuthConfig(): void
+    {
+        $authMap = [
+            'pickreview'              => $this->procuremenCanDispatch(),
+            'picksubmit'              => $this->hasProcuremenPerm(['picksubmit', 'pickreview', 'review']),
+            'pickdelete'              => $this->procuremenCanPickDelete(),
+            'completedirectly'        => $this->procuremenCanComplete(),
+            'snapshottoprocure'       => $this->hasProcuremenPerm(['snapshottoprocure', 'snapshotToProcure']),
+            'auditissue'              => $this->hasProcuremenPerm(['auditissue']),
+            'auditsubmit'             => $this->hasProcuremenPerm(['auditsubmit']),
+            'auditresendsms'          => $this->hasProcuremenPerm(['auditresendsms']),
+            'auditresendemail'        => $this->hasProcuremenPerm(['auditresendemail']),
+            'auditabandon'            => $this->hasProcuremenPerm(['auditabandon']),
+            'outward_detail'          => $this->hasProcuremenPerm(['outward_detail', 'outwarddetail']),
+            'purchaseconfirmpick'     => $this->hasProcuremenPerm(['purchaseconfirmpick', 'purchaseConfirmPick']),
+            'purchaseapprovalreject'  => $this->hasProcuremenPerm(['purchaseapprovalreject', 'purchaseApprovalReject']),
+            'details'                 => $this->hasProcuremenPerm(['details']),
+            'archiveabandon'          => $this->hasProcuremenPerm(['archiveabandon']),
+            'export_month_outward'    => $this->hasProcuremenPerm(['export_month_outward', 'exportMonthOutward']),
+            'review'                  => $this->hasProcuremenPerm(['review', 'picksubmit', 'pickreview']),
+            'reviewcompanies'         => $this->hasProcuremenPerm(['reviewcompanies', 'reviewCompanies', 'pickreview', 'picksubmit', 'review']),
+            'add'                     => $this->hasProcuremenPerm(['add']),
+            'rfqlist'                 => $this->hasProcuremenPerm(['rfqlist']),
+            'pickadd'                 => $this->hasProcuremenPerm(['pickadd', 'pickAdd']),
+        ];
+        $this->assignconfig('procuremenAuth', $authMap);
+    }
+
     /**
     /**
      * 手机端协助明细首页直达链接(登录后打开对应明细,免搜索)
      * 手机端协助明细首页直达链接(登录后打开对应明细,免搜索)
      * 配置 application/extra/mproc.php:mobile_base_url、mobile_index_path
      * 配置 application/extra/mproc.php:mobile_base_url、mobile_index_path
@@ -652,6 +812,10 @@ class Procuremen extends Backend
         $this->view->assign('sidebarYearMonths', $sidebar);
         $this->view->assign('sidebarYearMonths', $sidebar);
         $this->view->assign('procuremenStage', $stage);
         $this->view->assign('procuremenStage', $stage);
         $this->view->assign('procuremenPageTitle', $pageTitle);
         $this->view->assign('procuremenPageTitle', $pageTitle);
+        $this->view->assign('procuremenBtnDispatch', $this->procuremenCanDispatch());
+        $this->view->assign('procuremenBtnPickDelete', $this->procuremenCanPickDelete());
+        $this->view->assign('procuremenBtnComplete', $this->procuremenCanComplete());
+        $this->view->assign('procuremenBtnAuditAbandon', $this->hasProcuremenPerm(['auditabandon']));
     }
     }
 
 
     /** 协助下发(选工序+供应商,发短信邮件通知报价) */
     /** 协助下发(选工序+供应商,发短信邮件通知报价) */
@@ -2573,6 +2737,9 @@ class Procuremen extends Backend
         if (!$this->request->isPost() || !$this->request->isAjax()) {
         if (!$this->request->isPost() || !$this->request->isAjax()) {
             $this->error(__('参数错误'));
             $this->error(__('参数错误'));
         }
         }
+        if (!$this->procuremenCanComplete()) {
+            $this->error(__('You have no permission'));
+        }
         $row = json_decode($this->request->post('row_json', ''), true);
         $row = json_decode($this->request->post('row_json', ''), true);
         if (!is_array($row)) {
         if (!is_array($row)) {
             $this->error(__('Invalid parameters'));
             $this->error(__('Invalid parameters'));
@@ -5434,6 +5601,9 @@ class Procuremen extends Backend
      */
      */
     public function pickReview()
     public function pickReview()
     {
     {
+        if (!$this->hasProcuremenPerm(['pickreview', 'picksubmit', 'review'])) {
+            $this->error(__('You have no permission'));
+        }
         if ($this->request->isPost()) {
         if ($this->request->isPost()) {
             $this->error('请使用弹窗内「确认下发」提交');
             $this->error('请使用弹窗内「确认下发」提交');
         }
         }
@@ -5645,6 +5815,9 @@ class Procuremen extends Backend
         if (!$this->request->isPost() || !$this->request->isAjax()) {
         if (!$this->request->isPost() || !$this->request->isAjax()) {
             $this->error(__('Invalid parameters'));
             $this->error(__('Invalid parameters'));
         }
         }
+        if (!$this->procuremenCanPickDelete()) {
+            $this->error(__('You have no permission'));
+        }
         $rowsRaw = $this->request->post('rows_json', '[]');
         $rowsRaw = $this->request->post('rows_json', '[]');
         $rows = json_decode(is_string($rowsRaw) ? $rowsRaw : '', true);
         $rows = json_decode(is_string($rowsRaw) ? $rowsRaw : '', true);
         if (!is_array($rows) || $rows === []) {
         if (!is_array($rows) || $rows === []) {
@@ -6452,6 +6625,9 @@ class Procuremen extends Backend
      */
      */
     public function review()
     public function review()
     {
     {
+        if (!$this->hasProcuremenPerm(['review', 'picksubmit', 'pickreview'])) {
+            $this->error(__('You have no permission'));
+        }
         if ($this->request->isPost()) {
         if ($this->request->isPost()) {
             $this->error('请使用第一步「协助下发」通知供应商,再在「确认供应商」中选定一家');
             $this->error('请使用第一步「协助下发」通知供应商,再在「确认供应商」中选定一家');
         }
         }
@@ -6465,6 +6641,9 @@ class Procuremen extends Backend
      */
      */
     public function reviewCompanies()
     public function reviewCompanies()
     {
     {
+        if (!$this->hasProcuremenPerm(['reviewcompanies', 'pickreview', 'picksubmit', 'review'])) {
+            $this->error(__('You have no permission'));
+        }
         if (!$this->request->isAjax()) {
         if (!$this->request->isAjax()) {
             $this->error(__('Invalid parameters'));
             $this->error(__('Invalid parameters'));
         }
         }

+ 9 - 0
application/admin/controller/Procuremenarchive.php

@@ -15,6 +15,15 @@ class Procuremenarchive extends Backend
 {
 {
     protected $searchFields = 'CCYDH,CYJMC,CGYMC';
     protected $searchFields = 'CCYDH,CYJMC,CGYMC';
 
 
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->assignconfig('procuremenAuth', [
+            'details'        => $this->auth->check('procuremen/details'),
+            'archiveabandon' => $this->auth->check('procuremen/archiveabandon'),
+        ]);
+    }
+
     /** purchase_order.status 为已完结(兼容 varchar / 数字 / 首尾空格) */
     /** purchase_order.status 为已完结(兼容 varchar / 数字 / 首尾空格) */
     protected function applyPurchaseOrderCompletedWhere($query): void
     protected function applyPurchaseOrderCompletedWhere($query): void
     {
     {

+ 9 - 0
application/admin/controller/Procuremenexport.php

@@ -15,6 +15,15 @@ class Procuremenexport extends Backend
 {
 {
     protected $searchFields = 'CCYDH,CYJMC,CGYMC';
     protected $searchFields = 'CCYDH,CYJMC,CGYMC';
 
 
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->assignconfig('procuremenAuth', [
+            'details'             => $this->auth->check('procuremen/details'),
+            'export_month_outward' => $this->auth->check('procuremen/export_month_outward'),
+        ]);
+    }
+
     public function index()
     public function index()
     {
     {
         $this->relationSearch = false;
         $this->relationSearch = false;

+ 1 - 1
application/admin/view/index/login.html

@@ -196,7 +196,7 @@
     <div class="tmbg">
     <div class="tmbg">
     </div>
     </div>
     <div class="login-screen">
     <div class="login-screen">
-        <p class="head-title-logo">供应商存证系统</p>
+        <p class="head-title-logo">大数据协同系统</p>
         <div>
         <div>
             <div class="login-form">
             <div class="login-form">
                 <p id="profile-name" class="profile-name-card"></p>
                 <p id="profile-name" class="profile-name-card"></p>

+ 6 - 0
application/admin/view/procuremen/audit_issue.html

@@ -216,8 +216,12 @@
                 <td class="text-center">{$ln.subtotal_text|default=''|htmlentities}</td>
                 <td class="text-center">{$ln.subtotal_text|default=''|htmlentities}</td>
                 {if $lk == 1}
                 {if $lk == 1}
                 <td class="text-center audit-op-cell"{if condition="$co.display_rowspan gt 1"} rowspan="{$co.display_rowspan}"{/if} style="vertical-align:middle;">
                 <td class="text-center audit-op-cell"{if condition="$co.display_rowspan gt 1"} rowspan="{$co.display_rowspan}"{/if} style="vertical-align:middle;">
+                    {if $auth->check('procuremen/auditresendemail')}
                     <button type="button" class="btn btn-default btn-xs audit-row-send-email" data-company="{$co.name|default=''|htmlentities}">发邮件</button>
                     <button type="button" class="btn btn-default btn-xs audit-row-send-email" data-company="{$co.name|default=''|htmlentities}">发邮件</button>
+                    {/if}
+                    {if $auth->check('procuremen/auditresendsms')}
                     <button type="button" class="btn btn-default btn-xs audit-row-send-sms" data-company="{$co.name|default=''|htmlentities}">发短信</button>
                     <button type="button" class="btn btn-default btn-xs audit-row-send-sms" data-company="{$co.name|default=''|htmlentities}">发短信</button>
+                    {/if}
                 </td>
                 </td>
                 {/if}
                 {/if}
             </tr>
             </tr>
@@ -235,9 +239,11 @@
     <div class="form-group layer-footer">
     <div class="form-group layer-footer">
         <div class="row procuremen-audit-issue-footer-row">
         <div class="row procuremen-audit-issue-footer-row">
             <div class="col-xs-12 procuremen-audit-issue-footer-btns">
             <div class="col-xs-12 procuremen-audit-issue-footer-btns">
+                {if $auth->check('procuremen/auditsubmit')}
                 <button type="button" style="margin-right: 12px" class="btn btn-primary btn-embossed" id="btn-audit-issue-submit">
                 <button type="button" style="margin-right: 12px" class="btn btn-primary btn-embossed" id="btn-audit-issue-submit">
                     <i class="fa fa-check"></i> 确认
                     <i class="fa fa-check"></i> 确认
                 </button>
                 </button>
+                {/if}
                 <button type="button" class="btn btn-default btn-embossed" id="btn-audit-issue-close">
                 <button type="button" class="btn btn-default btn-embossed" id="btn-audit-issue-close">
                     <i class="fa fa-times"></i> 关闭
                     <i class="fa fa-times"></i> 关闭
                 </button>
                 </button>

+ 13 - 1
application/admin/view/procuremen/index.html

@@ -326,7 +326,11 @@
 <div class="panel panel-default panel-intro" id="procuremen-layout"
 <div class="panel panel-default panel-intro" id="procuremen-layout"
      data-default-ym="{$defaultYm|htmlentities}"
      data-default-ym="{$defaultYm|htmlentities}"
      data-procuremen-redis-api="{$procuremenRedisApi|htmlentities}"
      data-procuremen-redis-api="{$procuremenRedisApi|htmlentities}"
-     data-procuremen-stage="{$procuremenStage|default='pick'|htmlentities}">
+     data-procuremen-stage="{$procuremenStage|default='pick'|htmlentities}"
+     data-can-dispatch="{$procuremenBtnDispatch|default=0}"
+     data-can-pick-delete="{$procuremenBtnPickDelete|default=0}"
+     data-can-complete="{$procuremenBtnComplete|default=0}"
+     data-can-audit-abandon="{$procuremenBtnAuditAbandon|default=0}">
     {:build_heading()}
     {:build_heading()}
 
 
     <div class="panel-body">
     <div class="panel-body">
@@ -349,10 +353,18 @@
                             <div class="procuremen-table-area">
                             <div class="procuremen-table-area">
                                 <div id="toolbar" class="toolbar">
                                 <div id="toolbar" class="toolbar">
                                     <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" >刷新 <i class="fa fa-refresh"></i> </a>
                                     <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" >刷新 <i class="fa fa-refresh"></i> </a>
+                                    {if isset($procuremenBtnAuditAbandon) && $procuremenBtnAuditAbandon}
                                     <a href="javascript:;" class="btn btn-danger" id="btn-procuremen-audit-abandon" title="勾选一条或多条订单退回协助初选重新下发(历史记录保留)" style="display:none;"><i class="fa fa-repeat"></i> 重新下发</a>
                                     <a href="javascript:;" class="btn btn-danger" id="btn-procuremen-audit-abandon" title="勾选一条或多条订单退回协助初选重新下发(历史记录保留)" style="display:none;"><i class="fa fa-repeat"></i> 重新下发</a>
+                                    {/if}
+                                    {if isset($procuremenBtnDispatch) && $procuremenBtnDispatch}
                                     <a href="javascript:;" class="btn btn-info" id="btn-procuremen-pick-review" title="勾选一条或多条工序进行下发(多条须同一订单号)" style="display:none;"><i class="fa fa-paper-plane"></i> 下发</a>
                                     <a href="javascript:;" class="btn btn-info" id="btn-procuremen-pick-review" title="勾选一条或多条工序进行下发(多条须同一订单号)" style="display:none;"><i class="fa fa-paper-plane"></i> 下发</a>
+                                    {/if}
+                                    {if isset($procuremenBtnComplete) && $procuremenBtnComplete}
                                     <a href="javascript:;" class="btn btn-warning" id="btn-procuremen-batch-finish" title="勾选一条或多条工序标记为已完结" style="display:none;"><i class="fa fa-flag-checkered"></i> 完结</a>
                                     <a href="javascript:;" class="btn btn-warning" id="btn-procuremen-batch-finish" title="勾选一条或多条工序标记为已完结" style="display:none;"><i class="fa fa-flag-checkered"></i> 完结</a>
+                                    {/if}
+                                    {if isset($procuremenBtnPickDelete) && $procuremenBtnPickDelete}
                                     <a href="javascript:;" class="btn btn-danger" id="btn-procuremen-pick-delete" title="勾选一条或多条工序从初选列表移除" style="display:none;"><i class="fa fa-trash"></i> 删除</a>
                                     <a href="javascript:;" class="btn btn-danger" id="btn-procuremen-pick-delete" title="勾选一条或多条工序从初选列表移除" style="display:none;"><i class="fa fa-trash"></i> 删除</a>
+                                    {/if}
                                 </div>
                                 </div>
                                 <table id="table"
                                 <table id="table"
                                        class="table table-striped table-bordered table-hover">
                                        class="table table-striped table-bordered table-hover">

+ 4 - 0
application/admin/view/procuremen/outward_detail.html

@@ -239,8 +239,12 @@
     <div class="form-group layer-footer">
     <div class="form-group layer-footer">
         <div class="row procuremen-outward-confirm-footer-row">
         <div class="row procuremen-outward-confirm-footer-row">
             <div class="col-xs-12 procuremen-outward-confirm-footer-btns">
             <div class="col-xs-12 procuremen-outward-confirm-footer-btns">
+                {if $auth->check('procuremen/purchaseconfirmpick')}
                 <button type="button" style="margin-right: 20px" class="btn procuremen-btn-slate btn-embossed" id="btn-pod-purchase-confirm"><i class="fa fa-check"></i> 审批通过</button>
                 <button type="button" style="margin-right: 20px" class="btn procuremen-btn-slate btn-embossed" id="btn-pod-purchase-confirm"><i class="fa fa-check"></i> 审批通过</button>
+                {/if}
+                {if $auth->check('procuremen/purchaseapprovalreject')}
                 <button type="button" style="margin-right: 20px" class="btn btn-warning btn-embossed" id="btn-pod-purchase-reject"><i class="fa fa-undo"></i> 审批驳回</button>
                 <button type="button" style="margin-right: 20px" class="btn btn-warning btn-embossed" id="btn-pod-purchase-reject"><i class="fa fa-undo"></i> 审批驳回</button>
+                {/if}
                 <button type="button" style="margin-right: 20px" class="btn btn-default btn-embossed" id="btn-pod-purchase-close"><i class="fa fa-times"></i> 关闭</button>
                 <button type="button" style="margin-right: 20px" class="btn btn-default btn-embossed" id="btn-pod-purchase-close"><i class="fa fa-times"></i> 关闭</button>
             </div>
             </div>
         </div>
         </div>

+ 8 - 0
application/admin/view/procuremen/review.html

@@ -578,7 +578,15 @@
 
 
     <div class="layer-footer clearfix">
     <div class="layer-footer clearfix">
         <div class="pull-right">
         <div class="pull-right">
+            {if isset($pickMode) && $pickMode}
+            {if $auth->check('procuremen/picksubmit')}
             <button type="button" style="margin-right: 20px" id="btn-review-submit" class="btn procuremen-btn-slate btn-embossed">确认</button>
             <button type="button" style="margin-right: 20px" id="btn-review-submit" class="btn procuremen-btn-slate btn-embossed">确认</button>
+            {/if}
+            {else /}
+            {if $auth->check('procuremen/review')}
+            <button type="button" style="margin-right: 20px" id="btn-review-submit" class="btn procuremen-btn-slate btn-embossed">确认</button>
+            {/if}
+            {/if}
             <button type="button" style="margin-right: 20px" class="btn btn-default btn-embossed btn-close">{:__('Close')}</button>
             <button type="button" style="margin-right: 20px" class="btn btn-default btn-embossed btn-close">{:__('Close')}</button>
         </div>
         </div>
     </div>
     </div>

+ 2 - 0
application/admin/view/procuremenarchive/index.html

@@ -5,7 +5,9 @@
         <div class="widget-body no-padding">
         <div class="widget-body no-padding">
             <div id="toolbar" class="toolbar">
             <div id="toolbar" class="toolbar">
                 {:build_toolbar('refresh')}
                 {:build_toolbar('refresh')}
+                {if $auth->check('procuremen/archiveabandon')}
                 <a href="javascript:;" class="btn btn-danger" id="btn-archive-abandon" title="勾选一条或多条已完结订单退回协助初选重新下发"><i class="fa fa-repeat"></i> 重新下发</a>
                 <a href="javascript:;" class="btn btn-danger" id="btn-archive-abandon" title="勾选一条或多条已完结订单退回协助初选重新下发"><i class="fa fa-repeat"></i> 重新下发</a>
+                {/if}
             </div>
             </div>
             <table id="table" class="table table-striped table-bordered table-hover table-nowrap" width="100%"></table>
             <table id="table" class="table table-striped table-bordered table-hover table-nowrap" width="100%"></table>
         </div>
         </div>

+ 2 - 0
application/admin/view/procuremenexport/index.html

@@ -5,7 +5,9 @@
         <div class="widget-body no-padding">
         <div class="widget-body no-padding">
             <div id="toolbar" class="toolbar">
             <div id="toolbar" class="toolbar">
                 <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}"><i class="fa fa-refresh"></i> 刷新</a>
                 <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}"><i class="fa fa-refresh"></i> 刷新</a>
+                {if $auth->check('procuremen/export_month_outward')}
                 <a href="javascript:;" class="btn btn-success" id="btn-export-month-outward" title="导出当前所选月份的协助明细 Excel"><i class="fa fa-download"></i> 导出 Excel</a>
                 <a href="javascript:;" class="btn btn-success" id="btn-export-month-outward" title="导出当前所选月份的协助明细 Excel"><i class="fa fa-download"></i> 导出 Excel</a>
+                {/if}
                 <span class="procuremen-export-ym-wrap" style="display:inline-block;margin-left:12px;vertical-align:middle;">
                 <span class="procuremen-export-ym-wrap" style="display:inline-block;margin-left:12px;vertical-align:middle;">
                     <label style="margin:0 6px 0 0;font-weight:normal;">查看月份</label>
                     <label style="margin:0 6px 0 0;font-weight:normal;">查看月份</label>
                     <input type="month" id="export-preview-ym" class="form-control input-sm" style="display:inline-block;width:150px;height:30px;" />
                     <input type="month" id="export-preview-ym" class="form-control input-sm" style="display:inline-block;width:150px;height:30px;" />

+ 1 - 1
application/extra/site.php

@@ -12,7 +12,7 @@ return array (
     'backend' => 'zh-cn',
     'backend' => 'zh-cn',
     'frontend' => 'zh-cn',
     'frontend' => 'zh-cn',
   ),
   ),
-  'fixedpage' => 'dashboard',
+  'fixedpage' => 'procuremen/pick',
   'categorytype' => 
   'categorytype' => 
   array (
   array (
     'default' => 'Default',
     'default' => 'Default',

+ 75 - 10
public/assets/js/backend/procuremen.js

@@ -1,7 +1,5 @@
 define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
 define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
 
 
-    /* 列表:Controller.index 内顺序执行。审核:Controller.review 内顺序执行。无其它本文件自定义函数。 */
-
     function procuremenLayerTop() {
     function procuremenLayerTop() {
         try {
         try {
             if (typeof top !== 'undefined' && top.Layer) {
             if (typeof top !== 'undefined' && top.Layer) {
@@ -18,6 +16,62 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
         return typeof Layer !== 'undefined' ? Layer : null;
         return typeof Layer !== 'undefined' ? Layer : null;
     }
     }
 
 
+    function procuremenLayoutFlag(key) {
+        var $layout = $('#procuremen-layout');
+        if (!$layout.length) {
+            return null;
+        }
+        var raw = $layout.data(key);
+        if (raw === undefined || raw === null || raw === '') {
+            return null;
+        }
+        return parseInt(raw, 10) === 1;
+    }
+
+    /** 下发相关权限(弹窗 / 提交 / 确认页 任一即可见「下发」按钮) */
+    function procuremenCanDispatch() {
+        var fromLayout = procuremenLayoutFlag('canDispatch');
+        if (fromLayout !== null) {
+            return fromLayout;
+        }
+        return procuremenCan('pickreview') || procuremenCan('picksubmit') || procuremenCan('review');
+    }
+
+    function procuremenCanPickDelete() {
+        var fromLayout = procuremenLayoutFlag('canPickDelete');
+        if (fromLayout !== null) {
+            return fromLayout;
+        }
+        return procuremenCan('pickdelete');
+    }
+
+    function procuremenCanComplete() {
+        var fromLayout = procuremenLayoutFlag('canComplete');
+        if (fromLayout !== null) {
+            return fromLayout;
+        }
+        return procuremenCan('completedirectly');
+    }
+
+    function procuremenCanAuditAbandon() {
+        var fromLayout = procuremenLayoutFlag('canAuditAbandon');
+        if (fromLayout !== null) {
+            return fromLayout;
+        }
+        return procuremenCan('auditabandon');
+    }
+
+    /** 是否拥有采购子权限(与菜单规则 name 一致,如 picksubmit → procuremen/picksubmit) */
+    function procuremenCan(rule) {
+        var map = (typeof Config !== 'undefined' && Config.procuremenAuth) ? Config.procuremenAuth : null;
+        if (!map) {
+            return false;
+        }
+        var key = String(rule || '').toLowerCase().replace(/^procuremen\//, '');
+        var v = map[key];
+        return v === true || v === 1 || v === '1';
+    }
+
     function procuremenLayerNextZIndex() {
     function procuremenLayerNextZIndex() {
         var z = 19891014;
         var z = 19891014;
         var $doc;
         var $doc;
@@ -255,10 +309,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 table.bootstrapTable((stagePick || stageAudit) ? 'showColumn' : 'hideColumn', 'state');
                 table.bootstrapTable((stagePick || stageAudit) ? 'showColumn' : 'hideColumn', 'state');
             } catch (ignore) {
             } catch (ignore) {
             }
             }
-            $('#btn-procuremen-pick-review').toggle(stagePick);
-            $('#btn-procuremen-pick-delete').toggle(stagePick);
-            $('#btn-procuremen-batch-finish').toggle(stagePick);
-            $('#btn-procuremen-audit-abandon').toggle(stageAudit);
+            $('#btn-procuremen-pick-review').toggle(stagePick && procuremenCanDispatch());
+            $('#btn-procuremen-pick-delete').toggle(stagePick && procuremenCanPickDelete());
+            $('#btn-procuremen-batch-finish').toggle(stagePick && procuremenCanComplete());
+            $('#btn-procuremen-audit-abandon').toggle(stageAudit && procuremenCanAuditAbandon());
 
 
             $(document).off('click.procuremenYm', '.procuremen-ym-item').on('click.procuremenYm', '.procuremen-ym-item', function () {
             $(document).off('click.procuremenYm', '.procuremen-ym-item').on('click.procuremenYm', '.procuremen-ym-item', function () {
                 var ym = $(this).data('ym');
                 var ym = $(this).data('ym');
@@ -496,11 +550,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                         if (tab === 'pick') {
                         if (tab === 'pick') {
                             return '';
                             return '';
                         } else if (tab === 'audit') {
                         } else if (tab === 'audit') {
-                            parts.push('<a class="btn btn-xs btn-primary procuremen-op-open procuremen-btn-audit-issue"' + areaAudit + ' href="procuremen/auditissue" data-row-index="' + index + '" title=""><i class="fa fa-check"></i> 选择供应商</a>');
-                            parts.push('<a class="btn btn-xs btn-info procuremen-op-open procuremen-btn-details"' + areaDetails + ' href="procuremen/details" data-row-index="' + index + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>');
+                            if (procuremenCan('auditissue')) {
+                                parts.push('<a class="btn btn-xs btn-primary procuremen-op-open procuremen-btn-audit-issue"' + areaAudit + ' href="procuremen/auditissue" data-row-index="' + index + '" title=""><i class="fa fa-check"></i> 选择供应商</a>');
+                            }
+                            if (procuremenCan('details')) {
+                                parts.push('<a class="btn btn-xs btn-info procuremen-op-open procuremen-btn-details"' + areaDetails + ' href="procuremen/details" data-row-index="' + index + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>');
+                            }
                         } else if (tab === 'confirm') {
                         } else if (tab === 'confirm') {
-                            parts.push('<a class="btn btn-xs btn-success procuremen-op-open procuremen-btn-outward"' + areaConfirmOutward + ' href="procuremen/outward_detail?wff_tab=confirm" data-row-index="' + index + '" title="审批"><i class="fa fa-gavel"></i> 审批</a>');
-                            parts.push('<a class="btn btn-xs btn-info procuremen-op-open procuremen-btn-details"' + areaDetails + ' href="procuremen/details" data-row-index="' + index + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>');
+                            if (procuremenCan('outward_detail')) {
+                                parts.push('<a class="btn btn-xs btn-success procuremen-op-open procuremen-btn-outward"' + areaConfirmOutward + ' href="procuremen/outward_detail?wff_tab=confirm" data-row-index="' + index + '" title="审批"><i class="fa fa-gavel"></i> 审批</a>');
+                            }
+                            if (procuremenCan('details')) {
+                                parts.push('<a class="btn btn-xs btn-info procuremen-op-open procuremen-btn-details"' + areaDetails + ' href="procuremen/details" data-row-index="' + index + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>');
+                            }
                         }
                         }
                         return '<div class="btn-group">' + parts.join(' ') + '</div>';
                         return '<div class="btn-group">' + parts.join(' ') + '</div>';
                     },
                     },
@@ -1393,6 +1455,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                         if (!sid) {
                         if (!sid) {
                             return '';
                             return '';
                         }
                         }
+                        if (!procuremenCan('details')) {
+                            return '';
+                        }
                         return '<a href="javascript:;" class="btn btn-xs btn-info btn-rfq-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                         return '<a href="javascript:;" class="btn btn-xs btn-info btn-rfq-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                     },
                     },
                     events: {}
                     events: {}

+ 13 - 0
public/assets/js/backend/procuremenarchive.js

@@ -8,6 +8,16 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
             .replace(/"/g, '&quot;');
             .replace(/"/g, '&quot;');
     }
     }
 
 
+    function archiveCan(rule) {
+        var map = (typeof Config !== 'undefined' && Config.procuremenAuth) ? Config.procuremenAuth : null;
+        if (!map) {
+            return false;
+        }
+        var key = String(rule || '').toLowerCase().replace(/^procuremen\//, '');
+        var v = map[key];
+        return v === true || v === 1 || v === '1';
+    }
+
     var Controller = {
     var Controller = {
         index: function () {
         index: function () {
             Table.api.init({
             Table.api.init({
@@ -99,6 +109,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                                 if (!sid) {
                                 if (!sid) {
                                     return '';
                                     return '';
                                 }
                                 }
+                                if (!archiveCan('details')) {
+                                    return '';
+                                }
                                 return '<a href="javascript:;" class="btn btn-xs btn-info btn-archive-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                                 return '<a href="javascript:;" class="btn btn-xs btn-info btn-archive-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                             },
                             },
                             events: {}
                             events: {}

+ 13 - 0
public/assets/js/backend/procuremenexport.js

@@ -1,5 +1,15 @@
 define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
 define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
 
 
+    function exportCan(rule) {
+        var map = (typeof Config !== 'undefined' && Config.procuremenAuth) ? Config.procuremenAuth : null;
+        if (!map) {
+            return false;
+        }
+        var key = String(rule || '').toLowerCase().replace(/^procuremen\//, '');
+        var v = map[key];
+        return v === true || v === 1 || v === '1';
+    }
+
     var Controller = {
     var Controller = {
         index: function () {
         index: function () {
             var currYm = Controller.api.currentYm();
             var currYm = Controller.api.currentYm();
@@ -65,6 +75,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                                 if (!sid) {
                                 if (!sid) {
                                     return '';
                                     return '';
                                 }
                                 }
+                                if (!exportCan('details')) {
+                                    return '';
+                                }
                                 return '<a href="javascript:;" class="btn btn-xs btn-info btn-export-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                                 return '<a href="javascript:;" class="btn btn-xs btn-info btn-export-details" data-scydgy-id="' + sid + '" title="详情"><i class="fa fa-file-text-o"></i> 详情</a>';
                             }
                             }
                         }
                         }