feat(infra): 新增状态机管理功能模块
- 新增状态机模型和状态流转的完整 CRUD 功能 - 添加字典编码 OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE 用于对象类型下拉选择 - 实现状态机列表页、搜索组件、操作对话框和状态流转管理 - 新增 infra API 接口封装和类型定义 - 遵循项目规范:使用 TableSearchFields 搜索组件、BusinessTableActionCell 操作列、统一的状态标签展示 涉及文件: - src/constants/dict.ts: 新增对象类型字典编码 - src/service/api/infra.ts: 新增状态机和状态流转相关 API - src/typings/api/infra.d.ts: 新增状态机相关类型定义 - src/views/infra/state-machine/: 新增状态机管理页面及子组件
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE } from '@/constants/dict';
|
||||
import { fetchCreateObjectStatusModel, fetchGetObjectStatusModel, fetchUpdateObjectStatusModel } from '@/service/api';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import { statusOptions } from '../shared';
|
||||
|
||||
defineOptions({ name: 'StateMachineOperateDialog' });
|
||||
|
||||
interface Props {
|
||||
operateType: UI.TableOperateType;
|
||||
rowData?: Api.Infra.ObjectStatusModel | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
submitted: [statusModelId: string];
|
||||
}>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const { formRef, validate } = useForm();
|
||||
const { createRequiredRule } = useFormRules();
|
||||
const { dictOptions: objectTypeOptions } = useDict(OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE);
|
||||
|
||||
const detailLoading = ref(false);
|
||||
const submitting = ref(false);
|
||||
const isEdit = computed(() => props.operateType === 'edit');
|
||||
|
||||
const title = computed(() => {
|
||||
const titleMap: Record<UI.TableOperateType, string> = {
|
||||
add: '新增状态模型',
|
||||
edit: '编辑状态模型'
|
||||
};
|
||||
|
||||
return titleMap[props.operateType];
|
||||
});
|
||||
|
||||
type Model = Api.Infra.SaveObjectStatusModelParams;
|
||||
|
||||
const model = ref(createDefaultModel());
|
||||
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
objectType: 'product',
|
||||
statusCode: '',
|
||||
statusName: '',
|
||||
sort: 0,
|
||||
status: 0,
|
||||
initialFlag: false,
|
||||
terminalFlag: false,
|
||||
allowEdit: false,
|
||||
progressExcludedFlag: false,
|
||||
allowCreateProject: false,
|
||||
allowCreateRequirement: false,
|
||||
remark: ''
|
||||
};
|
||||
}
|
||||
|
||||
const rules = {
|
||||
objectType: createRequiredRule('请选择对象类型'),
|
||||
statusCode: createRequiredRule('请输入状态编码'),
|
||||
statusName: createRequiredRule('请输入状态名称'),
|
||||
sort: createRequiredRule('请输入排序值'),
|
||||
status: createRequiredRule('请选择配置状态')
|
||||
} satisfies Record<string, App.Global.FormRule>;
|
||||
|
||||
function closeModal() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function initModel() {
|
||||
model.value = createDefaultModel();
|
||||
|
||||
if (!isEdit.value || !props.rowData) {
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
return;
|
||||
}
|
||||
|
||||
detailLoading.value = true;
|
||||
|
||||
const { error, data } = await fetchGetObjectStatusModel(props.rowData.id);
|
||||
|
||||
detailLoading.value = false;
|
||||
|
||||
if (!error) {
|
||||
model.value = {
|
||||
objectType: data.objectType,
|
||||
statusCode: data.statusCode,
|
||||
statusName: data.statusName,
|
||||
sort: data.sort ?? 0,
|
||||
status: data.status,
|
||||
initialFlag: data.initialFlag,
|
||||
terminalFlag: data.terminalFlag,
|
||||
allowEdit: data.allowEdit,
|
||||
progressExcludedFlag: data.progressExcludedFlag,
|
||||
allowCreateProject: data.allowCreateProject,
|
||||
allowCreateRequirement: data.allowCreateRequirement,
|
||||
remark: data.remark ?? ''
|
||||
};
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await validate();
|
||||
|
||||
submitting.value = true;
|
||||
|
||||
const submitData: Api.Infra.SaveObjectStatusModelParams = {
|
||||
...model.value,
|
||||
statusCode: model.value.statusCode.trim(),
|
||||
statusName: model.value.statusName.trim(),
|
||||
remark: model.value.remark?.trim() || null
|
||||
};
|
||||
|
||||
let statusModelId = props.rowData?.id ?? '';
|
||||
|
||||
if (isEdit.value && props.rowData) {
|
||||
const { error } = await fetchUpdateObjectStatusModel({ id: props.rowData.id, ...submitData });
|
||||
|
||||
submitting.value = false;
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const { error, data } = await fetchCreateObjectStatusModel(submitData);
|
||||
|
||||
submitting.value = false;
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
statusModelId = data;
|
||||
}
|
||||
|
||||
window.$message?.success(isEdit.value ? '修改成功' : '新增成功');
|
||||
|
||||
closeModal();
|
||||
emit('submitted', statusModelId);
|
||||
}
|
||||
|
||||
watch(visible, value => {
|
||||
if (value) {
|
||||
initModel();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="lg"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="对象类型" prop="objectType">
|
||||
<ElSelect
|
||||
v-model="model.objectType"
|
||||
class="w-full"
|
||||
placeholder="请选择或输入对象类型"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
clearable
|
||||
:reserve-keyword="false"
|
||||
>
|
||||
<ElOption v-for="item in objectTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="状态编码" prop="statusCode">
|
||||
<ElInput v-model="model.statusCode" placeholder="请输入状态编码" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="状态名称" prop="statusName">
|
||||
<ElInput v-model="model.statusName" placeholder="请输入状态名称" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="排序值" prop="sort">
|
||||
<ElInputNumber v-model="model.sort" class="w-full" :min="0" placeholder="请输入排序值" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="配置状态" prop="status">
|
||||
<ElRadioGroup v-model="model.status" class="business-form-radio-group">
|
||||
<ElRadio v-for="{ label, value } in statusOptions" :key="value" :value="value">
|
||||
{{ label }}
|
||||
</ElRadio>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="是否初始状态" prop="initialFlag">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.initialFlag" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.initialFlag ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="是否终态" prop="terminalFlag">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.terminalFlag" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.terminalFlag ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="允许编辑主数据" prop="allowEdit">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.allowEdit" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.allowEdit ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="不参与上层进度统计" prop="progressExcludedFlag">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.progressExcludedFlag" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.progressExcludedFlag ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="允许新建项目" prop="allowCreateProject">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.allowCreateProject" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.allowCreateProject ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="允许新增需求" prop="allowCreateRequirement">
|
||||
<div class="business-form-switch-field">
|
||||
<ElSwitch v-model="model.allowCreateRequirement" />
|
||||
<span class="ml-8px text-12px text-[#606266]">{{ model.allowCreateRequirement ? '是' : '否' }}</span>
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="备注" prop="remark">
|
||||
<ElInput v-model="model.remark" type="textarea" :rows="4" placeholder="请输入备注" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user