m0_70156489 1 день назад
Родитель
Сommit
387f57cad7

+ 104 - 32
application/admin/controller/Procuremen.php

@@ -265,16 +265,18 @@ class Procuremen extends Backend
             'reviewcompanies'         => $this->hasProcuremenPerm(['reviewcompanies', 'reviewCompanies', 'pickreview', 'picksubmit', 'review']),
             'add'                     => $this->hasProcuremenPerm(['add']),
             'rfqlist'                 => $this->hasProcuremenPerm(['rfqlist']),
-            'rfqnotifysalesmen'       => $this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen']),
-            'rfqnotifysalesman'       => $this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesman']),
-            'rfqsalesmanoptions'      => $this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen', 'rfqsalesmanoptions', 'rfqappendsalesmen']),
-            'rfqappendsalesmen'       => $this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen', 'rfqappendsalesmen']),
-            'rfqissuesuppliers'       => $this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqissuesuppliers']),
-            'rfqissue'                => $this->hasProcuremenPerm(['rfqlist', 'rfqissue']),
-            'rfqissuesendmail'        => $this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqissuesendmail']),
-            'rfqquotes'               => $this->hasProcuremenPerm(['rfqlist', 'rfqquotes', 'rfqissue']),
-            'rfqappendsuppliers'      => $this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqappendsuppliers']),
-            'rfqsupplieroptions'      => $this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqappendsuppliers', 'rfqsupplieroptions']),
+            // 查询询价三个操作按钮:各自独立,不再因有 rfqlist 就全部放开
+            'rfqissue'                => $this->hasProcuremenPerm(['rfqissue']),
+            'rfqquotes'               => $this->hasProcuremenPerm(['rfqquotes']),
+            'rfqnotifysalesman'       => $this->hasProcuremenPerm(['rfqnotifysalesman', 'rfqnotifysalesmen']),
+            'rfqnotifysalesmen'       => $this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman']),
+            // 询价附属接口:有「询价」按钮权限即可(无需再单独勾选)
+            'rfqissuesuppliers'       => $this->hasProcuremenPerm(['rfqissue', 'rfqissuesuppliers']),
+            'rfqissuesendmail'        => $this->hasProcuremenPerm(['rfqissue', 'rfqissuesendmail']),
+            'rfqappendsuppliers'      => $this->hasProcuremenPerm(['rfqissue', 'rfqappendsuppliers']),
+            'rfqsupplieroptions'      => $this->hasProcuremenPerm(['rfqissue', 'rfqappendsuppliers', 'rfqsupplieroptions']),
+            'rfqsalesmanoptions'      => $this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman', 'rfqsalesmanoptions', 'rfqappendsalesmen']),
+            'rfqappendsalesmen'       => $this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman', 'rfqappendsalesmen']),
             'pickadd'                 => $this->hasProcuremenPerm(['pickadd', 'pickAdd']),
         ];
         $this->assignconfig('procuremenAuth', $authMap);
@@ -7934,7 +7936,7 @@ class Procuremen extends Backend
      * @param array<int, array{detail_id:int, cgymc:string, url:string}> $detailLinks
      * @return array<string, mixed>
      */
-    protected function composeSupplierNotifyBundle(array $c, array $ctx, array $detailLinks): array
+    protected function composeSupplierNotifyBundle(array $c, array $ctx, array $detailLinks, string $emailTplScene = 'review_email'): array
     {
         $toEmail = isset($c['email']) ? trim((string)$c['email']) : '';
         $companyName = isset($c['name']) ? trim((string)$c['name']) : '外协单位';
@@ -7965,7 +7967,8 @@ class Procuremen extends Backend
             'platform_links_html' => $platformLinksHtml,
         ];
         $smsContent = $this->renderNotifyTemplate('review_sms', $notifyVars);
