From 847303a8faae84c6856ed13acee071e74d79f775 Mon Sep 17 00:00:00 2001 From: mzl Date: Mon, 1 Sep 2025 10:08:51 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=B1=BD=E8=BD=A6=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VehDictI18nController.php | 33 ++ .../controller/VehDictMappingController.php | 33 ++ .../VehVehicleListingController.php | 33 ++ .../controller/VehVehicleSkuController.php | 204 ++++++++++ .../controller/VehVehicleUnitController.php | 33 ++ app/common/logic/Fingerprint.php | 262 +++++++++++++ app/common/logic/ModelNaming.php | 101 +++++ app/common/logic/SkuCodeBuilder.php | 233 ++++++++++++ app/common/logic/VehDictI18nLogic.php | 17 + app/common/logic/VehDictMappingLogic.php | 17 + app/common/logic/VehVehicleListingLogic.php | 17 + app/common/logic/VehVehicleSkuLogic.php | 55 +++ app/common/logic/VehVehicleUnitLogic.php | 17 + app/common/model/VehDictI18n.php | 49 +++ app/common/model/VehDictMapping.php | 52 +++ app/common/model/VehVehicleListing.php | 49 +++ app/common/model/VehVehicleSku.php | 81 ++++ app/common/model/VehVehicleUnit.php | 49 +++ app/common/service/VehDictI18nService.php | 75 ++++ app/common/service/VehDictMappingService.php | 57 +++ .../service/VehVehicleListingService.php | 31 ++ app/common/service/VehVehicleSkuService.php | 349 ++++++++++++++++++ app/common/service/VehVehicleUnitService.php | 31 ++ app/common/utils/scaffold/Generate.php | 8 +- app/common/validate/VehDictI18nValidate.php | 29 ++ .../validate/VehDictMappingValidate.php | 29 ++ .../validate/VehVehicleListingValidate.php | 29 ++ app/common/validate/VehVehicleSkuValidate.php | 128 +++++++ .../validate/VehVehicleUnitValidate.php | 29 ++ app/controller/IndexController.php | 12 +- app/functions.php | 23 ++ app/queue/redis/InquiryToCrm.php | 110 ------ app/queue/redis/InquiryToCrmUpdate.php | 110 ------ config/route.php | 12 + 34 files changed, 2167 insertions(+), 230 deletions(-) create mode 100644 app/common/controller/VehDictI18nController.php create mode 100644 app/common/controller/VehDictMappingController.php create mode 100644 app/common/controller/VehVehicleListingController.php create mode 100644 app/common/controller/VehVehicleSkuController.php create mode 100644 app/common/controller/VehVehicleUnitController.php create mode 100644 app/common/logic/Fingerprint.php create mode 100644 app/common/logic/ModelNaming.php create mode 100644 app/common/logic/SkuCodeBuilder.php create mode 100644 app/common/logic/VehDictI18nLogic.php create mode 100644 app/common/logic/VehDictMappingLogic.php create mode 100644 app/common/logic/VehVehicleListingLogic.php create mode 100644 app/common/logic/VehVehicleSkuLogic.php create mode 100644 app/common/logic/VehVehicleUnitLogic.php create mode 100644 app/common/model/VehDictI18n.php create mode 100644 app/common/model/VehDictMapping.php create mode 100644 app/common/model/VehVehicleListing.php create mode 100644 app/common/model/VehVehicleSku.php create mode 100644 app/common/model/VehVehicleUnit.php create mode 100644 app/common/service/VehDictI18nService.php create mode 100644 app/common/service/VehDictMappingService.php create mode 100644 app/common/service/VehVehicleListingService.php create mode 100644 app/common/service/VehVehicleSkuService.php create mode 100644 app/common/service/VehVehicleUnitService.php create mode 100644 app/common/validate/VehDictI18nValidate.php create mode 100644 app/common/validate/VehDictMappingValidate.php create mode 100644 app/common/validate/VehVehicleListingValidate.php create mode 100644 app/common/validate/VehVehicleSkuValidate.php create mode 100644 app/common/validate/VehVehicleUnitValidate.php delete mode 100644 app/queue/redis/InquiryToCrm.php delete mode 100644 app/queue/redis/InquiryToCrmUpdate.php diff --git a/app/common/controller/VehDictI18nController.php b/app/common/controller/VehDictI18nController.php new file mode 100644 index 0000000..6a87c9f --- /dev/null +++ b/app/common/controller/VehDictI18nController.php @@ -0,0 +1,33 @@ +service = new VehDictI18nService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/common/controller/VehDictMappingController.php b/app/common/controller/VehDictMappingController.php new file mode 100644 index 0000000..d1a1dfe --- /dev/null +++ b/app/common/controller/VehDictMappingController.php @@ -0,0 +1,33 @@ +service = new VehDictMappingService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/common/controller/VehVehicleListingController.php b/app/common/controller/VehVehicleListingController.php new file mode 100644 index 0000000..59d49aa --- /dev/null +++ b/app/common/controller/VehVehicleListingController.php @@ -0,0 +1,33 @@ +service = new VehVehicleListingService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/common/controller/VehVehicleSkuController.php b/app/common/controller/VehVehicleSkuController.php new file mode 100644 index 0000000..b99cacb --- /dev/null +++ b/app/common/controller/VehVehicleSkuController.php @@ -0,0 +1,204 @@ +service = new VehVehicleSkuService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } + + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } + + + public function store(Request $request) + { + try { + $data = $this->validate($this->service->getValidator(), $request->post(), 'store'); + $res = $this->service->serviceStore($request, $data); + return $this->success($res, '创建成功'); + } catch (\PDOException $e) { + $errorCode = $e->getCode(); + $errorMessage = $e->getMessage(); + if ($errorCode == '23000') { + if (strpos($errorMessage, "Duplicate entry") !== false && strpos($errorMessage, "uk_fingerprint") !== false) { + return $this->error("该车辆指纹已存在,请勿重复提交"); + } + // 其他类型的完整性约束错误 + throw new BusinessException("数据完整性错误", 0, $e); + } + // 重新抛出其他类型的异常 + throw $e; + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function update(Request $request) + { + try { + $data = $this->validate($this->service->getValidator(), $request->post(), 'update'); + $res = $this->service->serviceUpdate($request, $data); + return $this->success([], '更新成功'); + } catch (\PDOException $e) { + $errorCode = $e->getCode(); + $errorMessage = $e->getMessage(); + if ($errorCode == '23000') { + if (strpos($errorMessage, "Duplicate entry") !== false && strpos($errorMessage, "uk_fingerprint") !== false) { + return $this->error("该车辆指纹已存在,请勿重复提交"); + } + // 其他类型的完整性约束错误 + throw new BusinessException("数据完整性错误", 0, $e); + } + // 重新抛出其他类型的异常 + throw $e; + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + + public function index(Request $request) + { + $data = [ + 'sku_code' , // 'SKU编码,系统生成', + 'fingerprint' , // '规格指纹(sha256)去重', + 'brand_code' , // '品牌代码,如 BYD、HYUNDAI、KIA', + 'brand_name' , // '品牌名称展示,如 比亚迪、现代、起亚', + 'series_code' , // '车系代码,如 ELANTRA、SONGPLUS', + 'series_name' , // '车系名称展示', + 'model_code' , // '车型/配置代码(工厂/内部编码)', + 'model_name' , // '车型/配置名称(可读,如 伊兰特 1.5L、海狮07)', + 'model_year' , // '年款(YYYY)', + 'trim_code' , // '版型代码(TRIM)', + 'trim_level_code' , // '配置等级代码(TRIM_LEVEL)', + 'edition_code' , // '特别版代码(EDITION)', + 'trim' , // '版型/细分配置(如 TOP旗舰版、荣耀版)', + 'trim_level' , // '配置等级(豪华型/旗舰型等,便于筛选)', + 'edition_name' , // '特别版/纪念版(如 荣耀版、致敬版等)', + 'body_type_code' , // '车身类型:SEDAN/SUV/HB/MPV/Pickup', + 'drive_type_code' , // '驱动:FWD/RWD/AWD/4WD', + 'motor_layout_code' , // '电驱/电机布置(MOTOR_LAYOUT):FWD/RWD/AWD/DM-i/DM-p 等', + 'fuel_type_code' , // '能源:GAS/HEV/PHEV/EV/EREV', + 'engine_disp_l' , // '排量(L),如 1.5;纯电为空', + 'engine_turbo' , // '0' COMMENT '是否涡轮(0/1)', + 'engine_power_kw' , // '最大功率(kW)', + 'battery_kwh' , // '电池容量(kWh)', + 'transmission_code' , // '变速箱:MT/AT/CVT/DCT/1SPEED', + 'gears' , // '挡位数(EV多为1)', + 'range_km' , // '续航里程(km)', + 'range_std_code' , // '续航标准:CLTC/WLTP/EPA/NEDC', + 'doors' , // '门数', + 'seats' , // '座位数', + 'weight_kg' , // '整备质量(kg)', + 'dimensions_mm' , // '尺寸(mm):{length,width,height,wheelbase}', + 'color_exterior_code' , // '外观色代码', + 'color_exterior_text' , // '外观色名称', + 'color_interior_code' , // '内饰色代码', + 'color_interior_text' , // '内饰色名称', + 'options_official' , // '官方选装(结构化 JSON)', + 'features' , // '功能/安全/智能配置(结构化 JSON)', + 'emission_std_code' , // '排放标准:CHN6/EURO6/EPA', + 'origin_country' , // '原产国 ISO-3166-1 alpha-2', + 'currency' , // 'CNY' COMMENT '币种 ISO-4217', + 'msrp' , // '建议零售价/参考价', + 'is_active' , // '1' COMMENT '启用(1)/禁用(0)', + 'corp_id' , // '0' COMMENT '租户/公司(全局库可写0)', + 'remark' , // '备注', + 'created_by' , // '0', + 'updated_by' , // '0', + ]; + + + $data = [ + 'fingerprint' , // '规格指纹(sha256)去重', + 'brand_name' , // '品牌名称展示,如 比亚迪、现代、起亚', + 'series_name' , // '车系名称展示', + 'model_name' , // '车型/配置名称(可读,如 伊兰特 1.5L、海狮07)', + 'model_year' , // '年款(YYYY)', + 'trim' , // '版型/细分配置(如 TOP旗舰版、荣耀版)', + 'trim_level' , // '配置等级(豪华型/旗舰型等,便于筛选)', + 'edition_name' , // '特别版/纪念版(如 荣耀版、致敬版等)', + 'engine_disp_l' , // '排量(L),如 1.5;纯电为空', + 'engine_turbo' , // '0' COMMENT '是否涡轮(0/1)', + 'engine_power_kw' , // '最大功率(kW)', + 'battery_kwh' , // '电池容量(kWh)', + 'gears' , // '挡位数(EV多为1)', + 'range_km' , // '续航里程(km)', + 'doors' , // '门数', + 'seats' , // '座位数', + 'weight_kg' , // '整备质量(kg)', + 'dimensions_mm' , // '尺寸(mm):{length,width,height,wheelbase}', + 'color_exterior_text' , // '外观色名称', + 'color_interior_text' , // '内饰色名称', + 'options_official' , // '官方选装(结构化 JSON)', + 'features' , // '功能/安全/智能配置(结构化 JSON)', + 'origin_country' , // '原产国 ISO-3166-1 alpha-2', + 'currency' , // 'CNY' COMMENT '币种 ISO-4217', + 'msrp' , // '建议零售价/参考价', + 'is_active' , // '1' COMMENT '启用(1)/禁用(0)', + 'corp_id' , // '0' COMMENT '租户/公司(全局库可写0)', + 'remark' , // '备注', + 'created_by' , // '0', + 'updated_by' , // '0', + + 'body_type', // '车身类型' + 'drive_type', // '驱动:FWD/RWD/AWD/4WD', + 'motor_layout', // '电机布置(MOTOR_LAYOUT):FWD/RWD/AWD/DM-i/DM-p 等' + 'fuel_type', // '能源:GAS/HEV/PHEV/EV/EREV' + 'transmission', // '变速箱:MT/AT/CVT/DCT/1SPEED' + 'range_std', // '续航标准:CLTC/WLTP/EPA/NEDC' + 'emission_std', // '排放标准:CHN6/EURO6/EPA' + + 'sku_code' , // 'SKU编码,系统生成', + 'brand_code' , // '品牌代码,如 BYD、HYUNDAI、KIA', + 'series_code' , // '车系代码,如 ELANTRA、SONGPLUS', + 'model_code' , // '车型/配置代码(工厂/内部编码)', + 'trim_code' , // '版型代码(TRIM)', + 'trim_level_code' , // '配置等级代码(TRIM_LEVEL)', + 'edition_code' , // '特别版代码(EDITION)', + 'color_exterior_code' , // '外观色代码', + 'color_interior_code' , // '内饰色代码', + + 'body_type_code' , // '车身类型:SEDAN/SUV/HB/MPV/Pickup', + 'drive_type_code' , // '驱动:FWD/RWD/AWD/4WD', + 'motor_layout_code' , // '电驱/电机布置(MOTOR_LAYOUT):FWD/RWD/AWD/DM-i/DM-p 等', + 'fuel_type_code' , // '能源:GAS/HEV/PHEV/EV/EREV', + 'transmission_code' , // '变速箱:MT/AT/CVT/DCT/1SPEED', + 'range_std_code' , // '续航标准:CLTC/WLTP/EPA/NEDC', + 'emission_std_code' , // '排放标准:CHN6/EURO6/EPA', + ]; + } +} \ No newline at end of file diff --git a/app/common/controller/VehVehicleUnitController.php b/app/common/controller/VehVehicleUnitController.php new file mode 100644 index 0000000..3d2e7e2 --- /dev/null +++ b/app/common/controller/VehVehicleUnitController.php @@ -0,0 +1,33 @@ +service = new VehVehicleUnitService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/common/logic/Fingerprint.php b/app/common/logic/Fingerprint.php new file mode 100644 index 0000000..a066ada --- /dev/null +++ b/app/common/logic/Fingerprint.php @@ -0,0 +1,262 @@ +['msrp']]); // 可选排除 + */ +class Fingerprint +{ + /** 你的 veh_vehicle_sku 所有列(保持与表结构一致,顺序无关但建议完整) */ + public const COLS = [ + 'id','sku_code','fingerprint', + 'brand_code','brand_name','series_code','series_name', + 'model_code','model_name','model_year', + 'trim_code','trim_level_code','edition_code', + 'trim','trim_level','edition_name', + 'body_type_code','drive_type_code','motor_layout_code','fuel_type_code', + 'engine_disp_l','engine_turbo','engine_power_kw','battery_kwh', + 'transmission_code','gears','range_km','range_std_code', + 'doors','seats','weight_kg','dimensions_mm', + 'color_exterior_code','color_exterior_text', + 'color_interior_code','color_interior_text', + 'options_official','features','emission_std_code', + 'origin_country','currency','msrp', + 'is_active','corp_id','remark', + 'created_by','updated_by','created_at','updated_at', + ]; + + /** 默认剔除:技术/循环依赖字段 */ + public const EXCLUDE_DEFAULT = [ + 'id','sku_code','fingerprint', 'dimensions_mm', 'options_official', 'features', + 'origin_country','currency','msrp', + 'is_active','corp_id','remark', + 'created_by','updated_by','created_at','updated_at' + ]; + + /** 识别为“code类”的字段模式(统一大写) */ + private const CODE_FIELD_REGEX = '/(_code|_country|^currency)$/i'; + + /** 识别为 JSON 字段 */ + private const JSON_FIELDS = ['dimensions_mm','options_official','features']; + + /** + * 从 Eloquent 模型生成 + */ + public static function makeFromModel($model, array $opts = []): string + { + return self::makeFromArray($model->toArray(), $opts); + } + + /** + * 从数组生成指纹 + * @param array $row 一般为 $_POST 合并后的业务数据或 $model->toArray() + * @param array $opts ['exclude'=>[], 'extra'=>[], 'salt'=>string] + * - exclude: 额外排除的字段(默认仅排除 id,fingerprint) + * - extra : 额外拼入的键值(例如上下文、租户策略),会参与计算 + * - salt : 额外加盐字符串 + */ + public static function makeFromArray(array $row, array $opts = []): string + { + $exclude = array_values(array_unique(array_merge(self::EXCLUDE_DEFAULT, $opts['exclude'] ?? []))); + $extra = $opts['extra'] ?? []; + $salt = $opts['salt'] ?? ''; + + // 1) 统一抽取“表中定义的字段” + extra,缺失字段也要纳入(值按 NULL 处理) + $data = []; + foreach (self::COLS as $col) { + if (in_array($col, $exclude, true)) continue; + $data[$col] = array_key_exists($col, $row) ? $row[$col] : null; + } + // extra 也参与 + foreach ($extra as $k => $v) { + if (!is_string($k) || $k === '') continue; + $data['__extra__'.$k] = $v; + } + + // 2) 规范化(按字段特征) + $canon = []; + foreach ($data as $k => $v) { + $canon[$k] = self::normalize($k, $v); + } + + // 3) 键名排序,确保顺序无关 + ksort($canon, SORT_STRING); + + // 4) 拼成稳定串: key=value | key=value... + $parts = []; + foreach ($canon as $k => $v) { + // 为空也必须占位,避免 key 消失影响其他键的意义 + $parts[] = $k.'='.$v; + } + if ($salt !== '') { + $parts[] = '__salt__='.$salt; + } + $plain = implode('|', $parts); + + // 5) sha256 + return hash('sha256', $plain); + } + + /** + * 规范化单个字段 + * - NULL -> 特殊占位 "∅"(避免与空串混淆) + * - 布尔/整数/浮点 -> 统一数字字符串 + * - code类字段 -> 去首尾空白 & 转大写 + * - 普通字符串 -> trim & 压缩连续空白为单空格 + * - JSON字段 -> 解析后做“键排序 + 值规范化 + 索引数组可排序”,再无空白编码 + */ + private static function normalize(string $field, $value): string + { + if ($value === null) return '∅'; + + // 数值类型 + if (is_int($value)) return (string)$value; + if (is_bool($value)) return $value ? '1' : '0'; + + if (is_float($value) || (is_string($value) && is_numeric($value) && self::looksLikeNumberField($field))) { + // 统一浮点格式,最多 6 位小数并去尾零 + $num = (float)$value; + $s = number_format($num, 6, '.', ''); + $s = rtrim(rtrim($s, '0'), '.'); + return $s === '' ? '0' : $s; + } + + // JSON 字段 + if (in_array($field, self::JSON_FIELDS, true)) { + return self::normalizeJson($value); + } + + // 字符串 + if (is_string($value)) { + $s = trim($value); + // code类:统一大写 + if (preg_match(self::CODE_FIELD_REGEX, $field)) { + $s = mb_strtoupper($s, 'UTF-8'); + } else { + // 普通文本:压缩连续空白 + $s = preg_replace('/\s+/u', ' ', $s); + } + return $s === '' ? '' : $s; + } + + // 数组(极少出现,按 JSON 处理) + if (is_array($value)) { + return self::normalizeJson($value); + } + + // 其他类型(对象等):转 JSON 后处理 + return self::normalizeJson($value); + } + + /** 判断这个字段是否“看起来像数值字段” */ + private static function looksLikeNumberField(string $field): bool + { + static $numKeys = [ + 'engine_disp_l','engine_power_kw','battery_kwh','gears', + 'range_km','doors','seats','weight_kg','msrp','model_year', + 'created_at','updated_at','corp_id','is_active' + ]; + return in_array($field, $numKeys, true); + } + + /** + * JSON 规范化: + * - 字符串:若能 json_decode 则按 JSON;否则当普通字符串再规范化 + * - 对象:键名排序;值递归规范化 + * - 索引数组:元素递归规范化后,按字符串值排序(视为集合,避免顺序抖动) + * - 最终 json_encode(JSON_UNESCAPED_UNICODE|UNESCAPED_SLASHES) + */ + private static function normalizeJson($val): string + { + // 已是数组/对象 + if (is_array($val)) { + $normalized = self::canonArray($val); + return json_encode($normalized, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + + // 字符串尝试解析 + if (is_string($val)) { + $val = trim($val); + if ($val === '') return '""'; + $decoded = json_decode($val, true); + if (json_last_error() === JSON_ERROR_NONE) { + $normalized = self::canonArray($decoded); + return json_encode($normalized, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + // 非 JSON 字符串,按普通字符串规范化 + $s = preg_replace('/\s+/u', ' ', $val); + return json_encode($s, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + + // 其他类型:直接编码 + return json_encode($val, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + } + + /** 递归规范化数组/对象 */ + private static function canonArray($arr) + { + if (!is_array($arr)) return $arr; + + // 关联数组(对象) + if (self::isAssoc($arr)) { + $out = []; + ksort($arr, SORT_STRING); + foreach ($arr as $k => $v) { + $out[(string)$k] = self::canonValue($v); + } + return $out; + } + + // 索引数组(当集合处理:元素字符串化后排序) + $tmp = []; + foreach ($arr as $v) { + $tmp[] = self::canonValue($v); + } + // 将元素转为字符串再排序,确保稳定 + usort($tmp, function($a, $b) { + $sa = is_scalar($a) ? (string)$a : json_encode($a, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + $sb = is_scalar($b) ? (string)$b : json_encode($b, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + return strcmp($sa, $sb); + }); + return $tmp; + } + + private static function canonValue($v) + { + if (is_array($v)) return self::canonArray($v); + if (is_bool($v)) return $v ? 1 : 0; + if (is_int($v)) return $v; + if (is_float($v)) { + $s = number_format($v, 6, '.', ''); + $s = rtrim(rtrim($s, '0'), '.'); + return $s === '' ? '0' : $s; + } + if (is_string($v)) { + $s = trim($v); + $s = preg_replace('/\s+/u', ' ', $s); + return $s; + } + return $v; + } + + private static function isAssoc(array $arr): bool + { + // 有任意一个键不是 0..n 的递增整数,就视为关联数组 + $i = 0; + foreach ($arr as $k => $_) { + if ($k !== $i++) return true; + } + return false; + } +} \ No newline at end of file diff --git a/app/common/logic/ModelNaming.php b/app/common/logic/ModelNaming.php new file mode 100644 index 0000000..b50a4cf --- /dev/null +++ b/app/common/logic/ModelNaming.php @@ -0,0 +1,101 @@ + 15L + if (!empty($s['engine_turbo']) && (int)$s['engine_turbo'] === 1) $key[] = 'T'; + if (!empty($s['transmission_code'])) $key[] = self::tok($s['transmission_code']); + break; + + case 'HEV': + case 'PHEV': + case 'EREV': + $key[] = $fuel; + if (!empty($s['engine_disp_l'])) $key[] = self::dispToken($s['engine_disp_l']); + if (!empty($s['motor_layout_code'])) $key[] = self::tok($s['motor_layout_code']); // 如 DM-I/DM-P/AWD + break; + + default: + $key[] = $fuel; + } + + if (!empty($s['drive_type_code'])) $key[] = self::tok($s['drive_type_code']); + + $parts[] = implode('_', array_filter($key)); + return strtoupper(implode('_', array_filter($parts))); + } + + /** 生成中文可读的 model_name(走快照中文,不依赖 i18n) */ + public static function buildModelName(array $s): string + { + $seriesName = trim((string)($s['series_name'] ?? $s['series_code'] ?? '')); + $yearPart = !empty($s['model_year']) ? ($s['model_year'] . '款 ') : ''; + + $fuel = strtoupper($s['fuel_type_code'] ?? ''); + $tail = ''; + + if ($fuel === 'EV') { + $range = !empty($s['range_km']) ? (int)$s['range_km'] . 'KM ' : ''; + $drive = trim((string)($s['drive_type'] ?? $s['drive_type_code'] ?? '')); + $tail = "EV {$range}{$drive}"; + } elseif ($fuel === 'GAS') { + $disp = (!empty($s['engine_disp_l'])) + ? rtrim(rtrim(number_format((float)$s['engine_disp_l'], 1, '.', ''), '0'), '.') . 'L ' + : ''; + $trans = trim((string)($s['transmission'] ?? $s['transmission_code'] ?? '')); + $tail = "{$disp}{$trans}"; + } else { + $tail = trim((string)($s['fuel_type'] ?? $fuel)); + } + + $extras = []; + foreach (['trim','trim_level','edition_name'] as $k) { + if (!empty($s[$k])) $extras[] = trim((string)$s[$k]); + } + $extraStr = $extras ? ' ' . implode(' ', $extras) : ''; + + return trim($seriesName . ' ' . $yearPart . $tail . $extraStr); + } + + /* ===== Helpers ===== */ + + private static function tok($v): string + { + $v = strtoupper((string)$v); + return preg_replace('/[^A-Z0-9_]/', '', $v ?? ''); + } + + private static function numToken($v): string + { + return preg_replace('/[^0-9]/', '', (string)$v); + } + + /** 1.5L -> 15L;2.0L -> 20L(便于 code 稳定检索) */ + private static function dispToken($l): string + { + $x = (float)$l; + return (string)round($x * 10) . 'L'; + } +} \ No newline at end of file diff --git a/app/common/logic/SkuCodeBuilder.php b/app/common/logic/SkuCodeBuilder.php new file mode 100644 index 0000000..823b8dc --- /dev/null +++ b/app/common/logic/SkuCodeBuilder.php @@ -0,0 +1,233 @@ + 'FLG', + 'PREMIUM' => 'PRM', + 'STANDARD' => 'STD', + 'DELUXE' => 'DLX', + // edition + 'HONOR' => 'HNR', + 'CHAMPION' => 'CHP', + 'ANNIV' => 'ANV', + // trans + '1SPEED' => '1SP', + // drive/fuel/body 等一般已短,不必压缩 + ]; + + /** 入口:生成 sku_code */ + public static function build(array $s, array $opts = []): string + { + $maxLen = $opts['max_len'] ?? 40; + $ensureUnique = $opts['ensure_unique'] ?? true; + + $tokens = [ + 'brand' => self::tok($s['brand_code'] ?? ''), + 'series' => self::tok($s['series_code'] ?? ''), + 'year' => isset($s['model_year']) ? (string)intval($s['model_year']) : '', + 'fuel' => self::tok($s['fuel_type_code'] ?? ''), + 'drive' => self::tok($s['drive_type_code'] ?? ''), + 'spec' => self::buildSpec($s, self::tok($s['fuel_type_code'] ?? '')), + 'level' => self::abbr(self::tok($s['trim_level_code'] ?? '')), + 'edition' => self::abbr(self::tok($s['edition_code'] ?? '')), + ]; + + // 过滤空段并按既定顺序拼接 + $order = ['brand','series','year','fuel','drive','spec','level','edition']; + $parts = []; + foreach ($order as $k) { + if (!empty($tokens[$k])) $parts[$k] = $tokens[$k]; + } + + $sku = self::normalizeSku(implode('-', $parts)); + + if (strlen($sku) > $maxLen) { + $sku = self::shrink($parts, $maxLen); // 传入“带键名的 parts” + } + + if ($ensureUnique) { + $sku = self::ensureUnique($sku, $maxLen); + } + return $sku; + } + + /** 构造规格位(SPEC),按能源类型差异化 */ + private static function buildSpec(array $s, string $fuel): string + { + $fuel = strtoupper($fuel); + if ($fuel === 'EV') { + if (!empty($s['range_km'])) { + $r = (int)$s['range_km']; + $r10 = (int)round($r / 10) * 10; // 到 10 位 + return (string)$r10; + } + if (!empty($s['battery_kwh'])) { + return self::numToken($s['battery_kwh']) . 'KWH'; + } + return ''; + } + + if ($fuel === 'GAS') { + $bits = []; + if (!empty($s['engine_disp_l'])) { + $bits[] = self::dispToken($s['engine_disp_l']); // 1.5L -> 15L + } + if (!empty($s['engine_turbo']) && intval($s['engine_turbo']) === 1) { + $bits[] = 'T'; + } + if (!empty($s['transmission_code'])) { + $bits[] = self::abbr(self::tok($s['transmission_code'])); + } + return implode('', $bits); // 如 15LTCVT + } + + // HEV/PHEV/EREV 等 + $bits = []; + if (!empty($s['engine_disp_l'])) { + $bits[] = self::dispToken($s['engine_disp_l']); // 可空 + } + if (!empty($s['motor_layout_code'])) { + $bits[] = self::tok($s['motor_layout_code']); // 如 AWD / DM-I / DM-P + } + return implode('', $bits); + } + + /** 冲突检测并追加短校验(全局唯一) */ + private static function ensureUnique(string $sku, int $maxLen): string + { + if (!VehVehicleSku::where('sku_code', $sku)->exists()) { + return $sku; + } + // 用 crc32 生成 5~6 位 base36 校验(稳定且短) + $crc = self::base36Crc($sku); + $suffix = '-X' . $crc; + + if (strlen($sku . $suffix) > $maxLen) { + $sku = substr($sku, 0, max(0, $maxLen - strlen($suffix))); + $sku = rtrim($sku, '-'); // 避免尾部 '-' + } + $sku .= $suffix; + + // 若极端情况下仍冲突,追加递增计数 + $i = 2; + $candidate = $sku; + while (VehVehicleSku::where('sku_code', $candidate)->exists()) { + $extra = '-'.$i; + $cut = max(0, $maxLen - strlen($extra)); + $candidate = substr($sku, 0, $cut) . $extra; + $i++; + } + return $candidate; + } + + /** 把 token 数组尽量压到 maxLen(逐步压缩策略) */ + private static function shrink(array $partsByKey, int $maxLen): string + { + // 1) 先对 series/level/edition 做激进压缩 + $p = $partsByKey; + foreach (['series','level','edition'] as $k) { + if (!empty($p[$k])) $p[$k] = self::heavyAbbr($p[$k]); + } + $sku = self::normalizeSku(implode('-', $p)); + if (strlen($sku) <= $maxLen) return $sku; + + // 2) 依次移除不太关键的信息:edition → level(若存在) + if (!empty($p['edition'])) { unset($p['edition']); } + $sku = self::normalizeSku(implode('-', $p)); + if (strlen($sku) <= $maxLen) return $sku; + + if (!empty($p['level'])) { unset($p['level']); } + $sku = self::normalizeSku(implode('-', $p)); + if (strlen($sku) <= $maxLen) return $sku; + + // 3) 压缩 spec(如去 KM/KWH,仅保留核心) + if (!empty($p['spec'])) { $p['spec'] = self::compactSpec($p['spec']); } + $sku = self::normalizeSku(implode('-', $p)); + if (strlen($sku) <= $maxLen) return $sku; + + // 4) 仍超长:从右向左截断次要段(spec/drive/year),保留前三段(brand/series/fuel)优先 + $dropOrder = ['spec','drive','year']; + $q = $p; + foreach ($dropOrder as $k) { + if (!empty($q[$k])) { unset($q[$k]); } + $sku = self::normalizeSku(implode('-', $q)); + if (strlen($sku) <= $maxLen) return $sku; + } + + // 5) 最后兜底:硬截到 maxLen,后续 ensureUnique 会追加 -X 校验并避免冲突 + return substr(self::normalizeSku(implode('-', $p)), 0, $maxLen); + } + + /* ===== Helpers ===== */ + + private static function tok($v): string + { + $v = strtoupper((string)$v); + return preg_replace('/[^A-Z0-9_]/', '', $v ?? ''); + } + + private static function abbr(string $t): string + { + return self::ABBR[$t] ?? $t; + } + + private static function heavyAbbr(string $t): string + { + // 更激进:去除元音,连字符化 + $t = str_replace(['STANDARD','FLAGSHIP','PREMIUM','DELUXE'], ['STD','FLG','PRM','DLX'], $t); + $t = preg_replace('/[AEIOU]/', '', $t); + return $t; + } + + private static function compactSpec(string $s): string + { + // 规则:去 KM/KWH 等单位,只保留数字与核心字母 + $s = strtoupper($s); + $s = str_replace(['KM','KWH'], '', $s); + return $s; + } + + private static function numToken($v): string + { + return preg_replace('/[^0-9]/', '', (string)$v); + } + + /** 1.5L -> 15L;2.0L -> 20L */ + private static function dispToken($l): string + { + $x = (float)$l; + return (string)round($x * 10) . 'L'; + } + + private static function base36Crc(string $s): string + { + $crc = sprintf('%u', crc32($s)); // 无符号 + $n = (int)$crc; + $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $res = ''; + do { + $res = $chars[$n % 36] . $res; + $n = intdiv($n, 36); + } while ($n > 0); + return substr($res, -6); // 取后6位足够 + } + + private static function normalizeSku(string $s): string + { + // 连续的 '-' 合并,首尾修剪 + $s = preg_replace('/-+/', '-', $s); + $s = trim($s, '-'); + return $s; + } +} \ No newline at end of file diff --git a/app/common/logic/VehDictI18nLogic.php b/app/common/logic/VehDictI18nLogic.php new file mode 100644 index 0000000..f25b50b --- /dev/null +++ b/app/common/logic/VehDictI18nLogic.php @@ -0,0 +1,17 @@ + 'integer', + 'enabled' => 'integer', + 'sort_order' => 'integer', + 'created_at' => 'integer', + 'updated_at' => 'integer', + ]; + + protected $fillable = [ + 'field','dict','required','enabled','sort_order', + 'remark','created_at','updated_at' + ]; +} \ No newline at end of file diff --git a/app/common/model/VehVehicleListing.php b/app/common/model/VehVehicleListing.php new file mode 100644 index 0000000..77d238c --- /dev/null +++ b/app/common/model/VehVehicleListing.php @@ -0,0 +1,49 @@ + 'array', + 'features' => 'array', + 'dimensions_mm' => 'array', + 'model_year' => 'integer', + 'engine_turbo' => 'integer', + 'gears' => 'integer', + 'range_km' => 'integer', + 'doors' => 'integer', + 'seats' => 'integer', + 'weight_kg' => 'integer', + 'msrp' => 'float', + 'battery_kwh' => 'float', + 'engine_disp_l' => 'float', + 'is_active' => 'integer', + 'corp_id' => 'integer', + 'created_at' => 'integer', + 'updated_at' => 'integer', + ]; + + protected $fillable = [ + 'sku_code','fingerprint', + 'brand_code','brand_name', + 'series_code','series_name', + 'model_code','model_name','model_year', + 'trim_code','trim_level_code','edition_code', + 'trim','trim_level','edition_name', + 'body_type_code','drive_type_code','motor_layout_code', + 'fuel_type_code','engine_disp_l','engine_turbo','engine_power_kw', + 'battery_kwh','transmission_code','gears', + 'range_km','range_std_code', + 'doors','seats','weight_kg','dimensions_mm', + 'color_exterior_code','color_exterior_text', + 'color_interior_code','color_interior_text', + 'options_official','features','emission_std_code', + 'origin_country','currency','msrp', + 'is_active','corp_id','remark', + 'created_by','updated_by','created_at','updated_at', + 'body_type', 'drive_type', 'motor_layout', 'fuel_type', 'transmission', + 'range_std', 'emission_std' + ]; +} \ No newline at end of file diff --git a/app/common/model/VehVehicleUnit.php b/app/common/model/VehVehicleUnit.php new file mode 100644 index 0000000..28e38f1 --- /dev/null +++ b/app/common/model/VehVehicleUnit.php @@ -0,0 +1,49 @@ +validator; + } + + + /** 本进程缓存:[dict][code] => labels array */ + protected static array $labelsCache = []; + + public static function label(string $dict=null, ?string $code=null, string $locale='zh-CN', ?string $fallbackZh=null): ?string + { + if (!$dict || !$code) return $fallbackZh; + + $labels = self::labels($dict, $code); + if (!$labels) return $fallbackZh ?? $code; + + return $labels[$locale] ?? $labels['zh-CN'] ?? $code; + } + + /** 返回 labels 数组,命中缓存 */ + public static function labels(string $dict, string $code): ?array + { + $dict = strtoupper($dict); + $code = (string)$code; + + if (isset(self::$labelsCache[$dict][$code])) { + return self::$labelsCache[$dict][$code]; + } + + $term = DictTerm::where('dict',$dict)->where('code',$code)->first(['labels']); + if (!$term) return null; + + $labels = $term->labels ?? null; + if (!is_array($labels)) return null; + + self::$labelsCache[$dict][$code] = $labels; + return $labels; + } + + /** 校验 code 是否存在于字典(用于必填维度) */ + public static function ensureExists(string $dict, ?string $code, string $fieldNameForError): void + { + if ($code === null || $code === '') { + throw new \InvalidArgumentException("缺少必填字段:{$fieldNameForError}"); + } + $ok = VehDictI18n::where('dict',$dict)->where('code',$code)->where('status', 1)->exists(); + if (!$ok) throw new \InvalidArgumentException("字典不存在或未启用:{$dict}.{$code}"); + } +} \ No newline at end of file diff --git a/app/common/service/VehDictMappingService.php b/app/common/service/VehDictMappingService.php new file mode 100644 index 0000000..67c5288 --- /dev/null +++ b/app/common/service/VehDictMappingService.php @@ -0,0 +1,57 @@ +validator; + } + + + public static function all(): array + { + $rows = VehDictMapping::where('status', 1)->orderBy('sort')->orderBy('id')->get()->toArray(); + $out = []; + foreach ($rows as $r) { + $out[$r['dict']] = [ + 'field' => $r['field'], + 'dict' => $r['dict'], + 'required' => (int)$r['required'] === 1, + ]; + } + return $out; + } + + public static function requiredDicts(): array + { + return array_keys(array_filter(self::all(), fn($x)=>$x['required']===true)); + } + + public static function enabled(string $dict): bool + { + $all = self::all(); + return isset($all[$dict]); + } +} \ No newline at end of file diff --git a/app/common/service/VehVehicleListingService.php b/app/common/service/VehVehicleListingService.php new file mode 100644 index 0000000..3aee146 --- /dev/null +++ b/app/common/service/VehVehicleListingService.php @@ -0,0 +1,31 @@ +validator; + } +} \ No newline at end of file diff --git a/app/common/service/VehVehicleSkuService.php b/app/common/service/VehVehicleSkuService.php new file mode 100644 index 0000000..2cfb588 --- /dev/null +++ b/app/common/service/VehVehicleSkuService.php @@ -0,0 +1,349 @@ +validator; + } + + + // 枚举 + private const MAPS = [ + 'BODY' => [ + 'SEDAN' => '三厢轿车', 'SUV'=>'SUV', 'HB'=>'两厢/掀背', 'MPV'=>'MPV', 'PICKUP'=>'皮卡' + ], + 'DRIVE' => [ + 'FWD'=>'前驱', 'RWD'=>'后驱', 'AWD'=>'四驱(AWD)', '4WD'=>'四驱(4WD)' + ], + 'MOTOR_LAYOUT' => [ + 'FWD'=>'前置单电机', 'RWD'=>'后置单电机', 'AWD'=>'双电机四驱', 'DM-I'=>'DM-i', 'DM-P'=>'DM-p' + ], + 'FUEL' => [ + 'GAS'=>'汽油', 'HEV'=>'油电混动', 'PHEV'=>'插电混动', 'EV'=>'纯电', 'EREV'=>'增程' + ], + 'TRANS' => [ + 'MT'=>'手动', 'AT'=>'自动', 'CVT'=>'无级', 'DCT'=>'双离合', '1SPEED'=>'单速' + ], + 'RANGE_STD' => [ + 'CLTC'=>'CLTC', 'WLTP'=>'WLTP', 'EPA'=>'EPA', 'NEDC'=>'NEDC' + ], + 'EMISSION' => [ + 'CHN6'=>'国六', 'EURO6'=>'欧6', 'EPA'=>'美国EPA' + ], + ]; + + // *_code取中文 + public function label(string $dict, ?string $code): ?string + { + if ($code === null || $code === '') return null; + $dict = strtoupper($dict); + $code = strtoupper($code); + return self::MAPS[$dict][$code] ?? $code; + } + + // 静态映射把 *_code → 中文 + private function backfill(array $d): array + { + $d['body_type'] = $this->label('BODY', $d['body_type_code']); + $d['drive_type'] = $this->label('DRIVE', $d['drive_type_code']); + $d['motor_layout'] = $this->label('MOTOR_LAYOUT', $d['motor_layout_code']); + $d['fuel_type'] = $this->label('FUEL', $d['fuel_type_code']); + $d['transmission'] = $this->label('TRANS', $d['transmission_code']); + $d['range_std'] = $this->label('RANGE_STD', $d['range_std_code']); + $d['emission_std'] = $this->label('EMISSION', $d['emission_std_code']); + return $d; + } + + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'default': + $config['where']['is_active'] = 1; + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + break; + case 'index': + $config['where']['is_active'] = 1; + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + break; + case 'show': + $config['where']['id'] = $p['id']; + $config['where']['is_active'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } + + public function beforeServiceStore($data, Request $request) + { + $data = $this->backfill($data); + // 未提供时自动生成;若你想“强制覆盖人工输入”,可去掉 isset 判断 + if (empty($data['model_code'])) { + $data['model_code'] = ModelNaming::buildModelCode($data); + } + if (empty($data['model_name'])) { + $data['model_name'] = ModelNaming::buildModelName($data); + } + // 填充系统字段 + $data['sku_code'] = SkuCodeBuilder::build($data); + $data['corp_id'] = 0; + $data['created_by'] = $request->user->uid; + $data['updated_by'] = $request->user->uid; + // 指纹 + $data['fingerprint'] = Fingerprint::makeFromArray($data); + return $data; + } + + protected function afterServiceStore($res) + { + + return $res; + } + + + public function beforeServiceUpdate($data, Request $request) + { + $data = $this->backfill($data); + // 未提供时自动生成;若你想“强制覆盖人工输入”,可去掉 isset 判断 + if (empty($data['model_code'])) { + $data['model_code'] = ModelNaming::buildModelCode($data); + } + if (empty($data['model_name'])) { + $data['model_name'] = ModelNaming::buildModelName($data); + } + // 填充系统字段 + $data['updated_by'] = $request->user->uid; + // 指纹 + $data['fingerprint'] = Fingerprint::makeFromArray($data); + return $data; + } + + protected function afterServiceUpdate($res) + { + + return $res; + } + + + /** SKU 字段名 → dict 名(用于 i18n 取词 & 必填校验) */ + protected static array $SKU_FIELD_TO_DICT = [ + 'brand_code' => 'BRAND', + 'series_code' => 'SERIES', + 'model_code' => 'MODEL', + 'trim_code' => 'TRIM', + 'trim_level_code' => 'TRIM_LEVEL', + 'edition_code' => 'EDITION', + 'fuel_type_code' => 'FUEL', + 'drive_type_code' => 'DRIVE', + 'transmission_code' => 'TRANS', + 'motor_layout_code' => 'MOTOR_LAYOUT', + 'body_type_code' => 'BODY', + 'range_std_code' => 'RANGE_STD', + 'emission_std_code' => 'EMISSION', + 'color_exterior_code'=> 'COLOR', + 'color_interior_code'=> 'COLOR', + ]; + + /** 创建 SKU(含指纹与字典校验) */ + public static function create(array $p, int $userId=0, int $corpId=0): VehicleSku + { + // SkuValidator::validateForCreate($p); + + // 必填字典:由映射表控制(一般 BRAND/SERIES/FUEL) + $requiredDicts = MappingService::requiredDicts(); + foreach (self::$SKU_FIELD_TO_DICT as $field => $dict) { + if (!MappingService::enabled($dict)) continue; + $isRequired = in_array($dict, $requiredDicts, true); + if ($isRequired) { + DictService::ensureExists($dict, $p[$field] ?? null, $field); + } + } + + // 填充系统字段 + $now = time(); + $p['sku_code'] = $p['sku_code'] ?? ('SKU'.date('Ymd').'-'.substr(bin2hex(random_bytes(3)),0,6)); + $p['corp_id'] = $p['corp_id'] ?? $corpId; + $p['created_by'] = $p['created_by'] ?? $userId; + $p['updated_by'] = $p['updated_by'] ?? $userId; + $p['created_at'] = $p['created_at'] ?? $now; + $p['updated_at'] = $p['updated_at'] ?? $now; + + // 指纹 + $p['fingerprint'] = Fingerprint::make($p /*, $scopeCorp=true/false*/); + + return DB::connection()->transaction(function () use ($p) { + $sku = new VehicleSku($p); + $sku->save(); + return $sku; + }); + } + + /** 更新 SKU(部分字段;指纹随事实变动而刷新) */ + public static function update(int $id, array $p, int $userId=0): VehicleSku + { + SkuValidator::validateForUpdate($p); + + $sku = VehicleSku::findOrFail($id); + + // 若传入了必填 dict 的 code,需要确认字典存在 + $requiredDicts = MappingService::requiredDicts(); + foreach (self::$SKU_FIELD_TO_DICT as $field => $dict) { + if (!array_key_exists($field, $p)) continue; + if (!MappingService::enabled($dict)) continue; + $isRequired = in_array($dict, $requiredDicts, true); + if ($isRequired) { + DictService::ensureExists($dict, $p[$field], $field); + } else { + // 可选的:若传了 code 则也校验存在 + if (($p[$field] ?? null) !== null && $p[$field] !== '') { + $exists = \app\model\DictTerm::where('dict',$dict)->where('code',$p[$field])->exists(); + if (!$exists) throw new \InvalidArgumentException("字典不存在:{$dict}.{$p[$field]}"); + } + } + } + + // 刷新系统字段 + $p['updated_by'] = $userId; + $p['updated_at'] = time(); + + // 赋值保存 + $sku->fill($p); + + // 只要影响到指纹的事实字段变动,就重算指纹 + $fingerFields = [ + 'brand_code','series_code','model_year','fuel_type_code', + 'drive_type_code','transmission_code','body_type_code', + 'engine_disp_l','engine_turbo','battery_kwh','range_km', + 'range_std_code','emission_std_code', + 'corp_id' + ]; + foreach ($fingerFields as $f) { + if (array_key_exists($f, $p)) { + $sku->fingerprint = Fingerprint::make($sku->toArray()); + break; + } + } + + $sku->save(); + return $sku; + } + + /** 详情(带 i18n label 与标准标题) */ + public static function detail(int $id, string $locale='zh-CN'): array + { + $sku = VehicleSku::findOrFail($id); + $data = $sku->toArray(); + + $labelOf = function(string $field) use ($data, $locale) { + $dict = self::$SKU_FIELD_TO_DICT[$field] ?? null; + if (!$dict) return null; + + $code = $data[$field] ?? null; + // 若是品牌/车系,允许以中文兜底 + $fallback = null; + if ($field === 'brand_code') $fallback = $data['brand_name'] ?? null; + if ($field === 'series_code') $fallback = $data['series_name'] ?? null; + + // 版型/等级/特别版允许中文兜底 + if ($field === 'trim_code') $fallback = $data['trim'] ?? null; + if ($field === 'trim_level_code') $fallback = $data['trim_level'] ?? null; + if ($field === 'edition_code') $fallback = $data['edition_name'] ?? null; + + // 颜色兜底中文 + if ($field === 'color_exterior_code') $fallback = $data['color_exterior_text'] ?? null; + if ($field === 'color_interior_code') $fallback = $data['color_interior_text'] ?? null; + + return \app\service\DictService::label($dict, $code, $locale, $fallback); + }; + + $i18n = [ + 'brand_label' => $labelOf('brand_code'), + 'series_label' => $labelOf('series_code'), + 'model_label' => \app\service\DictService::label('MODEL', $data['model_code'] ?? null, $locale, $data['model_name'] ?? null), + 'trim_label' => $labelOf('trim_code'), + 'trim_level_label' => $labelOf('trim_level_code'), + 'edition_label' => $labelOf('edition_code'), + 'fuel_label' => $labelOf('fuel_type_code'), + 'drive_label' => $labelOf('drive_type_code'), + 'trans_label' => $labelOf('transmission_code'), + 'motor_layout_label' => $labelOf('motor_layout_code'), + 'body_label' => $labelOf('body_type_code'), + 'range_std_label' => $labelOf('range_std_code'), + 'emission_label' => $labelOf('emission_std_code'), + 'color_exterior_label' => $labelOf('color_exterior_code'), + 'color_interior_label' => $labelOf('color_interior_code'), + 'listing_title' => TitleBuilder::build($data, $locale), + ]; + + return ['sku'=>$data, 'i18n'=>$i18n]; + } + + /** 列表查询(支持基础筛选 & i18n 列) */ + public static function list(array $q, string $locale='zh-CN', int $page=1, int $pageSize=20): array + { + $builder = VehicleSku::query(); + + // 常用筛选 + if (!empty($q['brand_code'])) $builder->where('brand_code', $q['brand_code']); + if (!empty($q['series_code'])) $builder->where('series_code', $q['series_code']); + if (!empty($q['fuel_type_code'])) $builder->where('fuel_type_code', $q['fuel_type_code']); + if (!empty($q['model_year'])) $builder->where('model_year', (int)$q['model_year']); + if (isset($q['is_active'])) $builder->where('is_active', (int)$q['is_active']); + + $builder->orderByDesc('created_at'); + + $total = (clone $builder)->count(); + $rows = $builder->forPage($page, $pageSize)->get()->toArray(); + + // 附加 i18n 字段(轻量) + foreach ($rows as &$row) { + $row['brand_label'] = DictService::label('BRAND', $row['brand_code'] ?? null, $locale, $row['brand_name'] ?? null); + $row['series_label'] = DictService::label('SERIES', $row['series_code'] ?? null, $locale, $row['series_name'] ?? null); + $row['fuel_label'] = DictService::label('FUEL', $row['fuel_type_code'] ?? null, $locale, null); + $row['listing_title']= TitleBuilder::build($row, $locale); + } + + return ['total'=>$total, 'list'=>$rows, 'page'=>$page, 'page_size'=>$pageSize]; + } +} \ No newline at end of file diff --git a/app/common/service/VehVehicleUnitService.php b/app/common/service/VehVehicleUnitService.php new file mode 100644 index 0000000..4af3ea4 --- /dev/null +++ b/app/common/service/VehVehicleUnitService.php @@ -0,0 +1,31 @@ +validator; + } +} \ No newline at end of file diff --git a/app/common/utils/scaffold/Generate.php b/app/common/utils/scaffold/Generate.php index eb82025..2ed10a0 100644 --- a/app/common/utils/scaffold/Generate.php +++ b/app/common/utils/scaffold/Generate.php @@ -156,11 +156,11 @@ class Generate protected function deleteFileIfExists($path) { if (file_exists($path)) { - "文件: {$path} 已存在,核对后手动删除。\n"; - return; + // "文件: {$path} 已存在,核对后手动删除。\n"; + // return; - // unlink($path); - // echo "删除已存在文件: {$path} \n"; + unlink($path); + echo "删除已存在文件: {$path} \n"; } } diff --git a/app/common/validate/VehDictI18nValidate.php b/app/common/validate/VehDictI18nValidate.php new file mode 100644 index 0000000..cb65500 --- /dev/null +++ b/app/common/validate/VehDictI18nValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/validate/VehDictMappingValidate.php b/app/common/validate/VehDictMappingValidate.php new file mode 100644 index 0000000..1b4bc7a --- /dev/null +++ b/app/common/validate/VehDictMappingValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/validate/VehVehicleListingValidate.php b/app/common/validate/VehVehicleListingValidate.php new file mode 100644 index 0000000..ffa9c83 --- /dev/null +++ b/app/common/validate/VehVehicleListingValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/validate/VehVehicleSkuValidate.php b/app/common/validate/VehVehicleSkuValidate.php new file mode 100644 index 0000000..7305e71 --- /dev/null +++ b/app/common/validate/VehVehicleSkuValidate.php @@ -0,0 +1,128 @@ + 'max:40|alphaNum', + 'fingerprint' => 'length:64|alphaNum', + 'brand_code' => 'require|max:32', + 'brand_name' => 'require|max:64', + 'series_code' => 'max:64', + 'series_name' => 'max:128', + 'model_code' => 'max:64', + 'model_name' => 'require|max:128', + 'model_year' => 'require|number|between:1900,2100', + 'trim_code' => 'max:64', + 'trim_level_code' => 'max:64', + 'edition_code' => 'max:64', + 'trim' => 'max:128', + 'trim_level' => 'max:64', + 'edition_name' => 'max:64', + 'body_type_code' => 'max:32', + 'drive_type_code' => 'max:16', + 'motor_layout_code' => 'max:32', + 'fuel_type_code' => 'max:16', + 'engine_disp_l' => 'float|between:0,99.9', + 'engine_turbo' => 'in:0,1', + 'engine_power_kw' => 'number|between:0,2000', + 'battery_kwh' => 'float|between:0,999.99', + 'transmission_code' => 'max:16', + 'gears' => 'number|between:1,20', + 'range_km' => 'number|between:0,2000', + 'range_std_code' => 'max:16', + 'doors' => 'number|between:2,10', + 'seats' => 'number|between:1,20', + 'weight_kg' => 'number|between:0,10000', + 'dimensions_mm' => 'array', + 'color_exterior_code'=> 'max:32', + 'color_exterior_text'=> 'max:64', + 'color_interior_code'=> 'max:32', + 'color_interior_text'=> 'max:64', + 'options_official' => 'array', + 'features' => 'array', + 'emission_std_code' => 'max:16', + 'origin_country' => 'alpha|length:2', + 'currency' => 'require|alpha|length:3', + 'msrp' => 'float|between:0,9999999999.99', + 'is_active' => 'in:0,1', + 'corp_id' => 'require|number', + 'remark' => 'max:255', + 'created_by' => 'number', + 'updated_by' => 'number', + 'created_at' => 'require|number', + 'updated_at' => 'require|number', + ]; + + /** + * 字段别名 + */ + protected $field = [ + 'sku_code' => 'SKU编码', + 'fingerprint' => '规格指纹', + 'brand_code' => '品牌代码', + 'brand_name' => '品牌名称', + 'series_code' => '车系代码', + 'series_name' => '车系名称', + 'model_code' => '车型代码', + 'model_name' => '车型名称', + 'model_year' => '年款', + 'trim_code' => '版型代码', + 'trim_level_code' => '配置等级代码', + 'edition_code' => '特别版代码', + 'trim' => '版型/细分配置', + 'trim_level' => '配置等级', + 'edition_name' => '特别版名称', + 'body_type_code' => '车身类型', + 'drive_type_code' => '驱动方式', + 'motor_layout_code' => '电机布置', + 'fuel_type_code' => '能源类型', + 'engine_disp_l' => '排量(L)', + 'engine_turbo' => '是否涡轮', + 'engine_power_kw' => '最大功率(kW)', + 'battery_kwh' => '电池容量(kWh)', + 'transmission_code' => '变速箱代码', + 'gears' => '挡位数', + 'range_km' => '续航里程', + 'range_std_code' => '续航标准', + 'doors' => '门数', + 'seats' => '座位数', + 'weight_kg' => '整备质量', + 'dimensions_mm' => '车身尺寸', + 'color_exterior_code'=> '外观色代码', + 'color_exterior_text'=> '外观色名称', + 'color_interior_code'=> '内饰色代码', + 'color_interior_text'=> '内饰色名称', + 'options_official' => '官方选装', + 'features' => '功能配置', + 'emission_std_code' => '排放标准', + 'origin_country' => '原产国', + 'currency' => '币种', + 'msrp' => '建议零售价', + 'is_active' => '是否启用', + 'corp_id' => '公司ID', + 'remark' => '备注', + 'created_by' => '创建人', + 'updated_by' => '更新人', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + ]; + + /** + * 场景定义 + */ + protected $scene = [ + 'store' => [ + 'brand_code', 'brand_name', 'model_year','currency' + ], + 'update' => [ + 'id', 'brand_code','brand_name', 'model_year','currency' + ], + ]; +} \ No newline at end of file diff --git a/app/common/validate/VehVehicleUnitValidate.php b/app/common/validate/VehVehicleUnitValidate.php new file mode 100644 index 0000000..11f91a9 --- /dev/null +++ b/app/common/validate/VehVehicleUnitValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php index ba87d98..3871c59 100644 --- a/app/controller/IndexController.php +++ b/app/controller/IndexController.php @@ -78,25 +78,25 @@ class IndexController $options = [ 'controller' => [ 'module' => 'common', - 'name' => 'message_notifications' + 'name' => 'veh_dict_i18n' ], 'model' => [ 'module' => 'common', - 'name' => 'message_notifications' + 'name' => 'veh_dict_i18n' ], 'service' => [ 'module' => 'common', - 'name' => 'message_notifications' + 'name' => 'veh_dict_i18n' ], 'logic' => [ 'module' => 'common', - 'name' => 'message_notifications' + 'name' => 'veh_dict_i18n' ], 'validate' => [ 'module' => 'common', - 'name' => 'message_notifications' + 'name' => 'veh_dict_i18n' ], - 'table' => 'message_notifications' + 'table' => 'veh_dict_i18n' ]; $result = (new Generate($options))->doGenerate(); diff --git a/app/functions.php b/app/functions.php index d9bb411..db8cfe7 100644 --- a/app/functions.php +++ b/app/functions.php @@ -304,6 +304,29 @@ if (!function_exists('generateMsgId')) { // 随机部分(3位) $rand = mt_rand(100, 999); + // 拼接:日期时间 + 微秒 + 随机数 + return $date . $micro . $rand; + } +} + +/** + * 生成sku_code + * 格式:年月日时分秒 + 微秒 + 随机数 + * 例如:20250820175530987654321 + * + * @return string + */ +if (!function_exists('skuCode')) { + function skuCode(): string + { + // 时间部分(精确到微秒) + $time = microtime(true); + $micro = sprintf("%06d", ($time - floor($time)) * 1e6); + $date = date('YmdHis', (int)$time); + + // 随机部分(3位) + $rand = mt_rand(100, 999); + // 拼接:日期时间 + 微秒 + 随机数 return $date . $micro . $rand; } diff --git a/app/queue/redis/InquiryToCrm.php b/app/queue/redis/InquiryToCrm.php deleted file mode 100644 index 4d7ca3e..0000000 --- a/app/queue/redis/InquiryToCrm.php +++ /dev/null @@ -1,110 +0,0 @@ -where('id', $data['id'])->where('sync_crm', 0)->first(); - - if ($info) { - // 获取用户信息 - $recipient = 0; - $corpId = 0; - $uinfo = null; - if ($info->recipient) { - $recipient = $info->recipient; - $uinfo = User::where('id', $info->recipient)->first(); - if ($uinfo) { - $corpId = $uinfo->corp_id; - } - } - // 同步客户数据 - $crmCustomer = new CrmCustomer(); - $crmCustomer->sn = $info->order_no; - $crmCustomer->corp_abbr = $corpId; - $crmCustomer->user_id = $recipient; - $crmCustomer->type = 1; - $crmCustomer->channel_id = $info->channel; - $crmCustomer->country_id = $info->country; - $crmCustomer->magnitude = $info->quality; - $crmCustomer->email = $info->email; - $crmCustomer->phone = $info->tel; - $crmCustomer->WhatsApp = $info->whatsapp; - $crmCustomer->contacts = $info->contacts; - $crmCustomer->desc_collect = $info->content; - $crmCustomer->enter_user_id = $info->enter_user_id; - $crmCustomer->obtain = time(); - // 修改同步CRM状态 - $info->sync_crm = 1; - // 保存 - if (!$crmCustomer->save() || !$info->save()) { - throw new BusinessException('同步失败~'); - } - - // // 发送邮件消息 - // if ($uinfo && $uinfo->email) { - // $options = [ - // 'id' => $info->id, - // 'email' => $uinfo->email - // ]; - // // Log::info('发送邮件消息:' . json_encode($options)); - // \Webman\RedisQueue\Redis::send('email-message', $options); - // } - - $wsdata = [ - 'sender_id' => 0, - 'sender_type' => 'system', - 'title' => '有新的客户线索,' . $info->order_no . ',请及时处理', - 'content' => '有新的客户线索,' . $info->order_no . ',请及时处理', - 'scene' => 1, - 'recipient' => [$info->recipient] - ]; - // 异步推送 - \Webman\RedisQueue\Redis::send('notice', $wsdata); - } - } catch (\Throwable $th) { - throw $th; - } - } - - // 消费失败回调 - /* - $package = [ - 'id' => 1357277951, // 消息ID - 'time' => 1709170510, // 消息时间 - 'delay' => 0, // 延迟时间 - 'attempts' => 2, // 消费次数 - 'queue' => 'send-mail', // 队列名 - 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 - 'max_attempts' => 5, // 最大重试次数 - 'error' => '错误信息' // 错误信息 - ] - */ - public function onConsumeFailure(\Throwable $e, $package) - { - echo "consume failure\n"; - echo $e->getMessage() . "\n"; - // 无需反序列化 - var_export($package); - } -} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmUpdate.php b/app/queue/redis/InquiryToCrmUpdate.php deleted file mode 100644 index c4e6d02..0000000 --- a/app/queue/redis/InquiryToCrmUpdate.php +++ /dev/null @@ -1,110 +0,0 @@ -where('id', $data['id'])->first(); - - $corpId = 0; - if ($info->recipient) { - $uinfo = User::where('id', $info->recipient)->where('status', 1)->first(); - if ($uinfo) { - $corpId = $uinfo->corp_id; - } - } - - // 获取客户信息 - $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); - if ($crmCustomerInfo) { - $udata = [ - 'corp_abbr' => $corpId, - 'user_id' => $info->recipient, - 'channel_id' => $info->channel, - 'country_id' => $info->country, - 'magnitude' => $info->quality, - 'email' => $info->email, - 'phone' => $info->tel, - 'WhatsApp' => $info->whatsapp, - 'contacts' => $info->contacts, - 'desc_collect' => $info->content, - ]; - $crmCustomerInfo->update($udata); - } else { - // 同步客户数据 - $crmCustomer = new CrmCustomer(); - $crmCustomer->sn = $info->order_no; - $crmCustomer->corp_abbr = $corpId; - $crmCustomer->user_id = $info->recipient; - $crmCustomer->type = 1; - $crmCustomer->channel_id = $info->channel; - $crmCustomer->country_id = $info->country; - $crmCustomer->magnitude = $info->quality; - $crmCustomer->email = $info->email; - $crmCustomer->phone = $info->tel; - $crmCustomer->WhatsApp = $info->whatsapp; - $crmCustomer->contacts = $info->contacts; - $crmCustomer->desc_collect = $info->content; - $crmCustomer->enter_user_id = $info->enter_user_id; - // 修改同步CRM状态 - $info->sync_crm = 1; - // 保存 - if (!$crmCustomer->save() || !$info->save()) { - throw new BusinessException('同步失败~'); - } - - // 发送邮件消息 - if ($uinfo && $uinfo->email) { - $options = [ - 'id' => $info->id, - 'email' => $uinfo->email - ]; - \Webman\RedisQueue\Redis::send('email-message', $options); - } - } - } catch (\Throwable $th) { - throw $th; - } - } - - // 消费失败回调 - /* - $package = [ - 'id' => 1357277951, // 消息ID - 'time' => 1709170510, // 消息时间 - 'delay' => 0, // 延迟时间 - 'attempts' => 2, // 消费次数 - 'queue' => 'send-mail', // 队列名 - 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 - 'max_attempts' => 5, // 最大重试次数 - 'error' => '错误信息' // 错误信息 - ] - */ - public function onConsumeFailure(\Throwable $e, $package) - { - echo "consume failure\n"; - echo $e->getMessage() . "\n"; - // 无需反序列化 - var_export($package); - } -} \ No newline at end of file diff --git a/config/route.php b/config/route.php index 6393f2d..b2cb132 100644 --- a/config/route.php +++ b/config/route.php @@ -182,6 +182,18 @@ Route::group('/admin', function () { Route::any('/allocation', [app\crmAdmin\controller\CustomerController::class, 'allocation']); }); }); + + // 车辆 + Route::group('/vehicle', function () { + // 基础信息 + Route::group('/sku', function () { + Route::any('/list', [app\common\controller\VehVehicleSkuController::class, 'index']); + Route::any('/show', [app\common\controller\VehVehicleSkuController::class, 'show']); + Route::any('/store', [app\common\controller\VehVehicleSkuController::class, 'store']); + Route::any('/update', [app\common\controller\VehVehicleSkuController::class, 'update']); + Route::any('/destroy', [app\common\controller\VehVehicleSkuController::class, 'destroy']); + }); + }); }); From 29f573a467c9c74f35b3468242a59d45b08b9393 Mon Sep 17 00:00:00 2001 From: mzl Date: Mon, 1 Sep 2025 14:00:44 +0800 Subject: [PATCH 2/5] st --- .../controller/VehVehicleSkuController.php | 18 ++--- app/common/service/VehVehicleSkuService.php | 5 -- app/controller/IndexController.php | 67 +++++++------------ 3 files changed, 33 insertions(+), 57 deletions(-) diff --git a/app/common/controller/VehVehicleSkuController.php b/app/common/controller/VehVehicleSkuController.php index b99cacb..3ab3eb5 100644 --- a/app/common/controller/VehVehicleSkuController.php +++ b/app/common/controller/VehVehicleSkuController.php @@ -24,14 +24,14 @@ class VehVehicleSkuController extends BaseController * @param array $data * @return array */ - // protected function indexFormat($data) - // { - // if (isset($data['created_at'])) - // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); - // if (isset($data['updated_at'])) - // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); - // return $data; - // } + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } protected function showFormat($data) { @@ -90,7 +90,7 @@ class VehVehicleSkuController extends BaseController } - public function index(Request $request) + public function index22(Request $request) { $data = [ 'sku_code' , // 'SKU编码,系统生成', diff --git a/app/common/service/VehVehicleSkuService.php b/app/common/service/VehVehicleSkuService.php index 2cfb588..af171a7 100644 --- a/app/common/service/VehVehicleSkuService.php +++ b/app/common/service/VehVehicleSkuService.php @@ -90,12 +90,10 @@ class VehVehicleSkuService switch ($scene) { case 'default': $config['where']['is_active'] = 1; - $config['order']['sort'] = 'desc'; $config['order']['id'] = 'desc'; break; case 'index': $config['where']['is_active'] = 1; - $config['order']['sort'] = 'desc'; $config['order']['id'] = 'desc'; break; case 'show': @@ -118,14 +116,12 @@ class VehVehicleSkuService public function beforeServiceStore($data, Request $request) { $data = $this->backfill($data); - // 未提供时自动生成;若你想“强制覆盖人工输入”,可去掉 isset 判断 if (empty($data['model_code'])) { $data['model_code'] = ModelNaming::buildModelCode($data); } if (empty($data['model_name'])) { $data['model_name'] = ModelNaming::buildModelName($data); } - // 填充系统字段 $data['sku_code'] = SkuCodeBuilder::build($data); $data['corp_id'] = 0; $data['created_by'] = $request->user->uid; @@ -145,7 +141,6 @@ class VehVehicleSkuService public function beforeServiceUpdate($data, Request $request) { $data = $this->backfill($data); - // 未提供时自动生成;若你想“强制覆盖人工输入”,可去掉 isset 判断 if (empty($data['model_code'])) { $data['model_code'] = ModelNaming::buildModelCode($data); } diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php index 3871c59..a0f6dba 100644 --- a/app/controller/IndexController.php +++ b/app/controller/IndexController.php @@ -78,25 +78,25 @@ class IndexController $options = [ 'controller' => [ 'module' => 'common', - 'name' => 'veh_dict_i18n' + 'name' => 'stock_orders' ], 'model' => [ 'module' => 'common', - 'name' => 'veh_dict_i18n' + 'name' => 'stock_orders' ], 'service' => [ 'module' => 'common', - 'name' => 'veh_dict_i18n' + 'name' => 'stock_orders' ], 'logic' => [ 'module' => 'common', - 'name' => 'veh_dict_i18n' + 'name' => 'stock_orders' ], 'validate' => [ 'module' => 'common', - 'name' => 'veh_dict_i18n' + 'name' => 'stock_orders' ], - 'table' => 'veh_dict_i18n' + 'table' => 'stock_orders' ]; $result = (new Generate($options))->doGenerate(); @@ -106,43 +106,24 @@ class IndexController public function test() { + $params = [ + 'email' => '', + 'phone' => '11', + 'whatsApp' => '' + ]; + $corpId = 1; + $customer = \app\crm\model\Customer::where('corp_id', $corpId) + ->where((function (\Illuminate\Database\Eloquent\Builder $query) use ($params) { + if(!empty($params['email'])) + $query->Orwhere('email', '=', $params['email']); + if(!empty($params['phone'])) + $query->Orwhere('phone', '=', $params['phone']); + if(!empty($params['whatsApp'])) + $query->Orwhere('whatsApp', '=', $params['whatsApp']); + return $query; + })) + ->first(); - // $data = [ - // 'sender_id' => 0, - // 'sender_type' => 'system', - // 'title' => '测试消息 - 标题', - // 'content' => '测试消息 - 内容', - // 'scene' => 1, - // 'recipient' => [1], - // ]; - - // $data['recipient'] = [1, 74]; - // // // 同步推送 - // // (new MessageNotificationsService())->pushNotice($data); - - - - // // 异步推送 - // \Webman\RedisQueue\Redis::send('notice', $data); - - - $info = InquiryLog::with(['channelInfo', 'countryInfo', 'enter'])->where('id', 1)->where('sync_crm', 0)->first(); - - var_dump(empty($info->recipient)); - - if ($info) { - var_dump(11); - } else { - var_dump(22); - } - - - if ($info !== NULL) { - var_dump(33); - } else { - var_dump(44); - } - - return json(['code' => 0, 'msg' => 'success']); + return json($customer); } } \ No newline at end of file From b3d8029e6d35170710c1a636525c073260a43b86 Mon Sep 17 00:00:00 2001 From: mzl Date: Mon, 1 Sep 2025 14:06:34 +0800 Subject: [PATCH 3/5] Merge branch 'develop_bm' into feature/mzl_dev # Conflicts: # app/controller/IndexController.php # config/route.php --- app/admin/controller/BrandController.php | 53 +++++ .../controller/BrandSeriesController.php | 48 ++++ app/admin/controller/SysAccountController.php | 52 +++++ .../controller/SysCurrencyController.php | 52 +++++ app/admin/controller/SysDictController.php | 54 +++++ .../controller/SysDictItemController.php | 48 ++++ app/admin/controller/SysPortController.php | 53 +++++ app/admin/controller/VehColorController.php | 33 +++ .../controller/VehModificationController.php | 48 ++++ app/admin/logic/BrandLogic.php | 17 ++ app/admin/logic/BrandSeriesLogic.php | 17 ++ app/admin/logic/SysAccountLogic.php | 17 ++ app/admin/logic/SysCurrencyLogic.php | 17 ++ app/admin/logic/SysDictItemLogic.php | 17 ++ app/admin/logic/SysDictLogic.php | 17 ++ app/admin/logic/SysPortLogic.php | 17 ++ app/admin/logic/VehColorLogic.php | 17 ++ app/admin/logic/VehModificationLogic.php | 17 ++ app/admin/service/BrandSeriesService.php | 80 +++++++ app/admin/service/BrandService.php | 79 +++++++ app/admin/service/SysAccountService.php | 82 +++++++ app/admin/service/SysCurrencyService.php | 61 +++++ app/admin/service/SysDictItemService.php | 75 ++++++ app/admin/service/SysDictService.php | 81 +++++++ app/admin/service/SysPortService.php | 103 +++++++++ app/admin/service/VehColorService.php | 31 +++ app/admin/service/VehModificationService.php | 83 +++++++ app/admin/validate/BrandSeriesValidate.php | 29 +++ app/admin/validate/BrandValidate.php | 29 +++ app/admin/validate/SysAccountValidate.php | 29 +++ app/admin/validate/SysCurrencyValidate.php | 29 +++ app/admin/validate/SysDictItemValidate.php | 29 +++ app/admin/validate/SysDictValidate.php | 29 +++ app/admin/validate/SysPortValidate.php | 29 +++ app/admin/validate/VehColorValidate.php | 29 +++ .../validate/VehModificationValidate.php | 29 +++ app/common/controller/PresetController.php | 102 ++++++++ app/common/logic/BrandLogic.php | 22 ++ app/common/logic/BrandSeriesLogic.php | 22 ++ app/common/logic/SysAccountLogic.php | 22 ++ app/common/logic/SysCurrencyLogic.php | 21 ++ app/common/logic/SysDictItemLogic.php | 22 ++ app/common/logic/SysDictLogic.php | 27 +++ app/common/logic/SysPortLogic.php | 22 ++ app/common/logic/VehColorLogic.php | 22 ++ app/common/logic/VehModificationLogic.php | 22 ++ app/common/model/Brand.php | 49 ++++ app/common/model/BrandSeries.php | 49 ++++ app/common/model/SysAccount.php | 49 ++++ app/common/model/SysCurrency.php | 49 ++++ app/common/model/SysDict.php | 59 +++++ app/common/model/SysDictItem.php | 59 +++++ app/common/model/SysPort.php | 49 ++++ app/common/model/VehColor.php | 49 ++++ app/common/model/VehModification.php | 49 ++++ app/common/service/BrandSeriesService.php | 34 +++ app/common/service/BrandService.php | 24 ++ app/common/service/SysAccountService.php | 28 +++ app/common/service/SysCurrencyService.php | 25 ++ app/common/service/SysDictItemService.php | 42 ++++ app/common/service/SysDictService.php | 28 +++ app/common/service/SysPortService.php | 28 +++ app/common/service/VehColorService.php | 33 +++ app/common/service/VehModificationService.php | 28 +++ .../redis/InquiryToCrmNew_BACKUP_5243.php | 218 ++++++++++++++++++ app/queue/redis/InquiryToCrmNew_BASE_5243.php | 0 .../redis/InquiryToCrmNew_LOCAL_5243.php | 204 ++++++++++++++++ .../redis/InquiryToCrmNew_REMOTE_5243.php | 207 +++++++++++++++++ config/route.php | 89 +++++++ 69 files changed, 3283 insertions(+) create mode 100644 app/admin/controller/BrandController.php create mode 100644 app/admin/controller/BrandSeriesController.php create mode 100644 app/admin/controller/SysAccountController.php create mode 100644 app/admin/controller/SysCurrencyController.php create mode 100644 app/admin/controller/SysDictController.php create mode 100644 app/admin/controller/SysDictItemController.php create mode 100644 app/admin/controller/SysPortController.php create mode 100644 app/admin/controller/VehColorController.php create mode 100644 app/admin/controller/VehModificationController.php create mode 100644 app/admin/logic/BrandLogic.php create mode 100644 app/admin/logic/BrandSeriesLogic.php create mode 100644 app/admin/logic/SysAccountLogic.php create mode 100644 app/admin/logic/SysCurrencyLogic.php create mode 100644 app/admin/logic/SysDictItemLogic.php create mode 100644 app/admin/logic/SysDictLogic.php create mode 100644 app/admin/logic/SysPortLogic.php create mode 100644 app/admin/logic/VehColorLogic.php create mode 100644 app/admin/logic/VehModificationLogic.php create mode 100644 app/admin/service/BrandSeriesService.php create mode 100644 app/admin/service/BrandService.php create mode 100644 app/admin/service/SysAccountService.php create mode 100644 app/admin/service/SysCurrencyService.php create mode 100644 app/admin/service/SysDictItemService.php create mode 100644 app/admin/service/SysDictService.php create mode 100644 app/admin/service/SysPortService.php create mode 100644 app/admin/service/VehColorService.php create mode 100644 app/admin/service/VehModificationService.php create mode 100644 app/admin/validate/BrandSeriesValidate.php create mode 100644 app/admin/validate/BrandValidate.php create mode 100644 app/admin/validate/SysAccountValidate.php create mode 100644 app/admin/validate/SysCurrencyValidate.php create mode 100644 app/admin/validate/SysDictItemValidate.php create mode 100644 app/admin/validate/SysDictValidate.php create mode 100644 app/admin/validate/SysPortValidate.php create mode 100644 app/admin/validate/VehColorValidate.php create mode 100644 app/admin/validate/VehModificationValidate.php create mode 100644 app/common/logic/BrandLogic.php create mode 100644 app/common/logic/BrandSeriesLogic.php create mode 100644 app/common/logic/SysAccountLogic.php create mode 100644 app/common/logic/SysCurrencyLogic.php create mode 100644 app/common/logic/SysDictItemLogic.php create mode 100644 app/common/logic/SysDictLogic.php create mode 100644 app/common/logic/SysPortLogic.php create mode 100644 app/common/logic/VehColorLogic.php create mode 100644 app/common/logic/VehModificationLogic.php create mode 100644 app/common/model/Brand.php create mode 100644 app/common/model/BrandSeries.php create mode 100644 app/common/model/SysAccount.php create mode 100644 app/common/model/SysCurrency.php create mode 100644 app/common/model/SysDict.php create mode 100644 app/common/model/SysDictItem.php create mode 100644 app/common/model/SysPort.php create mode 100644 app/common/model/VehColor.php create mode 100644 app/common/model/VehModification.php create mode 100644 app/common/service/BrandSeriesService.php create mode 100644 app/common/service/BrandService.php create mode 100644 app/common/service/SysAccountService.php create mode 100644 app/common/service/SysCurrencyService.php create mode 100644 app/common/service/SysDictItemService.php create mode 100644 app/common/service/SysDictService.php create mode 100644 app/common/service/SysPortService.php create mode 100644 app/common/service/VehColorService.php create mode 100644 app/common/service/VehModificationService.php create mode 100644 app/queue/redis/InquiryToCrmNew_BACKUP_5243.php create mode 100644 app/queue/redis/InquiryToCrmNew_BASE_5243.php create mode 100644 app/queue/redis/InquiryToCrmNew_LOCAL_5243.php create mode 100644 app/queue/redis/InquiryToCrmNew_REMOTE_5243.php diff --git a/app/admin/controller/BrandController.php b/app/admin/controller/BrandController.php new file mode 100644 index 0000000..f416d9d --- /dev/null +++ b/app/admin/controller/BrandController.php @@ -0,0 +1,53 @@ +service = new BrandService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (!empty($data['logo'])) + $data['logo_full'] = (new OssService)->generatePrivateUrl($data['logo']); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (empty($data['logo'])) + $data['logo_full'] = (new OssService)->generatePrivateUrl($data['logo']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/BrandSeriesController.php b/app/admin/controller/BrandSeriesController.php new file mode 100644 index 0000000..c2d95f7 --- /dev/null +++ b/app/admin/controller/BrandSeriesController.php @@ -0,0 +1,48 @@ +service = new BrandSeriesService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/SysAccountController.php b/app/admin/controller/SysAccountController.php new file mode 100644 index 0000000..64398bb --- /dev/null +++ b/app/admin/controller/SysAccountController.php @@ -0,0 +1,52 @@ +service = new SysAccountService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name'); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + $data['currency_name'] = SysCurrency::where('id', $data['currency_id'])->value('currency_name'); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/SysCurrencyController.php b/app/admin/controller/SysCurrencyController.php new file mode 100644 index 0000000..0e96169 --- /dev/null +++ b/app/admin/controller/SysCurrencyController.php @@ -0,0 +1,52 @@ +service = new SysCurrencyService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['last_updated'])) + $data['last_updated'] = date('Y-m-d H:i:s', $data['last_updated']); + return $data; + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['last_updated'])) + $data['last_updated'] = date('Y-m-d H:i:s', $data['last_updated']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/SysDictController.php b/app/admin/controller/SysDictController.php new file mode 100644 index 0000000..0e0b8d7 --- /dev/null +++ b/app/admin/controller/SysDictController.php @@ -0,0 +1,54 @@ +service = new SysDictService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['sysDictItem'])) + $data['sysDictItem'] = SysDictItem::where('dict_id',$data['id'])->get(); + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + $data['sysDictItem'] = SysDictItem::where('dict_id',$data['id'])->get(); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/SysDictItemController.php b/app/admin/controller/SysDictItemController.php new file mode 100644 index 0000000..9262933 --- /dev/null +++ b/app/admin/controller/SysDictItemController.php @@ -0,0 +1,48 @@ +service = new SysDictItemService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/SysPortController.php b/app/admin/controller/SysPortController.php new file mode 100644 index 0000000..d98577e --- /dev/null +++ b/app/admin/controller/SysPortController.php @@ -0,0 +1,53 @@ +service = new SysPortService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + if (isset($data['country_id'])) + if (isset($data['country_id'])) + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr'); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + $data['country_name'] = Country::where('id', $data['country_id'])->value('cn_addr'); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/controller/VehColorController.php b/app/admin/controller/VehColorController.php new file mode 100644 index 0000000..0d208ae --- /dev/null +++ b/app/admin/controller/VehColorController.php @@ -0,0 +1,33 @@ +service = new VehColorService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/admin/controller/VehModificationController.php b/app/admin/controller/VehModificationController.php new file mode 100644 index 0000000..fc057e1 --- /dev/null +++ b/app/admin/controller/VehModificationController.php @@ -0,0 +1,48 @@ +service = new VehModificationService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + protected function indexFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } + + /** + * 数据格式化 + * + * @param array $data + * @return array + */ + protected function showFormat($data) + { + if (isset($data['created_at'])) + $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + if (isset($data['updated_at'])) + $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/logic/BrandLogic.php b/app/admin/logic/BrandLogic.php new file mode 100644 index 0000000..6b12364 --- /dev/null +++ b/app/admin/logic/BrandLogic.php @@ -0,0 +1,17 @@ +validator; + } + + /** + * 构建查询条件 + */ + + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + $config['where']['brand_id'] = $p['brand_id']; + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['series_code','series_name'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + //$config['where']['status'] = 1; + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/BrandService.php b/app/admin/service/BrandService.php new file mode 100644 index 0000000..c35df96 --- /dev/null +++ b/app/admin/service/BrandService.php @@ -0,0 +1,79 @@ +validator; + } + + /** + * 构建查询条件 + */ + + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['brand_code','brand_name'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + //$config['where']['status'] = 1; + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/SysAccountService.php b/app/admin/service/SysAccountService.php new file mode 100644 index 0000000..d413778 --- /dev/null +++ b/app/admin/service/SysAccountService.php @@ -0,0 +1,82 @@ +validator; + } + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 状态 + if (isset($p['type']) && $p['type']) { + $config['where']['type'] = $p['type']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['account_name','account_number','bank_name','bank_branch','description'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + //$config['where']['status'] = 1; + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/SysCurrencyService.php b/app/admin/service/SysCurrencyService.php new file mode 100644 index 0000000..19f0529 --- /dev/null +++ b/app/admin/service/SysCurrencyService.php @@ -0,0 +1,61 @@ +validator; + } + + + /** + * 构造 CrudUtil 查询配置 + */ + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'default': + $config['order']['id'] = 'desc'; + case 'index': + break; + case 'show': + $config['where']['id'] = $p['id']; + break; + case 'store': + break; + case 'update': + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/SysDictItemService.php b/app/admin/service/SysDictItemService.php new file mode 100644 index 0000000..577b9f0 --- /dev/null +++ b/app/admin/service/SysDictItemService.php @@ -0,0 +1,75 @@ +validator; + } + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'index'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + + $config['where']['dict_id'] = $p['id']; + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['item_label','item_value','remark'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + break; + case 'show': + $config['where']['id'] = $p['id']; + break; + case 'update': + case 'destroy': + $config['where']['id'] = $p['id']; + break; + case 'store': + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/SysDictService.php b/app/admin/service/SysDictService.php new file mode 100644 index 0000000..1d08fcb --- /dev/null +++ b/app/admin/service/SysDictService.php @@ -0,0 +1,81 @@ +validator; + } + + + /** + * 构建查询条件 + */ + protected function buildQueryConfig(Request $request, string $scene = 'index'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['dict_name','dict_code','description'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + + // ====== ====== 关联 ====== ====== + $config['with']['sysDictItem'][] = 'item_label'; + $config['with']['sysDictItem'][] = 'item_value'; + break; + case 'show': + $config['where']['id'] = $p['id']; + // ====== ====== 关联 ====== ====== + $config['with']['sysDictItem'][] = 'item_label'; + $config['with']['sysDictItem'][] = 'item_value'; + break; + case 'update': + case 'destroy': + $config['where']['id'] = $p['id']; + break; + case 'store': + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/service/SysPortService.php b/app/admin/service/SysPortService.php new file mode 100644 index 0000000..7a2dfd0 --- /dev/null +++ b/app/admin/service/SysPortService.php @@ -0,0 +1,103 @@ +validator; + } + + /** + * 构建查询条件 + */ + + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['port_code','port_name'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + //$config['where']['status'] = 1; + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } + + /** + * 添加前置处理 + */ + public function beforeServiceStore($data, Request $request) + { + if(empty($data['lat'])) + unset($data['lat']); + if(empty($data['lng'])) + unset($data['lng']); + return $data; + } + + /** + * 添加前置处理 + */ + public function beforeServiceUpdate($data, Request $request) + { + if(empty($data['lat'])) + unset($data['lat']); + if(empty($data['lng'])) + unset($data['lng']); + return $data; + } +} \ No newline at end of file diff --git a/app/admin/service/VehColorService.php b/app/admin/service/VehColorService.php new file mode 100644 index 0000000..a701ef4 --- /dev/null +++ b/app/admin/service/VehColorService.php @@ -0,0 +1,31 @@ +validator; + } +} \ No newline at end of file diff --git a/app/admin/service/VehModificationService.php b/app/admin/service/VehModificationService.php new file mode 100644 index 0000000..6c56d9b --- /dev/null +++ b/app/admin/service/VehModificationService.php @@ -0,0 +1,83 @@ +validator; + } + + /** + * 构建查询条件 + */ + + protected function buildQueryConfig(Request $request, string $scene = 'default'): array + { + $p = $request->all(); + + $config = []; + $config['model'] = $this->modelClass; + switch ($scene) { + case 'index': + // ====== ====== 排序 ====== ====== + $config['order']['sort'] = 'desc'; + $config['order']['id'] = 'desc'; + + // ====== ====== 筛选 ====== ====== + // 状态 + if (isset($p['status']) && in_array($p['status'], [0,1])) { + $config['where']['status'] = $p['status']; + } + // 状态 + if (isset($p['type']) && $p['type']) { + $config['where']['type'] = $p['type']; + } + // 关键字 + if (isset($p['keyword']) && $p['keyword']) { + $k = '%' . $p['keyword'] . '%'; + foreach (['code','name'] as $col) { + $config['orWhere'][] = [$col, 'like', $k]; + } + } + //$config['where']['status'] = 1; + break; + case 'show': + $config['where']['id'] = $p['id']; + //$config['where']['status'] = 1; + break; + case 'store': + break; + case 'update': + $config['where']['id'] = $p['id']; + break; + case 'destroy': + $config['where']['id'] = $p['id']; + break; + } + + return $config; + } +} \ No newline at end of file diff --git a/app/admin/validate/BrandSeriesValidate.php b/app/admin/validate/BrandSeriesValidate.php new file mode 100644 index 0000000..31e30e2 --- /dev/null +++ b/app/admin/validate/BrandSeriesValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/BrandValidate.php b/app/admin/validate/BrandValidate.php new file mode 100644 index 0000000..370728d --- /dev/null +++ b/app/admin/validate/BrandValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/SysAccountValidate.php b/app/admin/validate/SysAccountValidate.php new file mode 100644 index 0000000..65cc1d7 --- /dev/null +++ b/app/admin/validate/SysAccountValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/SysCurrencyValidate.php b/app/admin/validate/SysCurrencyValidate.php new file mode 100644 index 0000000..4aebb21 --- /dev/null +++ b/app/admin/validate/SysCurrencyValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/SysDictItemValidate.php b/app/admin/validate/SysDictItemValidate.php new file mode 100644 index 0000000..2d4ad58 --- /dev/null +++ b/app/admin/validate/SysDictItemValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/SysDictValidate.php b/app/admin/validate/SysDictValidate.php new file mode 100644 index 0000000..bdb6d1e --- /dev/null +++ b/app/admin/validate/SysDictValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/SysPortValidate.php b/app/admin/validate/SysPortValidate.php new file mode 100644 index 0000000..26cb9cd --- /dev/null +++ b/app/admin/validate/SysPortValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/VehColorValidate.php b/app/admin/validate/VehColorValidate.php new file mode 100644 index 0000000..1c619ec --- /dev/null +++ b/app/admin/validate/VehColorValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/admin/validate/VehModificationValidate.php b/app/admin/validate/VehModificationValidate.php new file mode 100644 index 0000000..805b049 --- /dev/null +++ b/app/admin/validate/VehModificationValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/controller/PresetController.php b/app/common/controller/PresetController.php index 37073c4..0d3ebf1 100644 --- a/app/common/controller/PresetController.php +++ b/app/common/controller/PresetController.php @@ -3,6 +3,15 @@ namespace app\common\controller; use app\admin\service\RoleService; +use app\common\service\BrandSeriesService; +use app\common\service\BrandService; +use app\common\service\SysAccountService; +use app\common\service\SysCurrencyService; +use app\common\service\SysDictItemService; +use app\common\service\SysDictService; +use app\common\service\SysPortService; +use app\common\service\VehColorService; +use app\common\service\VehModificationService; use support\Request; use app\common\service\CorpService; use app\common\service\CorpFeishuAppService; @@ -76,6 +85,99 @@ class PresetController extends BaseController } } + public function currency() + { + try { + $result = (new SysCurrencyService)->getList(); + return $this->success($result, '获取货币列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function brand() + { + try { + $result = (new BrandService)->getList(); + return $this->success($result, '获取品牌列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function series(Request $request) + { + try { + $params = $request->all(); + $result = (new BrandSeriesService)->getList($params); + return $this->success($result, '获取车系列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function account() + { + try { + $result = (new SysAccountService)->getList(); + return $this->success($result, '获取账号列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function dict() + { + try { + $result = (new SysDictService)->getList(); + return $this->success($result, '获取字典列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function dictItem(Request $request) + { + try { + $params = $request->all(); + $result = (new SysDictItemService)->getList($params); + return $this->success($result, '获取字典项列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function port() + { + try { + $result = (new SysPortService)->getList(); + return $this->success($result, '获取港口列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function color(Request $request) + { + try { + $params = $request->all(); + $result = (new VehColorService)->getList($params); + return $this->success($result, '获取颜色列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + + public function modification() + { + try { + $result = (new VehModificationService)->getList(); + return $this->success($result, '获取货币列表'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } + public function cacheClear() { diff --git a/app/common/logic/BrandLogic.php b/app/common/logic/BrandLogic.php new file mode 100644 index 0000000..3040572 --- /dev/null +++ b/app/common/logic/BrandLogic.php @@ -0,0 +1,22 @@ +orderBy('sort','desc')->get(['id', 'brand_code', 'brand_name', 'logo', 'description']); + } + +} \ No newline at end of file diff --git a/app/common/logic/BrandSeriesLogic.php b/app/common/logic/BrandSeriesLogic.php new file mode 100644 index 0000000..956ca55 --- /dev/null +++ b/app/common/logic/BrandSeriesLogic.php @@ -0,0 +1,22 @@ +where($where)->orderBy('sort','desc')->get(['id', 'series_code', 'series_name', 'description']); + } + +} \ No newline at end of file diff --git a/app/common/logic/SysAccountLogic.php b/app/common/logic/SysAccountLogic.php new file mode 100644 index 0000000..2f43410 --- /dev/null +++ b/app/common/logic/SysAccountLogic.php @@ -0,0 +1,22 @@ +orderBy('sort','desc')->get(['id', 'account_name', 'currency_id', 'account_number', 'bank_name', 'bank_branch', 'description']); + } + +} \ No newline at end of file diff --git a/app/common/logic/SysCurrencyLogic.php b/app/common/logic/SysCurrencyLogic.php new file mode 100644 index 0000000..206efa2 --- /dev/null +++ b/app/common/logic/SysCurrencyLogic.php @@ -0,0 +1,21 @@ +get(['id', 'currency_code', 'currency_name', 'currency_symbol', 'exchange_rate', 'float_percent']); + } +} \ No newline at end of file diff --git a/app/common/logic/SysDictItemLogic.php b/app/common/logic/SysDictItemLogic.php new file mode 100644 index 0000000..d6efc72 --- /dev/null +++ b/app/common/logic/SysDictItemLogic.php @@ -0,0 +1,22 @@ +where($where)->orderBy('sort','desc')->get(['id', 'item_label', 'item_value', 'remark', 'dict_id']); + } + +} \ No newline at end of file diff --git a/app/common/logic/SysDictLogic.php b/app/common/logic/SysDictLogic.php new file mode 100644 index 0000000..6447ed3 --- /dev/null +++ b/app/common/logic/SysDictLogic.php @@ -0,0 +1,27 @@ +where('code', $code)->orderBy('sort','desc')->first(['id']); + } + + public function getList() + { + return SysDict::where('status', 1)->get(['id', 'dict_name', 'dict_code', 'description']); + } + +} \ No newline at end of file diff --git a/app/common/logic/SysPortLogic.php b/app/common/logic/SysPortLogic.php new file mode 100644 index 0000000..a2e78a8 --- /dev/null +++ b/app/common/logic/SysPortLogic.php @@ -0,0 +1,22 @@ +orderBy('sort','desc')->get(['id', 'port_code', 'port_name', 'country_id', 'description']); + } + +} \ No newline at end of file diff --git a/app/common/logic/VehColorLogic.php b/app/common/logic/VehColorLogic.php new file mode 100644 index 0000000..7a36811 --- /dev/null +++ b/app/common/logic/VehColorLogic.php @@ -0,0 +1,22 @@ +where($where)->orderBy('sort','desc')->get(['id', 'color_code', 'color_text']); + } + +} \ No newline at end of file diff --git a/app/common/logic/VehModificationLogic.php b/app/common/logic/VehModificationLogic.php new file mode 100644 index 0000000..3317235 --- /dev/null +++ b/app/common/logic/VehModificationLogic.php @@ -0,0 +1,22 @@ +orderBy('sort','desc')->get(['id', 'code', 'name', 'type', 'price']); + } + +} \ No newline at end of file diff --git a/app/common/model/Brand.php b/app/common/model/Brand.php new file mode 100644 index 0000000..22c4704 --- /dev/null +++ b/app/common/model/Brand.php @@ -0,0 +1,49 @@ +hasMany(SysDictItem::class, 'dict_id', 'id'); + } +} \ No newline at end of file diff --git a/app/common/model/SysDictItem.php b/app/common/model/SysDictItem.php new file mode 100644 index 0000000..f53a7a9 --- /dev/null +++ b/app/common/model/SysDictItem.php @@ -0,0 +1,59 @@ +belongsTo(SysDict::class, 'dict_id', 'id'); + } +} \ No newline at end of file diff --git a/app/common/model/SysPort.php b/app/common/model/SysPort.php new file mode 100644 index 0000000..2249b98 --- /dev/null +++ b/app/common/model/SysPort.php @@ -0,0 +1,49 @@ +logic = (new BrandSeriesLogic()); + } + + /** + * 获取系统list + */ + public function getList($params) + { + if (empty($params['brand_id'])) + throw new BusinessException('品牌id不能为空'); + $where = []; + if(isset($params['brand_id']) && $params['brand_id']) + $where[] = ['brand_id', '=', $params['brand_id']]; + return $this->logic->getList($where); + } +} \ No newline at end of file diff --git a/app/common/service/BrandService.php b/app/common/service/BrandService.php new file mode 100644 index 0000000..c3430fe --- /dev/null +++ b/app/common/service/BrandService.php @@ -0,0 +1,24 @@ +logic = (new BrandLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/common/service/SysAccountService.php b/app/common/service/SysAccountService.php new file mode 100644 index 0000000..b9c59ad --- /dev/null +++ b/app/common/service/SysAccountService.php @@ -0,0 +1,28 @@ +logic = (new SysAccountLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/common/service/SysCurrencyService.php b/app/common/service/SysCurrencyService.php new file mode 100644 index 0000000..f0108d0 --- /dev/null +++ b/app/common/service/SysCurrencyService.php @@ -0,0 +1,25 @@ +logic = (new SysCurrencyLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/common/service/SysDictItemService.php b/app/common/service/SysDictItemService.php new file mode 100644 index 0000000..c1e51ed --- /dev/null +++ b/app/common/service/SysDictItemService.php @@ -0,0 +1,42 @@ +logic = (new SysDictItemLogic()); + } + + /** + * 获取系统list + */ + public function getList($params) + { + if (empty($params['dict_id']) && empty($params['dict_code'])) + throw new BusinessException('未明确要查询的字典组'); + $where = []; + if(isset($params['dict_id']) && $params['dict_id']) + $where[] = ['dict_id', '=', $params['dict_id']]; + if(isset($params['dict_code']) && $params['dict_code']){ + $dict = (new SysDictLogic)->getDictByCode($params['dict_code']); + if (empty($dict['id'])) + throw new BusinessException('字典组code错误'); + $where[] = ['dict_id', '=', $dict['id']]; + } + + return $this->logic->getList($where); + } +} \ No newline at end of file diff --git a/app/common/service/SysDictService.php b/app/common/service/SysDictService.php new file mode 100644 index 0000000..57ab33c --- /dev/null +++ b/app/common/service/SysDictService.php @@ -0,0 +1,28 @@ +logic = (new SysDictLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/common/service/SysPortService.php b/app/common/service/SysPortService.php new file mode 100644 index 0000000..2918a96 --- /dev/null +++ b/app/common/service/SysPortService.php @@ -0,0 +1,28 @@ +logic = (new SysPortLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/common/service/VehColorService.php b/app/common/service/VehColorService.php new file mode 100644 index 0000000..2060efe --- /dev/null +++ b/app/common/service/VehColorService.php @@ -0,0 +1,33 @@ +logic = (new VehColorLogic()); + } + + /** + * 获取系统list + */ + public function getList($params) + { + if (empty($params['type'])) + throw new BusinessException('类型不能为空'); + $where = []; + if(isset($params['type']) && $params['type']) + $where[] = ['type', '=', $params['type']]; + return $this->logic->getList($where); + } +} \ No newline at end of file diff --git a/app/common/service/VehModificationService.php b/app/common/service/VehModificationService.php new file mode 100644 index 0000000..31c7119 --- /dev/null +++ b/app/common/service/VehModificationService.php @@ -0,0 +1,28 @@ +logic = (new VehModificationLogic()); + } + + /** + * 获取系统list + */ + public function getList() + { + return $this->logic->getList(); + } +} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php b/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php new file mode 100644 index 0000000..d63b683 --- /dev/null +++ b/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php @@ -0,0 +1,218 @@ +where('id', $data['id'])->first(); + + // 无论添加 或 更新,询单必然要存在 + if (!$info) { + throw new BusinessException('询盘不存在:' . $data['id']); + } + + if ($info->status == 0 && $info->recipient == 0) { + // 如果询单未发、未分,则不与crm同步,不做任何处理 + return true; + } + + // 更改库信息 + $this->syncCustomer($info); + } catch (\Throwable $th) { + throw $th; + } + } + + public function pushWs($title, $content, $recipient = []) + { + $wsdata = [ + 'sender_id' => 0, + 'sender_type' => 'system', + 'title' => $title, + 'content' => $content, + 'scene' => 1, + 'recipient' => $recipient + ]; + // 异步推送 + \Webman\RedisQueue\Redis::send('notice', $wsdata); + } + + public function syncCustomer(Model $info) + { + $uInfo = $this->recipientInfo($info); + $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); + if ($crmCustomerInfo) { + + // 消息推送 + if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { + // $notice = '更新'; + $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + // $notice = '重新分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + + $udata = [ +<<<<<<< HEAD + 'corp_abbr' => $uInfo['corpId'], +======= + 'corp_id' => $uInfo['corpId'], +>>>>>>> feature/distinct + 'user_id' => $info->recipient, + 'channel_id' => $info->channel, + 'country_id' => $info->country, + 'magnitude' => $info->quality, + 'email' => $info->email, + 'phone' => $info->tel, + 'WhatsApp' => $info->whatsapp, + 'contacts' => $info->contacts, + 'desc_collect' => $info->content, + ]; + if (!$crmCustomerInfo->update($udata)) { + throw new BusinessException('同步失败,更新客户线索失败'); + } + } else { + $crmCustomer = new CrmCustomer(); + $crmCustomer->sn = $info->order_no; +<<<<<<< HEAD + $crmCustomer->corp_abbr = $uInfo['corpId']; +======= + $crmCustomer->corp_id = $uInfo['corpId']; +>>>>>>> feature/distinct + $crmCustomer->user_id = $uInfo['recipient']; + $crmCustomer->type = 1; + $crmCustomer->channel_id = $info->channel; + $crmCustomer->country_id = $info->country; + $crmCustomer->magnitude = $info->quality; + $crmCustomer->email = $info->email; + $crmCustomer->phone = $info->tel; + $crmCustomer->WhatsApp = $info->whatsapp; + $crmCustomer->contacts = $info->contacts; + $crmCustomer->desc_collect = $info->content; + $crmCustomer->enter_user_id = $info->enter_user_id; + $crmCustomer->obtain = time(); +<<<<<<< HEAD +======= + if(empty($uInfo['recipient'])){ + $crmCustomer->deleted_at = time(); + } +>>>>>>> feature/distinct + // 修改同步CRM状态 + $info->sync_crm = 1; + // 保存 + if (!$crmCustomer->save() || !$info->save()) { + throw new BusinessException('同步失败,创建客户线索失败'); + } + + // 消息推送 + if ($info->status == 1) { + // $notice = '发布'; + $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content); + } + + if ($info->status == 2) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + return true; + } + + public function recipientInfo(Model $info) + { + $recipient = 0; + $corpId = 0; + $uinfo = null; + if (!empty($info->recipient)) { + $recipient = $info->recipient; + $uinfo = User::where('id', $info->recipient)->first(); + if ($uinfo) { + $corpId = $uinfo->corp_id; + } + } + return [ + 'recipient' => $recipient, + 'corpId' => $corpId, + 'uinfo' => $uinfo + ]; + } + + // 消费失败回调 + /* + $package = [ + 'id' => 1357277951, // 消息ID + 'time' => 1709170510, // 消息时间 + 'delay' => 0, // 延迟时间 + 'attempts' => 2, // 消费次数 + 'queue' => 'send-mail', // 队列名 + 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 + 'max_attempts' => 5, // 最大重试次数 + 'error' => '错误信息' // 错误信息 + ] + */ + public function onConsumeFailure(\Throwable $e, $package) + { + echo "consume failure\n"; + echo $e->getMessage() . "\n"; + // 无需反序列化 + var_export($package); + } +} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmNew_BASE_5243.php b/app/queue/redis/InquiryToCrmNew_BASE_5243.php new file mode 100644 index 0000000..e69de29 diff --git a/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php b/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php new file mode 100644 index 0000000..a350c7e --- /dev/null +++ b/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php @@ -0,0 +1,204 @@ +where('id', $data['id'])->first(); + + // 无论添加 或 更新,询单必然要存在 + if (!$info) { + throw new BusinessException('询盘不存在:' . $data['id']); + } + + if ($info->status == 0 && $info->recipient == 0) { + // 如果询单未发、未分,则不与crm同步,不做任何处理 + return true; + } + + // 更改库信息 + $this->syncCustomer($info); + } catch (\Throwable $th) { + throw $th; + } + } + + public function pushWs($title, $content, $recipient = []) + { + $wsdata = [ + 'sender_id' => 0, + 'sender_type' => 'system', + 'title' => $title, + 'content' => $content, + 'scene' => 1, + 'recipient' => $recipient + ]; + // 异步推送 + \Webman\RedisQueue\Redis::send('notice', $wsdata); + } + + public function syncCustomer(Model $info) + { + $uInfo = $this->recipientInfo($info); + $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); + if ($crmCustomerInfo) { + + // 消息推送 + if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { + // $notice = '更新'; + $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + // $notice = '重新分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + + $udata = [ + 'corp_abbr' => $uInfo['corpId'], + 'user_id' => $info->recipient, + 'channel_id' => $info->channel, + 'country_id' => $info->country, + 'magnitude' => $info->quality, + 'email' => $info->email, + 'phone' => $info->tel, + 'WhatsApp' => $info->whatsapp, + 'contacts' => $info->contacts, + 'desc_collect' => $info->content, + ]; + if (!$crmCustomerInfo->update($udata)) { + throw new BusinessException('同步失败,更新客户线索失败'); + } + } else { + $crmCustomer = new CrmCustomer(); + $crmCustomer->sn = $info->order_no; + $crmCustomer->corp_abbr = $uInfo['corpId']; + $crmCustomer->user_id = $uInfo['recipient']; + $crmCustomer->type = 1; + $crmCustomer->channel_id = $info->channel; + $crmCustomer->country_id = $info->country; + $crmCustomer->magnitude = $info->quality; + $crmCustomer->email = $info->email; + $crmCustomer->phone = $info->tel; + $crmCustomer->WhatsApp = $info->whatsapp; + $crmCustomer->contacts = $info->contacts; + $crmCustomer->desc_collect = $info->content; + $crmCustomer->enter_user_id = $info->enter_user_id; + $crmCustomer->obtain = time(); + // 修改同步CRM状态 + $info->sync_crm = 1; + // 保存 + if (!$crmCustomer->save() || !$info->save()) { + throw new BusinessException('同步失败,创建客户线索失败'); + } + + // 消息推送 + if ($info->status == 1) { + // $notice = '发布'; + $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content); + } + + if ($info->status == 2) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + return true; + } + + public function recipientInfo(Model $info) + { + $recipient = 0; + $corpId = 0; + $uinfo = null; + if (!empty($info->recipient)) { + $recipient = $info->recipient; + $uinfo = User::where('id', $info->recipient)->first(); + if ($uinfo) { + $corpId = $uinfo->corp_id; + } + } + return [ + 'recipient' => $recipient, + 'corpId' => $corpId, + 'uinfo' => $uinfo + ]; + } + + // 消费失败回调 + /* + $package = [ + 'id' => 1357277951, // 消息ID + 'time' => 1709170510, // 消息时间 + 'delay' => 0, // 延迟时间 + 'attempts' => 2, // 消费次数 + 'queue' => 'send-mail', // 队列名 + 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 + 'max_attempts' => 5, // 最大重试次数 + 'error' => '错误信息' // 错误信息 + ] + */ + public function onConsumeFailure(\Throwable $e, $package) + { + echo "consume failure\n"; + echo $e->getMessage() . "\n"; + // 无需反序列化 + var_export($package); + } +} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php b/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php new file mode 100644 index 0000000..075deda --- /dev/null +++ b/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php @@ -0,0 +1,207 @@ +where('id', $data['id'])->first(); + + // 无论添加 或 更新,询单必然要存在 + if (!$info) { + throw new BusinessException('询盘不存在:' . $data['id']); + } + + if ($info->status == 0 && $info->recipient == 0) { + // 如果询单未发、未分,则不与crm同步,不做任何处理 + return true; + } + + // 更改库信息 + $this->syncCustomer($info); + } catch (\Throwable $th) { + throw $th; + } + } + + public function pushWs($title, $content, $recipient = []) + { + $wsdata = [ + 'sender_id' => 0, + 'sender_type' => 'system', + 'title' => $title, + 'content' => $content, + 'scene' => 1, + 'recipient' => $recipient + ]; + // 异步推送 + \Webman\RedisQueue\Redis::send('notice', $wsdata); + } + + public function syncCustomer(Model $info) + { + $uInfo = $this->recipientInfo($info); + $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); + if ($crmCustomerInfo) { + + // 消息推送 + if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { + // $notice = '更新'; + $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } else { + // $notice = '重新分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + + $udata = [ + 'corp_id' => $uInfo['corpId'], + 'user_id' => $info->recipient, + 'channel_id' => $info->channel, + 'country_id' => $info->country, + 'magnitude' => $info->quality, + 'email' => $info->email, + 'phone' => $info->tel, + 'WhatsApp' => $info->whatsapp, + 'contacts' => $info->contacts, + 'desc_collect' => $info->content, + ]; + if (!$crmCustomerInfo->update($udata)) { + throw new BusinessException('同步失败,更新客户线索失败'); + } + } else { + $crmCustomer = new CrmCustomer(); + $crmCustomer->sn = $info->order_no; + $crmCustomer->corp_id = $uInfo['corpId']; + $crmCustomer->user_id = $uInfo['recipient']; + $crmCustomer->type = 1; + $crmCustomer->channel_id = $info->channel; + $crmCustomer->country_id = $info->country; + $crmCustomer->magnitude = $info->quality; + $crmCustomer->email = $info->email; + $crmCustomer->phone = $info->tel; + $crmCustomer->WhatsApp = $info->whatsapp; + $crmCustomer->contacts = $info->contacts; + $crmCustomer->desc_collect = $info->content; + $crmCustomer->enter_user_id = $info->enter_user_id; + $crmCustomer->obtain = time(); + if(empty($uInfo['recipient'])){ + $crmCustomer->deleted_at = time(); + } + // 修改同步CRM状态 + $info->sync_crm = 1; + // 保存 + if (!$crmCustomer->save() || !$info->save()) { + throw new BusinessException('同步失败,创建客户线索失败'); + } + + // 消息推送 + if ($info->status == 1) { + // $notice = '发布'; + $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content); + } + + if ($info->status == 2) { + // $notice = '分配'; + $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; + $recipient = [$info->recipient]; + $this->pushWs($title, $content, $recipient); + } + } + return true; + } + + public function recipientInfo(Model $info) + { + $recipient = 0; + $corpId = 0; + $uinfo = null; + if (!empty($info->recipient)) { + $recipient = $info->recipient; + $uinfo = User::where('id', $info->recipient)->first(); + if ($uinfo) { + $corpId = $uinfo->corp_id; + } + } + return [ + 'recipient' => $recipient, + 'corpId' => $corpId, + 'uinfo' => $uinfo + ]; + } + + // 消费失败回调 + /* + $package = [ + 'id' => 1357277951, // 消息ID + 'time' => 1709170510, // 消息时间 + 'delay' => 0, // 延迟时间 + 'attempts' => 2, // 消费次数 + 'queue' => 'send-mail', // 队列名 + 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 + 'max_attempts' => 5, // 最大重试次数 + 'error' => '错误信息' // 错误信息 + ] + */ + public function onConsumeFailure(\Throwable $e, $package) + { + echo "consume failure\n"; + echo $e->getMessage() . "\n"; + // 无需反序列化 + var_export($package); + } +} \ No newline at end of file diff --git a/config/route.php b/config/route.php index 43e45b6..e5c77fc 100644 --- a/config/route.php +++ b/config/route.php @@ -61,8 +61,17 @@ Route::group('/common', function () { Route::any('/feishu/app', [app\common\controller\PresetController::class, 'feishuApp']); Route::any('/systems', [app\common\controller\PresetController::class, 'systems']); Route::any('/roles', [app\common\controller\PresetController::class, 'roles']); + Route::any('/currency', [app\common\controller\PresetController::class, 'currency']); Route::any('/cache/clear', [app\common\controller\PresetController::class, 'cacheClear']); Route::any('/menus', [app\common\controller\PresetController::class, 'menus']); + Route::any('/brand', [app\common\controller\PresetController::class, 'brand']); + Route::any('/brand/series', [app\common\controller\PresetController::class, 'series']); + Route::any('/account', [app\common\controller\PresetController::class, 'account']); + Route::any('/dict', [app\common\controller\PresetController::class, 'dict']); + Route::any('/dictItem', [app\common\controller\PresetController::class, 'dictItem']); + Route::any('/port', [app\common\controller\PresetController::class, 'port']); + Route::any('/color', [app\common\controller\PresetController::class, 'color']); + Route::any('/modification', [app\common\controller\PresetController::class, 'modification']); }); @@ -194,6 +203,86 @@ Route::group('/admin', function () { Route::any('/destroy', [app\common\controller\VehVehicleSkuController::class, 'destroy']); }); }); + + // 字典 + Route::group('/dict', function () { + Route::any('/list', [app\admin\controller\SysDictController::class, 'index']); + Route::any('/show', [app\admin\controller\SysDictController::class, 'show']); + Route::any('/store', [app\admin\controller\SysDictController::class, 'store']); + Route::any('/update', [app\admin\controller\SysDictController::class, 'update']); + Route::any('/destroy', [app\admin\controller\SysDictController::class, 'destroy']); + + Route::group('/item', function () { + Route::any('/list', [app\admin\controller\SysDictItemController::class, 'index']); + Route::any('/show', [app\admin\controller\SysDictItemController::class, 'show']); + Route::any('/store', [app\admin\controller\SysDictItemController::class, 'store']); + Route::any('/update', [app\admin\controller\SysDictItemController::class, 'update']); + Route::any('/destroy', [app\admin\controller\SysDictItemController::class, 'destroy']); + }); + }); + + // 货币 + Route::group('/currency', function () { + Route::any('/list', [app\admin\controller\SysCurrencyController::class, 'index']); + Route::any('/show', [app\admin\controller\SysCurrencyController::class, 'show']); + Route::any('/store', [app\admin\controller\SysCurrencyController::class, 'store']); + Route::any('/update', [app\admin\controller\SysCurrencyController::class, 'update']); + Route::any('/destroy', [app\admin\controller\SysCurrencyController::class, 'destroy']); + }); + + // 品牌 + Route::group('/brand', function () { + Route::any('/list', [app\admin\controller\BrandController::class, 'index']); + Route::any('/show', [app\admin\controller\BrandController::class, 'show']); + Route::any('/store', [app\admin\controller\BrandController::class, 'store']); + Route::any('/update', [app\admin\controller\BrandController::class, 'update']); + Route::any('/destroy', [app\admin\controller\BrandController::class, 'destroy']); + // 车系 + Route::group('/series', function () { + Route::any('/list', [app\admin\controller\BrandSeriesController::class, 'index']); + Route::any('/show', [app\admin\controller\BrandSeriesController::class, 'show']); + Route::any('/store', [app\admin\controller\BrandSeriesController::class, 'store']); + Route::any('/update', [app\admin\controller\BrandSeriesController::class, 'update']); + Route::any('/destroy', [app\admin\controller\BrandSeriesController::class, 'destroy']); + }); + }); + + // 汽车颜色 + Route::group('/color', function () { + Route::any('/list', [app\admin\controller\VehColorController::class, 'index']); + Route::any('/show', [app\admin\controller\VehColorController::class, 'show']); + Route::any('/store', [app\admin\controller\VehColorController::class, 'store']); + Route::any('/update', [app\admin\controller\VehColorController::class, 'update']); + Route::any('/destroy', [app\admin\controller\VehColorController::class, 'destroy']); + }); + + // 汽车改装项目 + Route::group('/modification', function () { + Route::any('/list', [app\admin\controller\VehModificationController::class, 'index']); + Route::any('/show', [app\admin\controller\VehModificationController::class, 'show']); + Route::any('/store', [app\admin\controller\VehModificationController::class, 'store']); + Route::any('/update', [app\admin\controller\VehModificationController::class, 'update']); + Route::any('/destroy', [app\admin\controller\VehModificationController::class, 'destroy']); + }); + + // 账户 + Route::group('/account', function () { + Route::any('/list', [app\admin\controller\SysAccountController::class, 'index']); + Route::any('/show', [app\admin\controller\SysAccountController::class, 'show']); + Route::any('/store', [app\admin\controller\SysAccountController::class, 'store']); + Route::any('/update', [app\admin\controller\SysAccountController::class, 'update']); + Route::any('/destroy', [app\admin\controller\SysAccountController::class, 'destroy']); + }); + + // 账户 + Route::group('/port', function () { + Route::any('/list', [app\admin\controller\SysPortController::class, 'index']); + Route::any('/show', [app\admin\controller\SysPortController::class, 'show']); + Route::any('/store', [app\admin\controller\SysPortController::class, 'store']); + Route::any('/update', [app\admin\controller\SysPortController::class, 'update']); + Route::any('/destroy', [app\admin\controller\SysPortController::class, 'destroy']); + }); + }); From 7ded55ca0e9fbbbe96c26d8c352c8b2465a5db1a Mon Sep 17 00:00:00 2001 From: mzl Date: Mon, 1 Sep 2025 17:08:02 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=A8=E9=87=8F?= =?UTF-8?q?=E8=8C=83=E5=9B=B4=E5=AD=97=E5=85=B8=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/SysDictController.php | 24 ++ app/admin/service/SysDictService.php | 28 +++ .../controller/VehVehicleSkuController.php | 2 +- .../redis/InquiryToCrmNew_BACKUP_5243.php | 218 ------------------ app/queue/redis/InquiryToCrmNew_BASE_5243.php | 0 .../redis/InquiryToCrmNew_LOCAL_5243.php | 204 ---------------- .../redis/InquiryToCrmNew_REMOTE_5243.php | 207 ----------------- config/route.php | 1 + 8 files changed, 54 insertions(+), 630 deletions(-) delete mode 100644 app/queue/redis/InquiryToCrmNew_BACKUP_5243.php delete mode 100644 app/queue/redis/InquiryToCrmNew_BASE_5243.php delete mode 100644 app/queue/redis/InquiryToCrmNew_LOCAL_5243.php delete mode 100644 app/queue/redis/InquiryToCrmNew_REMOTE_5243.php diff --git a/app/admin/controller/SysDictController.php b/app/admin/controller/SysDictController.php index 0e0b8d7..34be3e1 100644 --- a/app/admin/controller/SysDictController.php +++ b/app/admin/controller/SysDictController.php @@ -51,4 +51,28 @@ class SysDictController extends BaseController $data['sysDictItem'] = SysDictItem::where('dict_id',$data['id'])->get(); return $data; } + + + + public function listScopeFormat($data) + { + $rdata = []; + foreach ($data as $item) { + $rdata[$item['dict_code']] = $item['sysDictItem']; + } + return $rdata; + } + + public function listScope(Request $request) + { + try { + $raw = $this->service->serviceListAllScope($request); + $data = $this->transformData($raw, method_exists($this, 'listScopeFormat') + ? [$this, 'listScopeFormat'] + : null); + return $this->success($data); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } } \ No newline at end of file diff --git a/app/admin/service/SysDictService.php b/app/admin/service/SysDictService.php index 1d08fcb..1261c30 100644 --- a/app/admin/service/SysDictService.php +++ b/app/admin/service/SysDictService.php @@ -74,8 +74,36 @@ class SysDictService break; case 'store': break; + case 'scope': + $config['order']['id'] = 'desc'; + if (isset($p['scope']) && !empty($p['scope'])) { + $config['where']['id'] = ['in', explode(',', $p['scope'])]; + } + $config['with']['sysDictItem'][] = 'dict_id'; + $config['with']['sysDictItem'][] = 'item_label'; + $config['with']['sysDictItem'][] = 'item_value'; + break; } return $config; } + + + public function serviceListAllScope(Request $request) + { + $config = $this->buildQueryConfig($request, 'scope'); + $result = $this->logicListAll($config); + return $this->postProcess('ListAllScope', $result); + } + + + public function afterServiceListAllScope($data) + { + + // $data->each(function (&$item) { + + // }); + + return $data; + } } \ No newline at end of file diff --git a/app/common/controller/VehVehicleSkuController.php b/app/common/controller/VehVehicleSkuController.php index 3ab3eb5..3272f28 100644 --- a/app/common/controller/VehVehicleSkuController.php +++ b/app/common/controller/VehVehicleSkuController.php @@ -90,7 +90,7 @@ class VehVehicleSkuController extends BaseController } - public function index22(Request $request) + public function fields_desc(Request $request) { $data = [ 'sku_code' , // 'SKU编码,系统生成', diff --git a/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php b/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php deleted file mode 100644 index d63b683..0000000 --- a/app/queue/redis/InquiryToCrmNew_BACKUP_5243.php +++ /dev/null @@ -1,218 +0,0 @@ -where('id', $data['id'])->first(); - - // 无论添加 或 更新,询单必然要存在 - if (!$info) { - throw new BusinessException('询盘不存在:' . $data['id']); - } - - if ($info->status == 0 && $info->recipient == 0) { - // 如果询单未发、未分,则不与crm同步,不做任何处理 - return true; - } - - // 更改库信息 - $this->syncCustomer($info); - } catch (\Throwable $th) { - throw $th; - } - } - - public function pushWs($title, $content, $recipient = []) - { - $wsdata = [ - 'sender_id' => 0, - 'sender_type' => 'system', - 'title' => $title, - 'content' => $content, - 'scene' => 1, - 'recipient' => $recipient - ]; - // 异步推送 - \Webman\RedisQueue\Redis::send('notice', $wsdata); - } - - public function syncCustomer(Model $info) - { - $uInfo = $this->recipientInfo($info); - $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); - if ($crmCustomerInfo) { - - // 消息推送 - if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { - // $notice = '更新'; - $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - // $notice = '重新分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - - $udata = [ -<<<<<<< HEAD - 'corp_abbr' => $uInfo['corpId'], -======= - 'corp_id' => $uInfo['corpId'], ->>>>>>> feature/distinct - 'user_id' => $info->recipient, - 'channel_id' => $info->channel, - 'country_id' => $info->country, - 'magnitude' => $info->quality, - 'email' => $info->email, - 'phone' => $info->tel, - 'WhatsApp' => $info->whatsapp, - 'contacts' => $info->contacts, - 'desc_collect' => $info->content, - ]; - if (!$crmCustomerInfo->update($udata)) { - throw new BusinessException('同步失败,更新客户线索失败'); - } - } else { - $crmCustomer = new CrmCustomer(); - $crmCustomer->sn = $info->order_no; -<<<<<<< HEAD - $crmCustomer->corp_abbr = $uInfo['corpId']; -======= - $crmCustomer->corp_id = $uInfo['corpId']; ->>>>>>> feature/distinct - $crmCustomer->user_id = $uInfo['recipient']; - $crmCustomer->type = 1; - $crmCustomer->channel_id = $info->channel; - $crmCustomer->country_id = $info->country; - $crmCustomer->magnitude = $info->quality; - $crmCustomer->email = $info->email; - $crmCustomer->phone = $info->tel; - $crmCustomer->WhatsApp = $info->whatsapp; - $crmCustomer->contacts = $info->contacts; - $crmCustomer->desc_collect = $info->content; - $crmCustomer->enter_user_id = $info->enter_user_id; - $crmCustomer->obtain = time(); -<<<<<<< HEAD -======= - if(empty($uInfo['recipient'])){ - $crmCustomer->deleted_at = time(); - } ->>>>>>> feature/distinct - // 修改同步CRM状态 - $info->sync_crm = 1; - // 保存 - if (!$crmCustomer->save() || !$info->save()) { - throw new BusinessException('同步失败,创建客户线索失败'); - } - - // 消息推送 - if ($info->status == 1) { - // $notice = '发布'; - $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content); - } - - if ($info->status == 2) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - return true; - } - - public function recipientInfo(Model $info) - { - $recipient = 0; - $corpId = 0; - $uinfo = null; - if (!empty($info->recipient)) { - $recipient = $info->recipient; - $uinfo = User::where('id', $info->recipient)->first(); - if ($uinfo) { - $corpId = $uinfo->corp_id; - } - } - return [ - 'recipient' => $recipient, - 'corpId' => $corpId, - 'uinfo' => $uinfo - ]; - } - - // 消费失败回调 - /* - $package = [ - 'id' => 1357277951, // 消息ID - 'time' => 1709170510, // 消息时间 - 'delay' => 0, // 延迟时间 - 'attempts' => 2, // 消费次数 - 'queue' => 'send-mail', // 队列名 - 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 - 'max_attempts' => 5, // 最大重试次数 - 'error' => '错误信息' // 错误信息 - ] - */ - public function onConsumeFailure(\Throwable $e, $package) - { - echo "consume failure\n"; - echo $e->getMessage() . "\n"; - // 无需反序列化 - var_export($package); - } -} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmNew_BASE_5243.php b/app/queue/redis/InquiryToCrmNew_BASE_5243.php deleted file mode 100644 index e69de29..0000000 diff --git a/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php b/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php deleted file mode 100644 index a350c7e..0000000 --- a/app/queue/redis/InquiryToCrmNew_LOCAL_5243.php +++ /dev/null @@ -1,204 +0,0 @@ -where('id', $data['id'])->first(); - - // 无论添加 或 更新,询单必然要存在 - if (!$info) { - throw new BusinessException('询盘不存在:' . $data['id']); - } - - if ($info->status == 0 && $info->recipient == 0) { - // 如果询单未发、未分,则不与crm同步,不做任何处理 - return true; - } - - // 更改库信息 - $this->syncCustomer($info); - } catch (\Throwable $th) { - throw $th; - } - } - - public function pushWs($title, $content, $recipient = []) - { - $wsdata = [ - 'sender_id' => 0, - 'sender_type' => 'system', - 'title' => $title, - 'content' => $content, - 'scene' => 1, - 'recipient' => $recipient - ]; - // 异步推送 - \Webman\RedisQueue\Redis::send('notice', $wsdata); - } - - public function syncCustomer(Model $info) - { - $uInfo = $this->recipientInfo($info); - $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); - if ($crmCustomerInfo) { - - // 消息推送 - if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { - // $notice = '更新'; - $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - // $notice = '重新分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - - $udata = [ - 'corp_abbr' => $uInfo['corpId'], - 'user_id' => $info->recipient, - 'channel_id' => $info->channel, - 'country_id' => $info->country, - 'magnitude' => $info->quality, - 'email' => $info->email, - 'phone' => $info->tel, - 'WhatsApp' => $info->whatsapp, - 'contacts' => $info->contacts, - 'desc_collect' => $info->content, - ]; - if (!$crmCustomerInfo->update($udata)) { - throw new BusinessException('同步失败,更新客户线索失败'); - } - } else { - $crmCustomer = new CrmCustomer(); - $crmCustomer->sn = $info->order_no; - $crmCustomer->corp_abbr = $uInfo['corpId']; - $crmCustomer->user_id = $uInfo['recipient']; - $crmCustomer->type = 1; - $crmCustomer->channel_id = $info->channel; - $crmCustomer->country_id = $info->country; - $crmCustomer->magnitude = $info->quality; - $crmCustomer->email = $info->email; - $crmCustomer->phone = $info->tel; - $crmCustomer->WhatsApp = $info->whatsapp; - $crmCustomer->contacts = $info->contacts; - $crmCustomer->desc_collect = $info->content; - $crmCustomer->enter_user_id = $info->enter_user_id; - $crmCustomer->obtain = time(); - // 修改同步CRM状态 - $info->sync_crm = 1; - // 保存 - if (!$crmCustomer->save() || !$info->save()) { - throw new BusinessException('同步失败,创建客户线索失败'); - } - - // 消息推送 - if ($info->status == 1) { - // $notice = '发布'; - $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content); - } - - if ($info->status == 2) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - return true; - } - - public function recipientInfo(Model $info) - { - $recipient = 0; - $corpId = 0; - $uinfo = null; - if (!empty($info->recipient)) { - $recipient = $info->recipient; - $uinfo = User::where('id', $info->recipient)->first(); - if ($uinfo) { - $corpId = $uinfo->corp_id; - } - } - return [ - 'recipient' => $recipient, - 'corpId' => $corpId, - 'uinfo' => $uinfo - ]; - } - - // 消费失败回调 - /* - $package = [ - 'id' => 1357277951, // 消息ID - 'time' => 1709170510, // 消息时间 - 'delay' => 0, // 延迟时间 - 'attempts' => 2, // 消费次数 - 'queue' => 'send-mail', // 队列名 - 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 - 'max_attempts' => 5, // 最大重试次数 - 'error' => '错误信息' // 错误信息 - ] - */ - public function onConsumeFailure(\Throwable $e, $package) - { - echo "consume failure\n"; - echo $e->getMessage() . "\n"; - // 无需反序列化 - var_export($package); - } -} \ No newline at end of file diff --git a/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php b/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php deleted file mode 100644 index 075deda..0000000 --- a/app/queue/redis/InquiryToCrmNew_REMOTE_5243.php +++ /dev/null @@ -1,207 +0,0 @@ -where('id', $data['id'])->first(); - - // 无论添加 或 更新,询单必然要存在 - if (!$info) { - throw new BusinessException('询盘不存在:' . $data['id']); - } - - if ($info->status == 0 && $info->recipient == 0) { - // 如果询单未发、未分,则不与crm同步,不做任何处理 - return true; - } - - // 更改库信息 - $this->syncCustomer($info); - } catch (\Throwable $th) { - throw $th; - } - } - - public function pushWs($title, $content, $recipient = []) - { - $wsdata = [ - 'sender_id' => 0, - 'sender_type' => 'system', - 'title' => $title, - 'content' => $content, - 'scene' => 1, - 'recipient' => $recipient - ]; - // 异步推送 - \Webman\RedisQueue\Redis::send('notice', $wsdata); - } - - public function syncCustomer(Model $info) - { - $uInfo = $this->recipientInfo($info); - $crmCustomerInfo = CrmCustomer::where('sn', $info->order_no)->first(); - if ($crmCustomerInfo) { - - // 消息推送 - if ($info->status == 2 && empty($crmCustomerInfo->user_id)) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - if ($info->status == 2 && $crmCustomerInfo->user_id == $info->recipient) { - // $notice = '更新'; - $title = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $content = '[询单·更新] 客户线索' . $info->order_no . '有新的调整,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } else { - // $notice = '重新分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - - $udata = [ - 'corp_id' => $uInfo['corpId'], - 'user_id' => $info->recipient, - 'channel_id' => $info->channel, - 'country_id' => $info->country, - 'magnitude' => $info->quality, - 'email' => $info->email, - 'phone' => $info->tel, - 'WhatsApp' => $info->whatsapp, - 'contacts' => $info->contacts, - 'desc_collect' => $info->content, - ]; - if (!$crmCustomerInfo->update($udata)) { - throw new BusinessException('同步失败,更新客户线索失败'); - } - } else { - $crmCustomer = new CrmCustomer(); - $crmCustomer->sn = $info->order_no; - $crmCustomer->corp_id = $uInfo['corpId']; - $crmCustomer->user_id = $uInfo['recipient']; - $crmCustomer->type = 1; - $crmCustomer->channel_id = $info->channel; - $crmCustomer->country_id = $info->country; - $crmCustomer->magnitude = $info->quality; - $crmCustomer->email = $info->email; - $crmCustomer->phone = $info->tel; - $crmCustomer->WhatsApp = $info->whatsapp; - $crmCustomer->contacts = $info->contacts; - $crmCustomer->desc_collect = $info->content; - $crmCustomer->enter_user_id = $info->enter_user_id; - $crmCustomer->obtain = time(); - if(empty($uInfo['recipient'])){ - $crmCustomer->deleted_at = time(); - } - // 修改同步CRM状态 - $info->sync_crm = 1; - // 保存 - if (!$crmCustomer->save() || !$info->save()) { - throw new BusinessException('同步失败,创建客户线索失败'); - } - - // 消息推送 - if ($info->status == 1) { - // $notice = '发布'; - $title = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $content = '[询单·公海] 新的客户线索【' . $info->order_no . '】发布'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content); - } - - if ($info->status == 2) { - // $notice = '分配'; - $title = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $content = '[询单·分配] 新的客户线索【' . $info->order_no . '】,请及时处理'; - $recipient = [$info->recipient]; - $this->pushWs($title, $content, $recipient); - } - } - return true; - } - - public function recipientInfo(Model $info) - { - $recipient = 0; - $corpId = 0; - $uinfo = null; - if (!empty($info->recipient)) { - $recipient = $info->recipient; - $uinfo = User::where('id', $info->recipient)->first(); - if ($uinfo) { - $corpId = $uinfo->corp_id; - } - } - return [ - 'recipient' => $recipient, - 'corpId' => $corpId, - 'uinfo' => $uinfo - ]; - } - - // 消费失败回调 - /* - $package = [ - 'id' => 1357277951, // 消息ID - 'time' => 1709170510, // 消息时间 - 'delay' => 0, // 延迟时间 - 'attempts' => 2, // 消费次数 - 'queue' => 'send-mail', // 队列名 - 'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容 - 'max_attempts' => 5, // 最大重试次数 - 'error' => '错误信息' // 错误信息 - ] - */ - public function onConsumeFailure(\Throwable $e, $package) - { - echo "consume failure\n"; - echo $e->getMessage() . "\n"; - // 无需反序列化 - var_export($package); - } -} \ No newline at end of file diff --git a/config/route.php b/config/route.php index e5c77fc..38c7907 100644 --- a/config/route.php +++ b/config/route.php @@ -211,6 +211,7 @@ Route::group('/admin', function () { Route::any('/store', [app\admin\controller\SysDictController::class, 'store']); Route::any('/update', [app\admin\controller\SysDictController::class, 'update']); Route::any('/destroy', [app\admin\controller\SysDictController::class, 'destroy']); + Route::any('/scope', [app\admin\controller\SysDictController::class, 'listScope']); Route::group('/item', function () { Route::any('/list', [app\admin\controller\SysDictItemController::class, 'index']); From 476921e6b8322c23683d54f5844d3b766c96af01 Mon Sep 17 00:00:00 2001 From: mzl Date: Tue, 2 Sep 2025 09:36:37 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=A4=87=E8=B4=A7=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/StockOrdersController.php | 33 ++++ app/common/logic/StockOrdersLogic.php | 17 ++ app/common/model/StockOrders.php | 49 +++++ app/common/service/StockOrdersService.php | 31 +++ app/common/service/VehVehicleSkuService.php | 186 +----------------- app/common/validate/StockOrdersValidate.php | 29 +++ 6 files changed, 161 insertions(+), 184 deletions(-) create mode 100644 app/common/controller/StockOrdersController.php create mode 100644 app/common/logic/StockOrdersLogic.php create mode 100644 app/common/model/StockOrders.php create mode 100644 app/common/service/StockOrdersService.php create mode 100644 app/common/validate/StockOrdersValidate.php diff --git a/app/common/controller/StockOrdersController.php b/app/common/controller/StockOrdersController.php new file mode 100644 index 0000000..4bb5a50 --- /dev/null +++ b/app/common/controller/StockOrdersController.php @@ -0,0 +1,33 @@ +service = new StockOrdersService(); + } + + /** + * 列表页数据格式化 + * + * @param array $data + * @return array + */ + // protected function indexFormat($data) + // { + // if (isset($data['created_at'])) + // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']); + // if (isset($data['updated_at'])) + // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']); + // return $data; + // } +} \ No newline at end of file diff --git a/app/common/logic/StockOrdersLogic.php b/app/common/logic/StockOrdersLogic.php new file mode 100644 index 0000000..29d09ad --- /dev/null +++ b/app/common/logic/StockOrdersLogic.php @@ -0,0 +1,17 @@ +validator; + } +} \ No newline at end of file diff --git a/app/common/service/VehVehicleSkuService.php b/app/common/service/VehVehicleSkuService.php index af171a7..ca25040 100644 --- a/app/common/service/VehVehicleSkuService.php +++ b/app/common/service/VehVehicleSkuService.php @@ -115,7 +115,7 @@ class VehVehicleSkuService public function beforeServiceStore($data, Request $request) { - $data = $this->backfill($data); + // $data = $this->backfill($data); if (empty($data['model_code'])) { $data['model_code'] = ModelNaming::buildModelCode($data); } @@ -140,7 +140,7 @@ class VehVehicleSkuService public function beforeServiceUpdate($data, Request $request) { - $data = $this->backfill($data); + // $data = $this->backfill($data); if (empty($data['model_code'])) { $data['model_code'] = ModelNaming::buildModelCode($data); } @@ -159,186 +159,4 @@ class VehVehicleSkuService return $res; } - - - /** SKU 字段名 → dict 名(用于 i18n 取词 & 必填校验) */ - protected static array $SKU_FIELD_TO_DICT = [ - 'brand_code' => 'BRAND', - 'series_code' => 'SERIES', - 'model_code' => 'MODEL', - 'trim_code' => 'TRIM', - 'trim_level_code' => 'TRIM_LEVEL', - 'edition_code' => 'EDITION', - 'fuel_type_code' => 'FUEL', - 'drive_type_code' => 'DRIVE', - 'transmission_code' => 'TRANS', - 'motor_layout_code' => 'MOTOR_LAYOUT', - 'body_type_code' => 'BODY', - 'range_std_code' => 'RANGE_STD', - 'emission_std_code' => 'EMISSION', - 'color_exterior_code'=> 'COLOR', - 'color_interior_code'=> 'COLOR', - ]; - - /** 创建 SKU(含指纹与字典校验) */ - public static function create(array $p, int $userId=0, int $corpId=0): VehicleSku - { - // SkuValidator::validateForCreate($p); - - // 必填字典:由映射表控制(一般 BRAND/SERIES/FUEL) - $requiredDicts = MappingService::requiredDicts(); - foreach (self::$SKU_FIELD_TO_DICT as $field => $dict) { - if (!MappingService::enabled($dict)) continue; - $isRequired = in_array($dict, $requiredDicts, true); - if ($isRequired) { - DictService::ensureExists($dict, $p[$field] ?? null, $field); - } - } - - // 填充系统字段 - $now = time(); - $p['sku_code'] = $p['sku_code'] ?? ('SKU'.date('Ymd').'-'.substr(bin2hex(random_bytes(3)),0,6)); - $p['corp_id'] = $p['corp_id'] ?? $corpId; - $p['created_by'] = $p['created_by'] ?? $userId; - $p['updated_by'] = $p['updated_by'] ?? $userId; - $p['created_at'] = $p['created_at'] ?? $now; - $p['updated_at'] = $p['updated_at'] ?? $now; - - // 指纹 - $p['fingerprint'] = Fingerprint::make($p /*, $scopeCorp=true/false*/); - - return DB::connection()->transaction(function () use ($p) { - $sku = new VehicleSku($p); - $sku->save(); - return $sku; - }); - } - - /** 更新 SKU(部分字段;指纹随事实变动而刷新) */ - public static function update(int $id, array $p, int $userId=0): VehicleSku - { - SkuValidator::validateForUpdate($p); - - $sku = VehicleSku::findOrFail($id); - - // 若传入了必填 dict 的 code,需要确认字典存在 - $requiredDicts = MappingService::requiredDicts(); - foreach (self::$SKU_FIELD_TO_DICT as $field => $dict) { - if (!array_key_exists($field, $p)) continue; - if (!MappingService::enabled($dict)) continue; - $isRequired = in_array($dict, $requiredDicts, true); - if ($isRequired) { - DictService::ensureExists($dict, $p[$field], $field); - } else { - // 可选的:若传了 code 则也校验存在 - if (($p[$field] ?? null) !== null && $p[$field] !== '') { - $exists = \app\model\DictTerm::where('dict',$dict)->where('code',$p[$field])->exists(); - if (!$exists) throw new \InvalidArgumentException("字典不存在:{$dict}.{$p[$field]}"); - } - } - } - - // 刷新系统字段 - $p['updated_by'] = $userId; - $p['updated_at'] = time(); - - // 赋值保存 - $sku->fill($p); - - // 只要影响到指纹的事实字段变动,就重算指纹 - $fingerFields = [ - 'brand_code','series_code','model_year','fuel_type_code', - 'drive_type_code','transmission_code','body_type_code', - 'engine_disp_l','engine_turbo','battery_kwh','range_km', - 'range_std_code','emission_std_code', - 'corp_id' - ]; - foreach ($fingerFields as $f) { - if (array_key_exists($f, $p)) { - $sku->fingerprint = Fingerprint::make($sku->toArray()); - break; - } - } - - $sku->save(); - return $sku; - } - - /** 详情(带 i18n label 与标准标题) */ - public static function detail(int $id, string $locale='zh-CN'): array - { - $sku = VehicleSku::findOrFail($id); - $data = $sku->toArray(); - - $labelOf = function(string $field) use ($data, $locale) { - $dict = self::$SKU_FIELD_TO_DICT[$field] ?? null; - if (!$dict) return null; - - $code = $data[$field] ?? null; - // 若是品牌/车系,允许以中文兜底 - $fallback = null; - if ($field === 'brand_code') $fallback = $data['brand_name'] ?? null; - if ($field === 'series_code') $fallback = $data['series_name'] ?? null; - - // 版型/等级/特别版允许中文兜底 - if ($field === 'trim_code') $fallback = $data['trim'] ?? null; - if ($field === 'trim_level_code') $fallback = $data['trim_level'] ?? null; - if ($field === 'edition_code') $fallback = $data['edition_name'] ?? null; - - // 颜色兜底中文 - if ($field === 'color_exterior_code') $fallback = $data['color_exterior_text'] ?? null; - if ($field === 'color_interior_code') $fallback = $data['color_interior_text'] ?? null; - - return \app\service\DictService::label($dict, $code, $locale, $fallback); - }; - - $i18n = [ - 'brand_label' => $labelOf('brand_code'), - 'series_label' => $labelOf('series_code'), - 'model_label' => \app\service\DictService::label('MODEL', $data['model_code'] ?? null, $locale, $data['model_name'] ?? null), - 'trim_label' => $labelOf('trim_code'), - 'trim_level_label' => $labelOf('trim_level_code'), - 'edition_label' => $labelOf('edition_code'), - 'fuel_label' => $labelOf('fuel_type_code'), - 'drive_label' => $labelOf('drive_type_code'), - 'trans_label' => $labelOf('transmission_code'), - 'motor_layout_label' => $labelOf('motor_layout_code'), - 'body_label' => $labelOf('body_type_code'), - 'range_std_label' => $labelOf('range_std_code'), - 'emission_label' => $labelOf('emission_std_code'), - 'color_exterior_label' => $labelOf('color_exterior_code'), - 'color_interior_label' => $labelOf('color_interior_code'), - 'listing_title' => TitleBuilder::build($data, $locale), - ]; - - return ['sku'=>$data, 'i18n'=>$i18n]; - } - - /** 列表查询(支持基础筛选 & i18n 列) */ - public static function list(array $q, string $locale='zh-CN', int $page=1, int $pageSize=20): array - { - $builder = VehicleSku::query(); - - // 常用筛选 - if (!empty($q['brand_code'])) $builder->where('brand_code', $q['brand_code']); - if (!empty($q['series_code'])) $builder->where('series_code', $q['series_code']); - if (!empty($q['fuel_type_code'])) $builder->where('fuel_type_code', $q['fuel_type_code']); - if (!empty($q['model_year'])) $builder->where('model_year', (int)$q['model_year']); - if (isset($q['is_active'])) $builder->where('is_active', (int)$q['is_active']); - - $builder->orderByDesc('created_at'); - - $total = (clone $builder)->count(); - $rows = $builder->forPage($page, $pageSize)->get()->toArray(); - - // 附加 i18n 字段(轻量) - foreach ($rows as &$row) { - $row['brand_label'] = DictService::label('BRAND', $row['brand_code'] ?? null, $locale, $row['brand_name'] ?? null); - $row['series_label'] = DictService::label('SERIES', $row['series_code'] ?? null, $locale, $row['series_name'] ?? null); - $row['fuel_label'] = DictService::label('FUEL', $row['fuel_type_code'] ?? null, $locale, null); - $row['listing_title']= TitleBuilder::build($row, $locale); - } - - return ['total'=>$total, 'list'=>$rows, 'page'=>$page, 'page_size'=>$pageSize]; - } } \ No newline at end of file diff --git a/app/common/validate/StockOrdersValidate.php b/app/common/validate/StockOrdersValidate.php new file mode 100644 index 0000000..78fccf3 --- /dev/null +++ b/app/common/validate/StockOrdersValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file