| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- $(document).ready(() => {
- autoFlashHeight();
- class MultiHeaderObj {
- constructor () {
- const self = this;
- this.firstShowDone = false;
- this.spread = SpreadJsObj.createNewSpread($('#multi-spread')[0]);
- this.sheet = this.spread.getActiveSheet();
- const vStyle = new spreadNS.Style();
- vStyle.font = '12px 微软雅黑';
- vStyle.hAlign = 1;
- vStyle.vAlign = 1;
- vStyle.locked = false;
- this.sheet.setDefaultStyle(vStyle);
- this.spread.bind(spreadNS.Events.EditStarting, function(e, info) {
- if (info.row === info.sheet.getRowCount() - 1) {
- info.cancel = true;
- }
- });
- this.spread.bind(spreadNS.Events.ColumnWidthChanging, function(e, info) {
- info.cancel = true;
- });
- this.spread.bind(spreadNS.Events.RowHeightChanged, function(e, info) {
- self.multiHeader.headRowHeight[info.row] = info.sheet.getRowHeight(info.row);
- });
- $('#multi-header').on('shown.bs.modal', function() {
- if (!self.firstShowDone) {
- self.spread.refresh();
- self.firstShowDone = true;
- }
- });
- $('#header-row-count').change(function() {
- let count = parseInt($('#header-row-count').val());
- if (count > 4 || count < 1) {
- toastr.warning('仅支持1-4层表头');
- return;
- }
- self.setHeaderRows(count);
- });
- $.contextMenu({
- selector: '#multi-spread',
- build: function ($trigger, e) {
- const target = SpreadJsObj.safeRightClickSelection($trigger, e, self.spread);
- return (target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader);
- },
- items: {
- 'merge': {
- name: '合并单元格',
- callback: function (key, opt) {
- const sel = self.sheet.getSelections()[0];
- self.sheet.addSpan(sel.row, sel.col, sel.rowCount, sel.colCount);
- },
- disabled: function(key, opt) {
- const sel = self.sheet.getSelections()[0];
- return sel.row + sel.rowCount >= self.sheet.getRowCount();
- }
- },
- 'mergeCancel': {
- name: '取消合并',
- callback: function (key, opt) {
- const sel = self.sheet.getSelections()[0];
- console.log(sel);
- self.sheet.removeSpan(sel.row, sel.col);
- },
- disabled: function(key, opt) {
- const sel = self.sheet.getSelections()[0];
- return sel.row + sel.rowCount === self.sheet.getRowCount();
- }
- },
- }
- });
- $('#multi-header-ok').click(function() {
- if (self.afterSet) self.afterSet(self.getMultiHeader());
- $('#multi-header').modal('hide');
- });
- }
- setHeaderRows(count) {
- if (count === this.multiHeader.headRows) return;
- this.multiHeader = { headRows: count, headRowHeight: new Array(count).fill(32) };
- this.reloadRowHeaderData();
- }
- reloadRowHeaderData() {
- this.sheet.setRowCount(0);
- this.sheet.setRowCount(this.multiHeader.headRows);
- this.sheet.setColumnCount(this.colSet.length);
- for (const [i, height] of this.multiHeader.headRowHeight.entries()) {
- this.sheet.setRowHeight(i, height);
- }
- for (const [i, col] of this.colSet.entries()) {
- this.sheet.getCell(this.multiHeader.headRows - 1, i).text(col.title).hAlign(1).vAlign(1);
- this.sheet.setColumnWidth(i, col.width);
- }
- if (this.multiHeader.headSpan) {
- for (const span of this.multiHeader.headSpan) {
- this.sheet.addSpan(span.row, span.col, span.rowCount, span.colCount);
- this.sheet.getCell(span.row, span.col).text(span.title);
- }
- }
- }
- show(colSet, multiHeader, fun) {
- this.afterSet = fun;
- this.colSet = colSet;
- this.multiHeader = multiHeader || { headRows: 1, headRowHeight: [32] };
- $('#header-row-count').val(this.multiHeader.headRows);
- this.reloadRowHeaderData();
- $('#multi-header').modal('show');
- }
- getMultiHeader() {
- const result = JSON.parse(JSON.stringify(this.multiHeader));
- result.headSpan = [];
- const spans = this.sheet.getSpans();
- for (const s of spans) {
- result.headSpan.push({col: s.col, row: s.row, colCount: s.colCount, rowCount: s.rowCount, title: this.sheet.getText(s.row, s.col) });
- }
- return result;
- }
- }
- const multiHeaderObj = new MultiHeaderObj();
- class TemplateDetailObj {
- constructor() {
- const self = this;
- this.firstShowDone = false;
- this.spread = SpreadJsObj.createNewSpread($('#col-set-spread')[0]);
- this.sheet = this.spread.getActiveSheet();
- const getTypeValue = function(data) {
- const typeInfo = validColInfo.find(x => { return x.key === data.type; });
- return typeInfo.name || '';
- };
- this.spreadSetting = {
- cols: [
- { title: '类型', colSpan: '1', rowSpan: '1', field: 'type', hAlign: 1, width: 80, formatter: '@', readOnly: true, getValue: getTypeValue },
- { title: '列名', colSpan: '1', rowSpan: '1', field: 'title', hAlign: 0, width: 130, formatter: '@' },
- { title: '列宽', colSpan: '1', rowSpan: '1', field: 'width', hAlign: 1, width: 70, type: 'Number' },
- // { title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, cellType: 'unit' },
- {
- title: '计算代号', colSpan: '1', rowSpan: '1', field: 'calc_code', hAlign: 1, width: 80, cellType: 'customizeCombo',
- comboItems: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'],
- },
- { title: '小数位数', colSpan: '1', rowSpan: '1', field: 'decimal', hAlign: 1, width: 60, type: 'Number' },
- { title: '计算公式', colSpan: '1', rowSpan: '1', field: 'expr', hAlign: 0, width: 250 },
- ],
- emptyRows: 0,
- headRows: 1,
- headRowHeight: [32],
- defaultRowHeight: 21,
- headerFont: '12px 微软雅黑',
- font: '12px 微软雅黑',
- frozenLineColor: '#93b5e4',
- getColor: function(sheet, data, row, col, defaultColor) {
- if (!data) return defaultColor;
- const typeInfo = validColInfo.find(x => { return x.key === data.type; });
- if (!typeInfo) return defaultColor;
- return col && typeInfo.valid.indexOf(col.field) >= 0 ? defaultColor : '#f2f2f2';
- }
- };
- SpreadJsObj.initSheet(this.sheet, this.spreadSetting);
- this.spread.bind(spreadNS.Events.EditStarting, function(e, info) {
- if (self.readOnly) {
- info.cancel = true;
- return;
- }
- const col = info.sheet.zh_setting.cols[info.col];
- const select = SpreadJsObj.getSelectObject(info.sheet);
- const typeInfo = validColInfo.find(x => { return x.key === select.type; });
- if (typeInfo) {
- info.cancel = col && typeInfo.valid.indexOf(col.field) >= 0 ? false : true;
- } else {
- info.cancel = true;
- }
- });
- this.spread.bind(spreadNS.Events.EditEnded, function(e, info){
- if (!info.sheet.zh_setting) return;
- const select = SpreadJsObj.getSelectObject(info.sheet);
- const col = info.sheet.zh_setting.cols[info.col];
- const validText = col.field === 'spec_set' ? info.editingText : (info.editingText ? info.editingText.replace('\n', '') : '');
- if (col.field === 'spec_set') {
- select.spec_set = validText;
- } else if (col.field === 'calc_code') {
- const exist = self.colSetData.find(x => { return x.type === 'num' && x.calc_code === validText && x.field !== select.field; });
- if (exist) {
- toastr.warning('请勿输入重复的计算代号');
- } else {
- select.calc_code = validText;
- select.field = 'num_' + select.calc_code.toLowerCase();
- }
- } else if (col.field === 'width') {
- select.width = parseInt(validText);
- } else if (col.field === 'decimal') {
- const num = parseInt(validText);
- if (num < 0 || num > 6) {
- toastr.warning('小数位数仅可保留0-6位');
- } else {
- select.decimal = num;
- }
- } else {
- select[col.field] = validText;
- }
- SpreadJsObj.reLoadRowData(info.sheet, info.row);
- });
- SpreadJsObj.addDeleteBind(this.spread, function(sheet){
- if (!sheet.zh_setting) return;
- const sel = sheet.getSelections()[0];
- if (!sel) return;
- const col = sheet.zh_setting.cols[sel.col];
- if (col.readOnly) return;
- if (sel.colCount > 1) toastr.warning('请勿同时删除多列数据');
- for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow ++) {
- const node = sheet.zh_data[iRow];
- if (!node) continue;
- if (col.type === 'Number') {
- node[col.field] = 0
- } else {
- node[col.field] = '';
- }
- }
- SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
- });
- // 右键菜单
- $.contextMenu({
- selector: '#col-set-spread',
- build: function ($trigger, e) {
- const target = SpreadJsObj.safeRightClickSelection($trigger, e, self.spread);
- return (target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader) && !self.readOnly && self.template;
- },
- items: {
- 'add_str': {
- name: '新增文本列',
- icon: 'fa-plus',
- callback: function (key, opt) {
- const select = SpreadJsObj.getSelectObject(self.sheet);
- self.addCol('str', select);
- },
- },
- 'add_num': {
- name: '新增数值/计算列',
- icon: 'fa-plus',
- callback: function (key, opt) {
- const select = SpreadJsObj.getSelectObject(self.sheet);
- self.addCol('num', select);
- },
- },
- 'remove': {
- name: '删除',
- icon: 'fa-remove',
- callback: function (key, opt) {
- self.remove();
- },
- },
- addSpr: '----',
- upMove: {
- name: '上移',
- icon: 'fa-arrow-up',
- callback: function (key, opt) {
- const select = SpreadJsObj.getSelectObject(self.sheet);
- self.move('upMove', select);
- },
- },
- downMove: {
- name: '下移',
- icon: 'fa-arrow-down',
- callback: function (key, opt) {
- const select = SpreadJsObj.getSelectObject(self.sheet);
- self.move('downMove', select);
- },
- },
- moveSpr: '----',
- multiHeader: {
- name: '多行表头设置',
- callback: function(key, opt) {
- multiHeaderObj.show(self.getCurrentColSet(), self.multi_header, function(multiHeader) {
- self.multi_header = multiHeader;
- });
- }
- }
- }
- });
- $('#reset').click(function() {
- self.reset();
- });
- $('#save').click(function() {
- self.save();
- });
- }
- addCol(type, select) {
- const colInfo = validColInfo.find(x => { return x.key === type; });
- if (!colInfo) {
- toastr.error('未知类型');
- return;
- }
- const existCount = this.colSetData.filter(x => { return x.type === type; }).length;
- if (existCount >= colInfo.count) {
- toastr.error(`${colInfo.name}列仅支持${colInfo.count}个`);
- return;
- }
- const nData = JSON.parse(JSON.stringify(colInfo.def));
- for (const f of colInfo.fields) {
- if (!this.colSetData.find(x => { return x.field === f; })) {
- nData.field = f;
- break;
- }
- }
- if (select) {
- const index = this.colSetData.findIndex(x => { return x.field === select.field; });
- if (index < 0) {
- toastr.error('选择的列配置不存在');
- return;
- }
- this.colSetData.splice(index, 0, nData);
- } else {
- this.colSetData.push(nData);
- }
- SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
- }
- remove() {
- const sel = this.sheet.getSelections()[0];
- if (!sel) return;
- this.colSetData.splice(sel.row, sel.rowCount);
- SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
- }
- move(type, select) {
- const index = this.colSetData.findIndex(x => { return x.field === select.field; });
- if (type === 'upMove' && index === 0) {
- toastr.error('不可上移');
- return;
- }
- if (type === 'downMove' && index === this.colSetData.length - 1) {
- toastr.error('不可下移');
- return;
- }
- this.colSetData.splice(index, 1);
- this.colSetData.splice(type === 'upMove' ? index - 1 : index + 1, 0, select);
- SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
- }
- reset() {
- this.colSetData = JSON.parse(JSON.stringify(this.template.col_set));
- SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.colSetData);
- this.multi_header = this.template.multi_header ? JSON.parse(JSON.stringify(this.template.multi_header)) : null;
- }
- loadDetail(template) {
- this.template = template;
- this.readOnly = this.template.used_count > 0;
- if (!this.firstShowDone) {
- this.spread.refresh();
- this.firstShowDone = true;
- }
- if (this.readOnly) {
- $('#detail-ctrl').hide();
- } else {
- $('#detail-ctrl').show();
- }
- this.reset();
- }
- save(){
- const self = this;
- const update = { id: this.template.id, col_set: this.getCurrentColSet(), multi_header: this.multi_header || this.template.multi_header };
- if (!update.col_set) return;
- postData('save', { update }, function(result) {
- self.template.col_set = result.update.col_set;
- });
- }
- getCurrentColSet() {
- for (const col of this.colSetData) {
- if (col.type === 'num') {
- if (!col.calc_code) {
- toastr.error(`【${col.title}】未定义计算代号`);
- return null;
- }
- }
- }
- return this.colSetData;
- }
- export() {
- window.open(`/sp/${spid}/template/ctd?tid=${this.template.id}`);
- }
- import() {
- const self = this;
- BaseImportFile.show({
- validList: ['.ctd'],
- url: `/sp/${spid}/template/ctd/load?tid=${this.template.id}`,
- afterImport: function (result) {
- self.template.col_set = result.update.col_set;
- self.template.multi_header = result.update.multi_header;
- self.reset();
- }
- });
- }
- }
- const detailObj = new TemplateDetailObj();
- $('#preview').click(function() {
- const data = { type: 'cost', col_set: detailObj.getCurrentColSet(), multi_header: detailObj.multi_header || detailObj.template.multi_header };
- if (!data.col_set) return;
- calcTemplatePreview.preview(data);
- });
- const templateObj = (function(list){
- const templates = list;
- let curTemplate;
- const loadTemplateDetail = async function(template) {
- const result = await postDataAsync('load', { filter: 'detail', id: template.id, type: 'cost' });
- if (result && result.detail) {
- template.col_set = result.detail.col_set;
- template.multi_header = result.detail.multi_header;
- }
- };
- const refreshTemplate = async function() {
- if (!curTemplate) {
- // todo 隐藏模板详细界面
- } else {
- $('dd[templateId]').removeClass('bg-warning');
- $(`dd[templateId=${curTemplate.id}]`).addClass('bg-warning');
- if (!curTemplate.col_set) await loadTemplateDetail(curTemplate);
- detailObj.loadDetail(curTemplate);
- }
- };
- const setCurTemplate = function(template) {
- curTemplate = template;
- refreshTemplate();
- };
- const getCurTemplate = function() {
- return curTemplate;
- };
- const getTemplateCaptionHtml = function(template) {
- const usedHtml = template.used_count > 0 ? '<i class="ml-1 fa fa-lock text-danger"></i>' : '';
- return `<div class="d-flex justify-content-between align-items-center table-file" templateId="${template.id}"><div>${template.name}${usedHtml}</div>` +
- ' <div class="btn-group-table" style="display: none;">\n' +
- ' <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' +
- ' <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' +
- '</div></div>';
- };
- const getTemplateHtml = function(template) {
- const html = [];
- html.push(`<dd class="list-group-item" templateId="${template.id}">`, getTemplateCaptionHtml(template), '</dd>');
- return html.join('');
- };
- const addTemplate = function() {
- postData('save', {add: { name: '' }, type: 'cost'}, function(result) {
- templates.push(result.add);
- $('#template-list').append(getTemplateHtml(result.add));
- });
- };
- const renameTemplate = function(id, name) {
- postData('save', { update: { id, name }, type: 'cost'}, function(result){
- const template = templates.find(x => { return x.id === result.update.id; });
- template.name = result.update.name;
- $(`dd[templateId=${template.id}]`).html(getTemplateCaptionHtml(template));
- });
- };
- const delTemplate = function(id){
- postData('save', {del: id, type: 'cost'}, function(result) {
- $(`dd[templateId=${id}]`).remove();
- const tIndex = templates.findIndex(x => { return x.id === id; });
- templates.splice(tIndex, 1);
- if (curTemplate.id === id) {
- curTemplate = null;
- refreshTemplate();
- }
- });
- };
- if (templates.length > 0) setCurTemplate(templates[0]);
- return { setCurTemplate, getCurTemplate, addTemplate, delTemplate, renameTemplate, getTemplateCaptionHtml }
- })(templateList);
- $('body').on('click', '.table-file', function(e) {
- if (this.getAttribute('renaming') === '1') return;
- if (e.target.tagName === 'A' || e.target.tagName === 'I' || e.target.tagName === 'INPUT') return;
- const templateId = this.getAttribute('templateId');
- const template = templateList.find(x => { return x.id === templateId; });
- templateObj.setCurTemplate(template);
- });
- $('body').on('mouseenter', ".table-file", function(){
- $(this).children(".btn-group-table").css("display","block");
- });
- $('body').on('mouseleave', ".table-file", function(){
- $(this).children(".btn-group-table").css("display","none");
- });
- $('body').on('click', 'a[name=renameTemplate]', function(e){
- $(this).parents('.table-file').attr('renaming', '1');
- $(`#${this.getAttribute('aria-describedby')}`).remove();
- const templateId = $(this).parents('.table-file').attr('templateId');
- const template = templateList.find(x => { return x.id === templateId; });
- if (!template) return;
- const html = [];
- html.push(`<div><input type="text" class="form-control form-control-sm" style="width: 160px" value="${template.name}"/></div>`);
- html.push('<div class="btn-group-table" style="display: none;">',
- `<a href="javascript: void(0)" name="renameOk" class="mr-1"><i class="fa fa-check fa-fw"></i></a>`,
- `<a href="javascript: void(0)" class="mr-1" name="renameCancel"><i class="fa fa-remove fa-fw text-danger"></i></a>`, '</div>');
- $(`.table-file[templateId=${templateId}]`).html(html.join(''));
- e.stopPropagation();
- });
- $('body').on('click', 'a[name=renameOk]', function(){
- const templateId = $(this).parents('.table-file').attr('templateId');
- const newName = $(this).parents('.table-file').find('input').val();
- templateObj.renameTemplate(templateId, newName);
- $(this).parents('.table-file').attr('renaming', '0');
- });
- $('body').on('click', 'a[name=renameCancel]', function() {
- $(this).parents('.table-file').attr('renaming', '0');
- const templateId = $(this).parents('.table-file').attr('templateId');
- const template = templateList.find(x => { return x.id === templateId; });
- if (!template) return;
- $(`.table-file[templateId=${templateId}]`).html(templateObj.getTemplateCaptionHtml(template));
- });
- $('body').on('click', 'a[name=delTemplate]', function(e) {
- e.stopPropagation();
- const templateId = $(this).parents('.table-file').attr('templateId');
- templateObj.delTemplate(templateId);
- });
- $('#export').click(function() {
- detailObj.export();
- });
- $('#import').click(function() {
- detailObj.import();
- });
- $('#addTemplate').click(function() {
- templateObj.addTemplate();
- });
- });
|