From f04153a5b3a53445b53b7bc8b9fd9751454cb689 Mon Sep 17 00:00:00 2001
From: "WIN-C27C5MSVTPO\\16961" <1696136552@qq.com>
Date: Mon, 12 Jan 2026 15:32:16 +0800
Subject: [PATCH] 1
---
app/command/CrmRotateUserCommand.php | 105 ----
app/command/CustomerCodeCommand.php | 62 --
app/command/CustomerCreatedAtCommand.php | 69 ---
app/command/DomainCommand.php | 79 ---
app/command/EmailDetailCommand.php | 206 -------
app/command/EmailParseCommand.php | 144 -----
app/command/EmailUidCommand.php | 185 ------
app/command/FinanceRecoCommand.php | 32 -
app/command/FixInquiryLogOrderNo.php | 103 ----
app/command/ImportCustomerCommand.php | 178 ------
app/command/InitUserPasswordCommand.php | 34 --
app/command/TbCommand.php | 36 --
...UpdateInquiryLogFromCrmCustomerCommand.php | 144 -----
app/command/VehMoneyCommand.php | 29 -
app/common/controller/UsedCarController.php | 2 +-
app/common/utils/pdf/template/usedCar.stub | 10 +-
app/crmAdmin/controller/BaseController.php | 51 --
.../controller/CustomerController.php | 270 ---------
.../controller/StatisticsController.php | 187 ------
app/crmAdmin/logic/CustomerLogic.php | 34 --
app/crmAdmin/service/CustomerService.php | 557 ------------------
app/mobile/controller/InvItemController.php | 55 --
.../controller/InvRequisitionController.php | 55 --
.../InvRequisitionItemReturnController.php | 56 --
.../controller/AttachmentController.php | 11 -
app/ticket/controller/BaseController.php | 51 --
app/ticket/controller/CategorieController.php | 64 --
.../controller/ConversationController.php | 64 --
app/ticket/controller/TicketController.php | 88 ---
app/ticket/logic/AttachmentLogic.php | 82 ---
app/ticket/logic/CategorieLogic.php | 74 ---
app/ticket/logic/ConversationLogic.php | 60 --
app/ticket/logic/TicketLogic.php | 77 ---
app/ticket/model/Attachment.php | 66 ---
app/ticket/model/Categorie.php | 54 --
app/ticket/model/CategorieTranslation.php | 35 --
app/ticket/model/Conversation.php | 30 -
app/ticket/model/Ticket.php | 95 ---
app/ticket/service/CategorieService.php | 105 ----
app/ticket/service/ConversationService.php | 160 -----
app/ticket/service/TicketService.php | 167 ------
41 files changed, 6 insertions(+), 3960 deletions(-)
delete mode 100644 app/command/CrmRotateUserCommand.php
delete mode 100644 app/command/CustomerCodeCommand.php
delete mode 100644 app/command/CustomerCreatedAtCommand.php
delete mode 100644 app/command/DomainCommand.php
delete mode 100644 app/command/EmailDetailCommand.php
delete mode 100644 app/command/EmailParseCommand.php
delete mode 100644 app/command/EmailUidCommand.php
delete mode 100644 app/command/FinanceRecoCommand.php
delete mode 100644 app/command/FixInquiryLogOrderNo.php
delete mode 100644 app/command/ImportCustomerCommand.php
delete mode 100644 app/command/InitUserPasswordCommand.php
delete mode 100644 app/command/TbCommand.php
delete mode 100644 app/command/UpdateInquiryLogFromCrmCustomerCommand.php
delete mode 100644 app/command/VehMoneyCommand.php
delete mode 100644 app/crmAdmin/controller/BaseController.php
delete mode 100644 app/crmAdmin/controller/CustomerController.php
delete mode 100644 app/crmAdmin/controller/StatisticsController.php
delete mode 100644 app/crmAdmin/logic/CustomerLogic.php
delete mode 100644 app/crmAdmin/service/CustomerService.php
delete mode 100644 app/mobile/controller/InvItemController.php
delete mode 100644 app/mobile/controller/InvRequisitionController.php
delete mode 100644 app/mobile/controller/InvRequisitionItemReturnController.php
delete mode 100644 app/ticket/controller/AttachmentController.php
delete mode 100644 app/ticket/controller/BaseController.php
delete mode 100644 app/ticket/controller/CategorieController.php
delete mode 100644 app/ticket/controller/ConversationController.php
delete mode 100644 app/ticket/controller/TicketController.php
delete mode 100644 app/ticket/logic/AttachmentLogic.php
delete mode 100644 app/ticket/logic/CategorieLogic.php
delete mode 100644 app/ticket/logic/ConversationLogic.php
delete mode 100644 app/ticket/logic/TicketLogic.php
delete mode 100644 app/ticket/model/Attachment.php
delete mode 100644 app/ticket/model/Categorie.php
delete mode 100644 app/ticket/model/CategorieTranslation.php
delete mode 100644 app/ticket/model/Conversation.php
delete mode 100644 app/ticket/model/Ticket.php
delete mode 100644 app/ticket/service/CategorieService.php
delete mode 100644 app/ticket/service/ConversationService.php
delete mode 100644 app/ticket/service/TicketService.php
diff --git a/app/command/CrmRotateUserCommand.php b/app/command/CrmRotateUserCommand.php
deleted file mode 100644
index 5defb24..0000000
--- a/app/command/CrmRotateUserCommand.php
+++ /dev/null
@@ -1,105 +0,0 @@
-setHelp('查询 user 表中 status=2 且 corp_id=3 的用户,
-然后查找其关联的 crm_customer 记录,
-按顺序将这些 crm_customer.user_id 轮流设置为 1、2、3。');
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $corpId = 3;
- $status = 2;
- $roundRobinUserIds = [64,63,83,93,118,131,132,143,145,150,156,157,158,160];
-
- $output->writeln('开始执行 crm:rotate-user');
-
- try {
- // 1) 找到 user 表中满足条件的用户ID,派卡离职用户
- $userRows = Db::table('user')
- ->where('corp_id', $corpId)
- ->where('status', $status)
- ->get(['id','name']);
-
- $userIds = [];
- $userNames = [];
- foreach ($userRows as $row) {
- $userIds[] = (int)$row->id;
- $userNames[] = $row->name;
- }
-
- if (empty($userIds)) {
- $output->writeln('未找到满足条件的用户(status=2 且 corp_id=3)。无需处理。');
- return self::SUCCESS;
- }
-
- $output->writeln('匹配到用户数:' . count($userIds) .' '. implode(',',$userNames) . '');
-
- // 2) 查找 crm_customer 中属于这些用户的记录
- $customers = Db::table('crm_customer')
- ->whereIn('user_id', $userIds)
- ->orderBy('id', 'asc')
- ->get(['id','user_id']);
-
- if (!$customers || count($customers) === 0) {
- $output->writeln('未找到相关的 crm_customer 记录。');
- return self::SUCCESS;
- }
-
- $output->writeln('需要处理的 crm_customer 数量:' . count($customers) . '');
-
- // 3) 事务中按顺序轮流设置
- // 初始化 UID 轮询器
- $uidRotator = new \app\common\utils\RedisUidRotator('email_parsed_result_20250804');
- $uidRotator->setUids([64, 63, 83, 93, 118, 131, 132, 143, 145, 150, 156, 157, 158, 160], false);
-
- Db::connection()->transaction(function () use ($customers, $roundRobinUserIds, $output, $uidRotator) {
- $assignCount = 0;
- $targetCount = count($roundRobinUserIds);
-
- foreach ($customers as $index => $customer) {
- // 获取下一个分配的UID
- $newUserId = $uidRotator->next();
- Db::table('crm_customer')
- ->where('id', $customer->id)
- ->update(['user_id' => $newUserId]);
-
- $his = CustomerHis::create([
- 'customer_id' => $customer->id,
- 'user_his' => $customer->user_id,
- 'user_id' => $newUserId,
- ]);
-
-
- $assignCount++;
-
- if ($assignCount % 500 === 0) {
- $output->writeln('已处理:' . $assignCount . '');
- }
- }
-
- $output->writeln('处理完成,共更新 crm_customer:' . $assignCount . ' 条');
- });
-
- return self::SUCCESS;
- } catch (\Throwable $e) {
- $output->writeln('执行失败:' . $e->getMessage() . '');
- return self::FAILURE;
- }
- }
-}
-
diff --git a/app/command/CustomerCodeCommand.php b/app/command/CustomerCodeCommand.php
deleted file mode 100644
index a82ec0f..0000000
--- a/app/command/CustomerCodeCommand.php
+++ /dev/null
@@ -1,62 +0,0 @@
-setDescription('为crm_customer表所有记录生成唯一code码,分批处理');
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $batchSize = 1000;
- $total = Customer::withTrashed()->where('code','')->count();
- $output->writeln("总计需处理:$total 条记录");
-
- $processed = 0;
- do {
- // 查询一批未生成code的记录
- $customers = Customer::withTrashed()->where('code','')->limit($batchSize)->get();
- if ($customers->isEmpty()) {
- break;
- }
-
- // Eloquent 批量处理
- foreach ($customers as $customer) {
- // 生成唯一16位code,CM+14位
- $unique = strtoupper(substr(md5($customer->id . microtime(true) . mt_rand(1000, 9999)), 0, 14));
- $code = 'CM' . $unique;
-
- // 防止极小概率重复
- while (Customer::where('code', $code)->exists()) {
- $unique = strtoupper(substr(md5($customer->id . microtime(true) . mt_rand(1000, 9999)), 0, 14));
- $code = 'CM' . $unique;
- }
-
- $created_at = $customer->created_at->getTimestamp();
- $obtain = $created_at > strtotime('2025-07-29')?$created_at:strtotime('2025-07-29');
-
- $customer->code = $code;
- $customer->obtain = $obtain;
- $customer->save();
- $processed++;
- }
-
- $output->writeln("已处理:$processed / $total");
- } while (true);
-
- $output->writeln('全部处理完成!');
- return self::SUCCESS;
- }
-}
\ No newline at end of file
diff --git a/app/command/CustomerCreatedAtCommand.php b/app/command/CustomerCreatedAtCommand.php
deleted file mode 100644
index 57a4020..0000000
--- a/app/command/CustomerCreatedAtCommand.php
+++ /dev/null
@@ -1,69 +0,0 @@
-setHelp('该命令将查询 crm_customer 表中 sn 不为空的记录,并根据 sn 在 inquiry_log 表中查找对应的 order_no 记录,将 inquiry_log 的 created_at 更新到 crm_customer 的 created_at 字段');
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $output->writeln('开始更新 crm_customer 的 created_at 字段...');
-
- try {
- // 使用事务确保数据一致性
- DB::transaction(function () use ($output) {
- // 查询所有 sn 字段不为空的客户记录
- $customers = Db::table('crm_customer')
- ->where('sn', '<>', '')
- ->whereNotNull('sn')
- ->get(['id', 'sn']);
- $output->writeln(''.count($customers).'');
-
- $updatedCount = 0;
-
- foreach ($customers as $customer) {
- // 查找匹配的 inquiry_log 记录
- $inquiryLog = Db::table('inquiry_log')
- ->where('order_no', $customer->sn)
- ->first(['r_time','created_at']);
-
- // 如果找到匹配记录,则更新客户的 created_at 字段
- if ($inquiryLog && isset($inquiryLog->r_time)) {
- $created_at = $inquiryLog->r_time?:$inquiryLog->created_at;
- DB::table('crm_customer')
- ->where('id', $customer->id)
- ->update(['created_at' => $created_at]);
-
- $updatedCount++;
- $output->writeln("已更新客户 ID {$customer->id} 的 created_at 为: {$created_at}");
- }
- }
-
- $output->writeln("更新完成,总共更新了 {$updatedCount} 条记录。");
- });
-
- return self::SUCCESS;
- } catch (\Exception $e) {
- $output->writeln('执行过程中发生错误: ' . $e->getMessage() . '');
- return self::FAILURE;
- }
- }
-}
\ No newline at end of file
diff --git a/app/command/DomainCommand.php b/app/command/DomainCommand.php
deleted file mode 100644
index 7d09da5..0000000
--- a/app/command/DomainCommand.php
+++ /dev/null
@@ -1,79 +0,0 @@
-orderBy('id', 'desc')->get();
-
- foreach ($list as $item) {
- if (!$item->content) {
- continue;
- }
- $item->content = processRichTextImagesEnhanced($item->content);
- $item->save();
- $output->writeln("处理了{$item->id} \n");
- }
- return self::SUCCESS;
- }
-}
-
-/**
- * 增强版 - 处理富文本内容中的图片URL
- *
- * @param string $content 富文本HTML内容
- * @param string $newDomain 新域名(如: https://fdesk.hnxinyouhe.com)
- * @param string $oldDomain 旧域名(如: http://219.157.255.213:25326)
- * @return string 处理后的富文本内容
- */
-function processRichTextImagesEnhanced($content, $newDomain = 'https://x-server.hnxinyouhe.com', $oldDomain = 'http://219.157.255.213:25326') {
- // 标准化域名格式(去除末尾斜杠)
- $newDomain = rtrim($newDomain, '/');
- $oldDomain = rtrim($oldDomain, '/');
-
- // 要处理的属性列表
- $attributes = ['src', 'data-href', 'href', 'data-src', 'data-original'];
-
- foreach ($attributes as $attr) {
- // 情况1:替换旧域名为新域名
- $content = preg_replace(
- '/('.$attr.'=["\'])'.preg_quote($oldDomain, '/').'(\/uploads\/)/i',
- '$1' . $newDomain . '$2',
- $content
- );
-
- // 情况2:给无域名的路径添加新域名
- $content = preg_replace(
- '/('.$attr.'=["\'])(\/uploads\/)/i',
- '$1' . $newDomain . '$2',
- $content
- );
-
- // 情况3:处理可能存在的其他域名(可选)
- $content = preg_replace(
- '/('.$attr.'=["\'])(https?:\/\/[^\/]+)(\/uploads\/)/i',
- '$1' . $newDomain . '$3',
- $content
- );
- }
-
- return $content;
-}
\ No newline at end of file
diff --git a/app/command/EmailDetailCommand.php b/app/command/EmailDetailCommand.php
deleted file mode 100644
index 78e5720..0000000
--- a/app/command/EmailDetailCommand.php
+++ /dev/null
@@ -1,206 +0,0 @@
-addOption(
- 'per-page', 'p',
- InputOption::VALUE_OPTIONAL,
- '每批处理多少条详情',
- config('imap.per_page', 50)
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- try {
- $cfg = config('imap');
- $mailbox = $cfg['mailbox'];
- $username = $cfg['username'];
- $password = $cfg['password'];
- $batch = (int)$input->getOption('per-page');
-
- // 打开 IMAP
- $inbox = @imap_open($mailbox, $username, $password);
- if (!$inbox) {
- $output->writeln("IMAP 连接失败:". imap_last_error() ."");
- return Command::FAILURE;
- }
-
- // 阶段二:逐批拉取详情并写入 emails 表
- $output->writeln("依次拉取详情并写入 emails 表 …");
- while (true) {
- $pending = Db::table('email_uids')
- ->where('status', 0)
- // ->where('uid', '>', 13399)
- ->orderBy('uid', 'desc')
- ->limit(2)
- ->get();
-
- if (count($pending) === 0) {
- $output->writeln("所有 UID 均已处理完毕。");
- break;
- }
-
- $output->writeln("处理下一批 " . count($pending) . " 条 …");
-
- foreach ($pending as $row) {
- $uid = $row->uid;
-
- // 包裹整行处理在 try/catch 中,任何异常都不会中断循环
- try {
- $output->writeln("---- 开始处理 UID={$uid} ----");
-
- // 1. fetch overview
- $ov = @imap_fetch_overview($inbox, $uid, FT_UID)[0] ?? null;
- if (!$ov) {
- $err = imap_last_error() ?: '未知错误';
- $output->writeln("UID={$uid} overview 失败:{$err}");
- $this->logError("UID={$uid} overview 失败:{$err}");
- continue;
- }
- $subject = mb_convert_encoding($ov->subject ?? '', 'UTF-8', 'GBK,UTF-8');
- $from = $ov->from ?? '';
- $date = $ov->date ?? '';
-
- $output->writeln("UID={$uid} overview 成功,subject={$subject}");
-
- // 2. fetch body
- $body = $this->getMailBody($inbox, $uid, true);
- $output->writeln("UID={$uid} body 长度:" . strlen($body));
-
- // 3. sanitize & insert
- $body = $this->sanitizeUtf8($body);
- $now = time();
-
- try {
- Db::table('emails')->insert([
- 'uid' => $uid,
- 'subject' => $subject,
- 'from' => $from,
- 'date' => $date,
- 'body' => $body,
- 'created_at' => $now,
- 'updated_at' => $now,
- ]);
- $output->writeln("UID={$uid} 写入 emails 成功");
- } catch (\Throwable $e) {
- $output->writeln("UID={$uid} 写入失败:{$e->getMessage()}");
- $this->logError("UID={$uid} 写入失败:{$e->getMessage()}");
- continue;
- }
-
- // 4. 标记已处理
- try {
- Db::table('email_uids')
- ->where('uid', $uid)
- ->update([
- 'status' => 1,
- 'processed_at' => $now,
- ]);
- $output->writeln("UID={$uid} 标记为已处理");
- } catch (\Throwable $e) {
- $output->writeln("UID={$uid} 标记状态失败:{$e->getMessage()}");
- $this->logError("UID={$uid} 标记状态失败:{$e->getMessage()}");
- // 即使更新 status 失败,也继续下一条
- }
- } catch (\Throwable $e) {
- // 捕获任何非预期错误
- $output->writeln("UID={$uid} 处理异常:{$e->getMessage()}");
- $this->logError("UID={$uid} 处理异常:{$e->getMessage()}");
- continue;
- }
- }
-
- // 批次结束后稍作休眠,防止服务器过载
- sleep(1);
- }
-
- imap_close($inbox);
- $output->writeln("\n✅ 全部邮件处理完成。");
- return Command::SUCCESS;
- } catch (\Throwable $th) {
- dpr($th);
- return Command::FAILURE;
- }
- }
-
- /**
- * 将任意字符串清洗为有效 UTF-8,移除或替换无效字节
- */
- protected function sanitizeUtf8(string $text): string
- {
- return iconv('UTF-8', 'UTF-8//IGNORE', $text);
- }
-
- /**
- * 记录错误到日志
- */
- protected function logError(string $msg): void
- {
- $line = '[' . date('Y-m-d H:i:s') . '] ' . $msg . "\n";
- file_put_contents(
- runtime_path('logs/email_errors.log'),
- $line,
- FILE_APPEND | LOCK_EX
- );
- }
-
- /**
- * 按编码解码并保留 "\r\n"
- */
- protected function getMailBody($inbox, int $id, bool $isUid = false): string
- {
- $flags = $isUid ? FT_UID : 0;
- $structure = imap_fetchstructure($inbox, $id, $flags);
-
- if (!empty($structure->parts)) {
- // HTML 部分
- foreach ($structure->parts as $i => $part) {
- if (isset($part->subtype) && strtolower($part->subtype) === 'html') {
- $data = imap_fetchbody($inbox, $id, (string)($i+1), $flags);
- return $this->decodeBody($data, $part->encoding);
- }
- }
- // 文本部分
- foreach ($structure->parts as $i => $part) {
- if (isset($part->subtype) && strtolower($part->subtype) === 'plain') {
- $data = imap_fetchbody($inbox, $id, (string)($i+1), $flags);
- return $this->decodeBody($data, $part->encoding);
- }
- }
- // 原始 body
- return imap_body($inbox, $id, $flags);
- }
-
- return imap_body($inbox, $id, $flags);
- }
-
- /**
- * 按编码解码
- */
- protected function decodeBody(string $body, int $encoding): string
- {
- switch ($encoding) {
- case 3: return imap_base64($body);
- case 4: return imap_qprint($body);
- default: return $body;
- }
- }
-}
\ No newline at end of file
diff --git a/app/command/EmailParseCommand.php b/app/command/EmailParseCommand.php
deleted file mode 100644
index 3bf21f7..0000000
--- a/app/command/EmailParseCommand.php
+++ /dev/null
@@ -1,144 +0,0 @@
-orderBy('id', 'asc')
- ->limit($batchSize)
- ->offset($page * $batchSize)
- ->get();
-
- if ($rows->isEmpty()) {
- break;
- }
-
- $toInsert = [];
- foreach ($rows as $row) {
- $parsed = $this->parseHtml($row->body);
- if ($parsed === null) {
- $output->writeln(" ↳ [{$row->id}] skip: not a contact-form HTML");
- continue;
- }
-
- // 严格按 $fields 顺序填充每条记录,缺失的字段补 null
- $record = [];
- foreach ($fields as $col) {
- if ($col === 'email_id') {
- $record[$col] = $row->id;
- } else {
- $record[$col] = $parsed[$col] ?? null;
- }
- }
-
- $toInsert[] = $record;
- }
-
- if (!empty($toInsert)) {
- Db::table('email_parsed_result')->insert($toInsert);
- $output->writeln("Inserted batch #" . ($page + 1) . ", count: " . count($toInsert));
- }
-
- $page++;
- }
-
- $output->writeln("✔ All done.");
- return Command::SUCCESS;
- }
-
- /**
- * 解析 HTML,找不到
Preview
则返回 null,
- * 否则提取所有 Key: Value 为小写蛇形 key=>value 数组
- */
- protected function parseHtml(string $html): ?array
- {
- $doc = new \DOMDocument();
- libxml_use_internal_errors(true);
- $doc->loadHTML('' . $html);
- libxml_clear_errors();
-
- $xpath = new \DOMXPath($doc);
-
- // 类型检查
- if ($xpath->query("//h2[text()='Preview']")->length === 0) {
- return null;
- }
-
- $nodes = $xpath->query("//div[span]");
- $data = [];
-
- /** @var \DOMElement $node */
- foreach ($nodes as $node) {
- $span = $xpath->query("span", $node)->item(0);
- if (! $span) {
- continue;
- }
-
- // 原始键名
- $key = trim(str_replace(':', '', $span->textContent));
- // 转成小写蛇形
- $col = strtolower(str_replace(' ', '_', $key));
-
- // 获取值
- $a = $xpath->query(".//a", $node)->item(0);
- if ($a && $a->hasAttribute('href')) {
- $value = trim($a->getAttribute('href'));
- } else {
- $clone = $node->cloneNode(true);
- $spanClone = $xpath->query(".//span", $clone)->item(0);
- if ($spanClone) {
- $spanClone->parentNode->removeChild($spanClone);
- }
- $value = trim($clone->textContent);
- }
-
- $data[$col] = $value;
- }
-
- return $data;
- }
-}
\ No newline at end of file
diff --git a/app/command/EmailUidCommand.php b/app/command/EmailUidCommand.php
deleted file mode 100644
index bf0e744..0000000
--- a/app/command/EmailUidCommand.php
+++ /dev/null
@@ -1,185 +0,0 @@
-addOption(
- // 'per-page', 'p',
- // InputOption::VALUE_OPTIONAL,
- // '每批处理多少条详情',
- // config('imap.per_page', 50)
- // );
- // }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- try {
- $cfg = config('imap');
- $mailbox = $cfg['mailbox'];
- $username = $cfg['username'];
- $password = $cfg['password'];
- // $batch = (int)$input->getOption('per-page');
-
- $retryTimes = 3;
- $retryDelay = 10; // 秒
-
- $inbox = false;
- $attempt = 0;
-
- $maxUid = Db::table('email_uids')->max('uid');
-
- while ($attempt < $retryTimes) {
- $attempt++;
- $output->writeln("尝试第 {$attempt} 次连接 IMAP...");
- $inbox = @imap_open($mailbox, $username, $password);
-
- if ($inbox) {
- break;
- }
-
- $error = imap_last_error();
- $output->writeln("第 {$attempt} 次失败:{$error}");
-
- // 若出现 too many login failures 立即暂停一段时间
- if (stripos($error, 'Too many login failures') !== false) {
- $output->writeln("检测到登录失败次数过多,暂停 60 秒避免封禁");
- sleep(60);
- } else {
- sleep($retryDelay);
- }
- }
-
- if (!$inbox) {
- $output->writeln("最终仍然连接失败:" . imap_last_error() . "");
- return Command::FAILURE;
- }
-
- // 拉取 UID 并入库
- $output->writeln("开始拉取 UID 并入库 …");
- $uids = imap_search($inbox, 'ALL', SE_UID) ?: [];
-
- $uids = array_filter($uids, function($uid) use ($maxUid) {
- return $uid > $maxUid;
- });
-
- sort($uids);
- $now = time();
- $count = 0;
-
- foreach ($uids as $uid) {
- try {
- Db::table('email_uids')->insert([
- 'uid' => $uid,
- 'fetched_at' => $now,
- 'email' => $cfg['username']
- ]);
- $count++;
-
- $output->writeln("UID:".$uid." 已写入数据库");
- } catch (\Throwable $e) {
- $output->writeln("{$e->getMessage()}");
- }
- }
-
- imap_close($inbox);
- $output->writeln(date('Y-m-d H:i:s').":共拉到 {$count} 个 UID 并写入 email_uids 表。");
- return Command::SUCCESS;
- } catch (\Throwable $th) {
- dpr($th);
- return Command::FAILURE;
- }
- }
-}
-
-/**
- * 获取指定格式的日期字符串
- *
- * @param string|null $input_date 可选,指定的日期(可以是任何PHP可解析的日期格式)
- * @return string 返回格式为 'd-M-Y' 的日期字符串(如 '28-Jul-2025')
- */
-function getImapFormattedDate($input_date = null) {
- // 如果有传入日期参数,尝试解析
- if ($input_date !== null) {
- $timestamp = strtotime($input_date);
- if ($timestamp === false) {
- // 如果日期解析失败,使用当前日期并记录警告
- trigger_error("无法解析提供的日期: '$input_date',将使用当前日期", E_USER_WARNING);
- $timestamp = time();
- }
- } else {
- // 如果没有提供日期,使用当前日期
- $timestamp = time();
- }
-
- // 格式化为 IMAP 需要的日期格式 (如 '28-Jul-2025')
- return date('d-M-Y', $timestamp);
-}
-
-// // 使用示例
-// echo getImapFormattedDate(); // 输出当天的日期,如 '31-Jul-2025'
-// echo getImapFormattedDate('2025-07-28'); // 输出 '28-Jul-2025'
-// echo getImapFormattedDate('28/07/2025'); // 输出 '28-Jul-2025'
-// echo getImapFormattedDate('next Monday'); // 输出下个周一的日期
-
-/*
-
-// imap_search() 条件
-
-// 1. 基本日期搜索(按接收日期)
-// 搜索今天收到的邮件
-$today = date("d-M-Y");
-$uids = imap_search($inbox, 'SINCE "' . $today . '"', SE_UID);
-
-// 搜索特定日期之后的邮件
-$since_date = '15-Jul-2023';
-$uids = imap_search($inbox, 'SINCE "' . $since_date . '"', SE_UID);
-
-// 搜索特定日期之前的邮件
-$before_date = '20-Jul-2023';
-$uids = imap_search($inbox, 'BEFORE "' . $before_date . '"', SE_UID);
-
-// 搜索特定日期的邮件
-$on_date = '18-Jul-2023';
-$uids = imap_search($inbox, 'ON "' . $on_date . '"', SE_UID);
-
-// 2. 日期范围搜索
-// 搜索2023年7月15日到2023年7月20日之间的邮件
-$start_date = '15-Jul-2023';
-$end_date = '20-Jul-2023';
-$uids = imap_search($inbox, 'SINCE "' . $start_date . '" BEFORE "' . $end_date . '"', SE_UID);
-
-// 3. 结合日期和其他条件
-// 搜索2023年7月以后未读的邮件
-$date = '1-Jul-2023';
-$uids = imap_search($inbox, 'SINCE "' . $date . '" UNSEEN', SE_UID);
-
-// 搜索2023年7月来自某人的邮件
-$date = '1-Jul-2023';
-$from = 'example@domain.com';
-$uids = imap_search($inbox, 'SINCE "' . $date . '" FROM "' . $from . '"', SE_UID);
-
-// 4. 日期格式注意事项
-// - IMAP日期格式通常为 d-M-Y,例如 15-Jul-2023
-// - 月份使用英文缩写(Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)
-// - 日期格式必须用双引号括起来
-
-所有ID
-imap_search($inbox, 'ALL', SE_UID)
-
-*/
\ No newline at end of file
diff --git a/app/command/FinanceRecoCommand.php b/app/command/FinanceRecoCommand.php
deleted file mode 100644
index 1406ab9..0000000
--- a/app/command/FinanceRecoCommand.php
+++ /dev/null
@@ -1,32 +0,0 @@
-generatePrivateUrl('fdesk_test/20251104/20251104_财务.xlsx');;
-
- $service = new \app\common\service\FinanceReconDubaiFilesService();
- $result = $service->dImport('fdesk_test/20251104/20251104_迪拜.xlsx');
-
- return self::SUCCESS;
- }
-}
\ No newline at end of file
diff --git a/app/command/FixInquiryLogOrderNo.php b/app/command/FixInquiryLogOrderNo.php
deleted file mode 100644
index 91d3c04..0000000
--- a/app/command/FixInquiryLogOrderNo.php
+++ /dev/null
@@ -1,103 +0,0 @@
-writeln('Starting duplicate order_no fix process...');
-
- // Find all duplicate order_no values using Laravel-style query
- $duplicates = Db::table('inquiry_log')
- ->select('order_no', Db::raw('COUNT(*) as count'))
- ->groupBy('order_no')
- ->having('count', '>', 1)
- ->get();
-
- if ($duplicates->isEmpty()) {
- $output->writeln('No duplicate order_no values found.');
- Db::commit();
- return self::SUCCESS;
- }
-
- $output->writeln(sprintf('Found %d order_no values with duplicates.', $duplicates->count()));
-
- $totalFixed = 0;
-
- foreach ($duplicates as $dup) {
- $orderNo = $dup->order_no;
-
- $output->writeln("Processing duplicates for order_no: {$orderNo}");
-
- // Get all records with this order_no, ordered by created_at (oldest first)
- $records = Db::table('inquiry_log')
- ->where('order_no', $orderNo)
- ->orderBy('created_at', 'asc')
- ->get();
-
- // Keep the first record as is, modify the rest
- $keepOriginal = true;
-
- foreach ($records as $record) {
- if ($keepOriginal) {
- $output->writeln("Keeping original record ID {$record->id} with order_no {$record->order_no}");
- $keepOriginal = false;
- continue;
- }
-
- // Generate new order_no by appending suffix
- $newOrderNo = orderNum();
- $output->writeln("Updating record ID {$record->id} from {$record->order_no} to {$newOrderNo}");
-
- // Update the record
- Db::table('inquiry_log')
- ->where('id', $record->id)
- ->update(['order_no' => $newOrderNo]);
-
- $totalFixed++;
-
- sleep(1);
- }
- }
-
- Db::commit();
- $output->writeln("Successfully fixed {$totalFixed} duplicate records.");
-
- // Verify no duplicates remain
- $remainingDuplicates = Db::table('inquiry_log')
- ->select('order_no', Db::raw('COUNT(*) as count'))
- ->groupBy('order_no')
- ->having('count', '>', 1)
- ->get();
-
- if ($remainingDuplicates->isEmpty()) {
- $output->writeln('Verification: No duplicate order_no values remain.');
- } else {
- $output->writeln('Warning: Some duplicates still remain. Please run the command again.');
- }
-
- return self::SUCCESS;
- } catch (\Throwable $e) {
- Db::rollback();
- $output->writeln("Error: " . $e->getMessage());
- Log::error("FixInquiryLogOrderNo command failed: " . $e->getMessage());
- return self::FAILURE;
- }
- }
-}
\ No newline at end of file
diff --git a/app/command/ImportCustomerCommand.php b/app/command/ImportCustomerCommand.php
deleted file mode 100644
index 61551ac..0000000
--- a/app/command/ImportCustomerCommand.php
+++ /dev/null
@@ -1,178 +0,0 @@
-addArgument('file', InputArgument::REQUIRED, 'Excel文件路径')
-// ->addOption('user-id', 'u', InputOption::VALUE_REQUIRED, '用户ID', 0)
-// ->addOption('channel-id', 'c', InputOption::VALUE_REQUIRED, '渠道ID', 5)
-// ->addOption('corp-abbr', 'a', InputOption::VALUE_REQUIRED, '公司缩写', 2);
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
-// $filePath = $input->getArgument('file');
-// $userId = $input->getOption('user-id');
-// $channelId = $input->getOption('channel-id');
-// $corpAbbr = $input->getOption('corp-abbr');
- $filePath = 'C:\Users\16961\Downloads\中国制造 2023-2025-询盘导出.xls';
- $userId = 0;
- $channelId = 5;
- $corpAbbr = 2;
-
- // 检查文件是否存在
- if (!file_exists($filePath)) {
- $output->writeln("文件不存在: {$filePath}");
- return self::FAILURE;
- }
-
- try {
- $output->writeln("开始导入文件: {$filePath}");
-
- // 加载Excel文件
- $output->writeln("正在加载Excel文件...");
- $spreadsheet = IOFactory::load($filePath);
- $worksheet = $spreadsheet->getActiveSheet();
- $output->writeln("Excel文件加载成功");
-
- // 获取数据范围
- $highestRow = $worksheet->getHighestRow();
- $highestColumn = $worksheet->getHighestColumn();
-
- $output->writeln("文件包含 {$highestRow} 行数据");
-
- // 获取所有国家数据,用于匹配
- $output->writeln("正在获取国家数据...");
-// $countries = Country::select('id', 'cn_addr', 'en_addr')->get()->keyBy(function($item) {
-// return strtolower(trim($item->cn_addr));
-// });
-// $output->writeln("获取到 " . $countries->count() . " 个国家数据");
-
- $successCount = 0;
- $errorCount = 0;
- $errors = [];
-
- // 从第二行开始读取数据(第一行是标题)
- $output->writeln("开始读取Excel数据...");
- for ($row = 2; $row <= $highestRow; $row++) {
- try {
- $output->writeln("正在处理第 {$row} 行...");
-
- // 读取各列数据 - 使用坐标方法
- try {
- $countryName = trim($worksheet->getCell('B' . $row)->getValue() ?? '');
- $contacts = trim($worksheet->getCell('A' . $row)->getValue() ?? '');
- $email = trim($worksheet->getCell('C' . $row)->getValue() ?? '');
- $phone = trim($worksheet->getCell('D' . $row)->getValue() ?? '');
- $inquiryProduct = trim($worksheet->getCell('E' . $row)->getValue() ?? '');
- } catch (\Exception $cellError) {
- $output->writeln("读取第{$row}行单元格时出错: " . $cellError->getMessage() . "");
- continue;
- }
-
- $output->writeln("读取数据: 国家={$countryName}, 客户={$contacts}, 产品={$inquiryProduct}");
-
- // 跳过空行
-// if (empty($contacts)) {
-// continue;
-// }
-
- // 查找国家ID
- $countryId = 0;
-// if (!empty($countryName)) {
-// $countryKey = strtolower($countryName);
-// if ($countries->has($countryKey)) {
-// $countryId = $countries->get($countryKey)->id;
-// } else {
-// // 尝试英文名称匹配
-// $countryByEn = $countries->first(function($item) use ($countryName) {
-// return strtolower(trim($item->en_addr)) === strtolower($countryName);
-// });
-// if ($countryByEn) {
-// $countryId = $countryByEn->id;
-// }
-// }
-// }
-
- // 检查是否已存在相同客户名
-// $existingCustomer = Customer::where('contacts', $customerName)->first();
-// if ($existingCustomer) {
-// $output->writeln("跳过已存在的客户: {$customerName}");
-// continue;
-// }
-
- // 创建客户记录
-// $customerData = [
-// 'user_id' => $userId,
-// 'corp_abbr' => $corpAbbr,
-// 'channel_id' => $channelId,
-// 'country_id' => $countryId,
-// 'contacts' => $customerName,
-// 'email' => $email,
-// 'phone' => $phone,
-// 'desc_collect' => $inquiryProduct,
-// 'grade' => 0, // 默认等级
-// 'magnitude' => 1, // 默认商机
-// 'type' => 1, // 默认类型
-// 'sex' => 0, // 默认性别
-// 'enter_user_id' => $userId,
-// ];
- $where = [
- ['id', '<', 28110],
- ['id', '>', 25714],
- ];
- $customer = Customer::where('contacts',$email)->where($where)->first();
- $customer->email = $email;
- $customer->phone = $phone;
- $customer->contacts = $contacts;
- $customer->save();
- $successCount++;
-
- $output->writeln("成功导入客户: {$contacts} (ID: {$customer->id})");
-
- } catch (\Exception $e) {
- $errorCount++;
- $errorMsg = "第{$row}行导入失败: " . $e->getMessage();
- $errorMsg .= "\n文件: " . $e->getFile() . " 行: " . $e->getLine();
- $errorMsg .= "\n堆栈: " . $e->getTraceAsString();
- $errors[] = $errorMsg;
- $output->writeln("{$errorMsg}");
- }
- }
-
- $output->writeln("\n导入完成!");
- $output->writeln("成功导入: {$successCount} 条记录");
- $output->writeln("失败: {$errorCount} 条记录");
-
- if (!empty($errors)) {
- $output->writeln("\n错误详情:");
- foreach ($errors as $error) {
- $output->writeln("{$error}");
- }
- }
-
- return self::SUCCESS;
-
- } catch (\Exception $e) {
- $output->writeln("导入过程中发生错误: " . $e->getMessage() . "");
- $output->writeln("文件: " . $e->getFile() . " 行: " . $e->getLine() . "");
- $output->writeln("堆栈: " . $e->getTraceAsString() . "");
- return self::FAILURE;
- }
- }
-}
\ No newline at end of file
diff --git a/app/command/InitUserPasswordCommand.php b/app/command/InitUserPasswordCommand.php
deleted file mode 100644
index bdf76b5..0000000
--- a/app/command/InitUserPasswordCommand.php
+++ /dev/null
@@ -1,34 +0,0 @@
-orWhere('password', '')->get();
- $count = 0;
-
- foreach ($users as $user) {
- if (!empty($user->sn)) {
- $user->password = password_hash($user->sn, PASSWORD_DEFAULT);
- $user->save();
- $output->writeln("用户ID {$user->id} 密码已初始化");
- $count++;
- } else {
- $output->writeln("用户ID {$user->id} 的sn字段为空,无法初始化密码");
- }
- }
-
- $output->writeln("共初始化 {$count} 个用户密码");
- return self::SUCCESS;
- }
-}
\ No newline at end of file
diff --git a/app/command/TbCommand.php b/app/command/TbCommand.php
deleted file mode 100644
index 265d24c..0000000
--- a/app/command/TbCommand.php
+++ /dev/null
@@ -1,36 +0,0 @@
-all();
-
- // foreach ($list as $item) {
- // // UserSn::where('user_sn', $item->sn)->update(['user_id' => $item->id]);
- // }
-
- $m = new Emails();
- $m->fenpai();
-
- return self::SUCCESS;
- }
-}
\ No newline at end of file
diff --git a/app/command/UpdateInquiryLogFromCrmCustomerCommand.php b/app/command/UpdateInquiryLogFromCrmCustomerCommand.php
deleted file mode 100644
index 06afbc0..0000000
--- a/app/command/UpdateInquiryLogFromCrmCustomerCommand.php
+++ /dev/null
@@ -1,144 +0,0 @@
-setHelp('该命令将crm_customer表的user_id更新到inquiry_log表的recipient字段,将obtain字段更新到t_time字段。')
- ->addOption('dry-run', null, InputOption::VALUE_NONE, '仅显示将要执行的更新操作,不实际执行')
- ->addOption('limit', 'l', InputOption::VALUE_OPTIONAL, '限制处理的记录数量', 5000);
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $isDryRun = $input->getOption('dry-run');
- $limit = (int) $input->getOption('limit');
-
- if ($isDryRun) {
- $output->writeln('DRY RUN 模式 - 不会实际执行更新操作');
- }
-
- $output->writeln('开始更新 inquiry_log 表...');
- $output->writeln("处理限制: {$limit} 条记录");
-
- try {
- // 使用事务确保数据一致性
- DB::transaction(function () use ($output, $isDryRun, $limit) {
- // 查询需要更新的记录
- $customers = Db::table('crm_customer')
- ->select('id', 'sn', 'user_id', 'obtain','created_at')
- ->whereNotNull('sn')
- ->where('sn', '<>', '')
- ->offset($limit)
- ->limit(4000)
- ->orderBy('id', 'asc')
- ->get();
-
- $output->writeln("找到 " . count($customers) . " 条客户记录需要处理");
-
- $updatedCount = 0;
- $skippedCount = 0;
- $defaultTimestamp = strtotime('2025-08-26 00:00:00');
-
- $output->writeln("找到 " . count($customers) . " 条客户记录需要处理");
- $step = [];
- $updateId = [];
- foreach ($customers as $customer) {
- $output->writeln("处理客户 ID: {$customer->id}, SN: {$customer->sn}, User ID: {$customer->user_id}, obtain: {$customer->obtain}, created_at: {$customer->created_at}");
- // 查找匹配的 inquiry_log 记录
- $inquiryLog = Db::table('inquiry_log')
- ->where('order_no', $customer->sn)
- ->first(['id', 'recipient', 't_time']);
-
- if (!$inquiryLog) {
- $step[] = $customer->id;
- $output->writeln("跳过客户 ID {$customer->id} (sn: {$customer->sn}) - 未找到对应的 inquiry_log 记录");
- $skippedCount++;
- continue;
- }
- $output->writeln("$inquiryLog->id");
-
- // 准备更新数据
- $updateData = [];
-
- // 更新 recipient 字段 (user_id)
- if ($customer->user_id != $inquiryLog->recipient) {
- $updateData['recipient'] = $customer->user_id;
- $output->writeln("客户 ID {$customer->id}: recipient 将从 {$inquiryLog->recipient} 更新为 {$customer->user_id}");
- }
-
- if(empty($customer->obtain)&& !empty($customer->user_id)){
- if($customer->user_id == $inquiryLog->recipient){
- $obtain = $inquiryLog->t_time;
- }else{
- $obtain = strtotime('2025-08-01 10:00:00');
- $obtain = $customer->created_at > $obtain?$customer->created_at:$obtain;
- }
- Db::table('crm_customer')
- ->where('id', $customer->id)
- ->update(['obtain' => $obtain]);
- $output->writeln("更新obtain $obtain");
- }
-
- // 更新 t_time 字段 (obtain)
- $newTTime = $customer->obtain > 0 ? $customer->obtain : $defaultTimestamp;
- if ($newTTime != $inquiryLog->t_time && !empty($updateData['recipient'])) {
- $updateData['t_time'] = $newTTime;
- $timeStr = date('Y-m-d H:i:s', $newTTime);
- $output->writeln("客户 ID {$customer->id}: t_time 将从 " . ($inquiryLog->t_time ? date('Y-m-d H:i:s', $inquiryLog->t_time) : 'NULL') . " 更新为 {$timeStr}");
- }
- if($customer->user_id == 0 && $inquiryLog->recipient != 0){
- $updateData['recipient'] = 0;
- $updateData['t_time'] = time();
- $updateData['status'] = 1;
- $updateData['r_time'] = time();
-
- }
-
- // 如果有需要更新的字段,执行更新
- if (!empty($updateData)) {
- $updateId[] = $customer->id;
- if (!$isDryRun) {
- Db::table('inquiry_log')
- ->where('id', $inquiryLog->id)
- ->update($updateData);
- }
- $updatedCount++;
- $output->writeln("已更新 inquiry_log ID {$inquiryLog->id}");
- } else {
- $output->writeln("客户 ID {$customer->id} - 无需更新");
- }
- }
-
- $output->writeln("处理完成!");
- $output->writeln("总记录数: " . count($customers) . "");
- $updateIdstr = implode(",", $updateId);
- $output->writeln("更新记录数: {$updatedCount},更新id:$updateIdstr");
- $stepstr = implode(",", $step);
- $output->writeln("跳过记录数: {$skippedCount},跳过id: {$stepstr}");
-
- if ($isDryRun) {
- $output->writeln("DRY RUN 模式 - 未实际执行任何更新操作");
- }
- });
-
- return self::SUCCESS;
- } catch (\Exception $e) {
- $output->writeln('执行过程中发生错误: ' . $e->getMessage() . '');
- $output->writeln('错误位置: ' . $e->getFile() . ':' . $e->getLine() . '');
- return self::FAILURE;
- }
- }
-}
\ No newline at end of file
diff --git a/app/command/VehMoneyCommand.php b/app/command/VehMoneyCommand.php
deleted file mode 100644
index 0485e09..0000000
--- a/app/command/VehMoneyCommand.php
+++ /dev/null
@@ -1,29 +0,0 @@
-header('host');
+ $baseUrl = 'http://' . request()->header('host');
$url = $baseUrl . '/pdf/' . $raw['pdf_src'];
return $this->success([
diff --git a/app/common/utils/pdf/template/usedCar.stub b/app/common/utils/pdf/template/usedCar.stub
index c77f415..398986c 100644
--- a/app/common/utils/pdf/template/usedCar.stub
+++ b/app/common/utils/pdf/template/usedCar.stub
@@ -103,6 +103,11 @@
+车况介绍
+
+ = nl2br(htmlspecialchars($car['condition_desc'])) ?>
+
+
产品图
@@ -112,10 +117,5 @@
-车况介绍
-
- = nl2br(htmlspecialchars($car['condition_desc'])) ?>
-
-