feat: 低代码文件编辑历史记录 crud 功能完成
This commit is contained in:
parent
5c4aa42ecf
commit
e052752694
@ -2,10 +2,10 @@ import instance from './instance';
|
|||||||
import { type HistorySchema } from '@vtj/core';
|
import { type HistorySchema } from '@vtj/core';
|
||||||
|
|
||||||
export type LowCodeHistorySchema = {
|
export type LowCodeHistorySchema = {
|
||||||
project_id: string;
|
project_id: number;
|
||||||
id: string;
|
file_id: string;
|
||||||
page_id?: string;
|
history_id: string;
|
||||||
block_id?: string;
|
id?: string;
|
||||||
dsl?: HistorySchema;
|
dsl?: HistorySchema;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,8 +15,40 @@ function transformHistoryData(data: LowCodeHistorySchema) {
|
|||||||
dsl: JSON.stringify(data.dsl || {})
|
dsl: JSON.stringify(data.dsl || {})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export const getHistories = async () => {
|
|
||||||
const response = await instance.get('/api/v1/histories');
|
export type HistoriesResponse = {
|
||||||
|
code: number;
|
||||||
|
data: {
|
||||||
|
list: Array<{
|
||||||
|
id: number;
|
||||||
|
project_id: number;
|
||||||
|
file_id: string;
|
||||||
|
history_id: string;
|
||||||
|
dsl: Record<string, any>;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}>;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetHistoriesParams = {
|
||||||
|
project_id: number;
|
||||||
|
file_id: string;
|
||||||
|
page?: number;
|
||||||
|
per_page?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getHistories = async (params: GetHistoriesParams) => {
|
||||||
|
const response = await instance.get<HistoriesResponse>('/api/v1/histories', {
|
||||||
|
params: {
|
||||||
|
project_id: params.project_id,
|
||||||
|
file_id: params.file_id,
|
||||||
|
...(params.page && { page: params.page }),
|
||||||
|
...(params.per_page && { per_page: params.per_page })
|
||||||
|
}
|
||||||
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ import {
|
|||||||
updateHistory as updateLowCodeHistory,
|
updateHistory as updateLowCodeHistory,
|
||||||
deleteHistory as deleteLowCodeHistory,
|
deleteHistory as deleteLowCodeHistory,
|
||||||
getHistories as getLowCodeHistories,
|
getHistories as getLowCodeHistories,
|
||||||
createHistory as createLowCodeHistory
|
createHistory as createLowCodeHistory,
|
||||||
|
getHistories
|
||||||
} from '@/io';
|
} from '@/io';
|
||||||
import { isNumeric } from 'licia-es';
|
|
||||||
const storage = new Storage({
|
const storage = new Storage({
|
||||||
type: 'local',
|
type: 'local',
|
||||||
expired: 0
|
expired: 0
|
||||||
@ -41,7 +41,7 @@ const stringifyFields = [
|
|||||||
'meta'
|
'meta'
|
||||||
];
|
];
|
||||||
|
|
||||||
export class StorageService extends BaseService {
|
export class LowCodeService extends BaseService {
|
||||||
public async init(project: ProjectSchema): Promise<ProjectSchema> {
|
public async init(project: ProjectSchema): Promise<ProjectSchema> {
|
||||||
const remoteProject = await getProject('2');
|
const remoteProject = await getProject('2');
|
||||||
const model = new ProjectModel(remoteProject);
|
const model = new ProjectModel(remoteProject);
|
||||||
@ -81,7 +81,6 @@ export class StorageService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async saveFile(file: BlockSchema): Promise<boolean> {
|
public async saveFile(file: BlockSchema): Promise<boolean> {
|
||||||
console.log('saveFile', file);
|
|
||||||
if (file.id) {
|
if (file.id) {
|
||||||
const existFile = await getLowCodeFile(file.id);
|
const existFile = await getLowCodeFile(file.id);
|
||||||
if (existFile.file_id) {
|
if (existFile.file_id) {
|
||||||
@ -115,7 +114,6 @@ export class StorageService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getFile(id: string): Promise<BlockSchema> {
|
public async getFile(id: string): Promise<BlockSchema> {
|
||||||
console.log('getFile', id);
|
|
||||||
return getLowCodeFile(id).then((lowCodeFile) => {
|
return getLowCodeFile(id).then((lowCodeFile) => {
|
||||||
if (lowCodeFile.dsl) {
|
if (lowCodeFile.dsl) {
|
||||||
return Promise.resolve(lowCodeFile.dsl as BlockSchema);
|
return Promise.resolve(lowCodeFile.dsl as BlockSchema);
|
||||||
@ -130,14 +128,6 @@ export class StorageService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async saveHistory(history: HistorySchema): Promise<boolean> {
|
public async saveHistory(history: HistorySchema): Promise<boolean> {
|
||||||
console.log('saveHistory', history);
|
|
||||||
// const existHistory = await getLowCodeHistory(history.id);
|
|
||||||
// if (existHistory.history_id) {
|
|
||||||
// await updateLowCodeHistory(history.id, history);
|
|
||||||
// } else {
|
|
||||||
// await createLowCodeHistory(history);
|
|
||||||
// }
|
|
||||||
storage.save(`history_${history.id}`, history);
|
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,40 +140,52 @@ export class StorageService extends BaseService {
|
|||||||
console.log('uploader', file, projectId);
|
console.log('uploader', file, projectId);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
// TODO: 做成数据库存储后没啥用,保留就行
|
||||||
public removeHistory(id: string): Promise<boolean> {
|
public removeHistory(id: string): Promise<boolean> {
|
||||||
return deleteLowCodeHistory(id).then((res) => {
|
console.log('removeHistory', id);
|
||||||
console.log('removeHistory', res);
|
|
||||||
return Promise.resolve(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getHistory(id: string): Promise<HistorySchema> {
|
|
||||||
const dsl = storage.get(`history_${id}`);
|
|
||||||
console.log('getHistoryDSL', dsl);
|
|
||||||
const history = new HistoryModel(dsl || { id });
|
|
||||||
console.log('getHistory', dsl, id, history);
|
|
||||||
// const histories = await getLowCodeHistories(id);
|
|
||||||
return Promise.resolve(history.toDsl());
|
|
||||||
}
|
|
||||||
|
|
||||||
public getHistoryItem(fId: string, id: string): Promise<HistoryItem> {
|
|
||||||
const item = storage.get(`history_${fId}_${id}`);
|
|
||||||
console.log('getHistoryItem', item);
|
|
||||||
return Promise.resolve(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public saveHistoryItem(fileId: string, item: HistoryItem): Promise<boolean> {
|
|
||||||
console.log('saveHistoryItem', fileId, item);
|
|
||||||
storage.save(`history_${fileId}_${item.id}`, item);
|
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeHistoryItem(fId: string, ids: string[]): Promise<boolean> {
|
public async getHistory(fileId: string): Promise<HistorySchema> {
|
||||||
ids.forEach((id) => {
|
const histories = await getHistories({
|
||||||
storage.remove(`history_${fId}_${id}`);
|
project_id: 2,
|
||||||
console.log('removeHistoryItem', fId, id);
|
file_id: fileId,
|
||||||
|
per_page: 50
|
||||||
});
|
});
|
||||||
|
const formatDsl = {
|
||||||
|
id: histories.list[0].file_id,
|
||||||
|
items: histories.list.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
id: item.history_id,
|
||||||
|
label: item.created_at
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
const history = new HistoryModel(formatDsl);
|
||||||
|
return Promise.resolve(history.toDsl());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getHistoryItem(fId: string, id: string): Promise<HistoryItem> {
|
||||||
|
const history = await getLowCodeHistory(id);
|
||||||
|
return Promise.resolve(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveHistoryItem(
|
||||||
|
fileId: string,
|
||||||
|
historyItem: HistoryItem
|
||||||
|
): Promise<boolean> {
|
||||||
|
const saveHistory = await createLowCodeHistory({
|
||||||
|
project_id: 2,
|
||||||
|
file_id: fileId,
|
||||||
|
history_id: historyItem.id,
|
||||||
|
dsl: historyItem.dsl as HistorySchema
|
||||||
|
});
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async removeHistoryItem(fId: string, ids: string[]): Promise<boolean> {
|
||||||
|
await Promise.all(ids.map((id) => deleteLowCodeHistory(id)));
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
public publish(project: ProjectSchema): Promise<boolean> {
|
public publish(project: ProjectSchema): Promise<boolean> {
|
||||||
|
@ -10,16 +10,16 @@ import {
|
|||||||
// type ProjectModel
|
// type ProjectModel
|
||||||
} from '@vtj/pro';
|
} from '@vtj/pro';
|
||||||
|
|
||||||
import { StorageService } from '@/service';
|
import { LowCodeService } from '@/service';
|
||||||
|
|
||||||
const container = ref();
|
const container = ref();
|
||||||
const service = new StorageService();
|
const service = new LowCodeService();
|
||||||
|
|
||||||
const engine = new Engine({
|
const engine = new Engine({
|
||||||
container,
|
container,
|
||||||
service,
|
service,
|
||||||
project: {
|
project: {
|
||||||
id: 'test',
|
id: '2',
|
||||||
name: '测试'
|
name: '测试'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
import { ref, getCurrentInstance } from 'vue';
|
import { ref, getCurrentInstance } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { createProvider, ContextMode } from '@vtj/pro';
|
import { createProvider, ContextMode } from '@vtj/pro';
|
||||||
import { StorageService } from '@/service';
|
import { LowCodeService } from '@/service';
|
||||||
const service = new StorageService();
|
const service = new LowCodeService();
|
||||||
const { provider, onReady } = createProvider({
|
const { provider, onReady } = createProvider({
|
||||||
mode: ContextMode.Runtime,
|
mode: ContextMode.Runtime,
|
||||||
service,
|
service,
|
||||||
project: {
|
project: {
|
||||||
id: 'test',
|
id: '2'
|
||||||
name: '测试'
|
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
Vue: () => import('vue'),
|
Vue: () => import('vue'),
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
import { onMounted, computed, watch } from 'vue';
|
import { onMounted, computed, watch } from 'vue';
|
||||||
import { ElLoading } from 'element-plus';
|
import { ElLoading } from 'element-plus';
|
||||||
import Postmate from 'postmate';
|
import Postmate from 'postmate';
|
||||||
import { createRenderer } from '@vtj/renderer'
|
import { createRenderer, createProvider } from '@vtj/renderer'
|
||||||
import { getFile } from './io';
|
|
||||||
import { useQuery } from '@tanstack/vue-query';
|
import { useQuery } from '@tanstack/vue-query';
|
||||||
|
|
||||||
|
import { LowCodeService } from './service'
|
||||||
|
|
||||||
|
import { getFile } from './io';
|
||||||
|
|
||||||
|
const lowCodeService = new LowCodeService();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const handshake = new Postmate.Model({});
|
const handshake = new Postmate.Model({});
|
||||||
@ -16,12 +20,10 @@ handshake.then(parent => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { data: file, isFetching } = useQuery({
|
const { data: file, isFetching } = useQuery({
|
||||||
queryKey: ['file', '45tncm34d'],
|
queryKey: ['getFile'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
return getFile('45tncm34d');
|
return getFile('45tnbgeme');
|
||||||
},
|
},
|
||||||
retry: 3,
|
|
||||||
retryDelay: 2000,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(isFetching, (newVal) => {
|
watch(isFetching, (newVal) => {
|
||||||
@ -34,6 +36,19 @@ watch(isFetching, (newVal) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { provider, onReady } = createProvider({
|
||||||
|
// runtime: 'web',
|
||||||
|
service: lowCodeService,
|
||||||
|
project: {
|
||||||
|
id: '2'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
onReady(() => {
|
||||||
|
console.log('onReady');
|
||||||
|
});
|
||||||
|
|
||||||
const renderer = computed(() => {
|
const renderer = computed(() => {
|
||||||
console.log(file?.value?.dsl.id);
|
console.log(file?.value?.dsl.id);
|
||||||
if (file?.value?.dsl) {
|
if (file?.value?.dsl) {
|
||||||
|
@ -2,7 +2,6 @@ import { createApp } from "vue";
|
|||||||
import "@sy/web-vitals";
|
import "@sy/web-vitals";
|
||||||
import { IconsPlugin } from "@vtj/icons";
|
import { IconsPlugin } from "@vtj/icons";
|
||||||
import { VueQueryPlugin } from "@tanstack/vue-query";
|
import { VueQueryPlugin } from "@tanstack/vue-query";
|
||||||
// import "@sy/low-code-shared/styles/reset.css";
|
|
||||||
|
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import ElementPlus from "element-plus";
|
import ElementPlus from "element-plus";
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export * from "./file";
|
export * from "./file";
|
||||||
|
export * from "./project";
|
||||||
|
6
apps/renderer/src/io/project.ts
Normal file
6
apps/renderer/src/io/project.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import instance from "./instance";
|
||||||
|
|
||||||
|
export const getProject = async (id: string) => {
|
||||||
|
const response = await instance.get(`/api/v1/projects/${id}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
40
apps/renderer/src/service/index.ts
Normal file
40
apps/renderer/src/service/index.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import { type ProjectSchema, type BlockSchema, ProjectModel } from "@vtj/core";
|
||||||
|
import { BaseService } from "@vtj/renderer";
|
||||||
|
import { getProject, getFile as getLowCodeFile } from "@/io";
|
||||||
|
|
||||||
|
export class LowCodeService extends BaseService {
|
||||||
|
public async init(project: ProjectSchema) {
|
||||||
|
console.log("init", project);
|
||||||
|
const remoteProject = await getProject("2");
|
||||||
|
const model = new ProjectModel(remoteProject);
|
||||||
|
const dsl = model.toDsl();
|
||||||
|
return Promise.resolve(dsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveProject(project: ProjectSchema): Promise<boolean> {
|
||||||
|
const newProject = {
|
||||||
|
...project,
|
||||||
|
...Object.fromEntries(
|
||||||
|
Object.entries(project)
|
||||||
|
.filter(([key]) => stringifyFields.includes(key))
|
||||||
|
.map(([key, value]) => [key, JSON.stringify(value)])
|
||||||
|
),
|
||||||
|
};
|
||||||
|
updateProject("2", newProject);
|
||||||
|
const model = new ProjectModel(project);
|
||||||
|
storage.save(`project_${model.id}`, model.toDsl());
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFile(id: string): Promise<BlockSchema> {
|
||||||
|
console.log("getFile", id);
|
||||||
|
return getLowCodeFile(id).then((lowCodeFile) => {
|
||||||
|
if (lowCodeFile.dsl) {
|
||||||
|
return Promise.resolve(lowCodeFile.dsl as BlockSchema);
|
||||||
|
} else {
|
||||||
|
return Promise.reject(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "./node_modules/@vtj/cli/config/tsconfig.web.json",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["es2015", "dom"],
|
|
||||||
"noUnusedLocals": false,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": false,
|
"noUnusedParameters": false,
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
|
@ -8,4 +8,9 @@ export default defineConfig({
|
|||||||
port: 10010,
|
port: 10010,
|
||||||
},
|
},
|
||||||
plugins: [http2Proxy(), mkcert(), VuePlugin()],
|
plugins: [http2Proxy(), mkcert(), VuePlugin()],
|
||||||
|
esbuild: {
|
||||||
|
supported: {
|
||||||
|
"top-level-await": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user