-        $mailPlain = $this->renderNotifyTemplate('review_email', $notifyVars);
+        $emailTplScene = trim($emailTplScene) !== '' ? trim($emailTplScene) : 'review_email';
+        $mailPlain = $this->renderNotifyTemplate($emailTplScene, $notifyVars);
         $mailBody = $this->plainTextToHtmlEmailBody($mailPlain);
 
         return [
@@ -7985,7 +7988,7 @@ class Procuremen extends Backend
      * @param array<int, array<string, mixed>> $mergeRows
      * @param array{ccydh:string, pos:array} $bundle
      */
-    protected function sendAuditSupplierNotifyChannels(array $chosen, array $mergeRows, array $bundle, bool $sendSms, bool $sendEmail, string $emailLogScene = 'pick_issue'): void
+    protected function sendAuditSupplierNotifyChannels(array $chosen, array $mergeRows, array $bundle, bool $sendSms, bool $sendEmail, string $emailLogScene = 'pick_issue', string $emailTplScene = 'review_email'): void
     {
         if (!$sendSms && !$sendEmail) {
             return;
@@ -8079,8 +8082,9 @@ class Procuremen extends Backend
             throw new \Exception('未找到有效的手机端链接,无法发送通知');
         }
 
+        $emailTplScene = trim($emailTplScene) !== '' ? trim($emailTplScene) : 'review_email';
         $ctx = $this->buildIssueNotifyContext($mergeRows, $sysRqNotify);
-        $notifyBundle = $this->composeSupplierNotifyBundle($chosen, $ctx, $detailLinks);
+        $notifyBundle = $this->composeSupplierNotifyBundle($chosen, $ctx, $detailLinks, $emailTplScene);
         $notifyBundle['email_log_scene'] = $emailLogScene;
         $notifyBundle['email_log_scydgy_id'] = (int)array_key_first($sids);
         $poIdLog = 0;
@@ -8091,11 +8095,11 @@ class Procuremen extends Backend
         $notifyBundle['email_log_purchase_order_id'] = $poIdLog;
 
         if ($sendEmail) {
-            $mailTplRow = $this->loadNotifyTemplateRow('review_email');
+            $mailTplRow = $this->loadNotifyTemplateRow($emailTplScene);
             if ($mailTplRow === null || trim((string)($mailTplRow['content'] ?? '')) === '') {
-                throw new \Exception($this->notifyTemplateMissingMessage('review_email'));
+                throw new \Exception($this->notifyTemplateMissingMessage($emailTplScene));
             }
-            $mailSubject = $this->resolveProcuremenEmailSubject('review_email');
+            $mailSubject = $this->resolveProcuremenEmailSubject($emailTplScene);
             $mailConfig = $this->loadMailerConfig();
             if (!$this->isProcuremenNotifyDryRun()) {
                 if (empty($mailConfig['host'])) {
@@ -8495,6 +8499,7 @@ class Procuremen extends Backend
             'pick_issue'    => '初选下发',
             'audit_resend'  => '确认页重发',
             'rfq_salesman'  => '询价通知业务员',
+            'rfq_supplier'  => '供应商询价通知',
         ];
 
         return $map[$scene] ?? $scene;
@@ -8621,6 +8626,69 @@ class Procuremen extends Backend
         }
     }
 
+    /**
+     * 确保「供应商询价通知」邮箱模版存在(查询询价-询价/发邮件;可在短信模版配置中修改)
+     */
+    protected function ensureRfqSupplierEmailTemplate(): void
+    {
+        static $done = false;
+        if ($done) {
+            return;
+        }
+        $done = true;
+        $content = "您好,{company_name}:\n\n"
+            . "您有新的协助采购询价需求,请登录平台查看并处理。\n\n"
+            . "需求编号:{ccydh}\n"
+            . "印件名称:{cyjmc}\n"
+            . "{process_lines}\n\n"
+            . "请在 {deadline} 前完成回复。\n\n"
+            . "平台链接:{platform_url}\n";
+        try {
+            $row = Db::table('purchase_sms_template')
+                ->where('scene', 'rfq_supplier_email')
+                ->find();
+        } catch (\Throwable $e) {
+            return;
+        }
+        $now = date('Y-m-d H:i:s');
+        if (is_array($row) && $row !== []) {
+            return;
+        }
+        try {
+            $data = [
+                'scene'   => 'rfq_supplier_email',
+                'title'   => '供应商询价通知',
+                'content' => $content,
+                'remark'  => '查询询价-询价/发邮件通知供应商;模版名称作邮件主题',
+                'status'  => 1,
+            ];
+            try {
+                $cols = Db::query("SHOW COLUMNS FROM `purchase_sms_template`");
+            } catch (\Throwable $e) {
+                $cols = [];
+            }
+            $colNames = [];
+            foreach ($cols as $c) {
+                if (!is_array($c)) {
+                    continue;
+                }
+                $n = (string)($c['Field'] ?? $c['field'] ?? '');
+                if ($n !== '') {
+                    $colNames[$n] = true;
+                }
+            }
+            if (isset($colNames['updatetime'])) {
+                $data['updatetime'] = $now;
+            }
+            if (isset($colNames['createtime'])) {
+                $data['createtime'] = $now;
+            }
+            Db::table('purchase_sms_template')->insert($data);
+        } catch (\Throwable $e) {
+            // ignore
+        }
+    }
+
     /**
      * 确保「询价通知业务员-邮箱」模版存在(可在后台短信模版配置中修改)
      */
@@ -8998,6 +9066,7 @@ class Procuremen extends Backend
         $this->ensurePurchaseOrderNotifySalesmanColumn();
         $this->ensurePurchaseOrderRfqSalesmanNotifiedColumn();
         $this->ensureRfqSalesmanEmailTemplate();
+        $this->ensureRfqSupplierEmailTemplate();
 
         if ($this->request->isAjax()) {
             try {
@@ -9297,7 +9366,7 @@ class Procuremen extends Backend
      */
     public function rfqnotifysalesmen()
     {
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen'])) {
+        if (!$this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman'])) {
             $this->error(__('You have no permission'));
         }
         $this->ensurePurchaseOrderNotifySalesmanColumn();
@@ -9345,7 +9414,7 @@ class Procuremen extends Backend
      */
     public function rfqsalesmanoptions()
     {
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen', 'rfqsalesmanoptions', 'rfqappendsalesmen'])) {
+        if (!$this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman', 'rfqsalesmanoptions', 'rfqappendsalesmen'])) {
             $this->error(__('You have no permission'));
         }
         $out = [];
@@ -9371,7 +9440,7 @@ class Procuremen extends Backend
         if (!$this->request->isPost()) {
             $this->error(__('Invalid parameters'));
         }
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesmen', 'rfqappendsalesmen'])) {
+        if (!$this->hasProcuremenPerm(['rfqnotifysalesmen', 'rfqnotifysalesman', 'rfqappendsalesmen'])) {
             $this->error(__('You have no permission'));
         }
         $this->ensurePurchaseOrderNotifySalesmanColumn();
@@ -9455,7 +9524,7 @@ class Procuremen extends Backend
         if (!$this->request->isPost()) {
             $this->error(__('Invalid parameters'));
         }
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqnotifysalesman'])) {
+        if (!$this->hasProcuremenPerm(['rfqnotifysalesman', 'rfqnotifysalesmen'])) {
             $this->error(__('You have no permission'));
         }
         $this->ensurePurchaseOrderNotifySalesmanColumn();
@@ -9645,7 +9714,7 @@ class Procuremen extends Backend
      */
     public function rfqissuesuppliers()
     {
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqissuesuppliers'])) {
+        if (!$this->hasProcuremenPerm(['rfqissue', 'rfqissuesuppliers'])) {
             $this->error(__('You have no permission'));
         }
         $sid = (int)$this->request->param('scydgy_id', 0);
@@ -9695,7 +9764,7 @@ class Procuremen extends Backend
      */
     public function rfqsupplieroptions()
     {
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqappendsuppliers', 'rfqsupplieroptions'])) {
+        if (!$this->hasProcuremenPerm(['rfqissue', 'rfqappendsuppliers', 'rfqsupplieroptions'])) {
             $this->error(__('You have no permission'));
         }
         $names = array_values($this->loadRfqSupplierNameOptions());
@@ -9714,7 +9783,7 @@ class Procuremen extends Backend
         if (!$this->request->isPost()) {
             $this->error(__('Invalid parameters'));
         }
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqappendsuppliers'])) {
+        if (!$this->hasProcuremenPerm(['rfqissue', 'rfqappendsuppliers'])) {
             $this->error(__('You have no permission'));
         }
         $sid = (int)$this->request->post('scydgy_id', 0);
@@ -9781,9 +9850,10 @@ class Procuremen extends Backend
         if (!$this->request->isPost()) {
             $this->error(__('Invalid parameters'));
         }
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqissue'])) {
+        if (!$this->hasProcuremenPerm(['rfqissue'])) {
             $this->error(__('You have no permission'));
         }
+        $this->ensureRfqSupplierEmailTemplate();
         $sid = (int)$this->request->post('scydgy_id', 0);
         if ($sid >= 0) {
             $this->error('仅支持手工新增询价单');
@@ -9908,7 +9978,7 @@ class Procuremen extends Backend
             $cname = trim((string)($c['name'] ?? ''));
             try {
                 // 询价下发:仅邮箱通知供应商
-                $this->sendAuditSupplierNotifyChannels($c, $mergeRows, $notifyBundle, false, true, 'pick_issue');
+                $this->sendAuditSupplierNotifyChannels($c, $mergeRows, $notifyBundle, false, true, 'rfq_supplier', 'rfq_supplier_email');
             } catch (\Throwable $e) {
                 $notifyErrors[] = ($cname !== '' ? $cname : '供应商') . ':' . $e->getMessage();
             }
@@ -9932,9 +10002,10 @@ class Procuremen extends Backend
         if (!$this->request->isPost()) {
             $this->error(__('Invalid parameters'));
         }
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqissue', 'rfqissuesendmail'])) {
+        if (!$this->hasProcuremenPerm(['rfqissue', 'rfqissuesendmail'])) {
             $this->error(__('You have no permission'));
         }
+        $this->ensureRfqSupplierEmailTemplate();
         $sid = (int)$this->request->post('scydgy_id', 0);
         $companyName = trim((string)$this->request->post('company_name', ''));
         if ($sid >= 0) {
@@ -10015,7 +10086,7 @@ class Procuremen extends Backend
             'merge_rows' => $mergeRows,
         ];
         try {
-            $this->sendAuditSupplierNotifyChannels($contact, $mergeRows, $notifyBundle, false, true, 'pick_issue');
+            $this->sendAuditSupplierNotifyChannels($contact, $mergeRows, $notifyBundle, false, true, 'rfq_supplier', 'rfq_supplier_email');
         } catch (\Throwable $e) {
             $this->error('明细已保存,但邮件发送失败:' . $e->getMessage());
         }
@@ -10041,7 +10112,7 @@ class Procuremen extends Backend
      */
     public function rfqquotes()
     {
-        if (!$this->hasProcuremenPerm(['rfqlist', 'rfqquotes', 'rfqissue'])) {
+        if (!$this->hasProcuremenPerm(['rfqquotes', 'rfqissue'])) {
             $this->error(__('You have no permission'));
         }
         $sid = (int)$this->request->param('scydgy_id', 0);
@@ -13098,15 +13169,15 @@ class Procuremen extends Backend
 
     protected function resolveProcuremenEmailSubject(string $scene): string
     {
-        // 询价通知业务员:模版名称即邮件主题(可含 {ccydh})
-        if ($scene === 'rfq_salesman_email') {
+        // 询价通知业务员 / 供应商询价:模版名称即邮件主题
+        if ($scene === 'rfq_salesman_email' || $scene === 'rfq_supplier_email') {
             $row = $this->loadNotifyTemplateRow($scene);
             $title = is_array($row) ? trim((string)($row['title'] ?? '')) : '';
             if ($title !== '') {
                 return $title;
             }
 
-            return '协助采购询价通知';
+            return $scene === 'rfq_supplier_email' ? '供应商询价通知' : '协助采购询价通知';
         }
         $map = [
             'review_email' => '您有新的协助加工订单',
@@ -13128,6 +13199,7 @@ class Procuremen extends Backend
             'confirm_fail'       => '采购确认-未通过',
             'bid_open'           => '开标双重验证',
             'rfq_salesman_email' => '询价通知业务员-邮箱',
+            'rfq_supplier_email' => '供应商询价通知',
         ];
         $label = $map[$scene] ?? $scene;
         if ($titleRequired) {

+ 12 - 11
application/admin/model/Purchasesmstemplate.php

@@ -18,12 +18,13 @@ class Purchasesmstemplate extends Model
     public function getSceneList()
     {
         return [
-            'review_email'       => '协助下发-邮箱',
-            'review_sms'         => '协助下发-短信',
-            'confirm_ok'         => '采购确认-通过',
-            'confirm_fail'       => '采购确认-未通过',
-            'bid_open'           => '开标双重验证',
-            'rfq_salesman_email' => '询价通知业务员-邮箱',
+            'review_email'        => '协助下发-邮箱',
+            'review_sms'          => '协助下发-短信',
+            'confirm_ok'          => '采购确认-通过',
+            'confirm_fail'        => '采购确认-未通过',
+            'bid_open'            => '开标双重验证',
+            'rfq_salesman_email'  => '询价通知业务员-邮箱',
+            'rfq_supplier_email'  => '供应商询价通知',
         ];
     }
 
@@ -35,7 +36,7 @@ class Purchasesmstemplate extends Model
 
     public static function isEmailScene(string $scene): bool
     {
-        return $scene === 'review_email' || $scene === 'review' || $scene === 'rfq_salesman_email';
+        return in_array($scene, ['review_email', 'review', 'rfq_salesman_email', 'rfq_supplier_email'], true);
     }
 
     public static function isSmsScene(string $scene): bool
@@ -71,14 +72,14 @@ class Purchasesmstemplate extends Model
             ['tag' => '{ccydh}', 'label' => '订单号/需求编号', 'example' => 'YW20260730001', 'scenes' => '全部'],
             ['tag' => '{cyjmc}', 'label' => '印件名称', 'example' => '藏书票2', 'scenes' => '全部'],
             ['tag' => '{cgymc}', 'label' => '工序名称(单道工序)', 'example' => '骑马订', 'scenes' => '协助下发/询价通知'],
-            ['tag' => '{this_quantity}', 'label' => '本次数量', 'example' => '200', 'scenes' => '询价通知业务员'],
+            ['tag' => '{this_quantity}', 'label' => '本次数量', 'example' => '200', 'scenes' => '询价通知'],
             ['tag' => '{supplier_name}', 'label' => '供应商', 'example' => '台州某某有限公司', 'scenes' => '询价通知业务员'],
             ['tag' => '{cywyxm}', 'label' => '需求发起人', 'example' => '管理员', 'scenes' => '询价通知业务员'],
             ['tag' => '{category}', 'label' => '业务分类', 'example' => '出版物印刷', 'scenes' => '协助下发'],
-            ['tag' => '{deadline}', 'label' => '截止时间', 'example' => '2026-05-18 14:30', 'scenes' => '协助下发'],
+            ['tag' => '{deadline}', 'label' => '截止时间', 'example' => '2026-05-18 14:30', 'scenes' => '协助下发/供应商询价'],
             ['tag' => '{process_lines}', 'label' => '订单工序明细(文本)', 'example' => "订单号:YW20240629001\n印件名称:藏书票2\n1.工序名称:做刀版 单位:张 本次数量:500", 'scenes' => '全部'],
-            ['tag' => '{process_lines_html}', 'label' => '订单工序明细(表格)', 'example' => '<table>…</table>', 'scenes' => '协助下发邮箱'],
-            ['tag' => '{platform_url}', 'label' => '平台链接', 'example' => 'https://…', 'scenes' => '协助下发邮箱'],
+            ['tag' => '{process_lines_html}', 'label' => '订单工序明细(表格)', 'example' => '<table>…</table>', 'scenes' => '协助下发/供应商询价邮箱'],
+            ['tag' => '{platform_url}', 'label' => '平台链接', 'example' => 'https://…', 'scenes' => '协助下发/供应商询价邮箱'],
         ];
     }
 }

+ 9 - 5
public/assets/js/backend/procuremen.js

@@ -3027,14 +3027,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                         var progress = String(row.progress_text || '');
                         var canIssue = progress !== '已完结' && progress !== '待入库评分' && progress !== '待采购确认';
                         var html = '<span class="procuremen-rfq-op-btns">';
-                        if (canIssue) {
+                        if (canIssue && procuremenCan('rfqissue')) {
                             html += '<a href="javascript:;" class="btn btn-xs btn-info btn-rfq-issue" data-scydgy-id="'
                                 + rfqEscAttr(sid) + '">询价</a>';
                         }
-                        html += '<a href="javascript:;" class="btn btn-xs btn-warning btn-rfq-quotes" data-scydgy-id="'
-                            + rfqEscAttr(sid) + '">查看报价</a>';
-                        html += '<a href="javascript:;" class="btn btn-xs btn-success btn-rfq-notify-salesman" data-scydgy-id="'
-                            + rfqEscAttr(sid) + '">通知业务员</a>';
+                        if (procuremenCan('rfqquotes')) {
+                            html += '<a href="javascript:;" class="btn btn-xs btn-warning btn-rfq-quotes" data-scydgy-id="'
+                                + rfqEscAttr(sid) + '">查看报价</a>';
+                        }
+                        if (procuremenCan('rfqnotifysalesman') || procuremenCan('rfqnotifysalesmen')) {
+                            html += '<a href="javascript:;" class="btn btn-xs btn-success btn-rfq-notify-salesman" data-scydgy-id="'
+                                + rfqEscAttr(sid) + '">通知业务员</a>';
+                        }
                         html += '</span>';
                         return html;
                     },