CustomFieldSettingService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <?php
  2. namespace App\Service;
  3. use App\Jobs\ProcessOssTask;
  4. use App\Model\CustomFieldDefinitions;
  5. use App\Model\CustomFieldValue;
  6. use App\Model\SysOssTasks;
  7. use Illuminate\Support\Facades\DB;
  8. class CustomFieldSettingService extends Service
  9. {
  10. public function add($data,$user){
  11. list($status,$msg) = $this->fieldRule($data,$user);
  12. if(!$status) return [$status,$msg];
  13. try {
  14. DB::beginTransaction();
  15. CustomFieldDefinitions::insert($data['data']);
  16. DB::commit();
  17. }catch (\Exception $exception){
  18. DB::rollBack();
  19. return [false,$exception->getMessage()];
  20. }
  21. return [true,''];
  22. }
  23. public function edit($data,$user){
  24. list($status,$msg) = $this->fieldRule($data,$user, false);
  25. if(!$status) return [$status,$msg];
  26. try {
  27. DB::beginTransaction();
  28. $update = $msg['data'][0];
  29. $id = $update['id'];
  30. $model = new CustomFieldDefinitions();
  31. $model->where('id', $id)->update([
  32. 'menu_id' => $update['menu_id'],
  33. 'field_label' => $update['field_label'],
  34. 'field_type' => $update['field_type'],
  35. ]);
  36. DB::commit();
  37. }catch (\Exception $exception){
  38. DB::rollBack();
  39. return [false,$exception->getMessage()];
  40. }
  41. return [true,''];
  42. }
  43. public function del($data, $user){
  44. if(empty($data['id']) || ! is_array($data['id'])) return [false,'ID不能为空或格式错误'];
  45. try {
  46. CustomFieldDefinitions::whereIn('id', $data['id'])->update([
  47. 'del_time' => time()
  48. ]);
  49. }catch (\Exception $exception){
  50. DB::rollBack();
  51. return [false,$exception->getMessage()];
  52. }
  53. return [true,''];
  54. }
  55. public function fieldCommon($data,$user, $field = []){
  56. if(empty($field)) $field = CustomFieldDefinitions::$field;
  57. $model = CustomFieldDefinitions::TopClear($user,$data);
  58. $model = $model->where('del_time',0)
  59. ->select($field)
  60. ->orderby('id', 'desc');
  61. if(! empty($data['field_label'])) $model->where('field_label', 'LIKE', '%'.$data['field_label'].'%');
  62. return $model;
  63. }
  64. public function list($data, $user){
  65. $model = $this->fieldCommon($data, $user);
  66. $list = $this->limit($model,'',$data);
  67. $list = $this->fillList($list);
  68. return [true, $list];
  69. }
  70. public function fillList($data){
  71. if(empty($data['data'])) return $data;
  72. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'crt_id')));
  73. $menu_map = (new SysMenuService())->getMap(array_unique(array_column($data['data'],'menu_id')));
  74. foreach ($data['data'] as $key => $value){
  75. $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  76. $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  77. $data['data'][$key]['menu_title'] = $menu_map[$value['menu_id']] ?? '';
  78. $data['data'][$key]['field_type_title'] = CustomFieldDefinitions::State_Type[$value['field_type']] ?? '';
  79. }
  80. return $data;
  81. }
  82. public function detail($data, $user){
  83. if(empty($data['id'])) return [false,'id不能为空'];
  84. list($status, $return) = $this->list(['id' => [$data['id']]], $user);
  85. $return = $return['data'][0] ?? [];
  86. return [true, $return];
  87. }
  88. public function fieldRule(&$data,$user, $is_add = true){
  89. $data['top_depart_id'] = $user['top_depart_id'];
  90. // $bool = SysModules::where('del_time',0)
  91. // ->where('top_depart_id', $data['top_depart_id'])
  92. // ->where('menu_id', $data['menu_id'])
  93. // ->exists();
  94. // if(! $bool) return [false, $title . '不允许增加自定义表头'];
  95. if(empty($data['data'])) return [false,'自定义数据不能为空'];
  96. $title = array_column($data['data'],'field_label');
  97. $title = array_map(function($val) {
  98. return $val !== null ? $val : 0;
  99. }, $title);
  100. $title_count = array_count_values($title);
  101. foreach ($title as $value){
  102. if(empty($value)) return [false,'自定义名称不能为空!'];
  103. if($title_count[$value] > 1) return [false,'自定义名称不能重复'];
  104. }
  105. foreach ($data['data'] as $key => $value){
  106. if(empty($value['menu_id'])) return [false, '菜单不能为空'];
  107. if(empty($value['field_label'])) return [false, '自定义项名称不能为空'];
  108. if(empty($value['field_type'])) return [false, '自定义项类型不能为空'];
  109. if(! isset(CustomFieldDefinitions::State_Type[$value['field_type']])) return [false, '自定义项类型错误'];
  110. $top_depart_id = $user['top_depart_id'];
  111. $data['data'][$key]['menu_id'] = $value['menu_id'];
  112. $data['data'][$key]['top_depart_id'] = $top_depart_id;
  113. $data['data'][$key]['upd_time'] = time();
  114. if($is_add){
  115. $data['data'][$key]['crt_time'] = time();
  116. $fieldKey = 'f_' . substr(md5(microtime() . $value['field_label']), 0, 8);
  117. $data['data'][$key]['field_key'] = $fieldKey;
  118. $bool = CustomFieldDefinitions::where("field_label", $value['field_label'])
  119. ->where('top_depart_id', $top_depart_id)
  120. ->where('menu_id', $value['menu_id'])
  121. ->where('del_time',0)
  122. ->exists();
  123. }else{
  124. if($this->isEmpty($value,'id')) return [false,'id不能为空!'];
  125. $bool = CustomFieldDefinitions::where("field_label", $value['field_label'])
  126. ->where('top_depart_id', $top_depart_id)
  127. ->where('menu_id', $value['menu_id'])
  128. ->where('id','<>',$value['id'])
  129. ->where('del_time',0)
  130. ->exists();
  131. if(isset($value['field_key'])) unset($data['data'][$key]['field_key']);
  132. }
  133. if($bool) return [false,'自定义设置已存在'];
  134. }
  135. return [true, $data];
  136. }
  137. public static function syncCustomFieldData1($id, $data, $user)
  138. {
  139. $top_depart_id = $user['top_depart_id'];
  140. if (empty($data['menu_id'])) return [true, ''];
  141. $definitions = CustomFieldDefinitions::where('menu_id', $data['menu_id'])
  142. ->where('top_depart_id', $top_depart_id)
  143. ->get();
  144. if(empty($definitions)) return [true, ''];
  145. $pendingTasks = [];
  146. $time = time();
  147. try {
  148. foreach ($definitions as $df) {
  149. $key = $df->field_key;
  150. // 如果请求数据中没有这个自定义字段的 key,跳过
  151. if (!array_key_exists($key, $data)) continue;
  152. $newVal = (string)($data[$key] ?? '');
  153. // --- 附件类型逻辑处理 ---
  154. if ($df->field_type === CustomFieldDefinitions::TYPE_TWO) {
  155. // 查询数据库中已有的旧路径
  156. $oldVal = DB::table('custom_field_values')
  157. ->where('model_id', $id)
  158. ->where('definition_id', $df->id)
  159. ->value('field_value') ?? '';
  160. if ($newVal !== $oldVal) {
  161. //产生一个【删除任务】
  162. if (!empty($oldVal)) {
  163. $pendingTasks[] = [
  164. 'type' => SysOssTasks::type_one, // 删除旧文件
  165. 'url' => $oldVal,
  166. 'top_depart_id' => $top_depart_id,
  167. 'crt_time' => $time,
  168. ];
  169. }
  170. //产生一个【新增同步任务】
  171. if (!empty($newVal)) {
  172. $pendingTasks[] = [
  173. 'type' => SysOssTasks::type_two, // 新增同步到 OSS
  174. 'url' => $newVal,
  175. 'top_depart_id' => $top_depart_id,
  176. 'crt_time' => $time,
  177. ];
  178. }
  179. }
  180. }
  181. // --- 统一更新业务值表 (文本或附件路径) ---
  182. DB::table('custom_field_values')->updateOrInsert(
  183. [
  184. 'model_id' => $id,
  185. 'definition_id' => $df->id,
  186. 'top_depart_id' => $top_depart_id,
  187. 'field_type' => $df->field_type
  188. ],
  189. [
  190. 'field_value' => $newVal, // 如果是删除,这里存入空字符串
  191. 'upd_time' => time()
  192. ]
  193. );
  194. }
  195. //需要执行的oss的任务 调用这个方法的地方在 事务结束后触发下队列
  196. if(! empty($pendingTasks)) {
  197. SysOssTasks::insert($pendingTasks);
  198. ProcessOssTask::dispatch()->onQueue(SysOssTasks::job);
  199. }
  200. }catch (\Throwable $exception){
  201. return [false, $exception->getMessage()];
  202. }
  203. return [true, ''];
  204. }
  205. public function fillDataCustomField(&$data){
  206. if(! empty($data['custom_field_values'])){
  207. $fileUploadService = new FileUploadService();
  208. foreach ($data['custom_field_values'] as $key => $value){
  209. if($value['field_type'] == CustomFieldDefinitions::TYPE_TWO){
  210. $img_str = $fileUploadService->getFileShow($value['field_value']);
  211. $data['custom_field_values'][$key]['field_value_show'] = $img_str;
  212. }
  213. }
  214. }
  215. }
  216. public static function syncCustomFieldData($modelId, $tableName, $data, $user)
  217. {
  218. if(empty($tableName)) return [false, '表名不存在'];
  219. $top_depart_id = $user['top_depart_id'];
  220. $customFields = $data['custom_fields'] ?? [];
  221. $time = time();
  222. $pendingTasks = [];
  223. // 1. 预校验:过滤掉空标签后,判断剩下的标签是否重复
  224. $labels = array_filter(array_column($customFields, 'field_label'));
  225. if (count($labels) !== count(array_unique($labels))) return [false, '自定义字段名称不能重复'];
  226. try {
  227. // 2. 获取数据库现有的旧数据(仅限未删除的)
  228. $oldValues = CustomFieldValue::where('top_depart_id', $top_depart_id)
  229. ->where('table_name', $tableName)
  230. ->where('model_id', $modelId)
  231. ->where('del_time', 0)
  232. ->get()
  233. ->keyBy('id');
  234. $submittedIds = [];
  235. // 3. 处理前端提交的数据
  236. foreach ($customFields as $field) {
  237. $fId = (int)($field['id'] ?? 0);
  238. $label = trim((string)($field['field_label'] ?? ''));
  239. $newVal = (string)($field['field_value'] ?? '');
  240. $type = (int)($field['field_type'] ?? 1);
  241. $field_name = (string)($field['field_name'] ?? '');
  242. if ($label === '') continue; // 标签为空的直接跳过,不保存
  243. // --- OSS 附件逻辑 ---
  244. if ($type === 2) {
  245. $oldVal = isset($oldValues[$fId]) ? $oldValues[$fId]->field_value : '';
  246. if ($newVal !== $oldVal) {
  247. if (!empty($oldVal)) $pendingTasks[] = ['type' => SysOssTasks::type_one, 'url' => $oldVal, 'top_depart_id' => $top_depart_id, 'crt_time' => $time];
  248. if (!empty($newVal)) $pendingTasks[] = ['type' => SysOssTasks::type_two, 'url' => $newVal, 'top_depart_id' => $top_depart_id, 'crt_time' => $time];
  249. }
  250. }
  251. // --- 保存/更新 ---
  252. // 如果前端传了 ID,就按 ID 改;没传 ID,就新增(updateOrInsert 在 id 为 0 时会执行插入)
  253. $saveData = [
  254. 'top_depart_id' => $top_depart_id,
  255. 'table_name' => $tableName,
  256. 'model_id' => $modelId,
  257. 'field_label' => $label,
  258. 'field_value' => $newVal,
  259. 'field_type' => $type,
  260. 'field_name' => $field_name,
  261. ];
  262. if ($fId > 0) {
  263. CustomFieldValue::where('id', $fId)->update($saveData);
  264. $submittedIds[] = $fId;
  265. } else {
  266. $saveData['crt_time'] = $time;
  267. $saveData['crt_id'] = $user['id'];
  268. $newId = CustomFieldValue::insertGetId($saveData);
  269. $submittedIds[] = $newId;
  270. }
  271. }
  272. // 4. 清理:如果旧 ID 不在本次提交的 ID 列表中,说明被删除了
  273. foreach ($oldValues as $oldId => $oldRow) {
  274. if (!in_array($oldId, $submittedIds)) {
  275. // 如果删掉的是附件,加个删除任务
  276. if ($oldRow->field_type == 2 && !empty($oldRow->field_value)) {
  277. $pendingTasks[] = ['type' => SysOssTasks::type_one, 'url' => $oldRow->field_value, 'top_depart_id' => $top_depart_id, 'crt_time' => $time];
  278. }
  279. CustomFieldValue::where('id', $oldId)->update(['del_time' => $time]);
  280. }
  281. }
  282. // 5. 触发 OSS 任务
  283. if (!empty($pendingTasks)) {
  284. SysOssTasks::insert($pendingTasks);
  285. ProcessOssTask::dispatch()->onQueue(SysOssTasks::job);
  286. }
  287. } catch (\Throwable $exception) {
  288. return [false, $exception->getMessage()];
  289. }
  290. return [true, ''];
  291. }
  292. }