| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- 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<any>[],
- 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<Layout.LayoutStateProps>({
- 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<KeyType, any> = 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 <el-checkbox class={"el-checkbox__disabled-checked"} checked={true} disabled={true} label="111" />;
- // default: // 0
- // let bool = false;
- // return <el-checkbox v-model={bool} disabled={true} label="44" />;
- // }
- return (
- <>
- <el-checkbox
- v-model={_data[_field]}
- class={{ "el-checkbox__disabled-checked": Number(_data[_field]) }}
- true-value={1}
- false-value={0}
- disabled={!editable}
- />
- </>
- );
- };
- } 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 <el-input value={_item?.label} disabled={true} {...item.basicinfo.props} />;
- } 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 <div v-html={html_data} />;
- };
- }
- }
- 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 (
- <>
- <el-checkbox v-model={_data[_field]} true-value={1} false-value={0} class="vxe-edit-col-middle"></el-checkbox>
- </>
- );
- };
- } 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
- };
- };
|