ouyang 3 недель назад
Родитель
Сommit
d1ad5907db

+ 50 - 4
app-hd/controllers/OrderController.php

@@ -32,7 +32,9 @@ use common\services\xhPayToolService;
 use common\components\util;
 use common\components\stringUtil;
 use common\components\deliverySlipPrintUtil;
+use common\components\greetingCardPrintUtil;
 use common\components\cloudPrintUtil;
+use common\components\cloudPrintPaperSpec;
 use bizHd\promote\services\CouponService;
 use common\components\httpUtil;
 use biz\wx\classes\WxMessageClass;
@@ -1494,7 +1496,31 @@ class OrderController extends BaseController
     }
 
     /**
-     * 链科云打印 A4 鲜花配送单
+     * 链科云打印纸张类型列表
+     */
+    public function actionCloudPrintPaperTypes()
+    {
+        util::success(['list' => cloudPrintPaperSpec::listTypes()]);
+    }
+
+    /**
+     * 解析打印请求中的纸张参数
+     */
+    protected function parseCloudPrintPaperOptions()
+    {
+        $get = Yii::$app->request->get();
+        $options = [];
+        if (!empty($get['paperType'])) {
+            $options['paperType'] = $get['paperType'];
+        }
+        if (!empty($get['paperSize'])) {
+            $options['paperSize'] = intval($get['paperSize']);
+        }
+        return $options;
+    }
+
+    /**
+     * 链科云打印鲜花配送单
      */
     public function actionCloudPrintDeliverySlip()
     {
@@ -1506,10 +1532,30 @@ class OrderController extends BaseController
             util::fail('订单id不对');
         }
         try {
-//            deliverySlipPrintUtil::printByOrderId($id, $this->mainId);
-            deliverySlipPrintUtil::printByOrderId($id, "");
+            deliverySlipPrintUtil::printByOrderId($id, $this->mainId, $this->parseCloudPrintPaperOptions());
+        } catch (\Throwable $e) {
+            Yii::error('配送单云打印失败: ' . $e->getMessage(), __METHOD__);
+            util::fail($e->getMessage());
+        }
+        util::complete('已提交打印');
+    }
+
+    /**
+     * 链科云打印节日贺卡(文案暂写死)
+     */
+    public function actionCloudPrintGreetingCard()
+    {
+        if (!cloudPrintUtil::isEnabled()) {
+            util::fail('链科云打印未启用,请配置 .env 中 LIANKENET_*');
+        }
+        $id = intval(Yii::$app->request->get('id', 0));
+        if ($id <= 0) {
+            util::fail('订单id不对');
+        }
+        try {
+            greetingCardPrintUtil::printByOrderId($id, $this->mainId, $this->parseCloudPrintPaperOptions());
         } catch (\Throwable $e) {
-            Yii::error('A4配送单云打印失败: ' . $e->getMessage(), __METHOD__);
+            Yii::error('节日贺卡云打印失败: ' . $e->getMessage(), __METHOD__);
             util::fail($e->getMessage());
         }
         util::complete('已提交打印');

+ 165 - 0
common/components/cloudPrintPaperSpec.php

@@ -0,0 +1,165 @@
+<?php
+
+namespace common\components;
+
+/**
+ * 链科云打印纸张规格(HTML 排版 + dmPaperSize)
+ */
+class cloudPrintPaperSpec
+{
+    /** 场景:配送单 */
+    const SCENE_DELIVERY_SLIP = 'delivery_slip';
+    /** 场景:节日贺卡 */
+    const SCENE_GREETING_CARD = 'greeting_card';
+    /** 场景:默认 */
+    const SCENE_DEFAULT = 'default';
+
+    /**
+     * 内置纸张类型(paperType → 链科代码与 HTML @page)
+     * dmPaperSize 参考 Windows DMPAPER,具体以打印机参数为准
+     */
+    protected static function presets()
+    {
+        return [
+            'a4' => [
+                'label' => 'A4',
+                'dmPaperSize' => 9,
+                'pageSize' => 'A4 portrait',
+                'pageMargin' => '10mm',
+                'contentWidth' => '190mm',
+                'cardWidth' => '140mm',
+                'cardHeight' => '200mm',
+            ],
+            'a5' => [
+                'label' => 'A5',
+                'dmPaperSize' => 11,
+                'pageSize' => 'A5 portrait',
+                'pageMargin' => '8mm',
+                'contentWidth' => '128mm',
+                'cardWidth' => '100mm',
+                'cardHeight' => '148mm',
+            ],
+            'b5' => [
+                'label' => 'B5',
+                'dmPaperSize' => 13,
+                'pageSize' => 'B5 portrait',
+                'pageMargin' => '8mm',
+                'contentWidth' => '176mm',
+                'cardWidth' => '120mm',
+                'cardHeight' => '170mm',
+            ],
+            'letter' => [
+                'label' => 'Letter',
+                'dmPaperSize' => 1,
+                'pageSize' => 'letter portrait',
+                'pageMargin' => '10mm',
+                'contentWidth' => '190mm',
+                'cardWidth' => '140mm',
+                'cardHeight' => '200mm',
+            ],
+            // 贺卡常用竖版 10×15cm
+            'card_10x15' => [
+                'label' => '贺卡10×15cm',
+                'dmPaperSize' => 0,
+                'pageSize' => '100mm 150mm',
+                'pageMargin' => '5mm',
+                'contentWidth' => '90mm',
+                'cardWidth' => '90mm',
+                'cardHeight' => '130mm',
+            ],
+            // 贺卡竖版 13×18cm
+            'card_13x18' => [
+                'label' => '贺卡13×18cm',
+                'dmPaperSize' => 0,
+                'pageSize' => '130mm 180mm',
+                'pageMargin' => '6mm',
+                'contentWidth' => '118mm',
+                'cardWidth' => '118mm',
+                'cardHeight' => '160mm',
+            ],
+        ];
+    }
+
+    /**
+     * 解析纸张规格
+     *
+     * @param array $options scene, paperType, paperSize(dmPaperSize 数值优先)
+     */
+    public static function resolve(array $options = [])
+    {
+        $scene = (string)($options['scene'] ?? self::SCENE_DEFAULT);
+        $paperType = strtolower(trim((string)($options['paperType'] ?? '')));
+        $paperSize = intval($options['paperSize'] ?? 0);
+
+        if ($paperType === '') {
+            $paperType = strtolower(trim((string)self::envByScene($scene, 'PAPER_TYPE')));
+        }
+        if ($paperSize <= 0) {
+            $paperSize = intval(self::envByScene($scene, 'PAPER_SIZE'));
+        }
+        if ($paperType === '') {
+            $paperType = 'a4';
+        }
+
+        $presets = self::presets();
+        if (!isset($presets[$paperType])) {
+            throw new CloudPrinterApiException('不支持的纸张类型: ' . $paperType);
+        }
+
+        $spec = $presets[$paperType];
+        $dmPaperSize = $paperSize > 0 ? $paperSize : intval($spec['dmPaperSize']);
+        if ($dmPaperSize <= 0) {
+            $dmPaperSize = intval(getenv('LIANKENET_PAPER_SIZE') ?: 9);
+        }
+
+        return [
+            'paperType' => $paperType,
+            'label' => $spec['label'],
+            'dmPaperSize' => $dmPaperSize,
+            'pageSize' => $spec['pageSize'],
+            'pageMargin' => $spec['pageMargin'],
+            'contentWidth' => $spec['contentWidth'],
+            'cardWidth' => $spec['cardWidth'],
+            'cardHeight' => $spec['cardHeight'],
+        ];
+    }
+
+    /**
+     * 返回可选纸张类型列表(给前端或配置参考)
+     */
+    public static function listTypes()
+    {
+        $list = [];
+        foreach (self::presets() as $key => $item) {
+            $list[] = [
+                'paperType' => $key,
+                'label' => $item['label'],
+                'defaultDmPaperSize' => $item['dmPaperSize'],
+            ];
+        }
+        return $list;
+    }
+
+    /**
+     * 按场景读取 .env:LIANKENET_DELIVERY_SLIP_PAPER_TYPE 等
+     */
+    protected static function envByScene($scene, $suffix)
+    {
+        $map = [
+            self::SCENE_DELIVERY_SLIP => 'LIANKENET_DELIVERY_SLIP_' . $suffix,
+            self::SCENE_GREETING_CARD => 'LIANKENET_GREETING_CARD_' . $suffix,
+            self::SCENE_DEFAULT => 'LIANKENET_' . $suffix,
+        ];
+        $key = $map[$scene] ?? $map[self::SCENE_DEFAULT];
+        $value = getenv($key);
+        if ($value === false || $value === '') {
+            if ($scene !== self::SCENE_DEFAULT && $suffix === 'PAPER_TYPE') {
+                return getenv('LIANKENET_PAPER_TYPE') ?: '';
+            }
+            if ($scene !== self::SCENE_DEFAULT && $suffix === 'PAPER_SIZE') {
+                return getenv('LIANKENET_PAPER_SIZE') ?: 0;
+            }
+        }
+        return $value;
+    }
+}

+ 14 - 5
common/components/deliverySlipPrintUtil.php

@@ -15,7 +15,7 @@ class deliverySlipPrintUtil
     /**
      * 根据零售订单 ID 打印 A4 配送单
      */
-    public static function printByOrderId($orderId, $mainId = 0)
+    public static function printByOrderId($orderId, $mainId = 0, array $printOptions = [])
     {
         $order = OrderService::getById($orderId);
         if (empty($order)) {
@@ -26,21 +26,25 @@ class deliverySlipPrintUtil
         }
 
         $data = self::buildDataFromOrder($order);
-        return self::printByData($data);
+        return self::printByData($data, $printOptions);
     }
 
     /**
      * 直接按模板数据打印
      */
-    public static function printByData(array $data)
+    public static function printByData(array $data, array $printOptions = [])
     {
         if (!cloudPrintUtil::isEnabled()) {
             throw new CloudPrinterApiException('链科云打印未启用,请先在 .env 配置 LIANKENET_*');
         }
 
+        $paper = cloudPrintPaperSpec::resolve(array_merge([
+            'scene' => cloudPrintPaperSpec::SCENE_DELIVERY_SLIP,
+        ], $printOptions));
+        $data['paper'] = $paper;
+
         $html = self::renderHtml($data);
-        $paperSize = intval(getenv('LIANKENET_A4_PAPER_SIZE') ?: (getenv('LIANKENET_PAPER_SIZE') ?: 9));
-        return (new cloudPrintUtil())->printHtml($html, $paperSize);
+        return (new cloudPrintUtil())->printHtml($html, $paper['dmPaperSize']);
     }
 
     /**
@@ -133,6 +137,11 @@ class deliverySlipPrintUtil
      */
     public static function renderHtml(array $data)
     {
+        if (empty($data['paper'])) {
+            $data['paper'] = cloudPrintPaperSpec::resolve([
+                'scene' => cloudPrintPaperSpec::SCENE_DELIVERY_SLIP,
+            ]);
+        }
         $template = Yii::getAlias('@common/templates/delivery-slip-a4.php');
         if (!is_file($template)) {
             throw new CloudPrinterApiException('配送单模板不存在');

+ 83 - 0
common/components/greetingCardPrintUtil.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace common\components;
+
+use bizHd\order\services\OrderService;
+use Yii;
+
+/**
+ * 订单节日贺卡云打印(文字暂写死,纸张规格可配置)
+ */
+class greetingCardPrintUtil
+{
+    /**
+     * 根据订单 ID 打印节日贺卡
+     */
+    public static function printByOrderId($orderId, $mainId = 0, array $printOptions = [])
+    {
+        $order = OrderService::getById($orderId);
+        if (empty($order)) {
+            throw new CloudPrinterApiException('订单不存在');
+        }
+        if ($mainId > 0) {
+            OrderService::valid($order, $mainId);
+        }
+
+        return self::printByData(self::buildDefaultData(), $printOptions);
+    }
+
+    /**
+     * 直接打印贺卡
+     */
+    public static function printByData(array $data = [], array $printOptions = [])
+    {
+        if (!cloudPrintUtil::isEnabled()) {
+            throw new CloudPrinterApiException('链科云打印未启用,请先在 .env 配置 LIANKENET_*');
+        }
+
+        $paper = cloudPrintPaperSpec::resolve(array_merge([
+            'scene' => cloudPrintPaperSpec::SCENE_GREETING_CARD,
+        ], $printOptions));
+        $data['paper'] = $paper;
+
+        $html = self::renderHtml($data);
+        return (new cloudPrintUtil())->printHtml($html, $paper['dmPaperSize']);
+    }
+
+    /**
+     * 默认贺卡文案(写死,后续可改为订单 cardInfo / 收花人姓名等)
+     */
+    public static function buildDefaultData()
+    {
+        return [
+            'cardTitle' => '生日快乐贺卡',
+            'toText' => 'To 陈小姐',
+            'titleText' => '生日快乐',
+            'messageLines' => [
+                '愿你今天被鲜花和温柔包围,',
+                '生日快乐,天天开心。',
+            ],
+            'fromText' => 'From 你的朋友',
+        ];
+    }
+
+    /**
+     * 渲染贺卡 HTML
+     */
+    public static function renderHtml(array $data)
+    {
+        $data = array_merge(self::buildDefaultData(), $data);
+        if (empty($data['paper'])) {
+            $data['paper'] = cloudPrintPaperSpec::resolve([
+                'scene' => cloudPrintPaperSpec::SCENE_GREETING_CARD,
+            ]);
+        }
+        $template = Yii::getAlias('@common/templates/greeting-card-a4.php');
+        if (!is_file($template)) {
+            throw new CloudPrinterApiException('节日贺卡模板不存在');
+        }
+        ob_start();
+        include $template;
+        return (string)ob_get_clean();
+    }
+}

+ 9 - 5
common/templates/delivery-slip-a4.php

@@ -7,6 +7,11 @@
 $escape = function ($value) {
     return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
 };
+$paper = $data['paper'] ?? [
+    'pageSize' => 'A4 portrait',
+    'pageMargin' => '10mm',
+    'contentWidth' => '190mm',
+];
 ?>
 <!DOCTYPE html>
 <html lang="zh-CN">
@@ -15,8 +20,8 @@ $escape = function ($value) {
     <title><?= $escape($data['title'] ?? '鲜花配送单') ?></title>
     <style>
         @page {
-            size: A4 portrait;
-            margin: 10mm;
+            size: <?= $escape($paper['pageSize']) ?>;
+            margin: <?= $escape($paper['pageMargin']) ?>;
         }
         * {
             margin: 0;
@@ -36,7 +41,7 @@ $escape = function ($value) {
             border-collapse: collapse;
         }
         .delivery-wrap {
-            width: 190mm;
+            width: <?= $escape($paper['contentWidth']) ?>;
             max-width: 100%;
             margin: 0 auto;
             text-align: left;
@@ -155,7 +160,7 @@ $escape = function ($value) {
                 margin: 0;
             }
             .delivery-wrap {
-                width: 190mm;
+                width: <?= $escape($paper['contentWidth']) ?>;
                 margin: 0 auto;
             }
         }
@@ -216,7 +221,6 @@ $escape = function ($value) {
                         <td colspan="3"><?= nl2br($escape($data['cardInfo'] ?? '')) ?></td>
                     </tr>
                 </table>
-
                 <div class="footer-bottom">
                     <?php if (!empty($data['servicePhone'])): ?>
                     <div class="bottom-tip">

+ 153 - 0
common/templates/greeting-card-a4.php

@@ -0,0 +1,153 @@
+<?php
+/**
+ * A4 节日贺卡 HTML 模板(链科云打印)
+ *
+ * @var array $data
+ */
+$escape = function ($value) {
+    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
+};
+$paper = $data['paper'] ?? [
+    'pageSize' => 'A4 portrait',
+    'pageMargin' => '10mm',
+    'contentWidth' => '190mm',
+    'cardWidth' => '140mm',
+    'cardHeight' => '200mm',
+];
+?>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title><?= $escape($data['cardTitle'] ?? '节日贺卡') ?></title>
+    <style>
+        @page {
+            size: <?= $escape($paper['pageSize']) ?>;
+            margin: <?= $escape($paper['pageMargin']) ?>;
+        }
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+        }
+        body {
+            margin: 0;
+            padding: 0;
+            background: #ffffff;
+            font-family: "Microsoft YaHei", "PingFang SC", "SimSun", sans-serif;
+        }
+        .page-center {
+            width: 100%;
+            border: 0;
+            border-collapse: collapse;
+        }
+        .card-page {
+            width: <?= $escape($paper['contentWidth']) ?>;
+            max-width: 100%;
+            margin: 0 auto;
+            padding: 15mm 0;
+        }
+        .greeting-card {
+            position: relative;
+            width: <?= $escape($paper['cardWidth']) ?>;
+            height: <?= $escape($paper['cardHeight']) ?>;
+            margin: 0 auto;
+            background: #ffffff;
+            border-radius: 8mm;
+            box-shadow: 0 2mm 8mm rgba(0, 0, 0, 0.08);
+            overflow: hidden;
+            text-align: center;
+        }
+        /* 左上粉紫光晕 */
+        .glow-pink {
+            position: absolute;
+            left: -20mm;
+            top: -20mm;
+            width: 70mm;
+            height: 70mm;
+            background: radial-gradient(circle, rgba(255, 182, 193, 0.55) 0%, rgba(230, 190, 255, 0.25) 45%, transparent 70%);
+            pointer-events: none;
+        }
+        /* 右下暖黄光晕 */
+        .glow-yellow {
+            position: absolute;
+            right: -15mm;
+            bottom: -15mm;
+            width: 65mm;
+            height: 65mm;
+            background: radial-gradient(circle, rgba(255, 220, 120, 0.55) 0%, rgba(255, 235, 180, 0.2) 50%, transparent 72%);
+            pointer-events: none;
+        }
+        .card-inner {
+            position: relative;
+            z-index: 1;
+            height: 100%;
+            padding: 18mm 14mm 16mm;
+        }
+        .card-to {
+            margin-top: 6mm;
+            font-size: 20px;
+            color: #888888;
+            letter-spacing: 1px;
+        }
+        .card-title {
+            margin-top: 22mm;
+            font-size: 52px;
+            font-weight: bold;
+            color: #8B2942;
+            letter-spacing: 6px;
+        }
+        .card-message {
+            margin-top: 16mm;
+            font-size: 22px;
+            line-height: 2;
+            color: #555555;
+        }
+        .card-message p {
+            margin: 0;
+        }
+        .card-from {
+            position: absolute;
+            right: 14mm;
+            bottom: 16mm;
+            font-size: 20px;
+            color: #666666;
+            text-align: right;
+        }
+        @media print {
+            body {
+                padding: 0;
+                margin: 0;
+            }
+            .card-page {
+                width: <?= $escape($paper['contentWidth']) ?>;
+                margin: 0 auto;
+            }
+        }
+    </style>
+</head>
+<body>
+<table class="page-center" cellpadding="0" cellspacing="0" border="0">
+    <tr>
+        <td align="center" valign="top">
+            <div class="card-page">
+                <div class="greeting-card">
+                    <div class="glow-pink"></div>
+                    <div class="glow-yellow"></div>
+                    <div class="card-inner">
+                        <div class="card-to"><?= $escape($data['toText'] ?? '') ?></div>
+                        <div class="card-title"><?= $escape($data['titleText'] ?? '') ?></div>
+                        <div class="card-message">
+                            <?php foreach (($data['messageLines'] ?? []) as $line): ?>
+                            <p><?= $escape($line) ?></p>
+                            <?php endforeach; ?>
+                        </div>
+                        <div class="card-from"><?= $escape($data['fromText'] ?? '') ?></div>
+                    </div>
+                </div>
+            </div>
+        </td>
+    </tr>
+</table>
+</body>
+</html>