perf: 保存调整后的列宽

pull/361/head
xiaojunnuo 2025-03-18 10:00:16 +08:00
parent 4453070060
commit 873f2b618b
2 changed files with 185 additions and 171 deletions

View File

@ -6,16 +6,48 @@ import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExt
import "@fast-crud/fast-extends/dist/style.css"; import "@fast-crud/fast-extends/dist/style.css";
import UiAntdv from "@fast-crud/ui-antdv4"; import UiAntdv from "@fast-crud/ui-antdv4";
import "@fast-crud/ui-antdv4/dist/style.css"; import "@fast-crud/ui-antdv4/dist/style.css";
import { merge } from "lodash-es"; import { debounce, merge } from "lodash-es";
import { useCrudPermission } from "../permission"; import { useCrudPermission } from "../permission";
import { App } from "vue"; import { App } from "vue";
import { notification } from "ant-design-vue"; import { notification } from "ant-design-vue";
import { usePreferences } from "/@/vben/preferences"; import { usePreferences } from "/@/vben/preferences";
import { LocalStorage } from "/@/utils/util.storage";
class ColumnSizeSaver {
save: (key: string, size: number) => void;
constructor() {
this.save = debounce((key: string, size: number) => {
const saveKey = this.getKey();
let data = LocalStorage.get(saveKey);
if (!data) {
data = {};
}
data[key] = size;
LocalStorage.set(saveKey, data);
});
}
getKey() {
const loc = window.location;
const currentUrl = `${loc.pathname}${loc.search}${loc.hash}`;
return `columnSize-${currentUrl}`;
}
get(key: string) {
const saveKey = this.getKey();
const row = LocalStorage.get(saveKey);
return row?.[key];
}
clear() {
const saveKey = this.getKey();
LocalStorage.remove(saveKey);
}
}
const columnSizeSaver = new ColumnSizeSaver();
function install(app: App, options: any = {}) { function install(app: App, options: any = {}) {
app.use(UiAntdv); app.use(UiAntdv);
//设置日志级别 //设置日志级别
setLogger({ level: "info" }); setLogger({ level: "info" });
app.use(FastCrud, { app.use(FastCrud, {
i18n: options.i18n, i18n: options.i18n,
async dictRequest({ url }: any) { async dictRequest({ url }: any) {
@ -39,20 +71,21 @@ function install(app: App, options: any = {}) {
mobile: { mobile: {
enabled: true, enabled: true,
props: { props: {
isMobile: isMobile isMobile: isMobile,
} },
} },
} },
}, },
table: { table: {
scroll: { scroll: {
x: 960 x: 960,
}, },
size: "small", size: "small",
pagination: false, pagination: false,
onResizeColumn: (w: number | string, col: any) => { onResizeColumn: (w: number, col: any) => {
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) { if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
crudBinding.value.table.columnsMap[col.key].width = w; crudBinding.value.table.columnsMap[col.key].width = w;
columnSizeSaver.save(col.key, w);
} }
}, },
conditionalRender: { conditionalRender: {
@ -70,13 +103,18 @@ function install(app: App, options: any = {}) {
}, },
render() { render() {
return "-"; return "-";
} },
} },
}, },
toolbar: { toolbar: {
export: { export: {
fileType: "excel" fileType: "excel",
} },
columnsFilter: {
async onReset() {
columnSizeSaver.clear();
},
},
}, },
rowHandle: { rowHandle: {
fixed: "right", fixed: "right",
@ -84,13 +122,15 @@ function install(app: App, options: any = {}) {
view: { type: "link", text: null, icon: "ion:eye-outline" }, view: { type: "link", text: null, icon: "ion:eye-outline" },
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline" }, copy: { show: true, type: "link", text: null, icon: "ion:copy-outline" },
edit: { type: "link", text: null, icon: "ion:create-outline" }, edit: { type: "link", text: null, icon: "ion:create-outline" },
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline" } remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline" },
}, },
dropdown: { dropdown: {
more: { more: {
type: "link" type: "link",
} },
} },
resizable: true,
width: 200,
}, },
request: { request: {
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => { transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
@ -103,10 +143,10 @@ function install(app: App, options: any = {}) {
return { return {
page: { page: {
limit, limit,
offset offset,
}, },
query: form, query: form,
sort sort,
}; };
}, },
transformRes: ({ res }: TransformResProps): PageRes => { transformRes: ({ res }: TransformResProps): PageRes => {
@ -116,16 +156,16 @@ function install(app: App, options: any = {}) {
currentPage++; currentPage++;
} }
return { currentPage, pageSize, records: res.records, total: res.total, ...res }; return { currentPage, pageSize, records: res.records, total: res.total, ...res };
} },
}, },
search: { search: {
formItem: { formItem: {
wrapperCol: { wrapperCol: {
style: { style: {
width: "50%" width: "50%",
} },
} },
} },
}, },
form: { form: {
display: "flex", display: "flex",
@ -133,8 +173,8 @@ function install(app: App, options: any = {}) {
//固定label宽度 //固定label宽度
span: null, span: null,
style: { style: {
width: "145px" width: "145px",
} },
}, },
async afterSubmit({ mode }) { async afterSubmit({ mode }) {
if (mode === "add") { if (mode === "add") {
@ -144,13 +184,13 @@ function install(app: App, options: any = {}) {
} }
}, },
wrapperCol: { wrapperCol: {
span: null span: null,
}, },
wrapper: { wrapper: {
saveRemind: true saveRemind: true,
// inner: true, // inner: true,
// innerContainerSelector: "main.fs-framework-content" // innerContainerSelector: "main.fs-framework-content"
} },
}, },
columns: { columns: {
//最后一列空白,用于自动伸缩列宽 //最后一列空白,用于自动伸缩列宽
@ -158,23 +198,23 @@ function install(app: App, options: any = {}) {
title: "", title: "",
type: "text", type: "text",
form: { form: {
show: false show: false,
}, },
column: { column: {
order: 99999, order: 99999,
width: -1, width: -1,
columnSetShow: false, columnSetShow: false,
resizable: false resizable: false,
} },
} },
} },
}; };
// 从 useCrud({permission}) 里获取permission参数去设置各个按钮的权限 // 从 useCrud({permission}) 里获取permission参数去设置各个按钮的权限
const permission = props.context?.permission || null; const permission = props.context?.permission || null;
const crudPermission = useCrudPermission({ permission }); const crudPermission = useCrudPermission({ permission });
return crudPermission.merge(opts); return crudPermission.merge(opts);
} },
}); });
// fast-extends里面的扩展组件均为异步组件只有在使用时才会被加载并不会影响首页加载速度 // fast-extends里面的扩展组件均为异步组件只有在使用时才会被加载并不会影响首页加载速度
@ -202,19 +242,19 @@ function install(app: App, options: any = {}) {
url: action, url: action,
method: "post", method: "post",
headers: { headers: {
"Content-Type": "multipart/form-data" "Content-Type": "multipart/form-data",
}, },
timeout: 60000, timeout: 60000,
data, data,
onUploadProgress: (p: any) => { onUploadProgress: (p: any) => {
onProgress({ percent: Math.round((p.loaded / p.total) * 100) }); onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
} },
}); });
}, },
successHandle(res: any) { successHandle(res: any) {
return res; return res;
} },
} },
}); });
//安装editor //安装editor
@ -222,10 +262,10 @@ function install(app: App, options: any = {}) {
//编辑器的公共配置 //编辑器的公共配置
wangEditor: { wangEditor: {
editorConfig: { editorConfig: {
MENU_CONF: {} MENU_CONF: {},
}, },
toolbarConfig: {} toolbarConfig: {},
} },
}); });
app.use(FsExtendsJson); app.use(FsExtendsJson);
app.use(FsExtendsTime); app.use(FsExtendsTime);
@ -250,8 +290,8 @@ function install(app: App, options: any = {}) {
column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } }, column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } },
valueBuilder(context: any) { valueBuilder(context: any) {
console.log("time2,valueBuilder", context); console.log("time2,valueBuilder", context);
} },
} },
}); });
// 此处演示自定义字段合并插件 // 此处演示自定义字段合并插件
@ -266,32 +306,14 @@ function install(app: App, options: any = {}) {
// 合并column配置 // 合并column配置
merge(columnProps, { merge(columnProps, {
form: { show: false }, form: { show: false },
viewForm: { show: true } viewForm: { show: true },
}); });
} }
return columnProps; return columnProps;
} },
}); });
//默认宽度,支持自动拖动调整列宽 //默认宽度,支持自动拖动调整列宽
registerMergeColumnPlugin({
name: "resize-column-plugin",
order: 2,
handle: (columnProps: ColumnCompositionProps) => {
if (!columnProps.column) {
columnProps.column = {};
}
if (columnProps.column.resizable == null) {
columnProps.column.resizable = true;
if (!columnProps.column.width) {
columnProps.column.width = 200;
}
}
return columnProps;
}
});
registerMergeColumnPlugin({ registerMergeColumnPlugin({
name: "resize-column-plugin", name: "resize-column-plugin",
order: 2, order: 2,
@ -300,16 +322,19 @@ function install(app: App, options: any = {}) {
columnProps.column = {}; columnProps.column = {};
} }
columnProps.column.resizable = true; columnProps.column.resizable = true;
if (columnProps.column.width == null) { const savedColumnWidth = columnSizeSaver.get(columnProps.key as string);
if (savedColumnWidth) {
columnProps.column.width = savedColumnWidth;
} else if (columnProps.column.width == null) {
columnProps.column.width = 200; columnProps.column.width = 200;
} else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) { } else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) {
columnProps.column.width = parseInt(columnProps.column.width.replace("px", "")); columnProps.column.width = parseInt(columnProps.column.width.replace("px", ""));
} }
return columnProps; return columnProps;
} },
}); });
} }
export default { export default {
install install,
}; };

