import { Layout } from "./interface"; import { computed, reactive, toRefs } from "vue"; // import { useRoute } from "vue-router"; // import { useAuthStore } from "@/stores/modules/auth"; import { useLayoutStore } from "@/stores/modules/layout"; import { ColumnProps } from "@/components/LjVxeTable/interface"; import { isFunction, isObject, isString } from "@/utils/is"; import { cloneDeep, pick, has, get, set, defaultsDeep } from "lodash-es"; import { streamlineFunc, parseFormatType } from "@/utils"; import { defineColumnStyle } from "@/config/columnStyle"; import tableJson from "@/languages/modules/zh-cn/table.json"; import { TABLE_TYPE_FILTER } from "@/config/index"; /** * @description 表格布局信息 * @param {string} type 布局类型 * @param {Object} t i18n * @param {Array} columns 初始化布局数据 * @param {Array} layoutAttr 布局读取/保存时,赋值的属性名称 * @param {Object} layoutAttrDefine 布局默认设置,保存时移除,默认的属性 * @param {boolean} autoLoadLayout 自动获取布局 * @param {String} dwname 布局名称 * @param {Function} loadLayoutCallBack 加载布局时,返回的数据进行处理的方法 * @param {Function} flatColumnsCallBack 扁平化布局时,返回的数据进行处理的方法 * */ export const useDwLayout = ( dwtype: "table" | "detail", t: any, columns: ColumnProps[], layoutAttr: string[] = [], layoutAttrDefine: any = {}, autoLoadLayout: boolean = false, dwname?: string, loadLayoutCallBack?: (data: any) => any, flatColumnsCallBack?: (data: any) => any, editable?: boolean ) => { // 布局暂存数据 const layoutStore = useLayoutStore(); /** * @description 额外由后台决定的columns属性 */ const onlyReadAttr = ["datatype", "enum", "pbformat", "tabsequence"]; /** * @description 别名字段集合(field),由后台定义title值 */ const aliasAttr = ["status", "woodcode", "pcode", "mtrlsectype", "zxmtrlmode", "usermtrlmode", "otheramt", "excolumn"]; const state = reactive({ tableColumns: cloneDeep(columns), dwLayout: [], flatColumns: [] }); const dwFieldMap = new Map(); const loadLayoutFunc = async () => { if (dwname) { console.log("BF 数行化BF,还原个性设置 state.tableColumns.value :>> ", state.tableColumns); // console.log("await layoutStore.getDwLayout(dwname) :>> ", await layoutStore.getDwLayout(dwname, autoLoadLayout)); let layout = await layoutStore.getDwLayout(dwname, autoLoadLayout); console.log("BF loadLayoutFunc layout :>> ", layout); if (layout?.hasOwnProperty("itemvalue") && layout.itemvalue) { // 表格结构: {tableprop: string, columns: string} typeof layout.itemvalue == "string" && (layout.itemvalue = JSON.parse(layout.itemvalue.replace(/'/g, '"'))); // 兼容部分结构直接记录行数据 if (layout.itemvalue.hasOwnProperty("columns") && layout.itemvalue.columns) { state.dwLayout = layout.itemvalue.columns; } else { state.dwLayout = layout.itemvalue; } loadLayoutCallBack && loadLayoutCallBack(layout.itemvalue); } console.log("onMounted state.dwLayout :>> ", state.dwLayout); loadDwLayoutFunc(state.dwLayout); console.log("数行化BF,还原个性设置 state.tableColumns.value :>> ", state.tableColumns); // 扁平化,并读取个性设置 // state.flatColumns = flatColumnsFunc(state.tableColumns, dwFieldMap); // console.log("读取个性设置 state.flatColumns :>> ", state.flatColumns); // 数行化,还原个性设置 // tableColumns.value = restoreColumnsFunc(state.flatColumns); // console.log("数行化,还原个性设置 tableColumns.value :>> ", tableColumns.value); } state.flatColumns = flatColumnsFunc(state.tableColumns, dwFieldMap); console.log("state.flatColumns :>> ", state.flatColumns); }; /** * @description 读取个性布局,用Map()储存 * @param loadLayout 读取的布局数据 */ const loadDwLayoutFunc = (loadLayout: ColumnProps[] = [], sort: boolean = true) => { console.log("loadLayout.value :>> ", loadLayout); if (!loadLayout || !loadLayout.length) return false; if (sort) { // 个性布局加顺序号 for (const i in loadLayout) { loadLayout[i].colorder = Number(i); } } // 个性布局构建键值Map() dwFieldMap.clear(); for (const item of loadLayout) { dwFieldMap.set(item.field, item); } console.log("dwFieldMap :>> ", dwFieldMap); }; // /** // * @description 默认值赋值, // * @param {Object} item 数据项 // * @param {Object/Array} defineValue 默认数据 // */ // const setDefineVal = (item: any, defineValue: any) => { // for (const key in defineValue) { // if (key == "visible") { // item[key] = item[key] === false ? false : defineValue[key]; // } else { // if (isObject(item[key])) { // setDefineVal(item[key], defineValue[key]); // } else if (isArray(item[key])) { // item[key].forEach((itm: any) => { // setDefineVal(itm, defineValue[key][0]); // }); // } else { // item[key] = item[key] ?? defineValue[key]; // } // item[key] = item[key] ?? defineValue[key]; // } // } // }; let _checkAttr = [...layoutAttr, ...onlyReadAttr]; /** * 读取个性化布局 * @param {object} item 原始column数据 * @param {object} userStyle 个性化布局 * @returns {object} 返回完成恢复默认值的个性布局数据 */ const loadUserStyle = (item: any, userStyle: any) => { // let _item = cloneDeep(item); // 只有部分列的title值,取自后台数据 let attr = cloneDeep(_checkAttr); if (item.field && item.title && (!aliasAttr.includes(item.field) || (item.field == "status" && item.enum))) { attr = attr.filter((item: string) => item != "title"); } // if (item.field == "status") { // console.log("bf loadUserStyle attr :>> ", attr); // console.log("bf userStyle attr :>> ", userStyle); // } // 只读授权的字段 let _load = pick(userStyle, attr); // 先赋值datatype,处理并获取,默认赋值 _load.datatype && (item.datatype = _load.datatype); _load.enum && (item.enum = _load.enum); let _define = getDefineAttr(item, layoutAttrDefine); // 强→弱 defaultsDeep(_load, _define, item); // console.log("_load :>> ", item.field, _load); // console.log("item :>> ", item); // console.log("_define :>> ", _define); _load.colorder = userStyle.colorder; userStyle.table && (_load.table = userStyle.table); if (!userStyle?.basicinfo?.group && item?.basicinfo?.group) { delete _load.basicinfo.group; } // if (!userStyle?.basicinfo?.ishidden && item?.basicinfo?.ishidden) { // delete _load.basicinfo.ishidden; // } // console.log("loadUserStyle _load :>> ", _load); // if (item.field == "status") { // console.log("loadUserStyle _load :>> ", _load); // } return _load; }; /** * 默认值:补充具有指定特征的属性 * @param item column, 列 * @param layoutAttrDefine 默认值对象 * @returns 组合默认特征后的默认值对象 */ const getDefineAttr = (item: any, defineColumn: any) => { let _define: any = {}; if (item.hasOwnProperty("datatype")) { _define = cloneDeep(defineColumnStyle[item.datatype]); } else { let matched = false; for (const key in defineColumnStyle) { if (key.indexOf("$") > -1 || key.indexOf("^") > -1) { // 正则表达式 let reg = new RegExp(key); if (reg.test(item.field)) { _define = cloneDeep(defineColumnStyle[key]); matched = true; // if (key.indexOf("date") > -1) { // console.log("getDefineAttr item :>> ", item); // if (item.title.indexOf("日期") > -1) { // _define.format = "yyyy-MM-dd"; // } else if (item.title.indexOf("时间") > -1) { // _define.format = "yyyy-MM-dd HH:mm"; // _define.width = 160; // } // } break; } } } if (!matched && !item.datatype && !item.enum) { _define.align = "left"; } } // 弱→强 : 组件默认 + 特征默认 + 原始自定义 // return { ...defineColumn, ..._define, ...item }; return defaultsDeep(item, _define, defineColumn); }; const _tableJson = tableJson as any; /** * @description 扁平化 初始化 columns * @param argColumns * @param dwMap * @param flatArr * @returns */ const flatColumnsFunc = (argColumns: ColumnProps[], dwMap: Map = new Map(), flatArr: ColumnProps[] = []) => { argColumns.forEach(async (col: any) => { if (col._children?.length) flatArr.push(...flatColumnsFunc(col._children, dwMap)); if (dwMap.size) { // 读取个性设置属性 if (!dwMap.has(col.field)) { dwMap.set(col.field, {}); } let userStyle = dwMap.get(col.field) ?? undefined; if (userStyle && !userStyle?.limited) { col = loadUserStyle(col, userStyle); // console.log("col _define :>> ", col, userStyle); flatColumnsCallBack && (col = flatColumnsCallBack(col)); let _define = getDefineAttr(col, layoutAttrDefine); flatArr.push(_define); } /**补充:后台数据,没有输出的数据列 */ if (!userStyle) { if (TABLE_TYPE_FILTER.includes(col.type) || col.field == "pid") { flatArr.push(col); } } } else { /**当个性布局为空时,读取默认 */ let _define = getDefineAttr(col, layoutAttrDefine); let _limited = isFunction(_define?.limited) ? _define.limited() : _define?.limited ?? false; // console.log( // "当个性布局为空时,读取默认 isFunction(userStyle?.limited) :>>", // col.field, // _define, // isFunction(_define?.limited), // _limited // ); if (!_limited) { // 给每一项 column 添加默认属性 // setDefineVal(col, _define); defaultsDeep(col, _define); flatColumnsCallBack && (col = flatColumnsCallBack(col)); flatArr.push(col); } } if (TABLE_TYPE_FILTER.includes(col.type)) { } else if (col.field == "pid") { col.title = t(`table.${col.field}`); } else if (col.field == "operation") { col.title = t(`table.${col.field}`); } else { if (!["status", "woodcode", "pcode"].includes(col.field)) { if (col.table) { Object.keys(_tableJson).includes(col.table) && Object.keys(_tableJson[col.table]).includes(col.field) && (col.title = t(`table.${col.table}.${col.field}`)); } else { Object.keys(tableJson).includes(col.field) && (col.title = t(`table.${col.field}`)); } } } // col.title.indexOf("table") > -1 && (col.title = undefined); }); console.log("dwMap :>> ", dwMap, flatArr); /**补充前端没有,但后台有返回的数据列 */ dwMap.forEach((item, key) => { // console.log("补充前端没有,但后台有返回的数据列 item :>> ", item); if (item.limited) return; let index = flatArr.findIndex(item => item.field === key); if (index == -1) { let _define = getDefineAttr(item, layoutAttrDefine); let data = loadUserStyle({}, _define); flatColumnsCallBack && (data = flatColumnsCallBack(data)); flatArr.push(data); } }); // 读取个性设置后,排序, if (dwMap.size) { flatArr.sort((a, b) => { return a.colorder! - b.colorder!; }); } console.log("flatArr", flatArr); return flatArr.filter(item => !item._children?.length); }; /** * 补充数据列中,具有枚举的数据列,自动补充render * @param columns 数据列 * @returns */ const loadRenderAttr = (argColumns: any) => { argColumns.forEach((item: any) => { if (!item.render) { /** 复选框 */ if (item?.datatype == "checkbox") { item.render = (scope: any) => { let _keys = Object.keys(scope); let _data = _keys.includes("row") ? scope.row : _keys.includes("searchParam") ? scope.searchParam : scope; let _field = scope?.column.field ?? ""; // switch (Number(_data[_field])) { // case 1: // return ; // default: // 0 // let bool = false; // return ; // } return ( <> ); }; } else if (item.enum && item.enum.length) { /**普通:enum,数值转文本 */ item.render = (scope: any) => { let _keys = Object.keys(scope); let _data: any = _keys.includes("row") ? scope.row : _keys.includes("searchParam") ? scope.searchParam : scope; let _field = scope?.column.field ?? ""; let _item: any = {}; scope.enum && (_item = scope.enum.find((item: any) => item.value == Number(_data[_field]))); if (dwtype == "detail") { return ; } else { return _item?.label ?? ""; } }; item.exportMethod = ({ cellValue, row, column }) => { let _val = cellValue; let _item: any = {}; item.enum && (_item = item.enum.find((item: any) => item.value == Number(row[column.field]))); return _item?.label ?? _val; }; } else if (item?.datatype == "html") { item.render = (scope: any) => { let _keys = Object.keys(scope); let _data = _keys.includes("row") ? scope.row : _keys.includes("searchParam") ? scope.searchParam : scope; let _field = scope?.column.field ?? ""; let html_data = _data[_field]; if (html_data) { // 空格替换为  html_data = html_data.replace(/ /g, " "); } return
; }; } } if (!item.editRender && !item.editColRender && item.tabsequence) { console.log("item.enum :>> ", item.field, item.enum); if (item.enum) { item.editRender = { name: "$select", options: item.enum }; } else if (item.datatype == "checkbox") { item.editRender = {}; item.editColRender = (scope: any) => { const { column, row, status } = scope; let _keys = Object.keys(scope); let _data: any = _keys.includes("row") ? scope.row : scope; let _field = scope?.column.field ?? ""; // if (Number(_data[_field]) == 0) { // row[_field] = 0; // } return ( <> ); }; } else if (item.datatype == "date") { item.editRender = { name: "$input", props: { type: "date" } }; } else if (item.datatype == "datetime") { item.editRender = { name: "$input", props: { type: "datetime" } }; } else if (item.datatype == "integer") { item.editRender = { name: "$input", props: { type: "number" } }; } else if (item.datatype == "number") { const { digits } = parseFormatType(item.format); item.editRender = { name: "$input", props: { type: "float", controls: false, digits } }; } else if (item.datatype == "input") { item.editRender = { name: "$input", props: {} }; } } if (item.hasOwnProperty("editRender")) { item.editRender.autoFocus = true; item.editRender.autoSelect = true; } }); return argColumns; }; /** * 获取对象属性,或属性路径 * @param {Object} define 对象 * @param {string} pre 前缀 * @returns {Array} 默认值字段集合 */ const getKeys = (define: any, pre = "") => { let keys: string[] = []; for (const key in define) { if (Object.prototype.toString.call(define[key]) === `[object Object]`) { let _pre = pre ? pre + "." : ""; keys = keys.concat(getKeys(define[key], _pre + key)); } else { let _keys: string[] = [key]; pre && _keys.unshift(pre); let strKeys = _keys.join("."); keys.push(strKeys); } } return keys; }; /** * @description 去除默认值,保存个性化数据 * @param column 需要保存的数据列原型 * @param params 主表其他参数 {basicinfo: ..., tableprop: {scrollY: ..., search: ..., ... }} * @returns {Object} 主表保存数据模型 {tableprop:..., columns: ...} */ const columnStreamlineFunc = (column: any, params?: any, oColumns?: any) => { // 入参的columns被污染??? let _oriColumns = oColumns ?? cloneDeep(columns); // let _oriColumns = cloneDeep(columns); console.log("column :>> ", column); console.log("oriColumns :>> ", JSON.stringify(_oriColumns)); // 默认值字段集合 let defineAttr = getKeys(layoutAttrDefine); defineAttr.unshift("field"); // 取默认值 + 自定义业务columns = 动态默认值属性 let oriDedine = _oriColumns .filter((item: any) => item.field) .map((item: any) => { item.basicinfo && delete item.basicinfo.visible; item.basicinfo && delete item.basicinfo.ishidden; let _define = getDefineAttr(item, layoutAttrDefine); return pick(defaultsDeep(item, _define), defineAttr); }); console.log("streamlineFunc column :>> ", column); console.log("streamlineFunc props.layoutAttr :>> ", layoutAttr); console.log("streamlineFunc oriDedine :>> ", oriDedine); let _columns = column.filter((item: any) => item.field); // let saveCol: any = { // columns: streamlineFunc(_columns, layoutAttr, oriDedine) // }; let saveCol: any = {}; isObject(params) && (saveCol.tableprop = params); saveCol.columns = streamlineFunc(_columns, layoutAttr, oriDedine); console.log("columnStreamlineFunc settingConfirm saveCol :>> ", saveCol); return saveCol; }; /** * @description 获取最新的表格布局 * @param {boolean} keepBasicinfo 是否保留线上basicinfo部分 * @param {boolean} online 是否获取线上版本 * @param {number} empid 员工id * @param {Map} enumMap 各属性enum集合,还原记录 * @returns {Array} Columns */ const getOriColumns = async ( keepBasicinfo: boolean, online: boolean = false, empid?: number, enumMap?: any, oColumns?: any ) => { if (!dwname) return []; // 入参的columns被污染??? let _curCol = oColumns ?? columns; // console.log("layout _curCol :>> ", JSON.stringify(_curCol)); // console.log("layout oColumns :>> ", JSON.stringify(oColumns)); // console.log("layout columns :>> ", JSON.stringify(columns)); console.log("keepBasicinfo, online, empid :>> ", keepBasicinfo, online, empid); let layout: any; if (online) { layout = await layoutStore.getDwLayout_online(empid!, dwname, 1); } else { // 获取缓存中最新的表格布局 layout = await layoutStore.getDwLayout(dwname); } let oriColumns = []; console.log("getOriColumns layout :>> ", JSON.stringify(layout)); if (layout?.hasOwnProperty("itemvalue") && layout.itemvalue) { typeof layout.itemvalue == "string" && (layout.itemvalue = JSON.parse(layout.itemvalue.replace(/'/g, '"'))); // 兼容部分结构直接记录行数据 if (layout.itemvalue.hasOwnProperty("columns") && layout.itemvalue.columns) { oriColumns = layout.itemvalue.columns; } else { oriColumns = layout.itemvalue; } } else { return { columns: [] }; } console.log("layout oriColumns :>> ", JSON.stringify(oriColumns)); let prototype: any = []; if (keepBasicinfo) { // 读取默认属性 loadDwLayoutFunc(_curCol, false); console.log("keepBasicinfo dwFieldMap :>> ", keepBasicinfo, dwFieldMap); // 仅仅读取详情页的basicinfo部分,其他读取原有 let loadMaps = new Map(); for (const sitm of oriColumns) { let oriMap = dwFieldMap.get(sitm.field); console.log("sitm :>> ", oriMap, sitm); if (oriMap) { oriMap.basicinfo = defaultsDeep(sitm.basicinfo, oriMap.basicinfo); } else { oriMap = sitm; } if (enumMap.has(sitm.field)) { oriMap.enum = enumMap.get(sitm.field); } loadMaps.set(sitm.field, oriMap); } console.log("loadMaps :>> ", loadMaps); prototype = flatColumnsFunc(oriColumns, loadMaps); } else { // 读取默认属性 loadDwLayoutFunc(_curCol, false); prototype = flatColumnsFunc(oriColumns, dwFieldMap); } /**备用(重置):原始数据列 */ let _ori = prototype.filter((item: any) => !TABLE_TYPE_FILTER.includes(item.type!) && item.field !== "operation"); console.log("getOriColumns oriColumns _ori:>> ", _ori); // return _ori; return { ...layout.itemvalue, columns: _ori }; }; return { ...toRefs(state), dwFieldMap, loadLayoutFunc, loadDwLayoutFunc, flatColumnsFunc, getDefineAttr, loadRenderAttr, columnStreamlineFunc, getOriColumns }; };