add task edit dialog

This commit is contained in:
akrike
2025-09-15 21:01:09 +08:00
parent c52f7e2097
commit 09ae980ab5

View File

@@ -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-divider></v-divider>
<!-- 表单内容 -->
<v-card-text class="pt-6">
<v-container fluid>
<v-row dense>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
label="判断条件" label="判断条件"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="conditionSelect" :items="conditionSelect"
v-model="taskForm.condition" v-model="taskForm.condition"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
v-if="taskForm.condition != 3" :disabled="taskForm.condition == 3"
label="判断目标" label="判断目标"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="processSelect" :items="processSelect"
v-model="taskForm.processId" v-model="taskForm.processId"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
label="操作目标" label="操作目标"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="processSelect" :items="processSelect"
v-model="taskForm.operationTarget" v-model="taskForm.operationTarget"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
label="执行操作" label="执行操作"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="operationSelect" :items="operationSelect"
v-model="taskForm.operation" v-model="taskForm.operation"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
label="触发目标" label="触发目标"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="processSelect" :items="processSelect"
v-model="taskForm.triggerTarget" v-model="taskForm.triggerTarget"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
v-if="taskForm.triggerTarget != null" :disabled="taskForm.triggerTarget == null"
label="触发事件" label="触发事件"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="eventSelect" :items="eventSelect"
v-model="taskForm.triggerEvent" v-model="taskForm.triggerEvent"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete <v-autocomplete
label="后续任务" label="后续任务"
item-text="name" item-title="name"
item-value="value" item-value="value"
filled variant="outlined"
dense density="comfortable"
:items="taskSelect" :items="taskSelect"
v-model="taskForm.nextId" v-model="taskForm.nextId"
></v-autocomplete> />
</v-col>
<v-col cols="12" sm="6">
<v-text-field <v-text-field
label="定时任务" label="定时任务"
filled variant="outlined"
dense density="comfortable"
v-model="taskForm.cron" v-model="taskForm.cron"
></v-text-field> />
<v-text-field </v-col>
@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-col cols="12">
{{ taskForm?.key != null ? "刷新api" : "创建api" }} <v-text-field
<v-icon right dark> label="API"
{{ taskForm?.key != null ? "mdi-refresh" : "mdi-plus" }}</v-icon 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> </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>