Files
EasyFlow/easyflow-ui-admin/app/src/views/ai/workflow/WorkflowModal.vue
陈子默 22ceabff96 feat: 增加工作流和知识库三级权限
- 抽取统一资源访问骨架与部门可见范围判断

- 接入工作流和知识库的 READ/MANAGE 权限校验

- 增加可见范围配置与只读态前端交互
2026-03-29 17:25:55 +08:00

256 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { FormInstance, UploadInstance, UploadProps } from 'element-plus';
import { computed, onMounted, ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import {
ElForm,
ElFormItem,
ElInput,
ElMessage,
ElOption,
ElSelect,
ElUpload,
} from 'element-plus';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
// import Cropper from '#/components/upload/Cropper.vue';
import UploadAvatar from '#/components/upload/UploadAvatar.vue';
import { $t } from '#/locales';
import { syncProgrammaticFieldValidation } from '#/utils/form-validation';
const emit = defineEmits(['reload']);
// vue
onMounted(() => {});
defineExpose({
openDialog,
});
const saveForm = ref<FormInstance>();
// variables
const dialogVisible = ref(false);
const isAdd = ref(true);
const isImport = ref(false);
const jsonFile = ref<any>(null);
const uploadFileList = ref<any[]>([]);
const uploadRef = ref<UploadInstance>();
const createDefaultEntity = () => ({
alias: '',
deptId: '',
title: '',
description: '',
icon: '',
content: '',
englishName: '',
visibilityScope: 'PRIVATE',
});
const entity = ref<any>(createDefaultEntity());
const btnLoading = ref(false);
const visibilityScopeOptions = computed(() => [
{
label: $t('aiWorkflow.visibilityScopePrivate'),
value: 'PRIVATE',
},
{
label: $t('aiWorkflow.visibilityScopeDept'),
value: 'DEPT',
},
{
label: $t('aiWorkflow.visibilityScopePublic'),
value: 'PUBLIC',
},
]);
const jsonFileModel = computed({
get: () => (uploadFileList.value.length > 0 ? uploadFileList.value[0] : null),
set: (value: any) => {
if (!value) {
uploadFileList.value = [];
}
},
});
const rules = computed(() => ({
title: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
...(isImport.value && {
jsonFile: [
{ required: true, message: $t('message.required'), trigger: 'change' },
],
}),
}));
// functions
function openDialog(row: any, importMode = false) {
isImport.value = importMode;
isAdd.value = !row?.id;
entity.value = {
...createDefaultEntity(),
...(row || {}),
};
dialogVisible.value = true;
}
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
jsonFile.value = file;
uploadFileList.value = [file];
syncProgrammaticFieldValidation(saveForm, ['jsonFile']);
return false;
};
const handleChange: UploadProps['onChange'] = (file, fileList) => {
jsonFile.value = file.raw;
uploadFileList.value = fileList.slice(-1);
syncProgrammaticFieldValidation(saveForm, ['jsonFile']);
};
const handleRemove: UploadProps['onRemove'] = () => {
jsonFile.value = null;
uploadFileList.value = [];
syncProgrammaticFieldValidation(saveForm, ['jsonFile']);
};
function save() {
saveForm.value?.validate((valid) => {
if (valid) {
btnLoading.value = true;
if (isImport.value) {
const formData = new FormData();
formData.append('jsonFile', jsonFile.value!);
Object.keys(entity.value).forEach((key) => {
if (entity.value[key] !== null && entity.value[key] !== undefined) {
formData.append(key, entity.value[key]);
}
});
api
.post('/api/v1/workflow/importWorkFlow', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then((res) => {
btnLoading.value = false;
if (res.errorCode === 0) {
ElMessage.success(res.message);
emit('reload');
closeDialog();
}
})
.catch(() => {
btnLoading.value = false;
});
} else {
api
.post(
isAdd.value ? '/api/v1/workflow/save' : '/api/v1/workflow/update',
entity.value,
)
.then((res) => {
btnLoading.value = false;
if (res.errorCode === 0) {
ElMessage.success(res.message);
emit('reload');
closeDialog();
}
})
.catch(() => {
btnLoading.value = false;
});
}
}
});
}
function closeDialog() {
saveForm.value?.resetFields();
uploadRef.value?.clearFiles();
uploadFileList.value = [];
jsonFile.value = null;
isAdd.value = true;
isImport.value = false;
entity.value = createDefaultEntity();
dialogVisible.value = false;
}
</script>
<template>
<EasyFlowFormModal
v-model:open="dialogVisible"
:title="
isImport
? $t('button.import')
: isAdd
? $t('button.add')
: $t('button.edit')
"
:before-close="closeDialog"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
width="xl"
@confirm="save"
>
<ElForm
ref="saveForm"
:model="isImport ? { ...entity, jsonFile: jsonFileModel } : entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem v-if="isImport" prop="jsonFile" label="JSON文件" required>
<ElUpload
class="w-full"
ref="uploadRef"
v-model:file-list="uploadFileList"
:limit="1"
:auto-upload="false"
:on-change="handleChange"
:before-upload="beforeUpload"
:on-remove="handleRemove"
accept=".json"
drag
>
<div class="el-upload__text w-full">
json 文件拖到此处<em>点击上传</em>
</div>
</ElUpload>
</ElFormItem>
<ElFormItem prop="icon" :label="$t('aiWorkflow.icon')">
<!-- <Cropper v-model="entity.icon" crop /> -->
<UploadAvatar v-model="entity.icon" />
</ElFormItem>
<ElFormItem prop="title" :label="$t('aiWorkflow.title')">
<ElInput v-model.trim="entity.title" />
</ElFormItem>
<ElFormItem prop="categoryId" :label="$t('aiWorkflow.categoryId')">
<DictSelect
v-model="entity.categoryId"
dict-code="aiWorkFlowCategory"
/>
</ElFormItem>
<ElFormItem
prop="visibilityScope"
:label="$t('aiWorkflow.visibilityScope')"
>
<ElSelect v-model="entity.visibilityScope" class="w-full">
<ElOption
v-for="item in visibilityScopeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</ElSelect>
</ElFormItem>
<ElFormItem prop="alias" :label="$t('aiWorkflow.alias')">
<ElInput v-model.trim="entity.alias" />
</ElFormItem>
<ElFormItem prop="englishName" :label="$t('aiWorkflow.englishName')">
<ElInput v-model.trim="entity.englishName" />
</ElFormItem>
<ElFormItem prop="description" :label="$t('aiWorkflow.description')">
<ElInput v-model.trim="entity.description" />
</ElFormItem>
<ElFormItem prop="status" :label="$t('aiWorkflow.status')">
<DictSelect v-model="entity.status" dict-code="showOrNot" />
</ElFormItem>
</ElForm>
</EasyFlowFormModal>
</template>
<style scoped></style>