🔱: [client] sync upgrade with 6 commits [trident-sync]

chore:
build: publish success
fix: 修复新页面编辑无法正确获取数据的bug

Closes https://github.com/fast-crud/fast-crud/issues/460
fix: 修复antdv4示例没有源码跳转按钮的bug
pref: 添加代码编辑器功能

- 新增 fs-editor-code组件实现代码编辑功能
- 支持 javascript、json、yaml三种语言
- 集成 monaco-editor 并配置相关 worker
- 添加代码格式校验功能
- 在 fast-extends 中引入新功能模块
pull/349/head
GitHub Actions Bot 2025-03-30 19:24:09 +00:00
parent 6f30d82394
commit 88a4e5051b
14 changed files with 240 additions and 8 deletions

View File

@ -3,6 +3,13 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.25.7](https://github.com/fast-crud/fast-crud/compare/v1.25.6...v1.25.7) (2025-03-30)
### Bug Fixes
* 修复新页面编辑无法正确获取数据的bug ([e0df772](https://github.com/fast-crud/fast-crud/commit/e0df7729d0d8fff7a0bcd81477ec9379f6f23369))
* 修复antdv4示例没有源码跳转按钮的bug ([a8f6486](https://github.com/fast-crud/fast-crud/commit/a8f6486bccc441bb394ae5fb8bbe515de78f83d3))
## [1.25.6](https://github.com/fast-crud/fast-crud/compare/v1.25.5...v1.25.6) (2025-03-19) ## [1.25.6](https://github.com/fast-crud/fast-crud/compare/v1.25.5...v1.25.6) (2025-03-19)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4 **Note:** Version bump only for package @fast-crud/fs-admin-antdv4

View File

@ -1,6 +1,6 @@
{ {
"name": "@fast-crud/fs-admin-antdv4", "name": "@fast-crud/fs-admin-antdv4",
"version": "1.25.6", "version": "1.25.7",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@ -27,10 +27,10 @@
"@aws-sdk/client-s3": "^3.535.0", "@aws-sdk/client-s3": "^3.535.0",
"@aws-sdk/s3-request-presigner": "^3.535.0", "@aws-sdk/s3-request-presigner": "^3.535.0",
"@ctrl/tinycolor": "^4.1.0", "@ctrl/tinycolor": "^4.1.0",
"@fast-crud/fast-crud": "^1.25.6", "@fast-crud/fast-crud": "^1.25.7",
"@fast-crud/fast-extends": "^1.25.6", "@fast-crud/fast-extends": "^1.25.7",
"@fast-crud/ui-antdv4": "^1.25.6", "@fast-crud/ui-antdv4": "^1.25.7",
"@fast-crud/ui-interface": "^1.25.6", "@fast-crud/ui-interface": "^1.25.7",
"@iconify/tailwind": "^1.2.0", "@iconify/tailwind": "^1.2.0",
"@iconify/vue": "^4.1.1", "@iconify/vue": "^4.1.1",
"@manypkg/get-packages": "^2.2.2", "@manypkg/get-packages": "^2.2.2",
@ -56,9 +56,12 @@
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"defu": "^6.1.4", "defu": "^6.1.4",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"js-yaml": "^4.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lucide-vue-next": "^0.477.0", "lucide-vue-next": "^0.477.0",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"monaco-editor": "^0.52.2",
"monaco-yaml": "^5.3.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
"pinia": "2.1.7", "pinia": "2.1.7",
@ -80,6 +83,7 @@
"vue-router": "^4.3.0", "vue-router": "^4.3.0",
"vuedraggable": "^2.24.3", "vuedraggable": "^2.24.3",
"watermark-js-plus": "^1.5.8", "watermark-js-plus": "^1.5.8",
"yaml-language-server": "^1.17.0",
"zod": "^3.24.2", "zod": "^3.24.2",
"zod-defaults": "^0.1.3" "zod-defaults": "^0.1.3"
}, },
@ -134,6 +138,7 @@
"vite": "^5.1.6", "vite": "^5.1.6",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.2", "vite-plugin-html": "^3.2.2",
"vite-plugin-monaco-editor-esm": "^2.0.2",
"vite-plugin-theme": "^0.8.6", "vite-plugin-theme": "^0.8.6",
"vite-plugin-windicss": "^1.9.3", "vite-plugin-windicss": "^1.9.3",
"vue-eslint-parser": "^9.4.2", "vue-eslint-parser": "^9.4.2",

View File

@ -40,6 +40,7 @@ export default defineComponent({
position: fixed; position: fixed;
right: 3px; right: 3px;
bottom: 20px; bottom: 20px;
z-index: 1000;
.fs-source-link { .fs-source-link {
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;

View File

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { BasicLayout, LockScreen, UserDropdown } from "/@/vben/layouts"; import { BasicLayout, LockScreen, UserDropdown } from "/@/vben/layouts";
import FsSourceLink from "./components/source-link/index.vue";
import { computed } from "vue"; import { computed } from "vue";
import { VBEN_DOC_URL } from "/@/vben/constants"; import { VBEN_DOC_URL } from "/@/vben/constants";
import { BookOpenText } from "/@/vben/icons"; import { BookOpenText } from "/@/vben/icons";
@ -43,5 +43,8 @@ async function handleLogout() {
<template #lock-screen> <template #lock-screen>
<LockScreen :avatar @to-login="handleLogout" /> <LockScreen :avatar @to-login="handleLogout" />
</template> </template>
<template #extra>
<FsSourceLink />
</template>
</BasicLayout> </BasicLayout>
</template> </template>

View File

@ -188,7 +188,7 @@ const mockUtil: any = {
handle(req: any) { handle(req: any) {
let id = req.params.id; let id = req.params.id;
id = parseInt(id); id = parseInt(id);
const current = findById(req.body.id, list); const current = findById(id, list);
return { return {
code: 0, code: 0,
msg: "success", msg: "success",

View File

@ -2,7 +2,6 @@ import "./iconify";
import "./iconfont"; import "./iconfont";
import FastCrud from "./fast-crud"; import FastCrud from "./fast-crud";
import permission from "./permission"; import permission from "./permission";
function install(app: any, options: any = {}) { function install(app: any, options: any = {}) {
app.use(FastCrud, options); app.use(FastCrud, options);
app.use(permission); app.use(permission);

View File

@ -304,6 +304,12 @@ export const crudResources = [
path: "/crud/component/editor", path: "/crud/component/editor",
component: "/crud/component/editor/index.vue" component: "/crud/component/editor/index.vue"
}, },
{
title: "代码编辑器",
name: "ComponentCode",
path: "/crud/component/code",
component: "/crud/component/code/index.vue"
},
{ {
title: "图标", title: "图标",
name: "ComponentIcon", name: "ComponentIcon",

View File

@ -21,6 +21,7 @@ export default async function ({ crudExpose }: CreateCrudOptionsProps): Promise<
return { return {
crudOptions: { crudOptions: {
id: "right-table",
pagination: { pagination: {
showSizeChanger: false, // antdv showSizeChanger: false, // antdv
showQuickJumper: false // antdv showQuickJumper: false // antdv

View File

@ -31,6 +31,7 @@ export default function ({ crudExpose, context: { asideTableRef } }: CreateCrudO
}; };
return { return {
crudOptions: { crudOptions: {
id: "main-table",
table: { table: {
customRow(record: any, index: number) { customRow(record: any, index: number) {
const clazz = record.id === currentRow.value ? "fs-current-row" : ""; const clazz = record.id === currentRow.value ? "fs-current-row" : "";

View File

@ -21,6 +21,7 @@ export default function ({ crudExpose, context: { props, ctx } }: CreateCrudOpti
return { return {
crudOptions: { crudOptions: {
id: "sub-table",
table: { table: {
customRow(record: any, index: number) { customRow(record: any, index: number) {
const clazz = record.id === props.modelValue ? "fs-current-row" : ""; const clazz = record.id === props.modelValue ? "fs-current-row" : "";

View File

@ -0,0 +1,42 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/ComponentJson";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
data: query
});
}
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
}
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
}
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
}
export function GetObj(id: any) {
return request({
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}

View File

@ -0,0 +1,110 @@
import * as api from "./api";
import { FsEditorCodeValidators } from "@fast-crud/fast-extends";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, ValueBuilderContext, ValueResolveContext } from "@fast-crud/fast-crud";
export default async function ({ crudExpose }: CreateCrudOptionsProps): Promise<CreateCrudOptionsRet> {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
form: {
wrapper: {
async onOpened({ mode, formRef }) {
// if (!formRef.form.async) {
// setTimeout(() => {
// formRef.form.async = { aaa: "11", bb: "111" };
// }, 2000);
// }
}
}
},
columns: {
javascript: {
title: "js code",
type: "editor-code",
form: {
show: true,
component: {
language: "javascript"
}
}
},
yaml: {
title: "yaml",
type: "editor-code",
form: {
show: true,
rules: FsEditorCodeValidators.yamlRule,
component: {
language: "yaml",
schema: {
//数据校验提示
type: "object",
properties: {
p1: {
enum: ["v1", "v2"],
description: "数据校验提示"
},
property: {
description: "I have a description"
},
titledProperty: {
title: "I have a title",
description: "I also have a description"
},
markdown: {
markdownDescription: "Even **markdown** _descriptions_ `are` ~~not~~ supported!"
}
}
}
}
}
},
json: {
title: "json",
type: "editor-code",
form: {
show: true,
rules: FsEditorCodeValidators.jsonRule,
component: {
language: "json",
vModel: "modelValue",
schema: {
//校验提示
type: "object",
properties: {
p1: {
enum: ["v1", "v2"],
description: "数据校验示例"
}
}
},
config: {}
}
}
}
}
}
};
}

View File

@ -0,0 +1,32 @@
<template>
<fs-page>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import { useFsAsync, useFsRef } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud.js";
export default defineComponent({
name: "ComponentCode",
setup() {
const { crudRef, crudBinding } = useFsRef();
const monacoRef = ref();
//
onMounted(async () => {
const { crudExpose } = await useFsAsync({ crudBinding, crudRef, createCrudOptions });
await crudExpose.doRefresh();
});
return {
crudBinding,
crudRef,
monacoRef
};
}
});
</script>

View File

@ -0,0 +1,24 @@
import mockUtil from "/src/mock/base";
const options: any = {
name: "ComponentJson",
idGenerator: 0
};
const list: any = [
{
json: '{"p1":1,"b":2}',
yaml: `
property: 1
p1: 3
services:
certd:
container_name: certd
`,
javascript: `console.log(123)`
},
{
json: '{"p1":3,"b":4}'
}
];
options.list = list;
const mock = mockUtil.buildMock(options);
export default mock;