diff --git a/atune/web/package.json b/atune/web/package.json index ef5a01fdf2ad2b07b2b174610c8216ac2bab3b34..23d6b779b016c41dca06f8e1fb2ee1cbbb6238b2 100644 --- a/atune/web/package.json +++ b/atune/web/package.json @@ -11,8 +11,11 @@ "dependencies": { "axios": "^1.6.0", "element-plus": "^2.4.1", + "esbuild": "^0.19.10", + "konva": "^9.3.0", "pinia": "^2.1.7", "vue": "^3.3.4", + "vue-konva": "^3.0.2", "vue-router": "^4.2.5" }, "devDependencies": { diff --git a/atune/web/src/api/atune.ts b/atune/web/src/api/atune.ts index fa0cba1bdfe373c8ae9d7559e9429f3bc9a02868..0ea89bfb0517f4c1dc2590253c2b6c4f7b45d1fa 100644 --- a/atune/web/src/api/atune.ts +++ b/atune/web/src/api/atune.ts @@ -9,6 +9,24 @@ export function getTaskLists(data: Object) { }); } +// 新增任务 +export function addTask(data: object) { + return request({ + url: "/plugin/atune/run", + method: "post", + data, + }); +} + +// 删除任务 +export function deleteTask(data: object) { + return request({ + url: "/plugin/atune/delete", + method: "delete", + data, + }); +} + // 获取所有的调优列表 export function getAtuneAllName() { return request({ @@ -38,7 +56,7 @@ export function getTuneLists(data: object) { // 保存调优模板 export function saveTune(data: object) { return request({ - url: "/plugin/atune/save", + url: "/plugin/atune/save_tune", method: "post", data, }); @@ -47,7 +65,7 @@ export function saveTune(data: object) { // 删除调优模板 export function deleteTune(data: object) { return request({ - url: "/plugin/atune/delete", + url: "/plugin/atune/delete_tune", method: "delete", data, }); @@ -56,7 +74,7 @@ export function deleteTune(data: object) { // 高级搜索模板列表分页 export function searchTune(data: object) { return request({ - url: "/plugin/atune/search", + url: "/plugin/atune/search_tune", method: "get", params: data, }); @@ -65,7 +83,7 @@ export function searchTune(data: object) { // 编辑模板更新 export function updateTune(data: object) { return request({ - url: "/plugin/atune/update", + url: "/plugin/atune/update_tune", method: "post", data, }); diff --git a/atune/web/src/components/atuneList.vue b/atune/web/src/components/atuneList.vue deleted file mode 100644 index be5dd06d277e89d7cbe25ef792367bc845cc4b4c..0000000000000000000000000000000000000000 --- a/atune/web/src/components/atuneList.vue +++ /dev/null @@ -1,155 +0,0 @@ - - - - - diff --git a/atune/web/src/components/atuneTemplete.vue b/atune/web/src/components/atuneTemplete.vue index 602011ec591eac892713600ba1d14bd96fe25bef..f1937d043fab95c4e788374db5dc066bcc0b3514 100644 --- a/atune/web/src/components/atuneTemplete.vue +++ b/atune/web/src/components/atuneTemplete.vue @@ -1,164 +1,163 @@ - - diff --git a/atune/web/src/components/flowChart.ts b/atune/web/src/components/flowChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..88503722d870fa20d0287e3c9073d4ae9939846e --- /dev/null +++ b/atune/web/src/components/flowChart.ts @@ -0,0 +1,46 @@ +import { useCanvasStore } from "@/store/canvas"; +const fromX = useCanvasStore().width || 0; +console.log("起始位置X:", fromX); +export const rectStart = { + x: fromX / 2, + y: 50, + width: 100, + height: 40, + fill: "#fff", + stroke: "#fff", + shadowBlur: 2, + cornerRadius: 10, +}; + +export const rectPrepare = { + x: 20, + y: 50, + width: 100, + height: 40, + fill: "#fff", + stroke: "#fff", + shadowBlur: 2, + cornerRadius: 10, +}; + +export const rectTune = { + x: 20, + y: 50, + width: 100, + height: 40, + fill: "#fff", + stroke: "#fff", + shadowBlur: 2, + cornerRadius: 10, +}; + +export const rectRestore = { + x: 20, + y: 50, + width: 100, + height: 40, + fill: "#fff", + stroke: "#fff", + shadowBlur: 2, + cornerRadius: 10, +}; diff --git a/atune/web/src/components/flowChart.vue b/atune/web/src/components/flowChart.vue new file mode 100644 index 0000000000000000000000000000000000000000..6f76c79bed8f5ece954ab2335ed58f1d35420ce8 --- /dev/null +++ b/atune/web/src/components/flowChart.vue @@ -0,0 +1,145 @@ + + + diff --git a/atune/web/src/components/table.vue b/atune/web/src/components/table.vue index 8d19c5f66626bfcd059c44c66606c3b7e6b97adc..629cd42e1c30d859b3fb4f28aad55422a09842d3 100644 --- a/atune/web/src/components/table.vue +++ b/atune/web/src/components/table.vue @@ -24,7 +24,7 @@
>(); +const myTableRef = ref>(); const currentNum = ref(0); //复选框当前页数量 const keyWord = ref(""); const selectedRows = ref([] as any[]); @@ -97,19 +98,66 @@ const page = reactive({ }); onMounted(async () => { await getTableData(); - getAllData(); + // getAllData(); }); // 获取表格数据 const getTableData = () => { - loading.value = true; + // loading.value = true; + tableData.value = [ + { + id: 2, + task_name: "准备调优环境", + command: "ls", + task_status: "已完成", + create_time: "2023-12-25 11:23:18", + update_time: "2023-12-25 11:23:18", + results: [ + { + id: 2, + task_id: 2, + machine_uuid: "13ff60a7-0f7d-49d6-b7fc-b766cc347ba8", + machine_ip: "192.168.160.20", + command: "ls", + retcode: 0, + stdout: + "app\nconfig_agent.yaml\nconfig_agent.yaml.templete\nconfig_server.yaml\nconfig_server.yaml.templete\ndbmanager\nglobal\ngo.mod\ngo.sum\nuser.xlsx.templete\nutils\nvendor", + stderr: "", + is_update: true, + }, + ], + }, + { + id: 1, + task_name: "执行中", + command: "ls", + task_status: "执行中", + create_time: "2023-12-25 10:08:15", + update_time: "", + results: [ + { + id: 1, + task_id: 1, + machine_uuid: "13ff60a7-0f7d-49d6-b7fc-b766cc347ba8", + machine_ip: "192.168.160.20", + command: "ls", + retcode: 0, + stdout: + "app\nconfig_agent.yaml\nconfig_agent.yaml.templete\nconfig_server.yaml\nconfig_server.yaml.templete\ndbmanager\nglobal\ngo.mod\ngo.sum\nuser.xlsx.templete\nutils\nvendor", + stderr: "", + is_update: false, + }, + ], + }, + ]; props.getData!({ page: page.currentPage, size: page.pageSize }).then( - (res: any) => { - if (res.data && res.data.code === 200) { + (res: { data: ReaultData }) => { + let result: ReaultData = res.data; + if (result && result.code === 200) { loading.value = false; - tableData.value = res.data.data; - currentNum.value = res.data.data.length; - page.total = res.data.total; + tableData.value = result.data; + currentNum.value = result.data.length; + page.total = result.total; } else { loading.value = false; tableData.value = []; @@ -155,10 +203,19 @@ const handleSelectinChange = (rows: any) => { }; // 用户点击某一行的复选框 -const handleRowSelectionChange = (val: any, _row: any) => { +const handleRowSelectionChange = (val: [], _row: any) => { + // 输出当前选中的所有行数组 console.log(val); }; +// 刷新表格 +const handleRefresh = () => { + // 清空选项 + myTableRef.value?.clearSelection(); + // 重新获取数据 + getTableData(); +}; + // 删除 const handleDelete = () => { ElMessageBox.confirm("确定要删除吗?", "提示", { @@ -174,6 +231,7 @@ const handleDelete = () => { .then((res: any) => { if (res.data.code === 200) { ElMessage.success(res.data.msg); + handleRefresh(); } else { ElMessage.error(res.data.msg); } @@ -186,6 +244,8 @@ const handleDelete = () => { defineExpose({ getTableData, + handleDelete, + handleRefresh, }); diff --git a/atune/web/src/components/taskDetail.vue b/atune/web/src/components/taskDetail.vue deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/atune/web/src/main.ts b/atune/web/src/main.ts index b59e91f1ad4fbc5adc9ae8e302be84bf8545cf0b..0165c2a0f2b31482f0e42510bf7996d220f2b52a 100644 --- a/atune/web/src/main.ts +++ b/atune/web/src/main.ts @@ -1,16 +1,24 @@ -import './assets/main.css' +import "./assets/main.css"; -import { createApp } from 'vue'; -import App from './App.vue'; -import ElementPlus from 'element-plus'; -import 'element-plus/dist/index.css'; -import router from './router'; -import { createPinia } from 'pinia'; +import { createApp } from "vue"; +import App from "./App.vue"; +import ElementPlus from "element-plus"; +import MyTable from "@/components/table.vue"; +import MyButton from "@/components/myButton.vue"; +import "element-plus/dist/index.css"; +import router from "./router"; +import { createPinia } from "pinia"; +import VueKonva from "vue-konva"; const app = createApp(App); +// 设置全局变量 +// app.config.globalProperties.$router = router; +app.component("my-table", MyTable); +app.component("my-button", MyButton); app.use(createPinia()); app.use(router); app.use(ElementPlus); +app.use(VueKonva); -app.mount('#app'); +app.mount("#app"); diff --git a/atune/web/src/router/index.ts b/atune/web/src/router/index.ts index e40df3f34505869e8e01b3542083f83d05c5f81b..ba402a4e150ead7a8f715120bc153d3a96c2ff3b 100644 --- a/atune/web/src/router/index.ts +++ b/atune/web/src/router/index.ts @@ -1,7 +1,7 @@ import { createRouter, createWebHistory } from "vue-router"; import type { RouteRecordRaw } from "vue-router"; import Home from "@/views/Home.vue"; -import Atune from "@/components/atuneList.vue"; +import Atune from "@/views/atuneList.vue"; import Result from "@/views/ResultInfo.vue"; const routes: Array = [ @@ -16,6 +16,7 @@ const routes: Array = [ children: [ { path: "detail", + name: "taskDetail", component: () => import("../views/taskDetail.vue"), }, ], @@ -24,6 +25,13 @@ const routes: Array = [ path: "/atune", component: Atune, meta: { title: "模板列表" }, + children: [ + { + path: "detail", + name: "atuneDetail", + component: () => import("../views/atuneDetail.vue"), + }, + ], }, { path: "/result", diff --git a/atune/web/src/store/atune.ts b/atune/web/src/store/atune.ts index 7ad8093288c287bae45c7d680e06073ac2ea2423..65767fd26d756441985bbc338e0f33a3b302006e 100644 --- a/atune/web/src/store/atune.ts +++ b/atune/web/src/store/atune.ts @@ -1,7 +1,11 @@ -import { defineStore } from 'pinia'; +import { defineStore } from "pinia"; +import { Task, Atune } from "@/types/atune"; -export const useAtuneStore = defineStore('atune', { - state: () => ({ count: 0 }), +export const useAtuneStore = defineStore("atune", { + state: () => ({ + count: 0, + taskRow: {} as Task, + }), getters: { double: (state) => state.count * 2, }, @@ -9,6 +13,10 @@ export const useAtuneStore = defineStore('atune', { increment() { this.count++; }, + // 设置taskRow数据 + setTaskRow(row: Task) { + this.taskRow = row; + }, }, // persist: { // enabled: true, // 开启存储 diff --git a/atune/web/src/store/canvas.ts b/atune/web/src/store/canvas.ts new file mode 100644 index 0000000000000000000000000000000000000000..0e5dfbb50662c045522c5690133c66a2cf900686 --- /dev/null +++ b/atune/web/src/store/canvas.ts @@ -0,0 +1,112 @@ +import { defineStore } from "pinia"; +import { RectConfig } from "@/types/atune"; +export const useCanvasStore = defineStore("canvas", { + state: () => ({ + ctx: {}, + width: 0, + fromX: 0, + fromY: 50, + rectWidth: 100, + rectHeight: 50, + rectConfig: { + x: 0, + y: 0, + width: 100, + height: 50, + fill: "#fff", + stroke: "#fff", + shadowBlur: 2, + cornerRadius: 10, + }, + }), + getters: { + /** + * 箭头函数的写法,直接把 state 中的值传进来使用 + * 如果要在 Getter 中调用其他的计算属性方法,不能使用箭头函数 + * 注意:需要自己定义当前方法的返回值类型 + * @param state + * @returns + */ + // 计算各个图形的起始位置 + rectStart: (state) => { + let rectConfig: RectConfig = JSON.parse(JSON.stringify(state.rectConfig)); + rectConfig.x = state.width / 2 - state.rectWidth; + rectConfig.y = state.fromY; + return rectConfig; + }, + rectPrepare: (state) => { + let rectConfig: RectConfig = JSON.parse(JSON.stringify(state.rectConfig)); + rectConfig.x = state.width / 2 - state.rectWidth; + rectConfig.y = state.fromY + state.fromY * 2; + return rectConfig; + }, + rectTune: (state) => { + let rectConfig: RectConfig = JSON.parse(JSON.stringify(state.rectConfig)); + rectConfig.x = state.width / 2 - state.rectWidth; + rectConfig.y = state.fromY + state.fromY * 4; + return rectConfig; + }, + rectRestore: (state) => { + let rectConfig: RectConfig = JSON.parse(JSON.stringify(state.rectConfig)); + rectConfig.x = state.width / 2 - state.rectWidth; + rectConfig.y = state.fromY + state.fromY * 6; + return rectConfig; + }, + arrowStartX: (state) => { + return state.fromX - state.rectWidth / 2; + }, + arrowStartY: (state) => { + return state.fromY + state.rectHeight; + }, + }, + actions: { + setCtx(ctx: any) { + this.ctx = ctx; + }, + setWidth(width: number) { + this.width = width; + this.fromX = width / 2; + }, + drawArrow( + context: any, + shape: any, + fX: number, + tX: number, + fY: number, + tY: number + ) { + const headlen = 10; //箭头线的长度 + const theta = 30; //箭头线与直线的夹角 + const fromX = fX; + const fromY = fY; + const toX = tX; + const toY = tY; + let arrowX, arrowY; //箭头线终点坐标 + // 计算各角度和对应的箭头终点坐标 + let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI; + let angle1 = ((angle + theta) * Math.PI) / 180; + let angle2 = ((angle - theta) * Math.PI) / 180; + let topX = headlen * Math.cos(angle1); + let topY = headlen * Math.sin(angle1); + let botX = headlen * Math.cos(angle2); + let botY = headlen * Math.sin(angle2); + context.beginPath(); + // draw a line + context.moveTo(fromX, fromY); + context.lineTo(toX, toY); + // draw top arrow + arrowX = toX + topX; + arrowY = toY + topY; + context.moveTo(arrowX, arrowY); + context.lineTo(toX, toY); + // draw bottom arrow + arrowX = toX + botX; + arrowY = toY + botY; + context.lineTo(arrowX, arrowY); + context.closePath(); + + // special Konva.js method + context.fillStrokeShape(shape); + }, + }, +}); diff --git a/atune/web/src/types/atune.d.ts b/atune/web/src/types/atune.d.ts index 18ea8b2cedb779f1bbae28881d8b1b4c30cec218..349d456a099428c9fc4ddb2d0ecfa5ceeb3a263a 100644 --- a/atune/web/src/types/atune.d.ts +++ b/atune/web/src/types/atune.d.ts @@ -5,7 +5,7 @@ export interface Task { task_status: string; create_time: string; update_time: string; - results: [{}]; + results: Array; } export interface Atune { @@ -17,3 +17,34 @@ export interface Atune { restore: string; note: string; } + +// 画布矩形的参数配置 +export interface RectConfig { + x: number; + y: number; + width: number; + height: number; + fill: string; + stroke: string; + shadowBlur: number; + cornerRadius: number; +} + +// 导出接口字面量 +export type TaskArray = Task[]; +export type AtuneArray = Atune[]; + +// *接口api返回结果约束不含data +export interface Result { + code: number; + msg: string; +} + +// *接口api返回结果含有page信息 +export interface ReaultData extends Result { + data: Task[] | Atune[]; + ok?: string; + page: number; + size: number; + total: number; +} diff --git a/atune/web/src/views/Home.vue b/atune/web/src/views/Home.vue index d2d5845219c5b4e68af4942b5cc3e7cf00026349..6f51d4c717c5df4047aa686eaef8faf1842465a9 100644 --- a/atune/web/src/views/Home.vue +++ b/atune/web/src/views/Home.vue @@ -40,7 +40,8 @@ import { ref } from "vue"; import { ElDialog } from "element-plus"; import taskList from "./taskList.vue"; import atuneTemplete from "@/components/atuneTemplete.vue"; -import router from "../router/index.ts"; +import { useRouter } from "vue-router"; +import { Task, Atune } from "@/types/atune"; const selectedNodeData = ref(""); const searchTuneName = ref(""); @@ -50,6 +51,9 @@ const selectedEditRow = ref(); const refreshData = ref(false); const showDetail = ref(false); +// 路由管理器 +const router = useRouter(); + // 关闭dialog弹框 const closeDialog = () => { showDialog.value = false; @@ -64,19 +68,14 @@ const returnHome = () => { const handleCreat = () => {}; // 查看模板详情 -const handleAtuneDetail = (editRow: any) => { - selectedEditRow.value = editRow; +const handleAtuneDetail = (taskRow: Task | Atune) => { + selectedEditRow.value = taskRow; showDialog.value = true; }; // 查看任务详情 -const handleTaskDetail = (editRow: any) => { - router.push({ - path: "/task/detail", - params: { - row: editRow, - }, - }); +const handleTaskDetail = () => { + router.push("/task/detail"); showDetail.value = true; }; diff --git a/atune/web/src/views/ResultInfo.vue b/atune/web/src/views/ResultInfo.vue index 8814d52552f202acf7aebb213c899f0664eb8233..cc340bc4c9b9e6521aed291b67c90b6b45870aad 100644 --- a/atune/web/src/views/ResultInfo.vue +++ b/atune/web/src/views/ResultInfo.vue @@ -1,162 +1 @@ - - - - \ No newline at end of file + diff --git a/atune/web/src/views/atuneDetail.vue b/atune/web/src/views/atuneDetail.vue new file mode 100644 index 0000000000000000000000000000000000000000..e9e1d82f9c39ab5bab8b6cde3d07f5a522f7bbad --- /dev/null +++ b/atune/web/src/views/atuneDetail.vue @@ -0,0 +1,60 @@ + + + diff --git a/atune/web/src/views/atuneList.vue b/atune/web/src/views/atuneList.vue new file mode 100644 index 0000000000000000000000000000000000000000..29227d05e9ac2845af12836f61aa61ce057e1d49 --- /dev/null +++ b/atune/web/src/views/atuneList.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/atune/web/src/views/taskDetail.vue b/atune/web/src/views/taskDetail.vue index 5b52e6eefded3627a6099a5f8bd82d8160a4058c..d0fda5ff5fe3d458adbaed3a5ce83e4ecb07b3ca 100644 --- a/atune/web/src/views/taskDetail.vue +++ b/atune/web/src/views/taskDetail.vue @@ -1,10 +1,16 @@ - +