cost_tmpl.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. $(document).ready(() => {
  2. autoFlashHeight();
  3. class MultiHeaderObj {
  4. constructor () {
  5. const self = this;
  6. this.firstShowDone = false;
  7. this.spread = SpreadJsObj.createNewSpread($('#multi-spread')[0]);
  8. this.sheet = this.spread.getActiveSheet();
  9. const vStyle = new spreadNS.Style();
  10. vStyle.font = '12px 微软雅黑';
  11. vStyle.hAlign = 1;
  12. vStyle.vAlign = 1;
  13. vStyle.locked = false;
  14. this.sheet.setDefaultStyle(vStyle);
  15. this.spread.bind(spreadNS.Events.EditStarting, function(e, info) {
  16. if (info.row === info.sheet.getRowCount() - 1) {
  17. info.cancel = true;
  18. }
  19. });
  20. this.spread.bind(spreadNS.Events.ColumnWidthChanging, function(e, info) {
  21. info.cancel = true;
  22. });
  23. this.spread.bind(spreadNS.Events.RowHeightChanged, function(e, info) {
  24. self.multiHeader.headRowHeight[info.row] = info.sheet.getRowHeight(info.row);
  25. });
  26. $('#multi-header').on('shown.bs.modal', function() {
  27. if (!self.firstShowDone) {
  28. self.spread.refresh();
  29. self.firstShowDone = true;
  30. }
  31. });
  32. $('#header-row-count').change(function() {
  33. let count = parseInt($('#header-row-count').val());
  34. if (count > 4 || count < 1) {
  35. toastr.warning('仅支持1-4层表头');
  36. return;
  37. }
  38. self.setHeaderRows(count);
  39. });
  40. $.contextMenu({
  41. selector: '#multi-spread',
  42. build: function ($trigger, e) {
  43. const target = SpreadJsObj.safeRightClickSelection($trigger, e, self.spread);
  44. return (target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader);
  45. },
  46. items: {
  47. 'merge': {
  48. name: '合并单元格',
  49. callback: function (key, opt) {
  50. const sel = self.sheet.getSelections()[0];
  51. self.sheet.addSpan(sel.row, sel.col, sel.rowCount, sel.colCount);
  52. },
  53. disabled: function(key, opt) {
  54. const sel = self.sheet.getSelections()[0];
  55. return sel.row + sel.rowCount >= self.sheet.getRowCount();
  56. }
  57. },
  58. 'mergeCancel': {
  59. name: '取消合并',
  60. callback: function (key, opt) {
  61. const sel = self.sheet.getSelections()[0];
  62. console.log(sel);
  63. self.sheet.removeSpan(sel.row, sel.col);
  64. },
  65. disabled: function(key, opt) {
  66. const sel = self.sheet.getSelections()[0];
  67. return sel.row + sel.rowCount === self.sheet.getRowCount();
  68. }
  69. },
  70. }
  71. });
  72. $('#multi-header-ok').click(function() {
  73. if (self.afterSet) self.afterSet(self.getMultiHeader());
  74. $('#multi-header').modal('hide');
  75. });
  76. }
  77. setHeaderRows(count) {
  78. if (count === this.multiHeader.headRows) return;
  79. this.multiHeader = { headRows: count, headRowHeight: new Array(count).fill(32) };
  80. this.reloadRowHeaderData();
  81. }
  82. reloadRowHeaderData() {
  83. this.sheet.setRowCount(0);
  84. this.sheet.setRowCount(this.multiHeader.headRows);
  85. this.sheet.setColumnCount(this.colSet.length);
  86. for (const [i, height] of this.multiHeader.headRowHeight.entries()) {
  87. this.sheet.setRowHeight(i, height);
  88. }
  89. for (const [i, col] of this.colSet.entries()) {
  90. this.sheet.getCell(this.multiHeader.headRows - 1, i).text(col.title).hAlign(1).vAlign(1);
  91. this.sheet.setColumnWidth(i, col.width);
  92. }
  93. if (this.multiHeader.headSpan) {
  94. for (const span of this.multiHeader.headSpan) {
  95. this.sheet.addSpan(span.row, span.col, span.rowCount, span.colCount);
  96. this.sheet.getCell(span.row, span.col).text(span.title);
  97. }
  98. }
  99. }
  100. show(colSet, multiHeader, fun) {
  101. this.afterSet = fun;
  102. this.colSet = colSet;
  103. this.multiHeader = multiHeader || { headRows: 1, headRowHeight: [32] };
  104. $('#header-row-count').val(this.multiHeader.headRows);
  105. this.reloadRowHeaderData();
  106. $('#multi-header').modal('show');
  107. }
  108. getMultiHeader() {
  109. const result = JSON.parse(JSON.stringify(this.multiHeader));
  110. result.headSpan = [];
  111. const spans = this.sheet.getSpans();
  112. for (const s of spans) {
  113. result.headSpan.push({col: s.col, row: s.row, colCount: s.colCount, rowCount: s.rowCount, title: this.sheet.getText(s.row, s.col) });
  114. }
  115. return result;
  116. }
  117. }
  118. const multiHeaderObj = new MultiHeaderObj();
  119. class TemplateDetailObj {
  120. constructor() {
  121. const self = this;
  122. this.firstShowDone = false;
  123. this.spread = SpreadJsObj.createNewSpread($('#col-set-spread')[0]);
  124. this.sheet = this.spread.getActiveSheet();
  125. const getTypeValue = function(data) {
  126. const typeInfo = validColInfo.find(x => { return x.key === data.type; });
  127. return typeInfo.name || '';
  128. };
  129. const numCol = validColInfo.find(x => { return x.key === 'num'; });
  130. const validCalcCode = numCol.fields.map(x => { return x.replace('num_', '').toUpperCase(); });
  131. this.spreadSetting = {
  132. cols: [
  133. { title: '类型', colSpan: '1', rowSpan: '1', field: 'type', hAlign: 1, width: 80, formatter: '@', readOnly: true, getValue: getTypeValue },
  134. { title: '列名', colSpan: '1', rowSpan: '1', field: 'title', hAlign: 0, width: 130, formatter: '@' },
  135. { title: '列宽', colSpan: '1', rowSpan: '1', field: 'width', hAlign: 1, width: 70, type: 'Number' },
  136. // { title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, cellType: 'unit' },
  137. {
  138. title: '计算代号', colSpan: '1', rowSpan: '1', field: 'calc_code', hAlign: 1, width: 80, cellType: 'customizeCombo',
  139. comboItems: validCalcCode,
  140. },
  141. { title: '小数位数', colSpan: '1', rowSpan: '1', field: 'decimal', hAlign: 1, width: 60, type: 'Number' },
  142. { title: '期数据', colSpan: '1', rowSpan: '1', field: 'sum', hAlign: 1, width: 60, readOnly: true, cellType: 'signalCheckbox', show: function(data) {
  143. const typeInfo = validColInfo.find(x => { return x.key === data.type; }); return typeInfo.valid.indexOf('sum') >= 0;
  144. } },
  145. { title: '计算公式', colSpan: '1', rowSpan: '1', field: 'expr', hAlign: 0, width: 250 },
  146. ],
  147. emptyRows: 0,
  148. headRows: 1,
  149. headRowHeight: [32],
  150. defaultRowHeight: 21,
  151. headerFont: '12px 微软雅黑',
  152. font: '12px 微软雅黑',
  153. frozenLineColor: '#93b5e4',
  154. getColor: function(sheet, data, row, col, defaultColor) {
  155. if (!data) return defaultColor;
  156. const typeInfo = validColInfo.find(x => { return x.key === data.type; });
  157. if (!typeInfo) return defaultColor;
  158. return col && typeInfo.valid.indexOf(col.field) >= 0 ? defaultColor : '#f2f2f2';
  159. }
  160. };
  161. SpreadJsObj.initSheet(this.sheet, this.spreadSetting);
  162. this.spread.bind(spreadNS.Events.EditStarting, function(e, info) {
  163. if (self.readOnly) {
  164. info.cancel = true;
  165. return;
  166. }
  167. const col = info.sheet.zh_setting.cols[info.col];
  168. const select = SpreadJsObj.getSelectObject(info.sheet);
  169. const typeInfo = validColInfo.find(x => { return x.key === select.type; });
  170. if (typeInfo) {
  171. info.cancel = col && typeInfo.valid.indexOf(col.field) >= 0 ? false : true;
  172. } else {
  173. info.cancel = true;
  174. }
  175. });
  176. this.spread.bind(spreadNS.Events.EditEnded, function(e, info){
  177. if (!info.sheet.zh_setting) return;
  178. const select = SpreadJsObj.getSelectObject(info.sheet);
  179. const col = info.sheet.zh_setting.cols[info.col];
  180. const validText = col.field === 'spec_set' ? info.editingText : (info.editingText ? info.editingText.replace('\n', '') : '');
  181. if (col.field === 'spec_set') {
  182. select.spec_set = validText;
  183. } else if (col.field === 'calc_code') {
  184. const exist = self.colSetData.find(x => { return x.type === 'num' && x.calc_code === validText && x.field !== select.field; });
  185. if (exist) {
  186. toastr.warning('请勿输入重复的计算代号');
  187. } else {
  188. const typeInfo = validColInfo.find(x => { return x.key === select.type; });
  189. if (typeInfo.type === 'num') {
  190. select.calc_code = validText;
  191. select.field = 'num_' + select.calc_code.toLowerCase();
  192. }
  193. }
  194. } else if (col.field === 'width') {
  195. select.width = parseInt(validText);
  196. } else if (col.field === 'decimal') {
  197. const num = parseInt(validText);
  198. if (num < 0 || num > 6) {
  199. toastr.warning('小数位数仅可保留0-6位');
  200. } else {
  201. select.decimal = num;
  202. }
  203. } else {
  204. select[col.field] = validText;
  205. }
  206. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  207. });
  208. this.spread.bind(spreadNS.Events.ButtonClicked, function(e, info) {
  209. if (!info.sheet.zh_setting) return;
  210. const col = info.sheet.zh_setting.cols[info.col];
  211. if (col.field !== 'sum') return;
  212. const select = SpreadJsObj.getSelectObject(info.sheet);
  213. const typeInfo = validColInfo.find(x => { return x.key === select.type; });
  214. if (typeInfo.valid.indexOf('sum') <= 0) return;
  215. select.sum = !select.sum;
  216. if (select.sum) {
  217. info.sheet.zh_data.forEach(x => {
  218. if (x.field !== select.field) delete x.sum;
  219. })
  220. }
  221. SpreadJsObj.reloadColData(info.sheet, info.col);
  222. });
  223. SpreadJsObj.addDeleteBind(this.spread, function(sheet){
  224. if (!sheet.zh_setting) return;
  225. const sel = sheet.getSelections()[0];
  226. if (!sel) return;
  227. const col = sheet.zh_setting.cols[sel.col];
  228. if (col.readOnly) return;
  229. if (sel.colCount > 1) toastr.warning('请勿同时删除多列数据');
  230. for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow ++) {
  231. const node = sheet.zh_data[iRow];
  232. if (!node) continue;
  233. if (col.type === 'Number') {
  234. node[col.field] = 0
  235. } else {
  236. node[col.field] = '';
  237. }
  238. }
  239. SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
  240. });
  241. // 右键菜单
  242. $.contextMenu({
  243. selector: '#col-set-spread',
  244. build: function ($trigger, e) {
  245. const target = SpreadJsObj.safeRightClickSelection($trigger, e, self.spread);
  246. return (target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader) && !self.readOnly && self.template;
  247. },
  248. items: {
  249. 'add_code': {
  250. name: '新增编号列',
  251. icon: 'fa-plus',
  252. callback: function (key, opt) {
  253. const select = SpreadJsObj.getSelectObject(self.sheet);
  254. self.addCol('code', select);
  255. },
  256. },
  257. 'add_name': {
  258. name: '新增名称列',
  259. icon: 'fa-plus',
  260. callback: function (key, opt) {
  261. const select = SpreadJsObj.getSelectObject(self.sheet);
  262. self.addCol('name', select);
  263. },
  264. },
  265. 'add_party_b': {
  266. name: '新增乙方列',
  267. icon: 'fa-plus',
  268. callback: function (key, opt) {
  269. const select = SpreadJsObj.getSelectObject(self.sheet);
  270. self.addCol('party_b', select);
  271. },
  272. },
  273. 'add_yf_excl_tax_tp': {
  274. name: '新增应付(不含税)列',
  275. icon: 'fa-plus',
  276. callback: function (key, opt) {
  277. const select = SpreadJsObj.getSelectObject(self.sheet);
  278. self.addCol('yf_excl_tax_tp', select);
  279. },
  280. },
  281. 'add_in_excl_tax_tp': {
  282. name: '新增入账(不含税)列',
  283. icon: 'fa-plus',
  284. callback: function (key, opt) {
  285. const select = SpreadJsObj.getSelectObject(self.sheet);
  286. self.addCol('in_excl_tax_tp', select);
  287. },
  288. },
  289. 'add_sf_excl_tax_tp': {
  290. name: '新增实付(不含税)列',
  291. icon: 'fa-plus',
  292. callback: function (key, opt) {
  293. const select = SpreadJsObj.getSelectObject(self.sheet);
  294. self.addCol('sf_excl_tax_tp', select);
  295. },
  296. },
  297. 'add_sf_percent': {
  298. name: '新增实付比例列',
  299. icon: 'fa-plus',
  300. callback: function (key, opt) {
  301. const select = SpreadJsObj.getSelectObject(self.sheet);
  302. self.addCol('sf_percent', select);
  303. },
  304. },
  305. 'add_postil': {
  306. name: '新增本期批注列',
  307. icon: 'fa-plus',
  308. callback: function (key, opt) {
  309. const select = SpreadJsObj.getSelectObject(self.sheet);
  310. self.addCol('postil', select);
  311. },
  312. },
  313. addSpecSpr: '----',
  314. 'add_str': {
  315. name: '新增文本列',
  316. icon: 'fa-plus',
  317. callback: function (key, opt) {
  318. const select = SpreadJsObj.getSelectObject(self.sheet);
  319. self.addCol('str', select);
  320. },
  321. },
  322. 'add_num': {
  323. name: '新增数值/计算列',
  324. icon: 'fa-plus',
  325. callback: function (key, opt) {
  326. const select = SpreadJsObj.getSelectObject(self.sheet);
  327. self.addCol('num', select);
  328. },
  329. },
  330. 'remove': {
  331. name: '删除',
  332. icon: 'fa-remove',
  333. callback: function (key, opt) {
  334. self.remove();
  335. },
  336. },
  337. addSpr: '----',
  338. upMove: {
  339. name: '上移',
  340. icon: 'fa-arrow-up',
  341. callback: function (key, opt) {
  342. const select = SpreadJsObj.getSelectObject(self.sheet);
  343. self.move('upMove', select);
  344. },
  345. },
  346. downMove: {
  347. name: '下移',
  348. icon: 'fa-arrow-down',
  349. callback: function (key, opt) {
  350. const select = SpreadJsObj.getSelectObject(self.sheet);
  351. self.move('downMove', select);
  352. },
  353. },
  354. moveSpr: '----',
  355. multiHeader: {
  356. name: '多行表头设置',
  357. callback: function(key, opt) {
  358. multiHeaderObj.show(self.getCurrentColSet(), self.multi_header, function(multiHeader) {
  359. self.multi_header = multiHeader;
  360. });
  361. }
  362. }
  363. }
  364. });
  365. $('#reset').click(function() {
  366. self.reset();
  367. });
  368. $('#save').click(function() {
  369. self.save();
  370. });
  371. }
  372. addCol(type, select) {
  373. const colInfo = validColInfo.find(x => { return x.key === type; });
  374. if (!colInfo) {
  375. toastr.error('未知类型');
  376. return;
  377. }
  378. const existCount = this.colSetData.filter(x => { return x.type === type; }).length;
  379. if (existCount >= colInfo.count) {
  380. toastr.error(`${colInfo.name}列仅支持${colInfo.count}个`);
  381. return;
  382. }
  383. const nData = JSON.parse(JSON.stringify(colInfo.def));
  384. for (const f of colInfo.fields) {
  385. if (!this.colSetData.find(x => { return x.field === f; })) {
  386. nData.field = f;
  387. break;
  388. }
  389. }
  390. if (select) {
  391. const index = this.colSetData.findIndex(x => { return x.field === select.field; });
  392. if (index < 0) {
  393. toastr.error('选择的列配置不存在');
  394. return;
  395. }
  396. this.colSetData.splice(index, 0, nData);
  397. } else {
  398. this.colSetData.push(nData);
  399. }
  400. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
  401. }
  402. remove() {
  403. const sel = this.sheet.getSelections()[0];
  404. if (!sel) return;
  405. this.colSetData.splice(sel.row, sel.rowCount);
  406. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
  407. }
  408. move(type, select) {
  409. const index = this.colSetData.findIndex(x => { return x.field === select.field; });
  410. if (type === 'upMove' && index === 0) {
  411. toastr.error('不可上移');
  412. return;
  413. }
  414. if (type === 'downMove' && index === this.colSetData.length - 1) {
  415. toastr.error('不可下移');
  416. return;
  417. }
  418. this.colSetData.splice(index, 1);
  419. this.colSetData.splice(type === 'upMove' ? index - 1 : index + 1, 0, select);
  420. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
  421. }
  422. reset() {
  423. this.colSetData = JSON.parse(JSON.stringify(this.template.col_set));
  424. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
  425. this.multi_header = this.template.multi_header ? JSON.parse(JSON.stringify(this.template.multi_header)) : null;
  426. }
  427. loadDetail(template) {
  428. this.template = template;
  429. this.readOnly = this.template.used_count > 0;
  430. if (!this.firstShowDone) {
  431. this.spread.refresh();
  432. this.firstShowDone = true;
  433. }
  434. if (this.readOnly) {
  435. $('#detail-ctrl').hide();
  436. } else {
  437. $('#detail-ctrl').show();
  438. }
  439. this.reset();
  440. }
  441. save(){
  442. const self = this;
  443. const update = { id: this.template.id, col_set: this.getCurrentColSet(), multi_header: this.multi_header || this.template.multi_header };
  444. if (!update.col_set) return;
  445. postData('save', { update }, function(result) {
  446. self.template.col_set = result.update.col_set;
  447. });
  448. }
  449. getCurrentColSet() {
  450. for (const col of this.colSetData) {
  451. if (col.type === 'num') {
  452. if (!col.calc_code) {
  453. toastr.error(`【${col.title}】未定义计算代号`);
  454. return null;
  455. }
  456. }
  457. }
  458. const sumCol = this.colSetData.find(x => { return x.sum; });
  459. if (!sumCol) {
  460. toastr.error('未指定期数据显示的数据列');
  461. return null;
  462. }
  463. return this.colSetData;
  464. }
  465. export() {
  466. window.open(`/template/ctd?tid=${this.template.id}`);
  467. }
  468. import() {
  469. const self = this;
  470. BaseImportFile.show({
  471. validList: ['.ctd'],
  472. url: `/template/ctd/load?tid=${this.template.id}`,
  473. afterImport: function (result) {
  474. self.template.col_set = result.update.col_set;
  475. self.template.multi_header = result.update.multi_header;
  476. self.reset();
  477. }
  478. });
  479. }
  480. }
  481. const detailObj = new TemplateDetailObj();
  482. $('#preview').click(function() {
  483. const data = { type: 'cost', col_set: detailObj.getCurrentColSet(), multi_header: detailObj.multi_header || detailObj.template.multi_header };
  484. if (!data.col_set) return;
  485. calcTemplatePreview.preview(data);
  486. });
  487. const templateObj = (function(list){
  488. const templates = list;
  489. let curTemplate;
  490. const loadTemplateDetail = async function(template) {
  491. const result = await postDataAsync('load', { filter: 'detail', id: template.id, type: 'cost' });
  492. if (result && result.detail) {
  493. template.col_set = result.detail.col_set;
  494. template.multi_header = result.detail.multi_header;
  495. }
  496. };
  497. const refreshTemplate = async function() {
  498. if (!curTemplate) {
  499. // todo 隐藏模板详细界面
  500. } else {
  501. $('dd[templateId]').removeClass('bg-warning');
  502. $(`dd[templateId=${curTemplate.id}]`).addClass('bg-warning');
  503. if (!curTemplate.col_set) await loadTemplateDetail(curTemplate);
  504. detailObj.loadDetail(curTemplate);
  505. }
  506. };
  507. const setCurTemplate = function(template) {
  508. curTemplate = template;
  509. refreshTemplate();
  510. };
  511. const getCurTemplate = function() {
  512. return curTemplate;
  513. };
  514. const getTemplateCaptionInnerHtml = function(template) {
  515. const usedHtml = template.used_count > 0 ? '<i class="ml-1 fa fa-lock text-danger"></i>' : '';
  516. return `<div>${template.name}${usedHtml}</div>` +
  517. ' <div class="btn-group-table" style="display: none;">\n' +
  518. ' <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="编辑" name="renameTemplate"><i class="fa fa-pencil fa-fw"></i></a>\n' +
  519. ' <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="删除" name="delTemplate"><i class="fa fa-trash-o fa-fw text-danger"></i></a>\n' +
  520. '</div>';
  521. };
  522. const getTemplateCaptionHtml = function(template) {
  523. return `<div class="d-flex justify-content-between align-items-center table-file" templateId="${template.id}">` + getTemplateCaptionInnerHtml(template) + '</div>';
  524. };
  525. const getTemplateHtml = function(template) {
  526. const html = [];
  527. html.push(`<dd class="list-group-item" templateId="${template.id}">`, getTemplateCaptionHtml(template), '</dd>');
  528. return html.join('');
  529. };
  530. const addTemplate = function() {
  531. postData('save', {add: { name: '' }, type: 'cost'}, function(result) {
  532. templates.push(result.add);
  533. $('#template-list').append(getTemplateHtml(result.add));
  534. });
  535. };
  536. const renameTemplate = function(id, name) {
  537. postData('save', { update: { id, name }, type: 'cost'}, function(result){
  538. const template = templates.find(x => { return x.id === result.update.id; });
  539. template.name = result.update.name;
  540. $(`dd[templateId=${template.id}]`).html(getTemplateCaptionHtml(template));
  541. });
  542. };
  543. const delTemplate = function(id){
  544. postData('save', {del: id, type: 'cost'}, function(result) {
  545. $(`dd[templateId=${id}]`).remove();
  546. const tIndex = templates.findIndex(x => { return x.id === id; });
  547. templates.splice(tIndex, 1);
  548. if (curTemplate && curTemplate.id === id) {
  549. curTemplate = null;
  550. refreshTemplate();
  551. }
  552. });
  553. };
  554. if (templates.length > 0) setCurTemplate(templates[0]);
  555. return { setCurTemplate, getCurTemplate, addTemplate, delTemplate, renameTemplate, getTemplateCaptionHtml, getTemplateCaptionInnerHtml }
  556. })(templateList);
  557. $('body').on('click', '.table-file', function(e) {
  558. if (this.getAttribute('renaming') === '1') return;
  559. if (e.target.tagName === 'A' || e.target.tagName === 'I' || e.target.tagName === 'INPUT') return;
  560. const templateId = this.getAttribute('templateId');
  561. const template = templateList.find(x => { return x.id === templateId; });
  562. templateObj.setCurTemplate(template);
  563. });
  564. $('body').on('mouseenter', ".table-file", function(){
  565. $(this).children(".btn-group-table").css("display","block");
  566. });
  567. $('body').on('mouseleave', ".table-file", function(){
  568. $(this).children(".btn-group-table").css("display","none");
  569. });
  570. $('body').on('click', 'a[name=renameTemplate]', function(e){
  571. $(this).parents('.table-file').attr('renaming', '1');
  572. $(`#${this.getAttribute('aria-describedby')}`).remove();
  573. const templateId = $(this).parents('.table-file').attr('templateId');
  574. const template = templateList.find(x => { return x.id === templateId; });
  575. if (!template) return;
  576. const html = [];
  577. html.push(`<div><input type="text" class="form-control form-control-sm" style="width: 160px" value="${template.name}"/></div>`);
  578. html.push('<div class="btn-group-table" style="display: none;">',
  579. `<a href="javascript: void(0)" name="renameOk" class="mr-1"><i class="fa fa-check fa-fw"></i></a>`,
  580. `<a href="javascript: void(0)" class="mr-1" name="renameCancel"><i class="fa fa-remove fa-fw text-danger"></i></a>`, '</div>');
  581. $(`.table-file[templateId=${templateId}]`).html(html.join(''));
  582. e.stopPropagation();
  583. });
  584. $('body').on('click', 'a[name=renameOk]', function(){
  585. const templateId = $(this).parents('.table-file').attr('templateId');
  586. const newName = $(this).parents('.table-file').find('input').val();
  587. templateObj.renameTemplate(templateId, newName);
  588. $(this).parents('.table-file').attr('renaming', '0');
  589. });
  590. $('body').on('click', 'a[name=renameCancel]', function() {
  591. $(this).parents('.table-file').attr('renaming', '0');
  592. const templateId = $(this).parents('.table-file').attr('templateId');
  593. const template = templateList.find(x => { return x.id === templateId; });
  594. if (!template) return;
  595. $(`.table-file[templateId=${templateId}]`).html(templateObj.getTemplateCaptionInnerHtml(template));
  596. });
  597. $('body').on('click', 'a[name=delTemplate]', function(e) {
  598. e.stopPropagation();
  599. const templateId = $(this).parents('.table-file').attr('templateId');
  600. templateObj.delTemplate(templateId);
  601. });
  602. $('#export').click(function() {
  603. detailObj.export();
  604. });
  605. $('#import').click(function() {
  606. detailObj.import();
  607. });
  608. $('#addTemplate').click(function() {
  609. templateObj.addTemplate();
  610. });
  611. });