ryan 1 неделя назад
Родитель
Сommit
5f6edffa0a

+ 48 - 0
backendApi/modules/v1/controllers/ShopController.php

@@ -55,6 +55,7 @@ use common\models\UserInfo;
 use common\helpers\Tool;
 use Yii;
 use yii\web\HttpException;
+use yii\web\Response;
 use yii\web\UploadedFile;
 use yii\base\Exception;
 
@@ -1110,15 +1111,61 @@ class ShopController extends BaseController {
      */
     public function actionOrderPeriodAdjustRange()
     {
+        $isViewPage = (int)\Yii::$app->request->get('view', 0) === 1;
+
         if (\Yii::$app->request->isPost) {
             $formModel = new OrderPeriodAdjustRangeForm();
             $formModel->scenario = 'orderPeriodAdjustRange';
             if ($formModel->load(\Yii::$app->request->post(), '') && $result = $formModel->periodAdjustRange()) {
+                if ($isViewPage) {
+                    \Yii::$app->response->format = Response::FORMAT_HTML;
+                    return $this->renderPartial('order-period-adjust-range', [
+                        'defaults' => [],
+                        'formModel' => $formModel,
+                        'result' => $result,
+                        'errors' => [],
+                        'submitted' => true,
+                    ]);
+                }
                 return static::notice($result);
             }
+            if ($isViewPage) {
+                \Yii::$app->response->format = Response::FORMAT_HTML;
+                return $this->renderPartial('order-period-adjust-range', [
+                    'defaults' => [],
+                    'formModel' => $formModel,
+                    'result' => null,
+                    'errors' => $formModel->getErrors(),
+                    'submitted' => true,
+                ]);
+            }
             return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
         }
 
+        if ($isViewPage) {
+            \Yii::$app->response->format = Response::FORMAT_HTML;
+            $defaults = [
+                'start_time' => date('Y-m-01 00:00:00'),
+                'end_time' => date('Y-m-d H:i:s'),
+                'period_num' => (string)((new Period())->getNowPeriodNum()),
+                'operate_user' => 'admin_dba',
+            ];
+
+            $formModel = new OrderPeriodAdjustRangeForm();
+            $formModel->start_time = $defaults['start_time'];
+            $formModel->end_time = $defaults['end_time'];
+            $formModel->period_num = $defaults['period_num'];
+            $formModel->operate_user = $defaults['operate_user'];
+
+            return $this->renderPartial('order-period-adjust-range', [
+                'defaults' => $defaults,
+                'formModel' => $formModel,
+                'result' => null,
+                'errors' => [],
+                'submitted' => false,
+            ]);
+        }
+
         return static::notice([
             'requiredParams' => [
                 'start_time',
@@ -1127,6 +1174,7 @@ class ShopController extends BaseController {
                 'operate_user',
             ],
             'description' => 'Batch adjust orders by created_at range and target period.',
+            'viewUrl' => '/v1/shop/order-period-adjust-range?view=1',
         ]);
     }
 

+ 350 - 0
backendApi/modules/v1/views/shop/order-period-adjust-range.php

@@ -0,0 +1,350 @@
+<?php
+
+use yii\helpers\Html;
+use yii\helpers\Url;
+
+/** @var array $defaults */
+/** @var \common\models\forms\OrderPeriodAdjustRangeForm $formModel */
+/** @var array|null $result */
+/** @var array $errors */
+/** @var bool $submitted */
+
+$title = 'Order Period Adjust Range';
+
+$e = static function ($value): string {
+    return Html::encode((string)$value);
+};
+
+$renderList = static function (array $items) use ($e): string {
+    if (!$items) {
+        return '<div class="muted">None</div>';
+    }
+
+    $html = '<ul class="list">';
+    foreach ($items as $item) {
+        $html .= '<li>' . $e($item) . '</li>';
+    }
+    $html .= '</ul>';
+    return $html;
+};
+
+$renderErrorMap = static function (array $errorMap) use ($e): string {
+    if (!$errorMap) {
+        return '<div class="muted">None</div>';
+    }
+
+    $html = '<div class="error-map">';
+    foreach ($errorMap as $orderSn => $messages) {
+        $html .= '<div class="error-item">';
+        $html .= '<div><strong>' . $e($orderSn) . '</strong></div>';
+        foreach ((array)$messages as $field => $messageList) {
+            $html .= '<div class="muted">' . $e($field) . ': ' . $e(is_array($messageList) ? implode('; ', $messageList) : $messageList) . '</div>';
+        }
+        $html .= '</div>';
+    }
+    $html .= '</div>';
+    return $html;
+};
+
+?>
+<!doctype html>
+<html lang="zh-CN">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title><?= $e($title) ?></title>
+    <style>
+        :root {
+            --bg: #f3f5f7;
+            --card: #ffffff;
+            --text: #1f2937;
+            --muted: #6b7280;
+            --accent: #2563eb;
+            --accent-soft: #dbeafe;
+            --danger: #b91c1c;
+            --success: #15803d;
+            --border: #e5e7eb;
+        }
+        body {
+            margin: 0;
+            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
+            background: linear-gradient(180deg, #eef2ff 0%, var(--bg) 40%, #f8fafc 100%);
+            color: var(--text);
+        }
+        .wrap {
+            max-width: 1120px;
+            margin: 0 auto;
+            padding: 28px 18px 48px;
+        }
+        .hero {
+            margin-bottom: 18px;
+            padding: 20px 22px;
+            background: rgba(255,255,255,.86);
+            border: 1px solid rgba(148,163,184,.2);
+            border-radius: 18px;
+            box-shadow: 0 10px 30px rgba(15,23,42,.08);
+        }
+        .hero h1 {
+            margin: 0 0 8px;
+            font-size: 26px;
+        }
+        .hero p {
+            margin: 6px 0;
+            color: var(--muted);
+            line-height: 1.6;
+        }
+        .grid {
+            display: grid;
+            grid-template-columns: 1.2fr .8fr;
+            gap: 18px;
+        }
+        .card {
+            background: var(--card);
+            border: 1px solid var(--border);
+            border-radius: 18px;
+            box-shadow: 0 10px 30px rgba(15,23,42,.06);
+            overflow: hidden;
+        }
+        .card h2 {
+            margin: 0;
+            padding: 16px 18px;
+            border-bottom: 1px solid var(--border);
+            font-size: 18px;
+        }
+        .card-body {
+            padding: 18px;
+        }
+        .field {
+            margin-bottom: 14px;
+        }
+        .field label {
+            display: block;
+            margin-bottom: 6px;
+            font-weight: 600;
+            font-size: 14px;
+        }
+        .field input {
+            width: 100%;
+            box-sizing: border-box;
+            padding: 11px 12px;
+            border: 1px solid var(--border);
+            border-radius: 12px;
+            font-size: 14px;
+            outline: none;
+        }
+        .field input:focus {
+            border-color: var(--accent);
+            box-shadow: 0 0 0 3px var(--accent-soft);
+        }
+        .btn {
+            display: inline-flex;
+            align-items: center;
+            justify-content: center;
+            padding: 11px 16px;
+            border: none;
+            border-radius: 12px;
+            background: var(--accent);
+            color: #fff;
+            font-weight: 700;
+            cursor: pointer;
+        }
+        .btn:hover {
+            opacity: .95;
+        }
+        .summary {
+            display: grid;
+            grid-template-columns: repeat(4, minmax(0, 1fr));
+            gap: 10px;
+            margin-bottom: 14px;
+        }
+        .stat {
+            border: 1px solid var(--border);
+            border-radius: 14px;
+            padding: 12px 14px;
+            background: #fafafa;
+        }
+        .stat .label {
+            color: var(--muted);
+            font-size: 12px;
+            margin-bottom: 6px;
+        }
+        .stat .value {
+            font-size: 18px;
+            font-weight: 700;
+        }
+        .muted {
+            color: var(--muted);
+        }
+        .section {
+            margin-bottom: 16px;
+            padding-bottom: 16px;
+            border-bottom: 1px dashed var(--border);
+        }
+        .section:last-child {
+            margin-bottom: 0;
+            padding-bottom: 0;
+            border-bottom: 0;
+        }
+        .badge {
+            display: inline-block;
+            margin-left: 8px;
+            padding: 2px 8px;
+            border-radius: 999px;
+            background: var(--accent-soft);
+            color: var(--accent);
+            font-size: 12px;
+            font-weight: 700;
+        }
+        .success {
+            color: var(--success);
+        }
+        .danger {
+            color: var(--danger);
+        }
+        .list {
+            margin: 8px 0 0;
+            padding-left: 18px;
+        }
+        .error-map .error-item {
+            margin-top: 10px;
+            padding: 10px 12px;
+            border: 1px solid #fee2e2;
+            background: #fffafa;
+            border-radius: 12px;
+        }
+        pre {
+            margin: 0;
+            padding: 14px;
+            overflow: auto;
+            background: #0f172a;
+            color: #e2e8f0;
+            border-radius: 14px;
+            font-size: 12px;
+            line-height: 1.6;
+        }
+        @media (max-width: 900px) {
+            .grid, .summary {
+                grid-template-columns: 1fr;
+            }
+        }
+    </style>
+</head>
+<body>
+<div class="wrap">
+    <div class="hero">
+        <h1><?= $e($title) ?></h1>
+        <p>Use this page to batch adjust orders by <code>start_time</code>, <code>end_time</code>, <code>period_num</code> and <code>operate_user</code>.</p>
+        <p>Open via <code>/v1/shop/order-period-adjust-range?view=1</code>. The result panel shows successful, failed and skipped order numbers after execution.</p>
+    </div>
+
+    <div class="grid">
+        <div class="card">
+            <h2>Execution Form</h2>
+            <div class="card-body">
+                <?= Html::beginForm(Url::current(['view' => 1]), 'post') ?>
+                    <div class="field">
+                        <label for="start_time">start_time</label>
+                        <input id="start_time" name="start_time" value="<?= $e($formModel->start_time ?? ($defaults['start_time'] ?? '')) ?>">
+                    </div>
+                    <div class="field">
+                        <label for="end_time">end_time</label>
+                        <input id="end_time" name="end_time" value="<?= $e($formModel->end_time ?? ($defaults['end_time'] ?? '')) ?>">
+                    </div>
+                    <div class="field">
+                        <label for="period_num">period_num</label>
+                        <input id="period_num" name="period_num" value="<?= $e($formModel->period_num ?? ($defaults['period_num'] ?? '')) ?>">
+                    </div>
+                    <div class="field">
+                        <label for="operate_user">operate_user</label>
+                        <input id="operate_user" name="operate_user" value="<?= $e($formModel->operate_user ?? ($defaults['operate_user'] ?? '')) ?>">
+                    </div>
+                    <button class="btn" type="submit">Execute</button>
+                <?= Html::endForm() ?>
+            </div>
+        </div>
+
+        <div class="card">
+            <h2>Configuration</h2>
+            <div class="card-body">
+                <div class="section">
+                    <div class="muted">Default start_time</div>
+                    <div><?= $e($defaults['start_time'] ?? '') ?></div>
+                </div>
+                <div class="section">
+                    <div class="muted">Default end_time</div>
+                    <div><?= $e($defaults['end_time'] ?? '') ?></div>
+                </div>
+                <div class="section">
+                    <div class="muted">Default period_num</div>
+                    <div><?= $e($defaults['period_num'] ?? '') ?></div>
+                </div>
+                <div class="section">
+                    <div class="muted">Default operate_user</div>
+                    <div><?= $e($defaults['operate_user'] ?? '') ?></div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <?php if ($submitted): ?>
+        <div class="card" style="margin-top: 18px;">
+            <h2>Execution Result</h2>
+            <div class="card-body">
+                <?php if ($result): ?>
+                    <div class="summary">
+                        <div class="stat">
+                            <div class="label">Total</div>
+                            <div class="value"><?= $e($result['total_count'] ?? 0) ?></div>
+                        </div>
+                        <div class="stat">
+                            <div class="label success">Success</div>
+                            <div class="value success"><?= $e($result['success_count'] ?? 0) ?></div>
+                        </div>
+                        <div class="stat">
+                            <div class="label danger">Failed</div>
+                            <div class="value danger"><?= $e($result['failed_count'] ?? 0) ?></div>
+                        </div>
+                        <div class="stat">
+                            <div class="label">Skipped</div>
+                            <div class="value"><?= $e($result['skipped_count'] ?? 0) ?></div>
+                        </div>
+                    </div>
+
+                    <div class="section">
+                        <div><strong>Success order numbers</strong><span class="badge"><?= $e($result['success_count'] ?? 0) ?></span></div>
+                        <?= $renderList($result['success_order_sn_list'] ?? []) ?>
+                    </div>
+
+                    <div class="section">
+                        <div><strong>Failed order numbers</strong><span class="badge"><?= $e($result['failed_count'] ?? 0) ?></span></div>
+                        <?= $renderList($result['failed_order_sn_list'] ?? []) ?>
+                        <div style="margin-top: 12px;">
+                            <strong>Failure details</strong>
+                            <?= $renderErrorMap($result['failed_detail_map'] ?? []) ?>
+                        </div>
+                    </div>
+
+                    <div class="section">
+                        <div><strong>Skipped order numbers</strong><span class="badge"><?= $e($result['skipped_count'] ?? 0) ?></span></div>
+                        <?= $renderList($result['skipped_order_sn_list'] ?? []) ?>
+                    </div>
+
+                    <div class="section">
+                        <div><strong>Raw payload</strong></div>
+                        <pre><?= $e(json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)) ?></pre>
+                    </div>
+                <?php else: ?>
+                    <div class="danger"><strong>Execution failed.</strong></div>
+                    <?php if ($errors): ?>
+                        <div style="margin-top: 12px;">
+                            <strong>Validation errors</strong>
+                            <pre><?= $e(json_encode($errors, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)) ?></pre>
+                        </div>
+                    <?php endif; ?>
+                <?php endif; ?>
+            </div>
+        </div>
+    <?php endif; ?>
+</div>
+</body>
+</html>