dsk.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. 'use strict';
  2. const dsk = (function () {
  3. const projectType = [
  4. { key: 'folder', value: 1, name: '文件夹' },
  5. { key: 'project', value: 2, name: '建设项目' },
  6. { key: 'item', value: 3, name: '单项工程' },
  7. { key: 'unit', value: 4, name: '单位工程' },
  8. ];
  9. const FileType = {
  10. default: [
  11. { key: 'submission', value: 1, name: '投标' },
  12. { key: 'invitation', value: 2, name: '招标/预算' },
  13. { key: 'control', value: 3, name: '控制价' },
  14. { key: 'change_budget', value: 4, name: '变更预算' },
  15. { key: 'estimate', value: 5, name: '概算' },
  16. { key: 'settlement', value: 10, name: '结算' },
  17. { key: 'gusuan', value: 15, name: '估算(可行性估算)' },
  18. { key: 'suggest_gusuan', value: 16, name: '建议估算' },
  19. { key: 'three_bill_budget', value: 18, name: '三级清单预算' },
  20. { key: 'bills_budget', value: 19, name: '清单预算' },
  21. ],
  22. gl: [
  23. { key: 'submission', value: 1, name: '施工图预算' },
  24. { key: 'invitation', value: 2, name: '' },
  25. { key: 'control', value: 3, name: '' },
  26. { key: 'change_budget', value: 4, name: '变更清单预算' },
  27. { key: 'estimate', value: 5, name: '设计概算' },
  28. { key: 'settlement', value: 10, name: '结算' },
  29. { key: 'gusuan', value: 15, name: '可行性估算' },
  30. { key: 'suggest_gusuan', value: 16, name: '建议估算' },
  31. { key: 'three_bill_budget', value: 18, name: '分项清单预算' },
  32. { key: 'bills_budget', value: 19, name: '工程量清单预算' },
  33. ],
  34. js: [
  35. { key: 'submission', value: 1, name: '预算' },
  36. { key: 'invitation', value: 2, name: '' },
  37. { key: 'control', value: 3, name: '' },
  38. { key: 'change_budget', value: 4, name: '变更清单预算' },
  39. { key: 'estimate', value: 5, name: '概算' },
  40. { key: 'settlement', value: 10, name: '结算' },
  41. { key: 'gusuan', value: 15, name: '估算' },
  42. { key: 'suggest_gusuan', value: 16, name: '' },
  43. { key: 'three_bill_budget', value: 18, name: '' },
  44. { key: 'bills_budget', value: 19, name: '' },
  45. ]
  46. };
  47. // todo 每个编办下,文件类型对应的值不同,待需求整理数据
  48. const CompilationFileType = [
  49. { compliationId: '5de61133d46f6f000d15d347', name: '全国公路(2018)', fileType: FileType.gl },
  50. { compliationId: '63f31fe113566500140e4902', name: '广东公路(2018)', fileType: FileType.gl },
  51. { compliationId: '66b1f3f6ad66620013c13883', name: '浙江公路(2025)', fileType: FileType.gl },
  52. { compliationId: '5b52b027fd3bb0000b257cf8', name: '重庆建设(2018)', fileType: FileType.js },
  53. { compliationId: '5c66649650da2d000d8d37ba', name: '广东建设(2018)', fileType: FileType.js },
  54. ];
  55. const projectTypeKey = (function(arr) {
  56. const result = {};
  57. for (const a of arr) {
  58. result[a.key] = a.value;
  59. }
  60. return result;
  61. })(projectType);
  62. const checkBind = async function() {
  63. const data = await postDataAsync('/profile/dsk/api', {type: 'hadbind'});
  64. return data !== 1 && data !== 2;
  65. };
  66. const loadCompilation = async function () {
  67. const data = await postDataAsync('/profile/dsk/api', {type: 'compilation'});
  68. return data.compilation;
  69. };
  70. const loadProject = async function(compilationId, showWaiting = true) {
  71. return await postDataAsync('/profile/dsk/api', {type: 'project', compilationId}, showWaiting);
  72. };
  73. const loadProjectTree = async function (compilationId, projectId, showWaiting = true) {
  74. return await postDataAsync('/profile/dsk/api', {type: 'project_tree', compilationId, projectId}, showWaiting)
  75. };
  76. const loadBills = async function(compilationId, subjectId, showWaiting = true) {
  77. return await postDataAsync('/profile/dsk/api', {type: 'project_bills', compilationId, treeId: subjectId}, showWaiting)
  78. };
  79. class DskTree {
  80. /**
  81. *
  82. * @param setting - {Object}配置
  83. * setting中必须设置id,pid,order,rootId(id, 父id, 同层排序, 根节点id)
  84. * e.g.{id: 'ID', pid: 'parentID', order: 'seq'}
  85. * 目前仅用于载入建筑ybp文件中的清单部分,生成树结构以便汇总导入
  86. */
  87. constructor(setting) {
  88. this.setting = JSON.parse(JSON.stringify(setting));
  89. this.clearDatas();
  90. }
  91. clearDatas() {
  92. // 数据集合
  93. this.datas = [];
  94. // id索引
  95. this.items = {};
  96. // 排序索引
  97. this.nodes = [];
  98. // 首层节点
  99. this.children = [];
  100. }
  101. sortChildren(children, recursive) {
  102. const setting = this.setting;
  103. children.sort((x, y) => { return x[setting.order] > y[setting.order]; });
  104. if (!recursive) return;
  105. for (const c of children) {
  106. this.sortChildren(c.children);
  107. }
  108. }
  109. sort() {
  110. this.sortChildren(this.children, true);
  111. const self = this;
  112. const _loadNode = function(node) {
  113. self.nodes.push(node);
  114. for (const c of node.children) {
  115. _loadNode(c);
  116. }
  117. };
  118. for (const child of this.children) {
  119. _loadNode(child);
  120. }
  121. }
  122. loadDatas(datas) {
  123. this.clearDatas();
  124. const setting = this.setting;
  125. const self = this;
  126. const _loadData = function(d) {
  127. if (d[setting.pid] === setting.rootId) {
  128. self.children.push(d);
  129. } else {
  130. let parent = self.items[d[setting.pid]];
  131. if (!parent) {
  132. parent = datas.find(x => { return x[setting.id] === d[setting.pid]; });
  133. if (!parent) {
  134. return null;
  135. }
  136. parent = _loadData(parent);
  137. }
  138. if (!parent) return null;
  139. parent.children.push(d);
  140. }
  141. d.children = [];
  142. self.datas.push(d);
  143. self.items[d[setting.id]] = d;
  144. return d;
  145. };
  146. for (const d of datas) {
  147. if (this.items[d[setting.id]]) continue;
  148. _loadData(d);
  149. }
  150. this.sort();
  151. }
  152. }
  153. const chooseSubjectObj = {
  154. obj: null,
  155. compilationObj: null,
  156. subjectSpread: null,
  157. subjectSheet: null,
  158. compliation: null,
  159. loadCompilation: async function() {
  160. if (!this.compliation) {
  161. this.compliation = await loadCompilation();
  162. for (const c of this.compliation) {
  163. const cft = CompilationFileType.find(x => { return x.compliationId === c.ID; });
  164. const FileType = cft ? cft.fileType : FileType.default;
  165. c.project = await loadProject(c.ID);
  166. for (const p of c.project) {
  167. const pftype = p.property && p.property.fileType ? FileType.find(x => { return x.value === p.property.fileType; }) : null;
  168. p.file_type_str = pftype ? pftype.name : '';
  169. }
  170. }
  171. }
  172. const html = [];
  173. for (const c of this.compliation) {
  174. html.push(`<option value="${c.ID}">${c.name}</option>`);
  175. }
  176. this.compilationObj.html(html.join(''));
  177. },
  178. analysisSubjectTree(compilation) {
  179. const subjectTree = createNewPathTree('gather', {
  180. id: 'id',
  181. pid: 'pid',
  182. order: 'sort',
  183. level: 'level',
  184. rootId: -1,
  185. fullPath: 'full_path',
  186. });
  187. const tempTree = new DskTree({ id: 'ID', pid: 'parentID', order: 'seq', rootId: '-1' });
  188. tempTree.loadDatas(compilation.project);
  189. const projectTree = new DskTree({ id: 'ID', pid: 'parentID', order: 'seq', rootId: '-1' });
  190. const loadProjectTreeNode = function (data, parent, project) {
  191. let cur;
  192. if (data.type === projectTypeKey.project) {
  193. cur = parent;
  194. } else {
  195. const type = projectType.find(x => { return x.value === data.type; });
  196. const node = { type: type.value, type_str: type.name, dsk_id: data.ID, name: data.name, project_id: project.ID, compilation_id: compilation.ID };
  197. cur = subjectTree.addNode(node, parent);
  198. }
  199. if (data.children) {
  200. data.children.forEach(c => {
  201. loadProjectTreeNode(c, cur, project);
  202. })
  203. }
  204. };
  205. const loadTempTreeNode = function (data, parent) {
  206. const type = projectType.find(x => { return x.value === data.type; });
  207. const node = { type: type.value, type_str: type.name, file_type_str: data.file_type_str, dsk_id: data.ID, name: data.name, compilation_id: compilation.ID };
  208. const cur = subjectTree.addNode(node, parent);
  209. if (data.children) {
  210. data.children.forEach(c => {
  211. loadTempTreeNode(c, cur);
  212. })
  213. }
  214. if (data.type === projectTypeKey.project) {
  215. const top = data.subjects.find(x => { return x.ID === data.ID; });
  216. top.parentID = "-1";
  217. projectTree.loadDatas(data.subjects);
  218. cur.project_id = data.ID;
  219. projectTree.children.forEach(c => {
  220. loadProjectTreeNode(c, cur, data);
  221. });
  222. }
  223. };
  224. tempTree.children.forEach(c => {
  225. loadTempTreeNode(c, null);
  226. });
  227. subjectTree.sortTreeNode(true);
  228. compilation.subjectTree = subjectTree;
  229. },
  230. loadSubjects: async function (compilationId) {
  231. showWaitingView();
  232. const compilation = compilationId ? this.compliation.find(x => { return x.ID === compilationId}) : this.compliation[0];
  233. if (!compilation) return;
  234. if (!compilation.subjectTree) {
  235. for (const p of compilation.project) {
  236. if (p.type === projectTypeKey.project) p.subjects = await loadProjectTree(compilation.ID, p.ID, false);
  237. }
  238. this.analysisSubjectTree(compilation);
  239. }
  240. SpreadJsObj.loadSheetData(this.subjectSheet, SpreadJsObj.DataType.Tree, compilation.subjectTree);
  241. closeWaitingView();
  242. },
  243. getSelectSubjects: function () {
  244. const tree = this.subjectSheet.zh_tree;
  245. if (!tree) return [];
  246. return tree.datas.filter(x => { return x.type === projectTypeKey.unit && x.selected; }).map(x => { return { name: x.name, compilationId: x.compilation_id, subjectId: x.dsk_id }; });
  247. },
  248. csButtonClicked: function(e, info) {
  249. if (!info.sheet.zh_setting) return;
  250. const col = info.sheet.zh_setting.cols[info.col];
  251. if (col.field !== 'selected') return;
  252. const tree = info.sheet.zh_tree;
  253. const node = SpreadJsObj.getSelectObject(info.sheet);
  254. if (!node.selected) {
  255. const canChoose = chooseSubjectObj.setting.validCheck ? chooseSubjectObj.setting.validCheck(node, tree) : true;
  256. if (!canChoose) return;
  257. }
  258. node.selected = !node.selected;
  259. if (node.children && node.children.length > 0) {
  260. const posterity = tree.getPosterity(node);
  261. for (const p of posterity) {
  262. p.selected = node.selected;
  263. }
  264. SpreadJsObj.reLoadRowData(info.sheet, info.row, posterity.length + 1);
  265. } else {
  266. SpreadJsObj.reLoadRowData(info.sheet, info.row, 1);
  267. }
  268. },
  269. init() {
  270. if (this.subjectSpread) return;
  271. this.obj = $('#choose-dsk-subject');
  272. this.compilationObj = $('#cdsks-compilation');
  273. this.subjectSpread = SpreadJsObj.createNewSpread($('#cdsks-spread')[0]);
  274. this.subjectSheet = this.subjectSpread.getActiveSheet();
  275. SpreadJsObj.initSheet(this.subjectSheet, {
  276. cols: [
  277. {title: '选择', field: 'selected', hAlign: 1, width: 60, formatter: '@', cellType: 'checkbox'},
  278. {title: '项目/分段名称', field: 'name', hAlign: 0, width: 640, formatter: '@', cellType: 'tree'},
  279. {title: '项目类型', field: 'file_type_str', hAlign: 1, width: 100, formatter: '@' },
  280. {title: '类型', field: 'type_str', hAlign: 1, width: 80, formatter: '@' },
  281. ],
  282. emptyRows: 0,
  283. headRows: 1,
  284. headRowHeight: [32],
  285. defaultRowHeight: 21,
  286. headerFont: '12px 微软雅黑',
  287. font: '12px 微软雅黑',
  288. selectedBackColor: '#fffacd',
  289. readOnly: true,
  290. });
  291. this.subjectSpread.bind(spreadNS.Events.ButtonClicked, this.csButtonClicked);
  292. $('#choose-dsk-subject-ok').click(() => {
  293. if (chooseSubjectObj.setting.callback) {
  294. const subjects = chooseSubjectObj.getSelectSubjects();
  295. if (subjects.length === 0) {
  296. toastr.warning('请选择导入的计价分段');
  297. return;
  298. }
  299. chooseSubjectObj.setting.callback(subjects);
  300. this.obj.modal('hide');
  301. }
  302. });
  303. $('#choose-dsk-subject').on('shown.bs.modal', function() {
  304. chooseSubjectObj.subjectSpread.refresh();
  305. });
  306. $('#cdsks-compilation').click(function() {
  307. chooseSubjectObj.loadSubjects(this.value);
  308. });
  309. },
  310. async show (setting) {
  311. this.init();
  312. this.setting = setting;
  313. this.obj.modal('show');
  314. await this.loadCompilation();
  315. await this.loadSubjects();
  316. }
  317. };
  318. const chooseSubject = function (setting) {
  319. chooseSubjectObj.show(setting);
  320. };
  321. return {
  322. projectType, projectTypeKey,
  323. checkBind, loadCompilation, loadProject, loadProjectTree, loadBills,
  324. chooseSubject
  325. };
  326. })();