mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-10-05 16:06:51 +08:00
add task edit dialog
This commit is contained in:
@@ -66,121 +66,160 @@
|
|||||||
<!-- 这里可以放底部说明或按钮 -->
|
<!-- 这里可以放底部说明或按钮 -->
|
||||||
<v-icon class="mr-2" v-if="!item.running"> mdi-play </v-icon>
|
<v-icon class="mr-2" v-if="!item.running"> mdi-play </v-icon>
|
||||||
<v-icon class="mr-2" v-else> mdi-stop </v-icon>
|
<v-icon class="mr-2" v-else> mdi-stop </v-icon>
|
||||||
<v-icon class="mr-2"> mdi-pencil </v-icon>
|
<v-icon class="mr-2" @click="editTaskBefore(item)"> mdi-pencil </v-icon>
|
||||||
<v-icon> mdi-delete </v-icon>
|
<v-icon> mdi-delete </v-icon>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<v-dialog v-model="taskDialog" max-width="500px">
|
<v-dialog v-model="taskDialog" max-width="600px" persistent>
|
||||||
<v-card>
|
<v-card class="rounded-xl">
|
||||||
<v-card-title class="text-h5">{{
|
<!-- 标题 -->
|
||||||
addTask ? "添加任务" : "修改任务"
|
<v-card-title class="text-h6 font-weight-medium">
|
||||||
}}</v-card-title>
|
{{ isAdd ? "添加任务" : "修改任务" }}
|
||||||
<v-card-text style="margin-top: 20px">
|
</v-card-title>
|
||||||
<v-autocomplete
|
|
||||||
label="判断条件"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="conditionSelect"
|
|
||||||
v-model="taskForm.condition"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
v-if="taskForm.condition != 3"
|
|
||||||
label="判断目标"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="processSelect"
|
|
||||||
v-model="taskForm.processId"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
label="操作目标"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="processSelect"
|
|
||||||
v-model="taskForm.operationTarget"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
label="执行操作"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="operationSelect"
|
|
||||||
v-model="taskForm.operation"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
label="触发目标"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="processSelect"
|
|
||||||
v-model="taskForm.triggerTarget"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
v-if="taskForm.triggerTarget != null"
|
|
||||||
label="触发事件"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="eventSelect"
|
|
||||||
v-model="taskForm.triggerEvent"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-autocomplete
|
|
||||||
label="后续任务"
|
|
||||||
item-text="name"
|
|
||||||
item-value="value"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
:items="taskSelect"
|
|
||||||
v-model="taskForm.nextId"
|
|
||||||
></v-autocomplete>
|
|
||||||
<v-text-field
|
|
||||||
label="定时任务"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
v-model="taskForm.cron"
|
|
||||||
></v-text-field>
|
|
||||||
<v-text-field
|
|
||||||
@click="copyToClipboard"
|
|
||||||
:disabled="taskForm?.key == null"
|
|
||||||
label="api"
|
|
||||||
filled
|
|
||||||
dense
|
|
||||||
readonly
|
|
||||||
:value="taskForm.key != null ? urlBase + taskForm.key : '未创建api'"
|
|
||||||
></v-text-field>
|
|
||||||
|
|
||||||
<v-btn @click="changeApi" color="primary">
|
<v-divider></v-divider>
|
||||||
{{ taskForm?.key != null ? "刷新api" : "创建api" }}
|
|
||||||
<v-icon right dark>
|
<!-- 表单内容 -->
|
||||||
{{ taskForm?.key != null ? "mdi-refresh" : "mdi-plus" }}</v-icon
|
<v-card-text class="pt-6">
|
||||||
>
|
<v-container fluid>
|
||||||
</v-btn>
|
<v-row dense>
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
label="判断条件"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="conditionSelect"
|
||||||
|
v-model="taskForm.condition"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
:disabled="taskForm.condition == 3"
|
||||||
|
label="判断目标"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="processSelect"
|
||||||
|
v-model="taskForm.processId"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
label="操作目标"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="processSelect"
|
||||||
|
v-model="taskForm.operationTarget"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
label="执行操作"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="operationSelect"
|
||||||
|
v-model="taskForm.operation"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
label="触发目标"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="processSelect"
|
||||||
|
v-model="taskForm.triggerTarget"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
:disabled="taskForm.triggerTarget == null"
|
||||||
|
label="触发事件"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="eventSelect"
|
||||||
|
v-model="taskForm.triggerEvent"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-autocomplete
|
||||||
|
label="后续任务"
|
||||||
|
item-title="name"
|
||||||
|
item-value="value"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
:items="taskSelect"
|
||||||
|
v-model="taskForm.nextId"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" sm="6">
|
||||||
|
<v-text-field
|
||||||
|
label="定时任务"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
v-model="taskForm.cron"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-text-field
|
||||||
|
label="API"
|
||||||
|
variant="outlined"
|
||||||
|
density="comfortable"
|
||||||
|
readonly
|
||||||
|
v-model="apiUrl"
|
||||||
|
append-inner-icon="mdi-content-copy"
|
||||||
|
@click:append-inner="copyToClipboard"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<div class="d-flex justify-end mt-3">
|
||||||
|
<v-btn @click="changeApi" color="primary" variant="tonal">
|
||||||
|
{{ taskForm?.key != null ? "刷新 API" : "创建 API" }}
|
||||||
|
<v-icon end>
|
||||||
|
{{ taskForm?.key != null ? "mdi-refresh" : "mdi-plus" }}
|
||||||
|
</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</v-container>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
|
||||||
<v-spacer></v-spacer>
|
<v-divider></v-divider>
|
||||||
<v-btn color="blue darken-1" text @click="taskDialog = false"
|
|
||||||
>取消</v-btn
|
<!-- 底部操作按钮 -->
|
||||||
>
|
<v-card-actions class="justify-end pa-4">
|
||||||
<v-btn color="blue darken-1" text @click="submit">确认</v-btn>
|
<v-btn text @click="taskDialog = false">取消</v-btn>
|
||||||
<v-spacer></v-spacer>
|
<v-btn color="primary" @click="submit">确认</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { computed } from "vue";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
import {
|
import {
|
||||||
|
addTask,
|
||||||
changeTaskKey,
|
changeTaskKey,
|
||||||
editTask,
|
editTask,
|
||||||
editTaskEnable,
|
editTaskEnable,
|
||||||
@@ -191,13 +230,41 @@ import { useSnackbarStore } from "~/src/stores/snackbarStore";
|
|||||||
import { TaskItem } from "~/src/types/tassk/task";
|
import { TaskItem } from "~/src/types/tassk/task";
|
||||||
|
|
||||||
const snackbarStore = useSnackbarStore();
|
const snackbarStore = useSnackbarStore();
|
||||||
|
|
||||||
|
// 弹窗 & 表单
|
||||||
const taskDialog = ref(false);
|
const taskDialog = ref(false);
|
||||||
const taskForm = ref<Partial<TaskItem>>({});
|
const taskForm = ref<Partial<TaskItem>>({});
|
||||||
const addTask = ref(false);
|
const isAdd = ref(false);
|
||||||
/**
|
|
||||||
* 自定义列头:title -> 显示标题(中文),key -> 对应数据字段名
|
// 下拉框选项
|
||||||
* (Vuetify 3 的 headers 使用 title/key 风格)
|
const taskSelect = ref<any[]>([]);
|
||||||
*/
|
const processSelect = ref<any[]>([]);
|
||||||
|
const eventSelect = ref<any[]>([]);
|
||||||
|
const operationSelect = ref<any[]>([]);
|
||||||
|
const conditionSelect = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 映射表
|
||||||
|
const conditionMap = {
|
||||||
|
0: "运行中",
|
||||||
|
1: "已停止",
|
||||||
|
2: "错误",
|
||||||
|
3: "无条件",
|
||||||
|
};
|
||||||
|
const operationMap = {
|
||||||
|
0: "异步启动",
|
||||||
|
1: "异步停止",
|
||||||
|
2: "完成启动",
|
||||||
|
3: "完成停止",
|
||||||
|
};
|
||||||
|
const eventMap = {
|
||||||
|
0: "停止",
|
||||||
|
1: "启动",
|
||||||
|
2: "异常",
|
||||||
|
};
|
||||||
|
|
||||||
|
const urlBase = ref(`${window.location.origin}/api/task/api-key/`);
|
||||||
|
|
||||||
|
// 表头
|
||||||
const headers = [
|
const headers = [
|
||||||
{ title: "任务ID", key: "id" },
|
{ title: "任务ID", key: "id" },
|
||||||
{ title: "任务名", key: "processName" },
|
{ title: "任务名", key: "processName" },
|
||||||
@@ -210,18 +277,19 @@ const headers = [
|
|||||||
{ title: "启用API", key: "apiEnable" },
|
{ title: "启用API", key: "apiEnable" },
|
||||||
{ title: "操作", key: "operate" },
|
{ title: "操作", key: "operate" },
|
||||||
];
|
];
|
||||||
|
const apiUrl = computed(() =>
|
||||||
|
taskForm.value?.key ? urlBase.value + taskForm.value.key : "未创建api"
|
||||||
|
);
|
||||||
|
// 任务数据
|
||||||
|
const taskData = ref<TaskItem[]>([]);
|
||||||
|
|
||||||
// 单行数组(v-data-table 接受 items 数组)
|
// 格式化时间
|
||||||
const taskData = ref<TaskItem[]>();
|
const formatStartTime = (v: Date) => {
|
||||||
|
|
||||||
/** 格式化开始时间(兼容 null / 空字符串) */
|
|
||||||
const formatStartTime = (v) => {
|
|
||||||
if (!v) return "-";
|
if (!v) return "-";
|
||||||
try {
|
try {
|
||||||
const d = new Date(v);
|
if (Number.isNaN(v.getTime())) return v;
|
||||||
if (Number.isNaN(d.getTime())) return v;
|
return v.toLocaleString();
|
||||||
return d.toLocaleString();
|
} catch {
|
||||||
} catch (e) {
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -230,43 +298,129 @@ onMounted(() => {
|
|||||||
initTask();
|
initTask();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 打开添加任务弹窗
|
||||||
|
const addTaskBefore = () => {
|
||||||
|
isAdd.value = true;
|
||||||
|
taskForm.value = {}; // 清空表单
|
||||||
|
taskDialog.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开编辑任务弹窗
|
||||||
|
const editTaskBefore = (row: TaskItem) => {
|
||||||
|
isAdd.value = false;
|
||||||
|
getTaskById(row.id).then((res) => {
|
||||||
|
taskForm.value = res.data ?? {};
|
||||||
|
});
|
||||||
|
taskDialog.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 复制 API 地址
|
||||||
|
const copyToClipboard = () => {
|
||||||
|
if (!taskForm.value?.key) return;
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(urlBase.value + taskForm.value.key)
|
||||||
|
.then(() => {
|
||||||
|
snackbarStore.showSuccessMessage("复制成功");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("复制失败:", err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化任务 & 下拉框选项
|
||||||
const initTask = () => {
|
const initTask = () => {
|
||||||
getTaskAll().then((e) => {
|
getTaskAll().then((res) => {
|
||||||
taskData.value = e.data!;
|
const list = res.data ?? [];
|
||||||
|
taskData.value = list;
|
||||||
|
|
||||||
|
// 任务选择
|
||||||
|
taskSelect.value = list.map((t) => ({
|
||||||
|
name: t.id,
|
||||||
|
value: t.id,
|
||||||
|
}));
|
||||||
|
taskSelect.value.push({ name: "无", value: null });
|
||||||
|
|
||||||
|
// 进程选择
|
||||||
|
processSelect.value = list.map((t) => ({
|
||||||
|
name: t.processName,
|
||||||
|
value: t.processId,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 操作/事件/条件
|
||||||
|
operationSelect.value = Object.entries(operationMap).map(
|
||||||
|
([value, name]) => ({
|
||||||
|
name,
|
||||||
|
value: parseInt(value),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
eventSelect.value = Object.entries(eventMap).map(([value, name]) => ({
|
||||||
|
name,
|
||||||
|
value: parseInt(value),
|
||||||
|
}));
|
||||||
|
|
||||||
|
conditionSelect.value = Object.entries(conditionMap).map(
|
||||||
|
([value, name]) => ({
|
||||||
|
name,
|
||||||
|
value: parseInt(value),
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = (item) => {
|
// 修改任务
|
||||||
editTask(item).then((e) => {
|
const edit = (item: TaskItem) => {
|
||||||
if (e.code == 0) {
|
editTask(item).then((res) => {
|
||||||
snackbarStore.showSuccessMessage("success");
|
if (res.code === 0) {
|
||||||
|
snackbarStore.showSuccessMessage("修改成功");
|
||||||
initTask();
|
initTask();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeEnable = (item) => {
|
// 切换启用状态
|
||||||
editTaskEnable({
|
const changeEnable = (item: TaskItem) => {
|
||||||
id: item.id,
|
editTaskEnable({ id: item.id, enable: item.enable }).then((res) => {
|
||||||
enable: item.enable,
|
if (res.code === 0) {
|
||||||
}).then((e) => {
|
snackbarStore.showSuccessMessage("修改成功");
|
||||||
if (e.code == 0) {
|
|
||||||
snackbarStore.showSuccessMessage("success");
|
|
||||||
initTask();
|
initTask();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 生成/刷新 API Key
|
||||||
const changeApi = () => {
|
const changeApi = () => {
|
||||||
changeTaskKey(taskForm.value?.id).then((resp) => {
|
if (!taskForm.value?.id) return;
|
||||||
if (resp.code == 0) {
|
changeTaskKey(taskForm.value.id).then((res) => {
|
||||||
snackbarStore.showSuccessMessage("success");
|
if (res.code === 0) {
|
||||||
|
snackbarStore.showSuccessMessage("API 更新成功");
|
||||||
getTaskById(taskForm.value?.id).then((e) => {
|
getTaskById(taskForm.value?.id).then((e) => {
|
||||||
Object.assign(taskForm.value, e.data);
|
Object.assign(taskForm.value, e.data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submit = () => {
|
||||||
|
if (isAdd.value) {
|
||||||
|
addTask(taskForm.value).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
taskDialog.value = false;
|
||||||
|
snackbarStore.showSuccessMessage("添加成功");
|
||||||
|
initTask();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
editTask(taskForm.value).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
taskDialog.value = false;
|
||||||
|
snackbarStore.showSuccessMessage("修改成功");
|
||||||
|
initTask();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
Reference in New Issue
Block a user