2021.12.31 - 小计


明天就是元旦了,新的一年即将来临。

最近都在搞产品性能优化,还了好多技术债务。

产品的表单有一个组织项目筛选项,用的是建模的自定义多级下拉框,它会把集团、区域、公司、项目按照层级结构展示出来,本来一切都很完美,但是当数据量到达一定级别后,下拉框卡死,页面挂掉了。于是就来活了,我要负责将组织下拉框这块性能问题搞定。咱们建模内置的一个标准控件,其实也就是筛选项,做过大量优化,支持数据懒加载。但是自定义的多级下拉框啥都不支持。

把突破点放到标准的筛选项控件上,让建模对外提供这个组件,然后由决策平台进行一层简单的封装,产品这边提供数据源。模拟标准控件的功能解决这个该死的性能问题。

看看建模平台业务组件,他有一些属性及事件可以调用。

<title>基础用法</title>
<describe>项目控件的基础用法</describe>
<template>
  <hc-project-select
    source="标准项目过滤"
    filter-type="LeafProject,LeafCompany"
    display-type="Company,Project"
    @change="change"
  ></hc-project-select>
</template>
<script>
  export default {
    data: function () {
      return {};
    },
    methods: {
      change(e) {
        console.log(e);
      },
    },
  };
</script>

进行简单的封装:

<div class="project-select-main" v-if="isPropsValidator">
  <hc-project-select
    class="private-project-select"
    :display-type="displayType"
    :filter-type="filterType"
    @change="change"
    :source="source"
    ref="projectSelect"
  ></hc-project-select>
</div>
module.exports = {
  props: {
    source: String,
    filterTypeList: Array,
    displayTypeList: Array,
    elementCode: String,
  },
  data: function () {
    return {
      isPropsValidator: true,
      value: "",
    };
  },
  computed: {
    filterType: function () {
      var me = this;
      return me.filterTypeList.join(",");
    },
    displayType: function () {
      var me = this;
      return me.displayTypeList.join(",");
    },
  },
  created: function () {
    this._propsValidator();
  },
  mounted: function () {},
  methods: {
    change: function (item) {
      if (!this.value) {
        this.value = item;
        this.$emit("mounted", item);
      } else {
        this.value = item;
        this.$emit("changed", item);
      }
    },
    setValue: function (value) {
      this.$refs.projectSelect.setValue(value);
    },
    getValue: function () {
      return this.value;
    },
    getText: function () {
      return this.$refs.projectSelect.getText();
    },
    getElementCode: function () {
      if (
        this.elementCode &&
        this.value &&
        this.value.item &&
        this.value.item.extData &&
        this.value.item.extData[this.elementCode]
      ) {
        return this.value.item.extData[this.elementCode];
      } else {
        return "";
      }
    },
    _propsValidator: function () {
      if (!this.filterType || !this.displayType) {
        this.isPropsValidator = false;
        $notify.warning("组件配置错误,请重新配置。");
      } else {
        this.isPropsValidator = true;
      }
    },
  },
};

自定义数据源是个难点,刚开始几十万数据源构建每次耗时都有 30~40 秒左右,经过优化代码,现在首次打开在一秒左右完成,然后缓存数据,后续打开毫秒级别完成,完美解决了组织项目筛选项卡顿的问题。

private List<OptionItem> GetProjectsTree(List<OrganizationDTO> organizations)
{
    var items = new List<OptionItem>();
    var projects = _dataFilterAppService.Instance.GetProjectList();
    var dics = projects.GroupBy(x => x.BuGuid).ToDictionary(x => x.Key, x => x.ToList());
    foreach (var org in organizations)
    {
        var parentItem = new OptionItem
        {
            Text = org.BuName,
            Parent = org.ParentGuid.HasValue ? org.ParentGuid.Value.ToString() : string.Empty,
            Value = org.Buguid.ToString(),
            IsLeaf = false,
            ExtData = new Dictionary<string, object>
            {
                { "BUType", org.BuType },
                { "BUGUID", org.Buguid.ToString() },
                { "BUName", org.BuName },
                { "IsHasStage", org.IsEndCompany ? 0 : 1 },
                { "HierarchyCode", org.HierarchyCode },
                { "OrderHierarchyCode", org.OrderHierarchyCode }
            }
        };
        if (org.IsEndCompany)
        {
            parentItem.ExtData["IsEndCompany"] = true;
        }
        items.Add(parentItem);
        if (org.IsEndCompany)
        {
            var hasValue = dics.TryGetValue(org.Buguid, out List<ProjectMngDto> _projects);
            if (hasValue)
            {
                items.AddRange(_projects.Select(x => new OptionItem
                {
                    Text = x.ProjectName,
                    Value = x.ProjectGUID.ToString(),
                    Parent = org.Buguid.ToString(),
                    IsLeaf = true,
                    ExtData = new Dictionary<string, object>
                    {
                        { "BUType", 3 },
                        { "BUGUID", org.Buguid.ToString() },
                        { "BUName", org.BuName },
                        { "IsHasStage", org.IsEndCompany ? 0 : 1 },
                        { "HierarchyCode", x.HierarchyCode },
                        { "OrderHierarchyCode", org.OrderHierarchyCode }
                    }
                }));
            }
            else
            {
                items.Remove(parentItem);
            }
        }
    }
    var removeList = new List<string>();
    var list = items.Where(x => !x.IsLeaf).ToList();
    foreach (var item in list)
    {
        if (!items.Any(x => x.Parent == item.Value))
        {
            removeList.Add(item.Value);
        }
    }
    items = items.Where(x => !removeList.Contains(x.Value)).ToList();
    return items;
}

这是解决的第一个问题,还主责了项目地图的加载优化方案,产品调用了百度地图,需要在百度地图上面进行地块位置标点操作,但是当海量标点达到上万级别,地图就会卡死…

之前的方案是根据筛选条件查出所有地块位置及其地块的相关信息,当筛选条件全部命中时,会查出所有数据,进行自定义标点操作。这当然会卡,不卡才怪。

现在的方案,根据筛选条件查出所有数据按省份的汇总数据,首次加载页面只展示省份和省份下对应地块数量,这样首次加载就非常的快,不会有任何性能问题。当点击省份的时候再去调用接口查询省份下对应的地块位置,拿到地块位置和相关数据后再进行最后的标点操作。

还有一些零零散散的各种优化,拿地测算产品第一次进入主项发版,后面会进安装盘。2021 产品卖得貌似并不怎么好,没有几个客户,整个房地产行业都处于低迷状态。2022 来了,他能活过来吗?赶紧年底的 OKR 妥妥的凉了,入职不到一年,年终也不知道能拿多少。

不管怎么说,既来之则安之,把手头上的每件事都做好就行了,2022,希望一切都好。加油!


文章作者: 阿星𝑷𝒍𝒖𝒔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿星𝑷𝒍𝒖𝒔 !
评论
  目录