'required|array|min:1', 'updates.*.product_id' => 'required|integer|exists:product,id', 'updates.*.cost_price' => 'nullable|numeric|min:0|max:99999999', 'updates.*.level_id' => 'nullable|integer|exists:customer_level,id', 'updates.*.price_type' => 'nullable|integer|in:0,1', 'updates.*.price' => 'nullable|numeric|min:0|max:99999999', 'updates.*.percent' => 'nullable|numeric|min:0|max:999.99', ]; } /** * 行级交叉校验(在 after() 内按实际数据逐行判断,避免 required_with* 通配符参数解析不可靠): * - 每行必须至少包含成本价或等级价格更新 * - 出现等级字段(price/percent/price_type)时必须带 level_id * - 等级行必须有 price 或 percent * - 成本百分比计价(price_type=1)时上浮百分点必填 */ public function after(): Closure { return function (Validator $validator): void { $data = (array) $validator->getData(); foreach ((array) ($data['updates'] ?? []) as $index => $row) { $row = (array) $row; $hasCost = array_key_exists('cost_price', $row) && $row['cost_price'] !== null && $row['cost_price'] !== ''; $hasLevel = isset($row['level_id']); $hasPrice = array_key_exists('price', $row) && $row['price'] !== null && $row['price'] !== ''; $hasPercent = array_key_exists('percent', $row) && $row['percent'] !== null && $row['percent'] !== ''; $hasType = array_key_exists('price_type', $row); if (! $hasCost && ! $hasLevel) { $validator->errors()->add("updates.{$index}", '调价行缺少成本价或等级价格'); continue; } if (($hasPrice || $hasPercent || $hasType) && ! $hasLevel) { $validator->errors()->add("updates.{$index}.level_id", '等级价格行缺少客户等级'); continue; } if ($hasLevel && ! $hasPrice && ! $hasPercent) { $validator->errors()->add("updates.{$index}", '等级价格行缺少单价或上浮百分点'); continue; } $priceType = (int) ($row['price_type'] ?? ProductPriceModel::PRICE_TYPE_FIXED); if ($priceType === ProductPriceModel::PRICE_TYPE_PERCENT && ! $hasPercent) { $validator->errors()->add("updates.{$index}.percent", '按成本百分比计价时必须填写上浮百分点'); } } }; } public function messages(): array { return [ 'updates.required' => '请至少提交一条价格调整', 'updates.min' => '请至少提交一条价格调整', 'updates.*.product_id.required' => '调价行缺少商品', 'updates.*.product_id.exists' => '商品不存在', 'updates.*.cost_price.numeric' => '成本价必须为数字', 'updates.*.cost_price.min' => '成本价不能小于 0', 'updates.*.level_id.exists' => '客户等级不存在', 'updates.*.price_type.in' => '计价类型不正确', 'updates.*.price.numeric' => '单价必须为数字', 'updates.*.price.min' => '单价不能小于 0', 'updates.*.percent.numeric' => '上浮百分点必须为数字', 'updates.*.percent.min' => '上浮百分点不能小于 0', 'updates.*.percent.max' => '上浮百分点不能超过 999.99', ]; } }