feat(sj_1.0.0): 重试任务-批量新增-初稿

This commit is contained in:
dhb52 2024-04-21 22:03:04 +08:00
parent 4643f0ab12
commit 452f70103c
9 changed files with 315 additions and 14 deletions

View File

@ -9,6 +9,7 @@ const local: App.I18n.Schema = {
addSuccess: 'Add Success',
backToHome: 'Back to home',
batchDelete: 'Batch Delete',
batchAdd: 'Batch Add',
cancel: 'Cancel',
close: 'Close',
check: 'Check',
@ -38,11 +39,13 @@ const local: App.I18n.Schema = {
trigger: 'Trigger',
update: 'Update',
updateSuccess: 'Update Success',
updateFailed: 'Update Failed',
userCenter: 'User Center',
success: 'Success',
fail: 'Fail',
stop: 'Stop',
running: 'Running',
confirmStop: 'Are you sure you want to stop?',
yesOrNo: {
yes: 'Yes',
no: 'No'
@ -628,7 +631,8 @@ const local: App.I18n.Schema = {
sceneName: 'Please enter Scene name',
executorName: 'Please enter Actuator name',
taskType: 'Please enter Task type',
idempotentId: 'Please enter Idempotent ID'
idempotentId: 'Please enter Idempotent ID',
logStr: 'Please enter log info'
},
retryStatusType: {
retrying: 'Retrying',
@ -642,7 +646,8 @@ const local: App.I18n.Schema = {
},
generateIdempotentId: 'Generate by client',
addRetryTask: 'Add Retry task',
editRetryTask: 'Add Retry task'
editRetryTask: 'Add Retry task',
batchAddRetryTask: 'Batch add retry task'
},
retryScene: {
title: 'Scene List',

View File

@ -6,6 +6,7 @@ const local: App.I18n.Schema = {
common: {
action: '操作',
add: '新增',
batchAdd: '批量添加',
addSuccess: '添加成功',
backToHome: '返回首页',
batchDelete: '批量删除',
@ -38,11 +39,13 @@ const local: App.I18n.Schema = {
trigger: '触发',
update: '更新',
updateSuccess: '更新成功',
updateFailed: '更新失败',
userCenter: '个人中心',
success: '成功',
fail: '失败',
stop: '停止',
running: '运行中',
confirmStop: '确认停止吗?',
yesOrNo: {
yes: '是',
no: '否'
@ -624,7 +627,8 @@ const local: App.I18n.Schema = {
sceneName: '请输入场景名称',
executorName: '请输入执行器名称',
taskType: '请输入任务类型',
idempotentId: '请输入幂等id'
idempotentId: '请输入幂等ID',
logStr: '日志信息'
},
retryStatusType: {
retrying: '处理中',
@ -638,7 +642,8 @@ const local: App.I18n.Schema = {
},
generateIdempotentId: '通过客户端生成',
addRetryTask: '新增重试任务',
editRetryTask: '编辑重试任务'
editRetryTask: '编辑重试任务',
batchAddRetryTask: '批量新增重试任务'
},
retryScene: {
title: '场景列表',

View File

@ -18,6 +18,15 @@ export function fetchAddRetryTask(data: Api.RetryTask.RetryTask) {
});
}
/** batch add retryTask */
export function fetchBatchAddRetryTask(data: Api.RetryTask.RetryTaskBatchAdd) {
return request<boolean>({
url: '/retry-task/batch',
method: 'post',
data
});
}
/** edit retryTask */
export function fetchEditRetryTask(data: Api.RetryTask.RetryTask) {
return request<boolean>({
@ -26,3 +35,12 @@ export function fetchEditRetryTask(data: Api.RetryTask.RetryTask) {
data
});
}
/** update retryTask status */
export function fetchUpdateRetryTaskStatus(data: Api.RetryTask.RetryTaskUpdateStatusRequest) {
return request<boolean>({
url: '/retry-task/status',
method: 'put',
data
});
}

18
src/typings/api.d.ts vendored
View File

@ -651,6 +651,24 @@ declare namespace Api {
taskType?: TaskType;
}>;
type RetryTaskBatchAdd = {
/** 组名称 */
groupName: string;
/** 重试状态 0、重试中 1、重试完成 2、最大次数 3、暂停 */
retryStatus: RetryStatusType;
/** 日志 */
logStr: string;
};
type RetryTaskUpdateStatusRequest = {
/** id */
id: number;
/** 组名称 */
groupName: string;
/** 重试状态 0、重试中 1、重试完成 2、最大次数 3、暂停 */
retryStatus: RetryStatusType;
};
/** RetryTask search params */
type RetryTaskSearchParams = CommonType.RecordNullable<
Pick<Api.RetryTask.RetryTask, 'uniqueId' | 'groupName' | 'sceneName' | 'idempotentId' | 'bizNo' | 'retryStatus'> &

View File

@ -252,6 +252,7 @@ declare namespace App {
common: {
action: string;
add: string;
batchAdd: string;
addSuccess: string;
backToHome: string;
batchDelete: string;
@ -284,11 +285,13 @@ declare namespace App {
trigger: string;
update: string;
updateSuccess: string;
updateFailed: string;
userCenter: string;
success: string;
fail: string;
stop: string;
running: string;
confirmStop: string;
yesOrNo: {
yes: string;
no: string;
@ -797,6 +800,7 @@ declare namespace App {
executorName: string;
taskType: string;
idempotentId: string;
logStr: string;
};
retryStatusType: {
retrying: string;
@ -811,6 +815,7 @@ declare namespace App {
generateIdempotentId: string;
addRetryTask: string;
editRetryTask: string;
batchAddRetryTask: string;
};
retryScene: {
title: string;

View File

@ -1,11 +1,14 @@
<script setup lang="tsx">
import { NButton, NPopconfirm, NTag } from 'naive-ui';
import { fetchGetRetryTaskList } from '@/service/api';
import { useBoolean } from '@sa/hooks';
import { fetchGetRetryTaskList, fetchUpdateRetryTaskStatus } from '@/service/api';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { retryTaskStatusTypeRecord, retryTaskTypeRecord } from '@/constants/business';
import CustomerTableHeaderOperation from './modules/customer-table-header-operation.vue';
import RetryTaskOperateDrawer from './modules/retry-task-operate-drawer.vue';
import RetryTaskBatchAddDrawer from './modules/retry-task-batch-add-drawer.vue';
import RetryTaskSearch from './modules/retry-task-search.vue';
const appStore = useAppStore();
@ -134,6 +137,16 @@ const { columns, columnChecks, data, getData, loading, mobilePagination, searchP
)
}}
</NPopconfirm>
<NPopconfirm onPositiveClick={() => handleStop(Number(row.id!), row.groupName!)}>
{{
default: () => $t('common.confirmStop'),
trigger: () => (
<NButton type="error" ghost size="small">
{$t('common.stop')}
</NButton>
)
}}
</NPopconfirm>
</div>
)
}
@ -151,6 +164,8 @@ const {
// closeDrawer
} = useTableOperate(data, getData);
const { bool: batchAddDrawerVisible, setTrue: openBatchAddDrawer } = useBoolean();
function handleDelete(id: string) {
// request
console.log(id);
@ -161,6 +176,19 @@ function handleDelete(id: string) {
function edit(id: string) {
handleEdit(id);
}
function handleBatchAdd() {
openBatchAddDrawer();
}
async function handleStop(id: number, groupName: string) {
const { error } = await fetchUpdateRetryTaskStatus({ id, groupName, retryStatus: 3 });
if (error) {
window.$message?.error($t('common.updateFailed'));
return;
}
window.$message?.success($t('common.updateSuccess'));
}
</script>
<template>
@ -174,11 +202,12 @@ function edit(id: string) {
header-class="view-card-header"
>
<template #header-extra>
<TableHeaderOperation
<CustomerTableHeaderOperation
v-model:columns="columnChecks"
:disabled-delete="checkedRowKeys.length === 0"
:loading="loading"
@add="handleAdd"
@batch-add="handleBatchAdd"
@refresh="getData"
/>
</template>
@ -200,6 +229,7 @@ function edit(id: string) {
:row-data="editingData"
@submitted="getData"
/>
<RetryTaskBatchAddDrawer v-model:visible="batchAddDrawerVisible" :row-data="editingData" @submitted="getData" />
</NCard>
</div>
</template>

View File

@ -0,0 +1,86 @@
<script setup lang="ts">
defineOptions({
name: 'CustomerTableHeaderOperation'
});
interface Props {
itemAlign?: NaiveUI.Align;
disabledDelete?: boolean;
loading?: boolean;
showDelete?: boolean;
showAdd?: boolean;
}
withDefaults(defineProps<Props>(), {
showDelete: true,
showAdd: true
});
interface Emits {
(e: 'add'): void;
(e: 'batchAdd'): void;
(e: 'delete'): void;
(e: 'refresh'): void;
}
const emit = defineEmits<Emits>();
const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
default: () => []
});
function add() {
emit('add');
}
function batchAdd() {
emit('batchAdd');
}
function batchDelete() {
emit('delete');
}
function refresh() {
emit('refresh');
}
</script>
<template>
<NSpace :align="itemAlign" wrap justify="end" class="lt-sm:w-200px">
<slot name="default">
<NButton v-if="showAdd" size="small" ghost type="primary" @click="add">
<template #icon>
<icon-ic-round-plus class="text-icon" />
</template>
{{ $t('common.add') }}
</NButton>
<NButton v-if="showAdd" size="small" ghost type="primary" @click="batchAdd">
<template #icon>
<icon-ic-round-plus class="text-icon" />
</template>
{{ $t('common.batchAdd') }}
</NButton>
<NPopconfirm v-if="showDelete" @positive-click="batchDelete">
<template #trigger>
<NButton size="small" ghost type="error" :disabled="disabledDelete">
<template #icon>
<icon-ic-round-delete class="text-icon" />
</template>
{{ $t('common.batchDelete') }}
</NButton>
</template>
{{ $t('common.confirmDelete') }}
</NPopconfirm>
</slot>
<NButton size="small" @click="refresh">
<template #icon>
<icon-mdi-refresh class="text-icon" :class="{ 'animate-spin': loading }" />
</template>
{{ $t('common.refresh') }}
</NButton>
<TableColumnSetting v-model:columns="columns" />
</NSpace>
</template>
<style scoped></style>

View File

@ -0,0 +1,113 @@
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import OperateDrawer from '@/components/common/operate-drawer.vue';
import { $t } from '@/locales';
import { fetchBatchAddRetryTask, fetchGetAllGroupNameList } from '@/service/api';
import { translateOptions, translateOptions2 } from '@/utils/common';
import { retryTaskStatusTypeOptions } from '@/constants/business';
defineOptions({
name: 'RetryTaskBatchAddDrawer'
});
interface Emits {
(e: 'submitted'): void;
}
const emit = defineEmits<Emits>();
const visible = defineModel<boolean>('visible', {
default: false
});
const { formRef, validate, restoreValidation } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();
type Model = Pick<Api.RetryTask.RetryTaskBatchAdd, 'groupName' | 'retryStatus' | 'logStr'>;
const model: Model = reactive(createDefaultModel());
/** 组列表 */
const groupNameList = ref<string[]>([]);
function createDefaultModel(): Model {
return {
groupName: '',
retryStatus: 0,
logStr: ''
};
}
type RuleKey = Extract<keyof Model, 'groupName' | 'retryStatus' | 'logStr'>;
const rules: Record<RuleKey, App.Global.FormRule> = {
groupName: defaultRequiredRule,
retryStatus: defaultRequiredRule,
logStr: defaultRequiredRule
};
function closeDrawer() {
visible.value = false;
}
async function handleSubmit() {
await validate();
const { groupName, retryStatus, logStr } = model;
const { error } = await fetchBatchAddRetryTask({ groupName, retryStatus, logStr });
if (error) return;
window.$message?.success($t('common.addSuccess'));
closeDrawer();
emit('submitted');
}
async function getGroupNameList() {
const res = await fetchGetAllGroupNameList();
groupNameList.value = res.data as string[];
}
watch(visible, () => {
if (visible.value) {
restoreValidation();
}
});
onMounted(() => {
getGroupNameList();
});
</script>
<template>
<OperateDrawer v-model="visible" :title="$t('page.retryTask.batchAddRetryTask')" @handle-submit="handleSubmit">
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.retryTask.groupName')" path="groupName">
<NSelect
v-model:value="model.groupName"
:placeholder="$t('page.retryTask.form.groupName')"
:options="translateOptions2(groupNameList)"
/>
</NFormItem>
<NFormItem :label="$t('page.retryTask.retryStatus')" path="retryStatus">
<NSelect
v-model:value="model.retryStatus"
:placeholder="$t('page.retryTask.form.retryStatus')"
:options="translateOptions(retryTaskStatusTypeOptions)"
/>
</NFormItem>
<NFormItem :label="$t('page.retryTask.form.logStr')" path="logStr">
<NInput v-model:value="model.logStr" type="textarea" :placeholder="$t('page.retryTask.form.logStr')" />
</NFormItem>
</NForm>
<template #footer>
<NSpace :size="16">
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
<NButton type="primary" @click="handleSubmit">{{ $t('common.save') }}</NButton>
</NSpace>
</template>
</OperateDrawer>
</template>
<style scoped></style>

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import OperateDrawer from '@/components/common/operate-drawer.vue';
import { $t } from '@/locales';
@ -100,7 +100,16 @@ async function handleSubmit() {
if (props.operateType === 'add') {
const { groupName, sceneName, idempotentId, bizNo, executorName, argsStr, retryStatus } = model;
fetchAddRetryTask({ groupName, sceneName, idempotentId, bizNo, executorName, argsStr, retryStatus });
const { error } = await fetchAddRetryTask({
groupName,
sceneName,
idempotentId,
bizNo,
executorName,
argsStr,
retryStatus
});
if (error) return;
window.$message?.success($t('common.addSuccess'));
}
@ -141,9 +150,7 @@ function setIdempotentId() {
}
onMounted(() => {
nextTick(() => {
getGroupNameList();
});
getGroupNameList();
});
</script>
@ -155,6 +162,7 @@ onMounted(() => {
v-model:value="model.groupName"
:placeholder="$t('page.retryTask.form.groupName')"
:options="translateOptions2(groupNameList)"
:disabled="props.operateType === 'edit'"
@update-value="handleGroupNameUpdate"
/>
</NFormItem>
@ -163,21 +171,34 @@ onMounted(() => {
v-model:value="model.sceneName"
:placeholder="$t('page.retryTask.form.sceneName')"
:options="translateOptions2(sceneNameList)"
:disabled="props.operateType === 'edit'"
/>
</NFormItem>
<NFormItem :label="$t('page.retryTask.idempotentId')" path="idempotentId">
<NInputGroup>
<NInput v-model:value="model.idempotentId" :placeholder="$t('page.retryTask.form.idempotentId')" />
<NInput
v-model:value="model.idempotentId"
:placeholder="$t('page.retryTask.form.idempotentId')"
:disabled="props.operateType === 'edit'"
/>
<NButton type="primary" ghost :disabled="props.operateType === 'edit'" @click="setIdempotentId">
{{ $t('page.retryTask.generateIdempotentId') }}
</NButton>
</NInputGroup>
</NFormItem>
<NFormItem :label="$t('page.retryTask.bizNo')" path="bizNo">
<NInput v-model:value="model.bizNo" :placeholder="$t('page.retryTask.form.bizNo')" />
<NInput
v-model:value="model.bizNo"
:placeholder="$t('page.retryTask.form.bizNo')"
:disabled="props.operateType === 'edit'"
/>
</NFormItem>
<NFormItem :label="$t('page.retryTask.executorName')" path="executorName">
<NInput v-model:value="model.executorName" :placeholder="$t('page.retryTask.form.executorName')" />
<NInput
v-model:value="model.executorName"
:placeholder="$t('page.retryTask.form.executorName')"
:disabled="props.operateType === 'edit'"
/>
</NFormItem>
<NFormItem :label="$t('page.retryTask.argsStr')" path="argsStr">
<NInput v-model:value="model.argsStr" type="textarea" :placeholder="$t('page.retryTask.form.argsStr')" />