View File

@ -38,8 +38,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
data: [ data: [
{ label: "成功", value: "ok", color: "green" }, { label: "成功", value: "ok", color: "green" },
{ label: "检查中", value: "checking", color: "blue" }, { label: "检查中", value: "checking", color: "blue" },
{ label: "异常", value: "error", color: "red" } { label: "异常", value: "error", color: "red" },
] ],
}); });
return { return {
crudOptions: { crudOptions: {
@ -47,22 +47,22 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
pageRequest, pageRequest,
addRequest, addRequest,
editRequest, editRequest,
delRequest delRequest,
}, },
form: { form: {
labelCol: { labelCol: {
//固定label宽度 //固定label宽度
span: null, span: null,
style: { style: {
width: "100px" width: "100px",
} },
}, },
col: { col: {
span: 22 span: 22,
}, },
wrapper: { wrapper: {
width: 600 width: 600,
} },
}, },
actionbar: { actionbar: {
buttons: { buttons: {
@ -72,7 +72,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
//非plus //非plus
if (crudBinding.value.data.length >= 1) { if (crudBinding.value.data.length >= 1) {
notification.error({ notification.error({
message: "基础版只能添加一个监控站点,请赞助升级专业版" message: "基础版只能添加一个监控站点,请赞助升级专业版",
}); });
mitter.emit("openVipModal"); mitter.emit("openVipModal");
return; return;
@ -86,15 +86,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const max = suiteDetail.monitorCount.max; const max = suiteDetail.monitorCount.max;
if (max != -1 && max <= suiteDetail.monitorCount.used) { if (max != -1 && max <= suiteDetail.monitorCount.used) {
notification.error({ notification.error({
message: `对不起,您最多只能创建条${max}监控记录,请购买或升级套餐` message: `对不起,您最多只能创建条${max}监控记录,请购买或升级套餐`,
}); });
return; return;
} }
} }
await crudExpose.openAdd({}); await crudExpose.openAdd({});
} },
} },
} },
}, },
rowHandle: { rowHandle: {
fixed: "right", fixed: "right",
@ -105,18 +105,18 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
type: "link", type: "link",
text: null, text: null,
tooltip: { tooltip: {
title: "立即检查" title: "立即检查",
}, },
icon: "ion:play-sharp", icon: "ion:play-sharp",
click: async ({ row }) => { click: async ({ row }) => {
await api.DoCheck(row.id); await api.DoCheck(row.id);
await crudExpose.doRefresh(); await crudExpose.doRefresh();
notification.success({ notification.success({
message: "检查完成" message: "检查完成",
}); });
} },
} },
} },
}, },
columns: { columns: {
id: { id: {
@ -124,78 +124,67 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
key: "id", key: "id",
type: "number", type: "number",
search: { search: {
show: false show: false,
}, },
column: { column: {
width: 80, width: 80,
align: "center" align: "center",
}, },
form: { form: {
show: false show: false,
} },
}, },
name: { name: {
title: "站点名称", title: "站点名称",
search: { search: {
show: true show: true,
}, },
type: "text", type: "text",
form: { form: {
rules: [{ required: true, message: "请输入站点名称" }] rules: [{ required: true, message: "请输入站点名称" }],
}, },
column: { column: {
width: 160 width: 160,
} },
}, },
domain: { domain: {
title: "网站域名", title: "网站域名",
search: { search: {
show: true show: true,
}, },
type: "text", type: "text",
form: { form: {
rules: [ rules: [
{ required: true, message: "请输入域名" }, { required: true, message: "请输入域名" },
//@ts-ignore //@ts-ignore
{ type: "domains", message: "请输入正确的域名" } { type: "domains", message: "请输入正确的域名" },
] ],
}, },
column: { column: {
width: 200, width: 230,
sorter: true, sorter: true,
cellRender({ value }) { cellRender({ value, row }) {
const url = `https://${value}:${row.httpsPort}`;
return ( return (
<a-tooltip title={value} placement="left"> <a-tooltip title={value} placement="left">
<fs-copyable modelValue={value}></fs-copyable> <fs-copyable modelValue={value}>
<a target="_blank" href={url}>
{value}:{row.httpsPort}
</a>
</fs-copyable>
</a-tooltip> </a-tooltip>
); );
} },
}
},
httpsPort: {
title: "HTTPS端口",
search: {
show: false
}, },
type: "number",
form: {
value: 443,
rules: [{ required: true, message: "请输入端口" }]
},
column: {
align: "center",
width: 110,
show: false
}
}, },
certDomains: { certDomains: {
title: "证书域名", title: "证书域名",
search: { search: {
show: true show: true,
}, },
type: "text", type: "text",
form: { form: {
show: false show: false,
}, },
column: { column: {
width: 200, width: 200,
@ -207,56 +196,56 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
{value} {value}
</a-tooltip> </a-tooltip>
); );
} },
} },
}, },
certProvider: { certProvider: {
title: "颁发机构", title: "颁发机构",
search: { search: {
show: false show: false,
}, },
type: "text", type: "text",
form: { form: {
show: false show: false,
}, },
column: { column: {
width: 200, width: 200,
sorter: true, sorter: true,
cellRender({ value }) { cellRender({ value }) {
return <a-tooltip title={value}>{value}</a-tooltip>; return <a-tooltip title={value}>{value}</a-tooltip>;
} },
} },
}, },
certStatus: { certStatus: {
title: "证书状态", title: "证书状态",
search: { search: {
show: true show: true,
}, },
type: "dict-select", type: "dict-select",
dict: dict({ dict: dict({
data: [ data: [
{ label: "正常", value: "ok", color: "green" }, { label: "正常", value: "ok", color: "green" },
{ label: "过期", value: "expired", color: "red" } { label: "过期", value: "expired", color: "red" },
] ],
}), }),
form: { form: {
show: false show: false,
}, },
column: { column: {
width: 110, width: 100,
sorter: true, sorter: true,
show: true, show: true,
align: "center" align: "center",
} },
}, },
certExpiresTime: { certExpiresTime: {
title: "证书到期时间", title: "证书到期时间",
search: { search: {
show: false show: false,
}, },
type: "date", type: "date",
form: { form: {
show: false show: false,
}, },
column: { column: {
sorter: true, sorter: true,
@ -269,35 +258,56 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const color = leftDays < 20 ? "red" : "#389e0d"; const color = leftDays < 20 ? "red" : "#389e0d";
const percent = (leftDays / 90) * 100; const percent = (leftDays / 90) * 100;
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}`} />; return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}`} />;
} },
} },
}, },
lastCheckTime: { lastCheckTime: {
title: "上次检查时间", title: "上次检查时间",
search: { search: {
show: false show: false,
}, },
type: "datetime", type: "datetime",
form: { form: {
show: false show: false,
}, },
column: { column: {
sorter: true, sorter: true,
width: 155 width: 155,
} },
},
disabled: {
title: "禁用启用",
search: {
show: false,
},
type: "dict-switch",
dict: dict({
data: [
{ label: "启用", value: false, color: "green" },
{ label: "禁用", value: true, color: "red" },
],
}),
form: {
value: false,
},
column: {
width: 100,
sorter: true,
align: "center",
},
}, },
checkStatus: { checkStatus: {
title: "检查状态", title: "检查状态",
search: { search: {
show: false show: false,
}, },
type: "dict-select", type: "dict-select",
dict: checkStatusDict, dict: checkStatusDict,
form: { form: {
show: false show: false,
}, },
column: { column: {
width: 110, width: 100,
align: "center", align: "center",
sorter: true, sorter: true,
cellRender({ value, row, key }) { cellRender({ value, row, key }) {
@ -306,8 +316,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
<fs-values-format v-model={value} dict={checkStatusDict}></fs-values-format> <fs-values-format v-model={value} dict={checkStatusDict}></fs-values-format>
</a-tooltip> </a-tooltip>
); );
} },
} },
}, },
// error: { // error: {
// title: "错误信息", // title: "错误信息",
@ -329,51 +339,30 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
pipelineId: { pipelineId: {
title: "关联流水线id", title: "关联流水线id",
search: { search: {
show: false show: false,
}, },
form: { show: false }, form: { show: false },
type: "number", type: "number",
column: { column: {
width: 200, width: 200,
sorter: true, sorter: true,
show: false show: false,
} },
}, },
certInfoId: { certInfoId: {
title: "证书id", title: "证书id",
search: { search: {
show: false show: false,
}, },
type: "number", type: "number",
form: { show: false }, form: { show: false },
column: { column: {
width: 100, width: 100,
sorter: true, sorter: true,
show: false show: false,
} },
}, },
disabled: { },
title: "禁用启用", },
search: {
show: false
},
type: "dict-switch",
dict: dict({
data: [
{ label: "启用", value: false, color: "green" },
{ label: "禁用", value: true, color: "red" }
]
}),
form: {
value: false
},
column: {
width: 110,
sorter: true,
align: "center"
}
}
}
}
}; };
} }