智慧教务系统
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

<?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] ?? [];
}
}