Files
certd/packages/ui/certd-client/src/plugin/fast-crud/index.tsx
T

409 lines
12 KiB
TypeScript
Raw Normal View History

2025-04-12 23:59:03 +08:00
import { request } from "/src/api/service";
// import "/src/mock";
2025-10-31 16:57:32 +08:00
import { ColumnCompositionProps, CrudOptions, FastCrud, PageQuery, PageRes, setLogger, TransformResProps, useColumns, UseCrudProps, UserPageQuery, useTypes, utils, forEachTableColumns } from "@fast-crud/fast-crud";
import "@fast-crud/fast-crud/dist/style.css";
2025-09-14 02:29:22 +08:00
import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExtendsUploader, FsExtendsInput } from "@fast-crud/fast-extends";
import "@fast-crud/fast-extends/dist/style.css";
2024-03-08 17:07:53 +08:00
import UiAntdv from "@fast-crud/ui-antdv4";
import "@fast-crud/ui-antdv4/dist/style.css";
2025-03-18 10:00:16 +08:00
import { debounce, merge } from "lodash-es";
import { useCrudPermission } from "../permission";
2023-06-29 17:19:05 +08:00
import { App } from "vue";
import { notification } from "ant-design-vue";
import { usePreferences } from "/@/vben/preferences";
2025-03-18 10:00:16 +08:00
import { LocalStorage } from "/@/utils/util.storage";
2025-09-14 02:29:22 +08:00
import { FsEditorCode } from "@fast-crud/editor-code";
2025-10-05 07:59:56 +00:00
import "@fast-crud/editor-code/dist/style.css";
2025-09-14 02:29:22 +08:00
2025-03-18 10:00:16 +08:00
class ColumnSizeSaver {
2025-10-31 16:57:32 +08:00
type: string;
save: (key: string, value: any) => void;
constructor(type: string = "columnSize") {
this.type = type;
this.save = debounce((key: string, value: any) => {
2025-03-18 10:00:16 +08:00
const saveKey = this.getKey();
let data = LocalStorage.get(saveKey);
if (!data) {
data = {};
}
2025-10-31 16:57:32 +08:00
data[key] = value;
2025-03-18 10:00:16 +08:00
LocalStorage.set(saveKey, data);
});
}
getKey() {
const loc = window.location;
const currentUrl = `${loc.pathname}${loc.search}${loc.hash}`;
2025-10-31 16:57:32 +08:00
return `${this.type}-${currentUrl}`;
2025-03-18 10:00:16 +08:00
}
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();
2025-10-31 16:57:32 +08:00
const tableSortSaver = new ColumnSizeSaver("tableSorter");
2023-06-29 17:19:05 +08:00
function install(app: App, options: any = {}) {
app.use(UiAntdv);
//设置日志级别
2023-06-29 17:19:05 +08:00
setLogger({ level: "info" });
2025-03-18 10:00:16 +08:00
app.use(FastCrud, {
i18n: options.i18n,
async dictRequest({ url }: any) {
return await request({ url, method: "post" });
},
/**
* useCrud时会被执行
* @param propsuseCrud的参数
*/
commonOptions(props: UseCrudProps): CrudOptions {
utils.logger.debug("commonOptions:", props);
const crudBinding = props.crudExpose?.crudBinding;
2025-10-31 16:57:32 +08:00
const crudExpose = props.crudExpose;
const { isMobile } = usePreferences();
const opts: CrudOptions = {
settings: {
plugins: {
mobile: {
enabled: true,
props: {
2025-03-18 10:00:16 +08:00
isMobile: isMobile,
},
},
},
2025-10-31 16:57:32 +08:00
onUseCrud(bindings: any) {
const oldSorter = tableSortSaver.get("sorter");
if (oldSorter) {
const { prop, order } = oldSorter;
forEachTableColumns(bindings.table.columns, (column: any) => {
if (column.key === prop) {
column.sortOrder = order;
} else {
column.sortOrder = false;
}
});
bindings.table.sort = oldSorter;
}
},
},
table: {
scroll: {
2025-03-18 10:00:16 +08:00
x: 960,
},
size: "small",
pagination: false,
2025-03-18 10:00:16 +08:00
onResizeColumn: (w: number, col: any) => {
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
crudBinding.value.table.columnsMap[col.key].width = w;
2025-03-18 10:00:16 +08:00
columnSizeSaver.save(col.key, w);
}
},
conditionalRender: {
match(scope) {
if (scope.column.conditionalRenderDisabled) {
return false;
}
if (scope.key === "__blank__") {
return false;
}
//不能用 !scope.value 否则switch组件设置为关之后就消失了
const { value, key, props } = scope;
2025-08-15 19:11:03 +08:00
return !value && key != "_index" && value != false && value != 0;
},
render() {
return "-";
2025-03-18 10:00:16 +08:00
},
},
2025-10-31 16:57:32 +08:00
onSortChange: (sortChange: any) => {
const { isServerSort, prop, asc, order } = sortChange;
const oldSort = crudBinding.value.table.sort;
const newSorter = isServerSort ? { prop, order, asc } : null;
forEachTableColumns(crudBinding.value.table.columns, (column: any) => {
if (column.key === prop) {
column.sortOrder = order;
} else {
column.sortOrder = false;
}
});
crudBinding.value.table.sort = newSorter;
if (newSorter) {
tableSortSaver.save("sorter", newSorter);
} else {
tableSortSaver.clear();
}
if (isServerSort || oldSort != null) {
crudExpose.doRefresh();
}
},
},
toolbar: {
export: {
2025-03-18 10:00:16 +08:00
fileType: "excel",
},
columnsFilter: {
async onReset() {
columnSizeSaver.clear();
},
},
2025-06-03 10:23:28 +08:00
buttons: {
export: {
show: false,
},
},
},
rowHandle: {
fixed: "right",
buttons: {
view: { type: "link", text: null, icon: "ion:eye-outline", tooltip: { title: "查看" } },
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline", tooltip: { title: "复制" } },
edit: { type: "link", text: null, icon: "ion:create-outline", tooltip: { title: "编辑" } },
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline", tooltip: { title: "删除" } },
},
dropdown: {
more: {
2025-03-18 10:00:16 +08:00
type: "link",
},
},
resizable: true,
width: 200,
},
request: {
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
const limit = page.pageSize;
const currentPage = page.currentPage ?? 1;
const offset = limit * (currentPage - 1);
sort = sort == null ? {} : sort;
return {
page: {
limit,
2025-03-18 10:00:16 +08:00
offset,
},
query: form,
2025-03-18 10:00:16 +08:00
sort,
};
},
transformRes: ({ res }: TransformResProps): PageRes => {
const pageSize = res.limit;
let currentPage = res.offset / pageSize;
if (res.offset % pageSize === 0) {
currentPage++;
}
return { currentPage, pageSize, records: res.records, total: res.total, ...res };
2025-03-18 10:00:16 +08:00
},
},
search: {
formItem: {
wrapperCol: {
style: {
2025-03-18 10:00:16 +08:00
width: "50%",
},
},
},
},
form: {
display: "flex",
labelCol: {
//固定label宽度
span: null,
style: {
2025-03-18 10:00:16 +08:00
width: "145px",
},
},
async afterSubmit({ mode }) {
if (mode === "add") {
notification.success({ message: "添加成功" });
} else if (mode === "edit") {
notification.success({ message: "保存成功" });
}
},
wrapperCol: {
2025-03-18 10:00:16 +08:00
span: null,
2025-10-31 16:57:32 +08:00
buttons: {
copy: { show: false },
paste: { show: false },
},
},
wrapper: {
2025-03-18 10:00:16 +08:00
saveRemind: true,
// inner: true,
// innerContainerSelector: "main.fs-framework-content"
2025-03-18 10:00:16 +08:00
},
},
columns: {
//最后一列空白,用于自动伸缩列宽
__blank__: {
title: "",
type: "text",
form: {
2025-03-18 10:00:16 +08:00
show: false,
},
column: {
order: 99999,
width: -1,
columnSetShow: false,
2025-03-18 10:00:16 +08:00
resizable: false,
},
},
},
};
// 从 useCrud({permission}) 里获取permission参数,去设置各个按钮的权限
const permission = props.context?.permission || null;
const crudPermission = useCrudPermission({ permission });
return crudPermission.merge(opts);
2025-03-18 10:00:16 +08:00
},
});
// fast-extends里面的扩展组件均为异步组件,只有在使用时才会被加载,并不会影响首页加载速度
//安装uploader 公共参数
2023-06-29 17:19:05 +08:00
2024-07-26 21:42:25 +08:00
// @ts-ignore
app.use(FsExtendsUploader, {
2023-06-29 17:19:05 +08:00
// @ts-ignore
2024-10-14 00:19:55 +08:00
defaultType: "form",
form: {
keepName: true,
2024-10-27 00:52:26 +08:00
type: "form",
action: "/basic/file/upload",
name: "file",
withCredentials: false,
test: 22,
custom: { aaa: 22 },
uploadRequest: async (opts: any) => {
console.log("uploadRequest:", opts);
const { action, file, onProgress } = opts;
// @ts-ignore
const data = new FormData();
data.append("file", file);
return await request({
url: action,
method: "post",
headers: {
2025-03-18 10:00:16 +08:00
"Content-Type": "multipart/form-data",
},
timeout: 60000,
data,
2023-06-29 17:19:05 +08:00
onUploadProgress: (p: any) => {
onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
2025-03-18 10:00:16 +08:00
},
});
},
2024-10-27 00:52:26 +08:00
successHandle(res: any) {
return res;
2025-03-18 10:00:16 +08:00
},
},
});
//安装editor
app.use(FsExtendsEditor, {
//编辑器的公共配置
wangEditor: {
editorConfig: {
2025-03-18 10:00:16 +08:00
MENU_CONF: {},
},
2025-03-18 10:00:16 +08:00
toolbarConfig: {},
},
});
app.use(FsExtendsJson);
app.use(FsExtendsTime);
app.use(FsExtendsCopyable);
app.use(FsExtendsInput);
2025-09-14 02:29:22 +08:00
app.use(FsEditorCode);
const { addTypes, getType } = useTypes();
//此处演示修改官方字段类型
const textType = getType("text");
textType.search.autoSearchTrigger = "change"; //修改官方的字段类型,变化就触发 , "enter"=回车键触发
2024-10-14 00:19:55 +08:00
if (!textType.column) {
textType.column = {};
}
textType.column.ellipsis = true;
textType.column.showTitle = true;
// 此处演示自定义字段类型
addTypes({
time2: {
//如果与官方字段类型同名,将会覆盖官方的字段类型
form: { component: { name: "a-date-picker" } },
column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } },
2023-06-29 17:19:05 +08:00
valueBuilder(context: any) {
console.log("time2,valueBuilder", context);
2025-03-18 10:00:16 +08:00
},
},
});
// 此处演示自定义字段合并插件
const { registerMergeColumnPlugin } = useColumns();
registerMergeColumnPlugin({
name: "readonly-plugin",
order: 1,
handle: (columnProps: ColumnCompositionProps) => {
// 你可以在此处做你自己的处理
// 比如你可以定义一个readonly的公共属性,处理该字段只读,不能编辑
if (columnProps.readonly) {
// 合并column配置
merge(columnProps, {
form: { show: false },
2025-03-18 10:00:16 +08:00
viewForm: { show: true },
});
}
return columnProps;
2025-03-18 10:00:16 +08:00
},
});
//默认宽度,支持自动拖动调整列宽
registerMergeColumnPlugin({
name: "resize-column-plugin",
order: 2,
handle: (columnProps: ColumnCompositionProps) => {
if (!columnProps.column) {
columnProps.column = {};
}
columnProps.column.resizable = true;
2025-03-18 10:00:16 +08:00
const savedColumnWidth = columnSizeSaver.get(columnProps.key as string);
if (savedColumnWidth) {
columnProps.column.width = savedColumnWidth;
} else if (columnProps.column.width == null) {
columnProps.column.width = 200;
2024-08-04 02:35:45 +08:00
} else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) {
columnProps.column.width = parseInt(columnProps.column.width.replace("px", ""));
}
return columnProps;
2025-03-18 10:00:16 +08:00
},
});
2025-06-10 18:40:23 +08:00
2025-06-10 18:44:32 +08:00
registerMergeColumnPlugin({
name: "reset-values-format-colors",
order: 10,
handle: (columnProps: ColumnCompositionProps) => {
// 你可以在此处做你自己的处理
// 比如你可以定义一个readonly的公共属性,处理该字段只读,不能编辑
if (columnProps.column?.component?.name === "fs-values-format") {
// 合并column配置
if (!columnProps.column.component.autoColors) {
columnProps.column.component.autoColors = ["green", "cyan", "blue", "purple", "geekblue"];
}
}
return columnProps;
},
});
}
export default {
2025-03-18 10:00:16 +08:00
install,
};