store.js 8.13 KB
(function (global, wrapper) {
  global.diagramStore = wrapper();
}(window, function () {
  var params = {};
  var DEBUG = false;
  var modeTypes = {
    MODE: 'mode',
    WORKFLOW: 'workflow'
  };

  location.search
    .replace(/^\?/, '')
    .split('&')
    .forEach(function (param) {
      var values = param.split('=');
      var key = values[0];
      var value = values[1];

      params[key] = value;
    });

  var _ = {
    url: function (actName) {
      var prefix = '/api/cube/mode/mode/';
      var suffix = '';

      if (DEBUG) {
        prefix = './datas/';
        suffix = '.json';
      }

      return prefix + actName + suffix;
    },
    debounce: function (func, wait, immediate) {
      var timeout;
      return function () {
        var context = this, args = arguments;
        var later = function () {
          timeout = null;
          if(!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if(callNow) func.apply(context, args);
      };
    },
    throttle: function throttle(func, wait, options) {
      var context, args, result;
      var timeout = null;
      var previous = 0;
      if(!options) options = {};
      var later = function () {
        previous = options.leading === false ? 0 : Date.now();
        timeout = null;
        result = func.apply(context, args);
        if(!timeout) context = args = null;
      };
      return function () {
        var now = Date.now();
        if(!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if(remaining <= 0 || remaining > wait) {
          if(timeout) {
            clearTimeout(timeout);
            timeout = null;
          }
          previous = now;
          result = func.apply(context, args);
          if(!timeout) context = args = null;
        } else if(!timeout && options.trailing !== false) {
          timeout = setTimeout(later, remaining);
        }
        return result;
      };
    },
    isPlainObject: function (obj) {
      return JSON.stringify(obj) === '{}';
    },
    isUndefined: function (v) {
      return v === undefined;
    },
    toNumber: function (n, defaultVal) {
      n = Number(n);
      defaultVal = defaultVal || 0;

      return isNaN(n) ? defaultVal : n;
    },
    offset: function ($el) {
      var left = $el.css('left');
      var top = $el.css('top');

      left = parseFloat(left);
      top = parseFloat(top);

      return {
        left: this.toNumber(left),
        top: this.toNumber(top) 
      };
    },
    transformScale: function (scale) {
      return { transform: "scale(" + scale + ")" };
    }
  };
  var _store = {
    weight: function (mode) { // 获取模块排序的权重
      if(mode.isWorkflow) return 2; // 流程
      if(mode.fields.find(function (f) { return f.to; })) return 1; // 有浏览框的表
      return -1; // 无连线的表
    },
    getField: function (mode, source) {
      if(!source) return;
      if(!mode || mode.table !== source.table) return;

      return mode.fields.find(function (f) {
        return f.id === source.field;
      });
    },
    getType: function (mode) {
      return mode.isWorkflow ? modeTypes.WORKFLOW : modeTypes.MODE;
    },
    getModeInfo: function () {
      var url = _.url('getModeStructInfo');

      return $.ajax({
        url: url,
        data: {
          appid: params.appid
        },
        dataType: 'json'
      }).then(function (result) {
        if('1' !== result.status) return null;


        return result;
      });
    },
    initModelist: function (modelist) { // 主模块
      var TABLE_W = 260; // 表宽
      var TABLE_HEADER_H = 50; // 表头高
      var TABLE_FIELD_H = 30; // 表字段高度
      var TABLE_CONTENT_PD = 40; // 表内容间的padding
      var TABLE_MG_L = 60; // 表之间的左间距
      var TABLE_MG_T = 100; // 表之间的上间距
      var modeMap = {};
      var sources = [];
      var sums = {};
      var hasLayout = false;

      if (!modelist.length) return;

      modelist.forEach(function (mode) {
        hasLayout = hasLayout || (!_.isUndefined(mode.layout) && !_.isPlainObject(mode.layout));
        modeMap[mode.id] = mode;
        mode.fields.forEach(function (field) {

          var source = field.to;

          if(!source) return;

          var mode = modeMap[source.model];
          var field = _store.getField(mode, source);

          if(!field) {
            source.disable = true;
            return;
          }

          var targets = field.from || [];

          sources.push(source);
          targets.push(source);

          field.from = targets;
        });
      });

      if(hasLayout) return;

      sources.forEach(function (ref) {
        if(!modeMap[ref.model]) return;

        var key = ref.table + ref.model;
        var sum = sums[key];

        if(!sum) {
          sum = {
            num: 0,
            id: ref.model,
            table: ref.table
          };
        }

        sum.num++;
        sums[key] = sum;
      });

      var max = -1;
      var mainModel = {};

      Object.keys(sums).forEach(function (key) {
        var sum = sums[key];

        if(sum.num > max) {
          max = sum.num;
          mainModel = modeMap[sum.id];
        }
      });

      if (!mainModel.fields) {
        mainModel = modelist[0];
      } 

      mainModel.layout = {
        x: TABLE_MG_L,
        y: TABLE_MG_T / 2
      };

      var mainRefFields = mainModel.fields.filter(function (f) {
        return f.to;
      });
      var mainH = TABLE_HEADER_H + TABLE_FIELD_H * mainRefFields.length + TABLE_CONTENT_PD + mainModel.layout.y;

      modelist.filter(function (mode) {
        return mode.id !== mainModel.id;
      }).sort(function (m1, m2) {
        var w1 = _store.weight(m1);
        var w2 = _store.weight(m2);

        return w1 < w2 ? 1 : -1;
      }).forEach(function (mode, i) {
        mode.layout = {
          y: mainH + TABLE_MG_T,
          x: mainModel.layout.x + (TABLE_W + TABLE_MG_L) * i
        };
      });

       this.updateLayouts(modelist);
    },
    updateLayouts: function (modelist) {
      var positions = {};
      
      modelist.forEach(function (mode) {
        var layout = mode.layout;

        positions[mode.id] = {
          pos: [layout.x, layout.y],
        };
      });

      this.updateTablePos(positions);
    },
    posToData: function (positions) {
      return Object.keys(positions).map(function (key) {
        var mode = positions[key];
        var pos = mode.pos;

        return {
          objid: key,
          x: pos[0],
          y: pos[1],
        };
      });
    },
    updateTablePos: function (positions) {
      var data = this.posToData(positions);

      return $.ajax({
        type: 'post',
        url: _.url('saveStructLayoutInfo'),
        data: {
          layoutDatas: JSON.stringify(data)
        }
      });
    },
    updateZoomAndPos: function (zoom, position) {
      return $.ajax({
        type: 'post',
        url: _.url('saveStructZoomInfo'),
        data: {
          appid: params.appid,
          zoom: zoom,
          position: JSON.stringify(position)
        }
      });
    }
  };
  
  return {
    init: function () {
      return _store.getModeInfo().then(function (result) {
        if (!result) return;

        _store.initModelist(result.dataList);

        return result;
      });
    },
      updateModeName: function(modeid, modeName) {
          console.log(modeid, modeName)
          return $.ajax({
              type: 'post',
              url: _.url('updateModeName'),
              data: {
                  modeid: modeid,
                  modeName: modeName,
              }
          });
      },
    updateTablePos: (function () {
      var positions = {};
      var update = _.debounce(function () {
        _store.updateTablePos(positions);
        positions = {};
      }, 1500);

      return function (mode, pos) {
        positions[mode.id] = {
          pos: pos,
          type: _store.getType(mode)
        };
        
        update();
      };
    }()),
    updateZoomAndPos: _.debounce(_store.updateZoomAndPos, 1000),
    _: _
  }
}));