You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
11 KiB
326 lines
11 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\api\common;
|
|
|
|
use app\model\dict\Dict;
|
|
use core\base\BaseApiService;
|
|
|
|
/**
|
|
* 字典批量获取服务
|
|
* Class DictService
|
|
* @package app\service\api\common
|
|
*/
|
|
class DictService extends BaseApiService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->model = new Dict();
|
|
}
|
|
|
|
/**
|
|
* 批量获取字典数据
|
|
* @param array $keys 字典key数组
|
|
* @return array
|
|
*/
|
|
public function getBatchDict(array $keys = []): array
|
|
{
|
|
if (empty($keys)) {
|
|
return [];
|
|
}
|
|
|
|
// 验证keys参数
|
|
$validKeys = array_filter($keys, function($key) {
|
|
return is_string($key) && !empty(trim($key));
|
|
});
|
|
|
|
if (empty($validKeys)) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
// 批量查询字典数据
|
|
$dictData = $this->model
|
|
->whereIn('key', $validKeys)
|
|
->field('key, dictionary')
|
|
->select()
|
|
->toArray();
|
|
|
|
$result = [];
|
|
|
|
foreach ($dictData as $dict) {
|
|
$key = $dict['key'];
|
|
$dictionary = $dict['dictionary'];
|
|
|
|
// 解析字典值 - 手动处理JSON解析
|
|
if (!empty($dictionary)) {
|
|
if (is_array($dictionary)) {
|
|
// 已经是数组格式,直接使用
|
|
$result[$key] = $dictionary;
|
|
} else if (is_string($dictionary)) {
|
|
// 处理JSON字符串,可能包含转义字符
|
|
|
|
// 首先尝试直接解析
|
|
$decodedValue = json_decode($dictionary, true);
|
|
if (json_last_error() === JSON_ERROR_NONE) {
|
|
if (is_array($decodedValue)) {
|
|
// 解析结果是数组,直接使用
|
|
$result[$key] = $decodedValue;
|
|
} else if (is_string($decodedValue)) {
|
|
// 解析结果是字符串,可能是双重JSON编码,尝试再次解析
|
|
$secondDecodedValue = json_decode($decodedValue, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($secondDecodedValue)) {
|
|
$result[$key] = $secondDecodedValue;
|
|
} else {
|
|
// 字符串解析失败,使用字符串解析方法
|
|
$result[$key] = $this->parseStringValue($decodedValue);
|
|
}
|
|
} else {
|
|
$result[$key] = [];
|
|
}
|
|
} else {
|
|
// JSON解析失败,尝试其他方法
|
|
$cleanedDictionary = stripcslashes($dictionary);
|
|
$decodedValue = json_decode($cleanedDictionary, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decodedValue)) {
|
|
$result[$key] = $decodedValue;
|
|
} else {
|
|
// 使用字符串解析方法作为最后手段
|
|
$result[$key] = $this->parseStringValue($dictionary);
|
|
}
|
|
}
|
|
} else {
|
|
$result[$key] = [];
|
|
}
|
|
} else {
|
|
$result[$key] = [];
|
|
}
|
|
}
|
|
|
|
// 为没有找到的key返回空数组
|
|
foreach ($validKeys as $key) {
|
|
if (!isset($result[$key])) {
|
|
$result[$key] = [];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
|
|
} catch (\Exception $e) {
|
|
// 记录错误日志
|
|
trace('批量获取字典数据失败: ' . $e->getMessage(), 'error');
|
|
|
|
// 返回空结果
|
|
$result = [];
|
|
foreach ($validKeys as $key) {
|
|
$result[$key] = [];
|
|
}
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取单个字典数据(带缓存)
|
|
* @param string $key 字典key
|
|
* @param bool $useCache 是否使用缓存
|
|
* @return array
|
|
*/
|
|
public function getDict(string $key, bool $useCache = true): array
|
|
{
|
|
if (empty($key)) {
|
|
return [];
|
|
}
|
|
|
|
$cacheKey = "dict_cache_{$key}";
|
|
|
|
// 如果使用缓存,先尝试从缓存获取
|
|
if ($useCache) {
|
|
$cached = cache($cacheKey);
|
|
if ($cached !== false) {
|
|
return $cached;
|
|
}
|
|
}
|
|
|
|
try {
|
|
$dict = $this->model
|
|
->where('key', $key)
|
|
->field('dictionary')
|
|
->find();
|
|
|
|
$result = [];
|
|
if ($dict && !empty($dict['dictionary'])) {
|
|
if (is_array($dict['dictionary'])) {
|
|
$result = $dict['dictionary'];
|
|
} else {
|
|
$decodedValue = json_decode($dict['dictionary'], true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decodedValue)) {
|
|
$result = $decodedValue;
|
|
} else {
|
|
$result = $this->parseStringValue($dict['dictionary']);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 缓存结果(缓存30分钟)
|
|
if ($useCache) {
|
|
cache($cacheKey, $result, 1800);
|
|
}
|
|
|
|
return $result;
|
|
|
|
} catch (\Exception $e) {
|
|
trace('获取字典数据失败: ' . $e->getMessage(), 'error');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 清除字典缓存
|
|
* @param string|array $keys 要清除的字典key,为空则清除所有字典缓存
|
|
* @return bool
|
|
*/
|
|
public function clearDictCache($keys = null): bool
|
|
{
|
|
try {
|
|
if (is_null($keys)) {
|
|
// 清除所有字典缓存(需要实现cache标签功能或使用其他方式)
|
|
// 这里简化处理,实际项目中可以使用cache标签
|
|
return true;
|
|
}
|
|
|
|
if (is_string($keys)) {
|
|
$keys = [$keys];
|
|
}
|
|
|
|
if (is_array($keys)) {
|
|
foreach ($keys as $key) {
|
|
cache("dict_cache_{$key}", null);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
} catch (\Exception $e) {
|
|
trace('清除字典缓存失败: ' . $e->getMessage(), 'error');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 解析字符串格式的字典值
|
|
* @param string $value
|
|
* @return array
|
|
*/
|
|
private function parseStringValue(string $value): array
|
|
{
|
|
// 尝试按行分割,每行格式如:key|value 或 key:value
|
|
$lines = array_filter(explode("\n", $value));
|
|
$result = [];
|
|
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if (empty($line)) {
|
|
continue;
|
|
}
|
|
|
|
// 尝试多种分隔符
|
|
$separators = ['|', ':', '=', ','];
|
|
$parsed = false;
|
|
|
|
foreach ($separators as $sep) {
|
|
if (strpos($line, $sep) !== false) {
|
|
$parts = explode($sep, $line, 2);
|
|
if (count($parts) === 2) {
|
|
$result[] = [
|
|
'name' => trim($parts[1]),
|
|
'value' => trim($parts[0]),
|
|
'sort' => count($result),
|
|
'memo' => ''
|
|
];
|
|
$parsed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 如果没有找到分隔符,将整行作为值,索引作为key
|
|
if (!$parsed) {
|
|
$result[] = [
|
|
'name' => $line,
|
|
'value' => (string)count($result),
|
|
'sort' => count($result),
|
|
'memo' => ''
|
|
];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 获取常用字典映射
|
|
* @return array
|
|
*/
|
|
public function getCommonDictMapping(): array
|
|
{
|
|
return [
|
|
// 客户来源相关
|
|
'source_channel' => 'SourceChannel',
|
|
'source' => 'source',
|
|
'purchasing_power' => 'customer_purchasing_power',
|
|
'cognitive_idea' => 'cognitive_concept',
|
|
'decision_maker' => 'decision_maker',
|
|
'initial_intent' => 'preliminarycustomerintention',
|
|
'status' => 'kh_status',
|
|
'distance' => 'distance',
|
|
|
|
// 人员管理相关
|
|
'gender' => 'gender',
|
|
'education' => 'education',
|
|
'position' => 'position',
|
|
'department' => 'department',
|
|
|
|
// 课程相关
|
|
'course_type' => 'course_type',
|
|
'course_level' => 'course_level',
|
|
'course_status' => 'course_status',
|
|
|
|
// 其他常用字典
|
|
'yes_no' => 'yes_no',
|
|
'enable_disable' => 'enable_disable'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 根据业务场景获取字典keys
|
|
* @param string $scene 业务场景
|
|
* @return array
|
|
*/
|
|
public function getDictKeysByScene(string $scene): array
|
|
{
|
|
$sceneMapping = [
|
|
'customer_add' => [
|
|
'SourceChannel', 'source', 'customer_purchasing_power',
|
|
'cognitive_concept', 'decision_maker', 'preliminarycustomerintention',
|
|
'kh_status', 'distance'
|
|
],
|
|
'personnel_add' => [
|
|
'gender', 'education', 'position', 'department', 'enable_disable'
|
|
],
|
|
'course_add' => [
|
|
'course_type', 'course_level', 'course_status', 'enable_disable'
|
|
]
|
|
];
|
|
|
|
return $sceneMapping[$scene] ?? [];
|
|
}
|
|
}
|