ProjectUpdate.php 47.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
<?php

namespace App\Console\Commands\Update;

use App\Helper\Arr;
use App\Http\Logic\Bside\News\NewsLogic;
use App\Http\Logic\Bside\Product\CategoryLogic;
use App\Models\Blog\Blog;
use App\Models\Collect\CollectSource;
use App\Models\Collect\CollectTask;
use App\Models\Com\UpdateLog;
use App\Models\Com\UpdateOldInfo;
use App\Models\CustomModule\CustomModule;
use App\Models\CustomModule\CustomModuleCategory;
use App\Models\CustomModule\CustomModuleContent;
use App\Models\CustomModule\CustomModuleExtend;
use App\Models\CustomModule\CustomModuleExtentContent;
use App\Models\News\News;
use App\Models\News\NewsCategory;
use App\Models\Product\Category;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Extend;
use App\Models\Product\ExtendInfo;
use App\Models\Product\Keyword;
use App\Models\Product\Product;
use App\Models\RouteMap\RouteMap;
use App\Models\Template\BCustomTemplate;
use App\Models\WebSetting\WebSettingReceiving;
use App\Services\CosService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

/**
 * 4.0,5.0升级到6.0,内容同步
 * Class ProjectImport
 * @package App\Console\Commands
 * @author Akun
 * @date 2023/10/9 15:04
 */
