|
|
@@ -0,0 +1,191 @@
|
|
|
+package com.fs.app.controller;
|
|
|
+
|
|
|
+import com.fs.app.annotation.Login;
|
|
|
+import com.fs.common.core.domain.R;
|
|
|
+import com.fs.qw.domain.QwExternalContact;
|
|
|
+import com.fs.qw.param.ImFsUserRemarkTagsParam;
|
|
|
+import com.fs.qw.service.IQwExternalContactService;
|
|
|
+import com.fs.qw.service.IQwTagService;
|
|
|
+import com.fs.qw.vo.ImFsUserRemarkTagsVO;
|
|
|
+import com.google.gson.Gson;
|
|
|
+import com.google.gson.reflect.TypeToken;
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections.CollectionUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.LinkedHashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+/**
|
|
|
+ * IM:按 fs_user 批量查企微外部联系人备注、标签(
|
|
|
+ */
|
|
|
+@Api("IM-企微客户")
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping("/app/im/qwExternalContact")
|
|
|
+public class ImQwExternalContactController extends AppBaseController {
|
|
|
+ private static final Gson GSON = new Gson();
|
|
|
+ private static final Pattern ID_PATTERN = Pattern.compile("^[Uu]?(\\d+)$");
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IQwExternalContactService qwExternalContactService;
|
|
|
+ @Autowired
|
|
|
+ private IQwTagService iQwTagService;
|
|
|
+ @ApiOperation("批量查询企微备注与标签")
|
|
|
+ @Login
|
|
|
+ @PostMapping("/remarkTagsByFsUserIds")
|
|
|
+ public R remarkTagsByFsUserIds(@RequestBody ImFsUserRemarkTagsParam param) {
|
|
|
+ if (param == null || CollectionUtils.isEmpty(param.getUserIds())) {
|
|
|
+ return R.ok().put("data", Collections.emptyList());
|
|
|
+ }
|
|
|
+ List<Long> requested = normalizeFsUserIds(param.getUserIds());
|
|
|
+ if (CollectionUtils.isEmpty(requested)) {
|
|
|
+ return R.ok().put("data", Collections.emptyList());
|
|
|
+ }
|
|
|
+
|
|
|
+ List<QwExternalContact> contacts = qwExternalContactService.selectExternalByFsUserIds(requested);
|
|
|
+ Map<Long, QwExternalContact> bestByFsUser = pickBestExternalContactByFsUser(contacts);
|
|
|
+ Map<String, List<String>> parsedTagIdCache = new HashMap<>();
|
|
|
+ Map<String, String> tagNameMap = buildTagNameMap(bestByFsUser.values(), parsedTagIdCache);
|
|
|
+
|
|
|
+ List<ImFsUserRemarkTagsVO> rows = new ArrayList<>(requested.size());
|
|
|
+ for (Long uid : requested) {
|
|
|
+ ImFsUserRemarkTagsVO row = new ImFsUserRemarkTagsVO();
|
|
|
+ row.setUserId(uid);
|
|
|
+ QwExternalContact c = bestByFsUser.get(uid);
|
|
|
+ if (c != null) {
|
|
|
+ row.setRemark(c.getRemark());
|
|
|
+ row.setTagNames(resolveTagNamesLikeList(c.getTagIds(), parsedTagIdCache, tagNameMap));
|
|
|
+ } else {
|
|
|
+ row.setTagNames(Collections.emptyList());
|
|
|
+ }
|
|
|
+ rows.add(row);
|
|
|
+ }
|
|
|
+ return R.ok().put("data", rows);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Map<Long, QwExternalContact> pickBestExternalContactByFsUser(List<QwExternalContact> contacts) {
|
|
|
+ Map<Long, QwExternalContact> out = new HashMap<>();
|
|
|
+ if (CollectionUtils.isEmpty(contacts)) {
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+ for (QwExternalContact current : contacts) {
|
|
|
+ if (current == null || current.getFsUserId() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ QwExternalContact best = out.get(current.getFsUserId());
|
|
|
+ if (best == null || isBetter(current, best)) {
|
|
|
+ out.put(current.getFsUserId(), current);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean isBetter(QwExternalContact current, QwExternalContact best) {
|
|
|
+ boolean currentActive = Integer.valueOf(0).equals(current.getStatus());
|
|
|
+ boolean bestActive = Integer.valueOf(0).equals(best.getStatus());
|
|
|
+ if (currentActive != bestActive) {
|
|
|
+ return currentActive;
|
|
|
+ }
|
|
|
+ Long currentId = current.getId();
|
|
|
+ Long bestId = best.getId();
|
|
|
+ if (currentId == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (bestId == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return currentId > bestId;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> buildTagNameMap(Iterable<QwExternalContact> contacts, Map<String, List<String>> parsedTagIdCache) {
|
|
|
+ LinkedHashSet<String> allTagIds = new LinkedHashSet<>();
|
|
|
+ for (QwExternalContact contact : contacts) {
|
|
|
+ allTagIds.addAll(parseTagIds(contact.getTagIds(), parsedTagIdCache));
|
|
|
+ }
|
|
|
+ if (allTagIds.isEmpty()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ return iQwTagService.selectTagNameMapByTagIds(new ArrayList<>(allTagIds));
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> resolveTagNamesLikeList(String tagIds, Map<String, List<String>> parsedTagIdCache, Map<String, String> tagNameMap) {
|
|
|
+ List<String> ids = parseTagIds(tagIds, parsedTagIdCache);
|
|
|
+ if (CollectionUtils.isEmpty(ids)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<String> names = new ArrayList<>();
|
|
|
+ for (String id : ids) {
|
|
|
+ String name = tagNameMap.get(id);
|
|
|
+ if (name != null) {
|
|
|
+ names.add(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return names;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> parseTagIds(String tagIds, Map<String, List<String>> parsedTagIdCache) {
|
|
|
+ if (tagIds == null || Objects.equals(tagIds, "[]")) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ if (parsedTagIdCache.containsKey(tagIds)) {
|
|
|
+ return parsedTagIdCache.get(tagIds);
|
|
|
+ }
|
|
|
+ List<String> ids;
|
|
|
+ try {
|
|
|
+ ids = GSON.fromJson(
|
|
|
+ tagIds,
|
|
|
+ new TypeToken<List<String>>() {
|
|
|
+ }.getType());
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.warn("IM标签解析失败, tagIds={}", tagIds, ex);
|
|
|
+ parsedTagIdCache.put(tagIds, Collections.emptyList());
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(ids)) {
|
|
|
+ parsedTagIdCache.put(tagIds, Collections.emptyList());
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ parsedTagIdCache.put(tagIds, ids);
|
|
|
+ return ids;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Long> normalizeFsUserIds(List<String> rawUserIds) {
|
|
|
+ List<Long> normalized = new ArrayList<>();
|
|
|
+ for (String raw : rawUserIds) {
|
|
|
+ if (raw == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String trimmed = raw.trim();
|
|
|
+ if (trimmed.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Matcher matcher = ID_PATTERN.matcher(trimmed);
|
|
|
+ if (!matcher.matches()) {
|
|
|
+ log.warn("IM userId格式不支持, userId={}", raw);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ normalized.add(Long.parseLong(matcher.group(1)));
|
|
|
+ } catch (NumberFormatException ex) {
|
|
|
+ log.warn("IM userId转换失败, userId={}", raw, ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return normalized.stream().distinct().collect(Collectors.toList());
|
|
|
+ }
|
|
|
+}
|