class ProjectUpdate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'project_update';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '执行项目升级任务';


    public function handle()
    {
        ini_set('memory_limit', '512M');
        while (true) {
            $this->start_update();
        }
    }

    protected function start_update()
    {
        $task_id = $this->get_task();
        if (!$task_id) {
            sleep(60);
            return true;
        }

        $task = UpdateLog::where('id', $task_id)->where('status', UpdateLog::STATUS_UN)->first();
        if (!$task) {
            sleep(2);
            return true;
        }

        $project_id = $task->project_id;
        $api_type = $task->api_type;
        $api_url_arr = explode('?', $task->api_url);
        $api_url = $api_url_arr[0];
        $domain_arr = parse_url($api_url);

        $page_size = 20;

        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', task_type: ' . $api_type . ', update start' . PHP_EOL;

        $task->status = UpdateLog::STATUS_ING;//同步中
        $task->save();

        //获取站点原始域名信息
        $old_info = UpdateOldInfo::getOldDomain($project_id, $domain_arr['host']);
        $link_type = $old_info['link_type'];
        $web_url_domain = $old_info['web_url_domain'];
        $home_url = $old_info['home_url'];

        //获取所有语种
        $language_list = [];
        $url_language = 'https://' . $domain_arr['host'] . '/wp-content/plugins/proofreading/json/user_language.json';
        $data_language = curl_c($url_language);
        if ($data_language) {
            $language_list = array_column($data_language, 'short');
        }

        //获取所有页面
        $page_list = [];
        $url_page = 'https://' . $domain_arr['host'] . '/wp-content/cache/pages_list.json';
        $data_page = curl_c($url_page);
        if ($data_page) {
            $page_list = array_column($data_page, 'path');
        }

        //设置数据库
        $project = ProjectServer::useProject($project_id);
        if ($project) {
            if ($api_type == 'category') {
                //产品分类
                $url = $api_url . '?' . http_build_query(['w' => 'category']);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $items = $data['data'] ?? [];
                    $this->category_insert($project_id, $items, 0);
                } else {
                    return true;
                }
            } elseif ($api_type == 'category_news') {
                // 新闻分类
                $url = $api_url . '?' . http_build_query(['w' => 'category_news']);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $items = $data['data'] ?? [];
                    $this->category_news_insert($project_id, $items, 0);
                } else {
                    return true;
                }
            } elseif ($api_type == 'tag') {
                //关键词
                $url = $api_url . '?' . http_build_query(['w' => 'tag', 'page' => 1, 'pagesize' => 0]);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $count = $data['data']['count'] ?? 0;

                    $total_page = ceil($count / $page_size);
                    for ($page = 1; $page <= $total_page; $page++) {
                        $url_page = $api_url . '?' . http_build_query(['w' => 'tag', 'page' => $page, 'pagesize' => $page_size]);
                        $data_page = curl_c($url_page);
                        if (isset($data_page['code']) && $data_page['code'] == 200) {
                            $items = $data_page['data']['data'] ?? [];

                            $model = new Keyword();
                            foreach ($items as $item) {
                                $route = $this->get_url_route($item['url'] ?? '');
                                if ($route) {
                                    //判断路由是否存在
                                    $route_info = RouteMap::where('project_id', $project_id)->where('route', $route)->where('path', '')->first();
                                    if ($route_info) {
                                        continue;
                                    }
                                    $keyword = $model->read(['route' => $route], 'id');
                                    if (!$keyword) {
                                        try {
                                            $item['name'] = $this->special2str($item['name'] ?? '');
                                            $id = $model->addReturnId([
                                                'project_id' => $project_id,
                                                'title' => $item['name'],
                                                'seo_title' => $item['seo_title'] ?? '',
                                                'seo_keywords' => $item['seo_keywords'] ?? '',
                                                'seo_description' => $item['seo_description'] ?? '',
                                                'is_upgrade' => 1,
                                                'route' => $route
                                            ]);
                                            $this->set_map($route, RouteMap::SOURCE_PRODUCT_KEYWORD, $id, $project_id);
                                        } catch (\Exception $e) {
                                            echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                            continue;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    return true;
                }
            } elseif ($api_type == 'website_info') {
                //网站信息
                $url = $api_url . '?' . http_build_query(['w' => 'website_info']);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $phones = $data['data']['phones'] ?? '';
                    $emails = $data['data']['emails'] ?? '';
                    $custom_types = $data['data']['customposttypes'] ?? '';

                    $model = new WebSettingReceiving();
                    if ($phones) {
                        $phone_arr = explode(',', $phones);
                        foreach ($phone_arr as $v_phone) {
                            if ($v_phone) {
                                $receiving_phones = $model->read(['type' => 2, 'values' => $v_phone]);
                                if (!$receiving_phones) {
                                    try {
                                        $model->add([
                                            'type' => 2,
                                            'values' => $v_phone,
                                            'project_id' => $project_id
                                        ]);
                                    } catch (\Exception $e) {
                                        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    if ($emails) {
                        $email_arr = explode(',', $emails);
                        foreach ($email_arr as $v_email) {
                            if ($v_email) {
                                $receiving_emails = $model->read(['type' => 1, 'values' => $v_email]);
                                if (!$receiving_emails) {
                                    try {
                                        $model->add([
                                            'type' => 1,
                                            'values' => $v_email,
                                            'project_id' => $project_id
                                        ]);
                                    } catch (\Exception $e) {
                                        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    if ($custom_types) {
                        $custom_model = new CustomModule();
                        foreach ($custom_types as $v_custom) {
                            $log = UpdateLog::where('project_id', $project_id)->where('api_type', $v_custom)->first();
                            if (empty($log)) {
                                try {
                                    $custom_info = $custom_model->read(['route' => $v_custom]);
                                    if (!$custom_info) {
                                        $custom_model->add([
                                            'name' => $v_custom,
                                            'project_id' => $project_id,
                                            'route' => $v_custom
                                        ]);
                                    }
                                    UpdateLog::createLog($project_id, $v_custom, $task->api_url);
                                } catch (\Exception $e) {
                                    echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                    continue;
                                }
                            }
                        }
                    }
                } else {
                    return true;
                }
            } elseif ($api_type == 'post') {
                //产品
                $url = $api_url . '?' . http_build_query(['w' => 'post', 'page' => 1, 'pagesize' => 0]);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $count = $data['data']['count'] ?? 0;

                    $total_page = ceil($count / $page_size);
                    for ($page = 1; $page <= $total_page; $page++) {
                        $url_page = $api_url . '?' . http_build_query(['w' => 'post', 'page' => $page, 'pagesize' => $page_size]);
                        $data_page = curl_c($url_page);
                        if (isset($data_page['code']) && $data_page['code'] == 200) {
                            $items = $data_page['data']['data'] ?? [];

                            $model = new Product();
                            $category_model = new Category();
                            $extend_model = new Extend();
                            $extend_info_model = new ExtendInfo();
                            $logic = new CategoryLogic();

                            foreach ($items as $item) {
                                $route = $this->get_url_route($item['url'] ?? '');
                                if ($route) {
                                    //图片
                                    $gallery = [];
                                    if ($item['images'] ?? []) {
                                        foreach ($item['images'] as $k_img => $img) {
                                            $gallery[] = ['alt' => '', 'url' => $this->source_download($img, $project_id, $domain_arr['host'], $web_url_domain, $home_url)];
                                        }
                                    }
                                    //分类
                                    $category_id = '';
                                    $category_arr = [];
                                    if ($item['category'] ?? []) {
                                        $category_arr = $category_model->list(['original_id' => ['in', array_column($item['category'], 'id')]]);
                                        $category_id = $logic->getLastCategory(array_column($category_arr, 'id'));
                                    }
                                    //名称去掉特殊符号
                                    $item['ttile'] = $this->special2str($item['ttile'] ?? '');

                                    try {
                                        $product = $model->read(['route' => $route], 'id');
                                        if (!$product) {
                                            $id = $model->insertGetId([
                                                'project_id' => $project_id,
                                                'title' => $item['ttile'],
                                                'intro' => $item['short_description'] ?? '',
                                                'content' => $item['content'] ?? '',
                                                'category_id' => $category_id,
                                                'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '',
                                                'gallery' => Arr::a2s($gallery),
                                                'seo_mate' => Arr::a2s([
                                                    'title' => $item['ttile'],
                                                    'keyword' => $item['keywords'] ?? '',
                                                    'description' => $item['description'] ?? ''
                                                ]),
                                                'status' => Product::STATUS_ON,
                                                'created_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'updated_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'sort' => $item['sort'] ?? 0,
                                                'is_upgrade' => 1,
                                                'six_read' => 1,
                                                'route' => $route
                                            ]);
                                            $this->set_map($route, RouteMap::SOURCE_PRODUCT, $id, $project_id);
                                            CollectTask::_insert($item['url'], $project_id, RouteMap::SOURCE_PRODUCT, $id, $domain_arr['host'], $link_type, $language_list, $page_list);
                                        } else {
                                            $id = $product['id'];
                                            $model->edit([
                                                'title' => $item['ttile'],
                                                'intro' => $item['short_description'] ?? '',
                                                'content' => $item['content'] ?? '',
                                                'category_id' => $category_id,
                                                'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '',
                                                'gallery' => Arr::a2s($gallery),
                                                'seo_mate' => Arr::a2s([
                                                    'title' => $item['ttile'],
                                                    'keyword' => $item['keywords'] ?? '',
                                                    'description' => $item['description'] ?? ''
                                                ]),
                                                'sort' => $item['sort'] ?? 0,
                                            ], ['id' => $id]);
                                        }

                                        //关联分类
                                        if ($category_arr) {
                                            CategoryRelated::saveRelated($id, array_column($category_arr, 'id'));
                                        }

                                        //扩展字段
                                        if ($item['extend'] ?? []) {
                                            foreach (array_reverse($item['extend']) as $ke => $ve) {
                                                $extend = $extend_model->read(['title' => $ke]);
                                                if (!$extend) {
                                                    $extend_key = $this->get_extend_key($extend_model);
                                                    $extend_model->add([
                                                        'project_id' => $project_id,
                                                        'title' => $ke,
                                                        'type' => 1,
                                                        'key' => $extend_key
                                                    ]);
                                                } else {
                                                    $extend_key = $extend['key'];
                                                }

                                                $extend_info = $extend_info_model->read(['key' => $extend_key, 'product_id' => $id]);
                                                if (!$extend_info) {
                                                    $extend_info_model->add([
                                                        'key' => $extend_key,
                                                        'project_id' => $project_id,
                                                        'product_id' => $id,
                                                        'values' => $ve,
                                                        'type' => 1
                                                    ]);
                                                }
                                            }
                                        }
                                    } catch (\Exception $e) {
                                        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                } else {
                    return true;
                }
            } elseif ($api_type == 'news' || $api_type == 'blog') {
                //新闻或博客
                $url = $api_url . '?' . http_build_query(['w' => $api_type, 'page' => 1, 'pagesize' => 0]);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $count = $data['data']['count'] ?? 0;

                    $total_page = ceil($count / $page_size);
                    for ($page = 1; $page <= $total_page; $page++) {
                        $url_page = $api_url . '?' . http_build_query(['w' => $api_type, 'page' => $page, 'pagesize' => $page_size]);
                        $data_page = curl_c($url_page);
                        if (isset($data_page['code']) && $data_page['code'] == 200) {
                            $items = $data_page['data']['data'] ?? [];

                            if ($api_type == 'news') {
                                $model = new News();
                                $category_model = new NewsCategory();
                                $logic = new NewsLogic();
                            } else {
                                $model = new Blog();
                            }

                            foreach ($items as $item) {
                                $route = $this->get_url_route($item['url'] ?? '');
                                if ($route) {
                                    //分类
                                    $category_id = '';
                                    if ($api_type == 'news' && ($item['category'] ?? [])) {
                                        $category_arr = $category_model->list(['original_id' => ['in', array_column($item['category'], 'id')]]);
                                        $category_id = $logic->getCategory(array_column($category_arr, 'id'));
                                    }
                                    //图片
                                    if (is_array($item['images'] ?? '')) {
                                        $image = $item['images'][0] ?? '';
                                    } else {
                                        $image = $item['images'] ?? '';
                                    }
                                    $new_img = $this->source_download($image, $project_id, $domain_arr['host'], $web_url_domain, $home_url);
                                    //名称去掉特殊符号
                                    $item['ttile'] = $this->special2str($item['ttile'] ?? '');

                                    try {
                                        $news = $model->read(['url' => $route], 'id');
                                        if (!$news) {
                                            $id = $model->insertGetId([
                                                'project_id' => $project_id,
                                                'name' => $item['ttile'],
                                                'category_id' => $category_id,
                                                'seo_title' => $item['ttile'],
                                                'seo_keywords' => $item['keywords'] ?? '',
                                                'seo_description' => $item['description'] ?? '',
                                                'text' => $item['content'] ?? '',
                                                'image' => $new_img,
                                                'status' => $api_type == 'news' ? News::STATUS_ONE : Blog::STATUS_ONE,
                                                'created_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'updated_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'sort' => $item['sort'] ?? 0,
                                                'is_upgrade' => 1,
                                                'six_read' => 1,
                                                'url' => $route
                                            ]);
                                            $this->set_map($route, $api_type == 'news' ? RouteMap::SOURCE_NEWS : RouteMap::SOURCE_BLOG, $id, $project_id);

                                            CollectTask::_insert($item['url'], $project_id, $api_type == 'news' ? RouteMap::SOURCE_NEWS : RouteMap::SOURCE_BLOG, $id, $domain_arr['host'], $link_type, $language_list, $page_list);
                                        } else {
                                            $id = $news['id'];
                                            $model->edit([
                                                'name' => $item['ttile'],
                                                'category_id' => $category_id,
                                                'seo_title' => $item['ttile'],
                                                'seo_keywords' => $item['keywords'] ?? '',
                                                'seo_description' => $item['description'] ?? '',
                                                'text' => $item['content'] ?? '',
                                                'image' => $new_img,
                                                'sort' => $item['sort'] ?? 0,
                                            ], ['id' => $id]);
                                        }
                                    } catch (\Exception $e) {
                                        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                } else {
                    return true;
                }
            } elseif ($api_type == 'page') {
                //单页
                $url = $api_url . '?' . http_build_query(['w' => 'page', 'page' => 1, 'pagesize' => 0]);
                $data = curl_c($url);
                if (isset($data['code']) && $data['code'] == 200) {
                    $count = $data['data']['count'] ?? 0;

                    $total_page = ceil($count / $page_size);
                    for ($page = 1; $page <= $total_page; $page++) {
                        $url_page = $api_url . '?' . http_build_query(['w' => 'page', 'page' => $page, 'pagesize' => $page_size]);
                        $data_page = curl_c($url_page);
                        if (isset($data_page['code']) && $data_page['code'] == 200) {
                            $items = $data_page['data']['data'] ?? [];

                            $model = new BCustomTemplate();

                            foreach ($items as $item) {
                                $route = $this->get_url_route($item['url'] ?? '');
                                if ($route) {
                                    //名称去掉特殊符号
                                    $item['ttile'] = $this->special2str($item['ttile'] ?? '');
                                    try {
                                        $custom = $model->read(['url' => $route], 'id');
                                        if (!$custom) {
                                            $id = $model->insertGetId([
                                                'project_id' => $project_id,
                                                'name' => $item['ttile'],
                                                'title' => $item['ttile'],
                                                'keywords' => $item['keywords'] ?? '',
                                                'description' => $item['description'] ?? '',
                                                'html' => $item['content'] ?? '',
                                                'status' => 1,
                                                'created_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'updated_at' => $item['post_date'] ?? date('Y-m-d H:i:s'),
                                                'is_upgrade' => 1,
                                                'six_read' => 1,
                                                'url' => $route
                                            ]);
                                            $this->set_map($route, RouteMap::SOURCE_PAGE, $id, $project_id);

                                            CollectTask::_insert($item['url'], $project_id, RouteMap::SOURCE_PAGE, $id, $domain_arr['host'], $link_type, $language_list, $page_list);
                                        } else {
                                            $id = $custom['id'];
                                            $model->edit([
                                                'name' => $item['ttile'],
                                                'title' => $item['ttile'],
                                                'keywords' => $item['keywords'] ?? '',
                                                'description' => $item['description'] ?? '',
                                                'html' => $item['content'] ?? '',
                                            ], ['id' => $id]);
                                        }
                                    } catch (\Exception $e) {
                                        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                } else {
                    return true;
                }
            } else {
                //自定义模块
                $custom_model = new CustomModule();
                $custom_info = $custom_model->read(['route' => $api_type]);
                if ($custom_info) {
                    $url = $api_url . '?' . http_build_query(['w' => $api_type, 'page' => 1, 'pagesize' => 0]);
                    $data = curl_c($url);
                    if (isset($data['code']) && $data['code'] == 200) {
                        $category = [
                            [
                                'id' => 0,
                                'name' => $custom_info['route'],
                                'url' => '/' . $custom_info['route'],
                                'parent' => 0,
                                'children' => $data['data']['category'] ?? []
                            ]
                        ];
                        $this->category_custom_insert($project_id, $custom_info['id'], $category, 0);

                        $count = $data['data']['count'] ?? 0;

                        $total_page = ceil($count / $page_size);
                        for ($page = 1; $page <= $total_page; $page++) {
                            $url_page = $api_url . '?' . http_build_query(['w' => $api_type, 'page' => $page, 'pagesize' => $page_size]);
                            $data_page = curl_c($url_page);
                            if (isset($data_page['code']) && $data_page['code'] == 200) {
                                $items = $data_page['data']['data'] ?? [];

                                $model = new CustomModuleContent();
                                $category_model = new CustomModuleCategory();
                                $extend_model = new CustomModuleExtend();
                                $extend_info_model = new CustomModuleExtentContent();

                                foreach ($items as $item) {
                                    $route = $this->get_url_route($item['url'] ?? '');
                                    if ($route) {
                                        //分类
                                        $category_id = '';
                                        if ($item['category'] ?? []) {
                                            $category_arr = $category_model->list(['original_id' => ['in', array_column($item['category'], 'id')]]);
                                            $category_id = implode(',', array_column($category_arr, 'id'));
                                        } else {
                                            $category_custom = $category_model->read(['route' => $custom_info['route']], 'id');
                                            if ($category_custom) {
                                                $category_id = $category_custom['id'];
                                            }
                                        }
                                        //图片
                                        if (is_array($item['images'] ?? '')) {
                                            $image = $item['images'][0] ?? '';
                                        } else {
                                            $image = $item['images'] ?? '';
                                        }
                                        $new_img = $this->source_download($image, $project_id, $domain_arr['host'], $web_url_domain, $home_url);
                                        //名称去掉特殊符号
                                        $item['title'] = $this->special2str($item['title'] ?? '');

                                        try {
                                            $custom_content = $model->read(['route' => $route], 'id');
                                            if (!$custom_content) {
                                                $id = $model->insertGetId([
                                                    'project_id' => $project_id,
                                                    'name' => $item['title'],
                                                    'module_id' => $custom_info['id'],
                                                    'category_id' => $category_id,
                                                    'content' => $item['content'] ?? '',
                                                    'image' => $new_img,
                                                    'created_at' => $item['post_time'] ?? date('Y-m-d H:i:s'),
                                                    'updated_at' => $item['post_time'] ?? date('Y-m-d H:i:s'),
                                                    'is_upgrade' => 1,
                                                    'six_read' => 1,
                                                    'route' => $route
                                                ]);
                                                $this->set_map($route, RouteMap::SOURCE_MODULE, $id, $project_id);

                                                CollectTask::_insert($item['url'], $project_id, RouteMap::SOURCE_MODULE, $id, $domain_arr['host'], $link_type, $language_list, $page_list);
                                            } else {
                                                $id = $custom_content['id'];
                                                $model->edit([
                                                    'name' => $item['title'],
                                                    'category_id' => $category_id,
                                                    'content' => $item['content'] ?? '',
                                                    'image' => $new_img
                                                ], ['id' => $id]);
                                            }

                                            //扩展字段
                                            if ($item['extend'] ?? []) {
                                                foreach ($item['extend'] as $ke => $ve) {
                                                    $extend = $extend_model->read(['title' => $ke]);
                                                    if ($extend) {
                                                        $extend_info = $extend_info_model->read(['key' => $extend['key'], 'content_id' => $id]);
                                                        if (!$extend_info) {
                                                            if ($extend['type'] == 3) {
                                                                $gallery = [];
                                                                if (is_array($ve)) {
                                                                    foreach ($ve as $ve_img) {
                                                                        $gallery[] = ['title' => '', 'description' => '', 'url' => $this->source_download($ve_img, $project_id, $domain_arr['host'], $web_url_domain, $home_url)];
                                                                    }
                                                                }else{
                                                                    $gallery[] = ['title' => '', 'description' => '', 'url' => $this->source_download($ve, $project_id, $domain_arr['host'], $web_url_domain, $home_url)];
                                                                }
                                                                $value = Arr::a2s($gallery);
                                                            } elseif ($extend['type'] == 4) {
                                                                $value = Arr::a2s([$this->source_download($ve, $project_id, $domain_arr['host'], $web_url_domain, $home_url)]);
                                                            } else {
                                                                $value = $ve;
                                                            }
                                                            $extend_info_model->add([
                                                                'key' => $extend['key'],
                                                                'type' => $extend['type'],
                                                                'project_id' => $project_id,
                                                                'content_id' => $id,
                                                                'module_id' => $custom_info['id'],
                                                                'values' => $value,
                                                            ]);
                                                        }
                                                    }
                                                }
                                            }
                                        } catch (\Exception $e) {
                                            echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', error: ' . $e->getMessage() . PHP_EOL;
                                            continue;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        return true;
                    }
                }
            }
        }
        //关闭数据库
        DB::disconnect('custom_mysql');

        $task->status = UpdateLog::STATUS_COM;//同步完成
        $task->save();

        echo 'date:' . date('Y-m-d H:i:s') . ', task_id: ' . $task->id . ', task_type: ' . $api_type . ', update end ' . PHP_EOL;

        sleep(2);
    }

    //获取任务
    protected function get_task()
    {
        $key = 'console_update_task';
        $task_id = Redis::rpop($key);
        if ($task_id) {
            return $task_id;
        }

        $task_list = UpdateLog::where('status', UpdateLog::STATUS_UN)->orderBy('sort', 'asc')->orderBy('updated_at', 'asc')->limit(20)->get();
        if ($task_list->count() == 0) {
            return false;
        }

        foreach ($task_list as $value) {
            Redis::lpush($key, $value->id);
        }

        $task_id = Redis::rpop($key);
        return $task_id;
    }

    //获取地址路由
    protected function get_url_route($url)
    {
        if (strpos($url, '%ec') !== false) {
            $url = str_replace('%ec', 'v6SpecialStr', $url);
            $url = urldecode($url);
            $url = str_replace('v6SpecialStr', '%ec', $url);
        } else {
            $url = urldecode($url);
        }
        $arr = parse_url($url);
        if (empty($arr['path'])) {
            return '';
        }
        $path = $arr['path'];

        $path_arr = explode('/', $path);

        return end($path_arr) ? end($path_arr) : $path_arr[count($path_arr) - 2];
    }

    //产品多级分类入库
    protected function category_insert($project_id, $items, $pid = 0)
    {
        $model = new Category();
        foreach ($items as $item) {
            $route = $this->get_url_route($item['url'] ?? '');
            if ($route) {
                $parent = $model->read(['pid' => $pid, 'route' => $route], 'id');
                if (!$parent) {
                    try {
                        $item['name'] = $this->special2str($item['name'] ?? '');
                        $parent_id = $model->addReturnId([
                            'project_id' => $project_id,
                            'title' => $item['name'],
                            'pid' => $pid,
                            'keywords' => $item['keywords'] ?? '',
                            'describe' => $item['description'] ?? '',
                            'original_id' => $item['id'],
                            'route' => $route
                        ]);
                        $this->set_map($route, RouteMap::SOURCE_PRODUCT_CATE, $parent_id, $project_id);
                    } catch (\Exception $e) {
                        echo 'date:' . date('Y-m-d H:i:s') . ', category_insert error: ' . $e->getMessage() . PHP_EOL;
                        continue;
                    }
                } else {
                    $parent_id = $parent['id'];
                }

                if (!empty($item['children'] ?? [])) {
                    $this->category_insert($project_id, $item['children'], $parent_id);
                }
            }
        }
    }

    //新闻多级分类入库
    protected function category_news_insert($project_id, $items, $pid = 0)
    {
        $model = new NewsCategory();
        foreach ($items as $item) {
            $route = $this->get_url_route($item['url'] ?? '');
            if ($route) {
                $parent = $model->read(['pid' => $pid, 'alias' => $route], 'id');
                if (!$parent) {
                    try {
                        $item['name'] = $this->special2str($item['name'] ?? '');
                        $parent_id = $model->addReturnId([
                            'project_id' => $project_id,
                            'name' => $item['name'],
                            'pid' => $pid,
                            'original_id' => $item['id'],
                            'alias' => $route
                        ]);
                        $this->set_map($route, RouteMap::SOURCE_NEWS_CATE, $parent_id, $project_id);
                    } catch (\Exception $e) {
                        echo 'date:' . date('Y-m-d H:i:s') . ', category_news_insert error: ' . $e->getMessage() . PHP_EOL;
                        continue;
                    }
                } else {
                    $parent_id = $parent['id'];
                }

                if (!empty($item['children'] ?? [])) {
                    $this->category_news_insert($project_id, $item['children'], $parent_id);
                }
            }
        }
    }

    //扩展模块多级分类入库
    protected function category_custom_insert($project_id, $module_id, $items, $pid = 0)
    {
        $model = new CustomModuleCategory();
        foreach ($items as $item) {
            $route = $this->get_url_route($item['url'] ?? '');
            if ($route) {
                $parent = $model->read(['pid' => $pid, 'route' => $route], 'id');
                if (!$parent) {
                    try {
                        $item['name'] = $this->special2str($item['name'] ?? '');
                        $parent_id = $model->addReturnId([
                            'project_id' => $project_id,
                            'module_id' => $module_id,
                            'name' => $item['name'],
                            'pid' => $pid,
                            'original_id' => $item['id'],
                            'route' => $route
                        ]);
                        $this->set_map($route, RouteMap::SOURCE_MODULE_CATE, $parent_id, $project_id);
                    } catch (\Exception $e) {
                        echo 'date:' . date('Y-m-d H:i:s') . ', category_custom_insert error: ' . $e->getMessage() . PHP_EOL;
                        continue;
                    }
                } else {
                    $parent_id = $parent['id'];
                }

                if (!empty($item['children'] ?? [])) {
                    $this->category_custom_insert($project_id, $module_id, $item['children'], $parent_id);
                }
            }
        }
    }

    //特殊字符转换
    protected function special2str($str)
    {
        if (strpos($str, ';') === false) {
            return $str;
        }

        $list = [
            '&lt;' => '<',
            '&gt;' => '>',
            '&amp;' => '&',
            '&acute;' => '´',
            '&quot;' => '“',
            '&nbsp;' => ' '
        ];

        foreach ($list as $k => $v) {
            $str = str_replace($k, $v, $str);
        }

        return $str;
    }

    //路由入库
    protected function set_map($route, $source, $source_id, $project_id)
    {
        if ($route) {
            $route_map = RouteMap::where('project_id', $project_id)->where('source', $source)->where('source_id', $source_id)->first();
            if (!$route_map) {
                $route_map = new RouteMap();
                $route_map->project_id = $project_id;
                $route_map->source = $source;
                $route_map->source_id = $source_id;
                $route_map->route = $route;

                if ($source == RouteMap::SOURCE_NEWS) {
                    $route_map->path = RouteMap::SOURCE_NEWS;
                } elseif ($source == RouteMap::SOURCE_BLOG) {
                    $route_map->path = RouteMap::SOURCE_BLOG . 's';
                }

                $route_map->save();
            }
        }
    }

    //资源下载
    protected function source_download($url, $project_id, $domain, $web_url_domain, $home_url)
    {
        if (!$url) {
            return '';
        }

        $arr = parse_url($url);
        $scheme = $arr['scheme'] ?? '';
        $host = $arr['host'] ?? '';
        $path = $arr['path'] ?? '';

        if (
            (empty($scheme) || $scheme == 'https' || $scheme == 'http')
            && (empty($host) || (strpos($web_url_domain, $host) !== false) || (strpos($home_url, $host) !== false))
            && $path
        ) {
            $source = CollectSource::where('project_id', $project_id)->where('origin', $url)->first();
            if (!$source) {
                if (empty($scheme) && empty($host) && substr($path, 0, 1) != '/') {
                    $path = '/' . $path;
                }
                $url_complete = ($scheme ?: 'https') . '://' . $domain . $path;
                $new_url = CosService::uploadRemote($project_id, 'image_product', $url_complete);

                if ($new_url) {
                    CollectSource::insert([
                        'project_id' => $project_id,
                        'origin' => $url,
                        'target' => $new_url,
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                    ]);

                    return getImageUrl($new_url);
                } else {
                    return $url_complete;
                }
            } else {
                return getImageUrl($source['target']);
            }
        } else {
            return ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path;
        }
    }

    //获取自定义字段key
    protected function get_extend_key($model, $i = 1)
    {
        $key = 'pd_extended_field_';
        $info = $model->read(['key' => $key . $i]);
        if ($info !== false) {
            return $this->get_extend_key($model, $i + 1);
        } else {
            return $key . $i;
        }
    }
}