Forráskód Böngészése

feat: 审批节点管理页

wyf 9 hónapja
szülő
commit
cba264fd17

+ 110 - 0
mock/approval/approval-node.ts

@@ -0,0 +1,110 @@
+import { resultSuccess } from '../_util';
+
+const list = {
+  records: [
+    {
+      id: 1,
+      approvalTemplateId: 1001,
+      approvalOrder: 1,
+      nodeDescription: '部门经理初审',
+      approverType: 0,
+      approverInfoList: [{ approverId: 101, approverName: '张三' }],
+      approvalType: 0,
+    },
+    {
+      id: 2,
+      approvalTemplateId: 1001,
+      approvalOrder: 2,
+      nodeDescription: '总监审核',
+      approverType: 0,
+      approverInfoList: [{ approverId: 102, approverName: '李四' }],
+      approvalType: 0,
+    },
+    {
+      id: 3,
+      approvalTemplateId: 1001,
+      approvalOrder: 3,
+      nodeDescription: '财务审核',
+      approverType: 0,
+      approverInfoList: [
+        { approverId: 103, approverName: '王五' },
+        { approverId: 104, approverName: '赵六' },
+      ],
+      approvalType: 1,
+    },
+    {
+      id: 4,
+      approvalTemplateId: 1001,
+      approvalOrder: 4,
+      nodeDescription: '人力资源确认',
+      approverType: 0,
+      approverInfoList: [{ approverId: 105, approverName: '孙七' }],
+      approvalType: 0,
+    },
+    {
+      id: 5,
+      approvalTemplateId: 1001,
+      approvalOrder: 5,
+      nodeDescription: '分管副总审批',
+      approverType: 0,
+      approverInfoList: [{ approverId: 106, approverName: '周八' }],
+      approvalType: 0,
+    },
+    {
+      id: 6,
+      approvalTemplateId: 1001,
+      approvalOrder: 6,
+      nodeDescription: '总经理终审',
+      approverType: 0,
+      approverInfoList: [{ approverId: 107, approverName: '吴九' }],
+      approvalType: 0,
+    },
+    {
+      id: 7,
+      approvalTemplateId: 1002,
+      approvalOrder: 1,
+      nodeDescription: '项目经理初审',
+      approverType: 0,
+      approverInfoList: [{ approverId: 201, approverName: '郑十' }],
+      approvalType: 0,
+    },
+    {
+      id: 8,
+      approvalTemplateId: 1002,
+      approvalOrder: 2,
+      nodeDescription: '技术总监审核',
+      approverType: 0,
+      approverInfoList: [{ approverId: 202, approverName: '钱十一' }],
+      approvalType: 0,
+    },
+    {
+      id: 9,
+      approvalTemplateId: 1002,
+      approvalOrder: 3,
+      nodeDescription: '客户确认',
+      approverType: 1,
+      approverInfoList: [],
+    },
+    {
+      id: 10,
+      approvalTemplateId: 1002,
+      approvalOrder: 4,
+      nodeDescription: '归档',
+      approverType: 0,
+      approverInfoList: [{ approverId: 203, approverName: '孙十二' }],
+      approvalType: 0,
+    },
+  ],
+  totalRow: 10,
+};
+
+export default [
+  {
+    url: '/safety_mock_api/approvalManagement/queryApprovalTemplateDetail',
+    timeout: 1000,
+    method: 'post',
+    response: () => {
+      return resultSuccess(list);
+    },
+  },
+];

+ 75 - 0
mock/approval/approval.ts

@@ -0,0 +1,75 @@
+import { resultSuccess } from '../_util';
+
+const list = {
+  records: [
+    {
+      id: 1,
+      templateName: '审批1',
+      description: '审批1描述1242323rw2c3r2c3535c4',
+    },
+    {
+      id: 2,
+      templateName: '审批2',
+    },
+    {
+      id: 3,
+      templateName: '审批3',
+      description: '审批3描述fwq  xc  3er xr  3xr2 rq2x',
+    },
+    {
+      id: 4,
+      templateName: '审批21c q2cr24',
+      description: '审批4描述     1d3x    13  1xx3crdx     r  3',
+    },
+    {
+      id: 5,
+      templateName: '审批5插入2呈现出13传参   23r',
+      description: '审批5描述 23 让传入请人才从1传入吃仍持续  ',
+    },
+    {
+      id: 6,
+      templateName: '审批6',
+      description: '审批描述   23   23   23',
+    },
+    {
+      id: 7,
+      templateName: '审批7',
+      description:
+        '审批7描述   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23',
+    },
+    {
+      id: 8,
+      templateName: '审批8',
+      description:
+        '审批8描述   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23',
+    },
+    {
+      id: 9,
+      templateName: '审批9',
+      description:
+        '审批9描述   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23',
+    },
+    {
+      id: 10,
+      templateName: '审批10',
+    },
+    {
+      id: 11,
+      templateName: '审批11',
+      description:
+        '审批11描述   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23   23',
+    },
+  ],
+  totalRow: 11,
+};
+
+export default [
+  {
+    url: '/safety_mock_api/approvalManagement/queryApprovalTemplatePage',
+    timeout: 1000,
+    method: 'post',
+    response: () => {
+      return resultSuccess(list);
+    },
+  },
+];

+ 57 - 0
src/api/approval/approval.ts

@@ -0,0 +1,57 @@
+import { http } from '@/utils/http/axios';
+import type { QueryPageRequest, QueryPageResponse } from '@/types/basic-query';
+import {
+  ApprovalInstanceType,
+  ApprovalInstanceRuleForm,
+  ApprovalNodeInstanceRuleForm,
+} from '@/views/system/approval/types';
+
+export function getApprovalInstanceList(query: QueryPageRequest<any>) {
+  return http.request<QueryPageResponse<any>>({
+    url: '/approvalManagement/queryApprovalTemplatePage',
+    method: 'post',
+    data: query,
+  });
+}
+
+export function getApprovalNodeInstanceList(id: number) {
+  return http.request<ApprovalInstanceType>({
+    url: `/approvalManagement/queryApprovalTemplateDetail?approvalTemplateId=${id}`,
+    method: 'get',
+  });
+}
+
+export function addApprovalInstance(params: ApprovalInstanceRuleForm) {
+  return http.request({
+    url: '/approvalManagement/saveOrUpdateApprovalTemplate',
+    method: 'post',
+    data: params,
+  });
+}
+
+export function updateApprovalInstance(params: ApprovalInstanceRuleForm) {
+  return addApprovalInstance(params);
+}
+
+export function delApprovalInstance(id: number) {
+  return http.request({
+    url: `/approvalManagement/deleteApprovalTemplate?id=${id}`,
+    method: 'delete',
+  });
+}
+
+export function addApprovalNodeInstance(params: ApprovalNodeInstanceRuleForm) {
+  return http.request({
+    url: '/approvalManagement/saveOrUpdateApprovalNode',
+    method: 'post',
+    data: params,
+  });
+}
+
+export function updateApprovalNodeInstance(params: ApprovalNodeInstanceRuleForm) {
+  return addApprovalNodeInstance(params);
+}
+
+export function updateApprvoerInfo(params: ApprovalNodeInstanceRuleForm) {
+  return addApprovalNodeInstance(params);
+}

+ 1 - 1
src/views/system/person-group/components/PersonGroupFilter.vue

@@ -72,7 +72,7 @@
 <script lang="ts" setup>
   import { ref, onMounted, onBeforeUnmount } from 'vue';
   import { Loading } from '@element-plus/icons-vue';
-  import { usePersonGroupFilter } from '../hooks/usePersonGroupFilter';
+  import { usePersonGroupFilter } from './hooks/usePersonGroupFilter';
   import { PersonGroupItem } from '@/types/person-group/type';
   import { debounce } from 'lodash-es';
 

src/views/system/person-group/hooks/usePersonGroupFilter.ts → src/components/PersonSelector/hooks/usePersonGroupFilter.ts


+ 6 - 4
src/components/UploadLoading.vue

@@ -2,15 +2,16 @@
   <div
     class="upload-loading"
     v-loading="formLoading"
-    element-loading-text="表单上传中。。。"
+    :element-loading-text="loadingText || '表单上传中。。。'"
     element-loading-background="rgba(0,0,0, 0.2)"
   />
 </template>
 
 <script setup lang="ts">
-defineProps<{
-  formLoading: boolean;
-}>();
+  defineProps<{
+    formLoading: boolean;
+    loadingText?: string;
+  }>();
 </script>
 
 <style lang="scss" scoped>
@@ -21,5 +22,6 @@ defineProps<{
     top: 0;
     width: 100vw;
     height: 100vh;
+    z-index: 9999;
   }
 </style>

+ 19 - 1
src/router/routers/platform.ts

@@ -40,8 +40,8 @@ const platformRoutes = {
         {
           // 账号管理
           path: 'account',
-          name: 'UserAccount',
           component: '/system/user/user',
+          name: 'UserAccount',
           meta: {
             icon: '',
             title: '账号管理',
@@ -88,6 +88,24 @@ const platformRoutes = {
         title: '字典管理',
       },
     },
+    {
+      path: 'approval',
+      name: 'SystemApproval',
+      component: '/system/approval/PageApproval',
+      meta: {
+        icon: 'UserOutlined',
+        title: '审批管理',
+      },
+    },
+    {
+      path: 'approval-node',
+      name: 'SystemApprovalNode',
+      component: '/system/approval/PageApprovalNode',
+      meta: {
+        icon: 'UserOutlined',
+        title: '编辑审批流程',
+      },
+    },
   ],
 };
 

+ 99 - 0
src/views/system/approval/PageApproval.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="safety-platform-container">
+    <header class="safety-platform-container__header">
+      <div class="breadcrumb-title"> 审批管理 </div>
+    </header>
+    <main class="safety-platform-container__main">
+      <div class="search-table-container">
+        <header>
+          <el-button type="primary" @click="handleCreateApproval" :icon="Plus">添加审批流程</el-button>
+        </header>
+        <BasicTable
+          :tableConfig="tableConfig"
+          :tableData="tableData"
+          @update:pageSize="handleSizeChange"
+          @update:pageNumber="handleCurrentChange"
+        >
+          <template #action="scope">
+            <ActionButton text="设置审批流程" @click="handleEditApproval(scope.row.id)" />
+            <ActionButton
+              text="删除"
+              :popconfirm="{
+                title: '确定要删除?',
+              }"
+              @confirm="handleDeleteApproval(scope.row.id)"
+            />
+          </template>
+        </BasicTable>
+      </div>
+    </main>
+  </div>
+  <ApprovalCreateDialog ref="approvalCreateDialogRef" @success="getTabelData" />
+</template>
+
+<script setup lang="ts">
+  import { Plus } from '@element-plus/icons-vue';
+  import BasicTable from '@/components/BasicTable.vue';
+  import ActionButton from '@/components/ActionButton.vue';
+  import useTableConfig from '@/hooks/useTableConfigHook';
+  import { TABLE_OPTIONS, APPROVAL_TABLE_COLUMNS } from './config/table';
+  import { onMounted, ref } from 'vue';
+  import { getApprovalInstanceList, delApprovalInstance } from '@/api/approval/approval';
+  import { useRouter } from 'vue-router';
+  import { ApprovalInstanceType } from './types';
+  import ApprovalCreateDialog from './components/ApprovalCreateDialog.vue';
+
+  const router = useRouter();
+
+  const { tableConfig, pagination } = useTableConfig(APPROVAL_TABLE_COLUMNS, TABLE_OPTIONS);
+
+  const tabelQuery = ref({
+    pageNumber: pagination.pageNumber,
+    pageSize: pagination.pageSize,
+    queryParam: undefined,
+  });
+
+  const tableData = ref<ApprovalInstanceType[]>([]);
+  const handleSizeChange = () => {};
+  const handleCurrentChange = () => {};
+  async function getTabelData() {
+    tableConfig.loading = true;
+
+    const res = await getApprovalInstanceList(tabelQuery.value);
+    tableData.value = res.records;
+    pagination.total = res.totalRow;
+    tableConfig.loading = false;
+  }
+
+  onMounted(() => {
+    getTabelData();
+  });
+
+  const approvalCreateDialogRef = ref<InstanceType<typeof ApprovalCreateDialog>>();
+  const handleCreateApproval = () => {
+    approvalCreateDialogRef.value?.openDialog();
+  };
+
+  const handleEditApproval = (id: number) => {
+    router.push({
+      name: 'SystemApprovalNode',
+      query: {
+        id,
+      },
+    });
+  };
+  const handleDeleteApproval = async (id: number) => {
+    try {
+      tableConfig.loading = true;
+      await delApprovalInstance(id);
+      getTabelData();
+    } catch (e) {
+      console.log(e);
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  @use '@/styles/page-details-layout.scss' as *;
+  @use '@/styles/page-main-layout.scss' as *;
+</style>

+ 172 - 0
src/views/system/approval/PageApprovalNode.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="safety-platform-container">
+    <header class="safety-platform-container__header">
+      <BreadcrumbBack />
+      <span class="breadcrumb-title">{{ '编辑审批流程' }}</span>
+    </header>
+    <main class="safety-platform-container__main">
+      <div class="approval-node-container">
+        <div class="approval-node-container__title">流程模板信息</div>
+        <BasicForm
+          style="height: auto"
+          ref="basicFormRef"
+          :formData="ruleFormData"
+          :formRules="formRules"
+          :formConfig="ruleFormConfig"
+        >
+        </BasicForm>
+        <div class="approval-node-container__button">
+          <el-button type="primary" @click="handleEditApproval">保存</el-button>
+        </div>
+        <div class="approval-node-container__title">审批流程设置</div>
+        <div class="approval-node-container__button" style="">
+          <el-button type="primary" @click="handleCreateApprovalNode" :icon="Plus">添加审批节点</el-button>
+        </div>
+        <div style="flex-grow: 1">
+          <BasicTable :tableConfig="tableConfig" :tableData="tableData">
+            <template #approverType="scope">
+              <span> {{ APPROVER_TYPE_MAP[scope.row.approverType] }}</span>
+            </template>
+            <template #approvalType="scope">
+              <span> {{ APPROVAL_TYPE_MAP[scope.row.approvalType] }}</span>
+            </template>
+            <template #action="scope">
+              <ActionButton text="编辑节点" @click="handleEditApprovalNode(scope.row)" />
+              <ActionButton
+                v-if="scope.row.approverType === 0"
+                text="选择审批人"
+                @click="handleOpenAppoverSelect(scope.row)"
+              />
+              <ActionButton
+                text="删除节点"
+                :popconfirm="{
+                  title: '确定要删除?',
+                }"
+                @confirm="handleDeleteNode(scope.row.id)"
+              />
+            </template>
+          </BasicTable>
+        </div>
+      </div>
+    </main>
+    <ApproverSelectDialog ref="approverSelectDialogRef" />
+    <ApprovalNodeCreateDialog ref="approvalNodeCreateDialogRef" />
+    <UploadLoading loading-text="加载中" :form-loading="formLoading" v-if="formLoading" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { useRoute } from 'vue-router';
+  import { ElMessage } from 'element-plus';
+  import { Plus } from '@element-plus/icons-vue';
+  import { onMounted, ref } from 'vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import UploadLoading from '@/components/UploadLoading.vue';
+  import BasicForm from '@/components/BasicForm.vue';
+  import ActionButton from '@/components/ActionButton.vue';
+  import BasicTable from '@/components/BasicTable.vue';
+  import { ApprovalInstanceRuleForm, ApprovalNodeInstanceType } from './types';
+  import { APPROVAL_FORM_CONFIG, APPROVAL_FORM_DATA, APPROVAL_FORM_RULES } from './config/form';
+  import useTableConfig from '@/hooks/useTableConfigHook';
+  import { APPROVAL_NODE_TABLE_COLUMNS, NODE_TABLE_OPTIONS } from './config/table';
+  import { APPROVER_TYPE_MAP, APPROVAL_TYPE_MAP } from './constants';
+  import ApproverSelectDialog from './components/ApproverSelectDialog.vue';
+  import ApprovalNodeCreateDialog from './components/ApprovalNodeCreateDialog.vue';
+  import { getApprovalNodeInstanceList } from '@/api/approval/approval';
+  import { updateApprovalInstance } from '@/api/approval/approval';
+  import { queryUserInfoByIds } from '@/api/system/person-group';
+
+  const route = useRoute();
+
+  const id = route.query.id;
+  const approvalInstance = ref<ApprovalInstanceRuleForm>();
+
+  const formLoading = ref(false);
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+  const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
+    useFormConfigHook<ApprovalInstanceRuleForm>(APPROVAL_FORM_CONFIG, APPROVAL_FORM_DATA, APPROVAL_FORM_RULES);
+  function initForm(initData: ApprovalInstanceRuleForm) {
+    ruleFormData.id = initData.id;
+    ruleFormData.templateName = initData.templateName;
+    ruleFormData.description = initData.description;
+  }
+
+  const { tableConfig } = useTableConfig(APPROVAL_NODE_TABLE_COLUMNS, NODE_TABLE_OPTIONS, false);
+  const tableData = ref<ApprovalNodeInstanceType[]>([]);
+
+  async function getTabelData() {
+    tableConfig.loading = true;
+    approvalInstance.value = await getApprovalNodeInstanceList(Number(id));
+    tableData.value = approvalInstance.value.approvalNodeInfoList!;
+    tableData.value.forEach((item) => {
+      item.approverNameList = item.approverInfoList.map((item) => item.approverName).join(',');
+    });
+    tableConfig.loading = false;
+  }
+
+  onMounted(async () => {
+    formLoading.value = true;
+    await getTabelData();
+    initForm(approvalInstance.value!);
+    cloneRuleFormData();
+    beforeRouteLeave();
+    formLoading.value = false;
+  });
+
+  const handleEditApproval = async () => {
+    const validate = await basicFormRef.value?.validateForm();
+    if (!validate) return;
+    // 提交表单接口
+    try {
+      formLoading.value = true;
+      await updateApprovalInstance(ruleFormData);
+      formLoading.value = false;
+      ElMessage.success('提交成功');
+      cloneRuleFormData();
+    } catch (e) {
+      console.log(e);
+    }
+  };
+
+  const approvalNodeCreateDialogRef = ref();
+  const handleCreateApprovalNode = () => {
+    approvalNodeCreateDialogRef.value.initForm(true, { approvalTemplateId: id });
+    approvalNodeCreateDialogRef.value.openDialog();
+  };
+  const handleEditApprovalNode = (row: ApprovalNodeInstanceType) => {
+    console.log(row);
+    // approvalNodeCreateDialogRef.value.initForm(false, row);
+    // approvalNodeCreateDialogRef.value.openDialog();
+  };
+
+  const approverSelectDialogRef = ref();
+  const handleOpenAppoverSelect = async (node: ApprovalNodeInstanceType) => {
+    if (approverSelectDialogRef.value) {
+      const res = await queryUserInfoByIds(node.approverInfoList.map((x) => x.approverId));
+      approverSelectDialogRef.value.setSelectedUser(res);
+      approverSelectDialogRef.value.openDialog();
+    }
+  };
+  const handleDeleteNode = (id: number) => {};
+</script>
+
+<style lang="scss" scoped>
+  @use '@/styles/page-details-layout.scss' as *;
+  .safety-platform-container__header {
+    flex-direction: row !important;
+    justify-content: flex-start !important;
+    gap: 8px !important;
+  }
+  .approval-node-container {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+  }
+  .approval-node-container__title {
+    margin: 5px 0 10px;
+  }
+  .approval-node-container__button {
+    text-align: start;
+    margin: 10px 0 20px;
+  }
+</style>

+ 61 - 0
src/views/system/approval/components/ApprovalCreateDialog.vue

@@ -0,0 +1,61 @@
+<template>
+  <BasicDialog ref="basicDialogRef" title="添加审批流程" @refresh="refreshFromData">
+    <template #form>
+      <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig" />
+    </template>
+    <template #footer>
+      <el-button type="primary" @click="handleSumbit">提交</el-button>
+      <el-button @click="basicDialogRef?.closeDialog">取消</el-button>
+    </template>
+  </BasicDialog>
+  <UploadLoading :form-loading="formLoading" v-if="formLoading" />
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import BasicDialog from '@/components/BasicDialog.vue';
+  import BasicForm from '@/components/BasicForm.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import { ApprovalInstanceRuleForm } from '../types';
+  import { APPROVAL_FORM_CONFIG, APPROVAL_FORM_DATA, APPROVAL_FORM_RULES } from '../config/form';
+  import { addApprovalInstance } from '@/api/approval/approval';
+  import UploadLoading from '@/components/UploadLoading.vue';
+
+  const basicDialogRef = ref<InstanceType<typeof BasicDialog>>();
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+  const { ruleFormConfig, ruleFormData, formRules } = useFormConfigHook<ApprovalInstanceRuleForm>(
+    APPROVAL_FORM_CONFIG,
+    APPROVAL_FORM_DATA,
+    APPROVAL_FORM_RULES,
+  );
+  const formLoading = ref(false);
+
+  const emits = defineEmits<{
+    (e: 'success'): void;
+  }>();
+  const openDialog = () => {
+    basicDialogRef.value?.openDialog();
+  };
+  const handleSumbit = async () => {
+    const validate = await basicFormRef.value?.validateForm();
+    if (!validate) return;
+    // 提交表单接口
+    try {
+      formLoading.value = true;
+      await addApprovalInstance(ruleFormData);
+      emits('success');
+      formLoading.value = false;
+      basicDialogRef.value?.closeDialog();
+    } catch (e) {
+      console.log(e);
+    }
+  };
+  const refreshFromData = () => {
+    basicFormRef.value?.clearValidate();
+  };
+  defineExpose({
+    openDialog,
+  });
+</script>
+
+<style scoped lang="scss"></style>

+ 73 - 0
src/views/system/approval/components/ApprovalNodeCreateDialog.vue

@@ -0,0 +1,73 @@
+<template>
+  <BasicDialog ref="basicDialogRef" :title="dialogTitle + '审批节点'" @refresh="refreshFromData">
+    <template #form>
+      <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig" />
+    </template>
+    <template #footer>
+      <el-button type="primary" @click="handleSumbit">提交</el-button>
+      <el-button @click="basicDialogRef?.closeDialog">取消</el-button>
+    </template>
+  </BasicDialog>
+  <UploadLoading :form-loading="formLoading" v-if="formLoading" />
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import BasicDialog from '@/components/BasicDialog.vue';
+  import BasicForm from '@/components/BasicForm.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import { ApprovalNodeInstanceRuleForm } from '../types';
+  import { APPROVAL_NODE_FORM_CONFIG, APPROVAL_NODE_FORM_DATA, APPROVAL_NODE_FORM_RULES } from '../config/form';
+  import { addApprovalNodeInstance } from '@/api/approval/approval';
+  import UploadLoading from '@/components/UploadLoading.vue';
+
+  const basicDialogRef = ref<InstanceType<typeof BasicDialog>>();
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+  const { ruleFormConfig, ruleFormData, formRules } = useFormConfigHook<ApprovalNodeInstanceRuleForm>(
+    APPROVAL_NODE_FORM_CONFIG,
+    APPROVAL_NODE_FORM_DATA,
+    APPROVAL_NODE_FORM_RULES,
+  );
+
+  const dialogTitle = ref();
+  const formLoading = ref(false);
+
+  function initForm(isCreate: boolean, initData?: ApprovalNodeInstanceRuleForm) {
+    ruleFormData.approvalTemplateId = initData?.approvalTemplateId;
+    if (isCreate) {
+      dialogTitle.value = '添加';
+      return;
+    }
+    if (!initData) return;
+    dialogTitle.value = '编辑';
+    ruleFormData.id = initData.id;
+  }
+
+  const emits = defineEmits<{
+    (e: 'success'): void;
+  }>();
+  const openDialog = () => {
+    basicDialogRef.value?.openDialog();
+  };
+  const handleSumbit = async () => {
+    const validate = await basicFormRef.value?.validateForm();
+    if (!validate) return;
+    // 提交表单接口
+    try {
+      await addApprovalNodeInstance(ruleFormData);
+      emits('success');
+      basicDialogRef.value?.closeDialog();
+    } catch (e) {
+      console.log(e);
+    }
+  };
+  const refreshFromData = () => {
+    basicFormRef.value?.clearValidate();
+  };
+  defineExpose({
+    initForm,
+    openDialog,
+  });
+</script>
+
+<style scoped lang="scss"></style>

+ 53 - 0
src/views/system/approval/components/ApproverSelectDialog.vue

@@ -0,0 +1,53 @@
+<template>
+  <el-dialog
+    v-model="dialogOpened"
+    title="选择审批人"
+    align-center
+    :close-on-click-modal="false"
+    style="height: 583px"
+    :width="731"
+    :destroy-on-close="true"
+    class="workShopDialog"
+  >
+    <PersonGroupFilter
+      ref="dialogInstance"
+      :init-selected="selectedUser"
+      @cancel="handlePersonDialogCancle"
+      @submit="handlePersonDialogSubmit"
+    />
+  </el-dialog>
+</template>
+
+<script lang="ts" setup>
+  import PersonGroupFilter from '@/components/PersonSelector/PersonGroupFilter.vue';
+  import { ref } from 'vue';
+  import { PersonGroupItem } from '@/types/person-group/type';
+
+  const dialogOpened = ref(false);
+
+  const selectedUser = ref<PersonGroupItem[]>([]);
+
+  const handlePersonDialogCancle = () => {
+    dialogOpened.value = false;
+  };
+  const handlePersonDialogSubmit = (selectedData: PersonGroupItem[]) => {
+    selectedUser.value = selectedData;
+    console.log(selectedUser.value);
+    dialogOpened.value = false;
+  };
+
+  function openDialog() {
+    dialogOpened.value = true;
+  }
+
+  function setSelectedUser(selectedData: PersonGroupItem[]) {
+    selectedUser.value = selectedData;
+  }
+
+  defineExpose({
+    openDialog,
+    setSelectedUser,
+  });
+</script>
+
+<style scoped></style>

+ 115 - 0
src/views/system/approval/config/form.ts

@@ -0,0 +1,115 @@
+/**
+ * 审批流程表单配置
+ */
+
+import { FormConfig } from '@/types/basic-form';
+
+export const APPROVAL_FORM_CONFIG: FormConfig[] = [
+  {
+    label: '审批流程名称:',
+    prop: 'templateName',
+    component: 'ElInput',
+    componentProps: { placeholder: '请输入审批流程名称' },
+  },
+  {
+    label: '审批流程描述:',
+    prop: 'description',
+    component: 'ElInput',
+    componentProps: { placeholder: '请输入审批流程描述' },
+  },
+];
+
+export const APPROVAL_FORM_DATA = {
+  templateName: '',
+  description: '',
+};
+
+export const APPROVAL_FORM_RULES = {
+  templateName: [{ required: true, message: '请输入审批流程名称', trigger: 'blur' }],
+};
+
+export const APPROVAL_NODE_FORM_CONFIG: FormConfig[] = [
+  {
+    label: '节点描述:',
+    prop: 'nodeDescription',
+    component: 'ElInput',
+    componentProps: { placeholder: '请输入节点描述' },
+  },
+  {
+    label: '审批人选择方式:',
+    prop: 'approverType',
+    component: 'ElSelect',
+    selectOptions: [
+      {
+        label: '自选',
+        value: 0,
+      },
+      {
+        label: '固定',
+        value: 1,
+      },
+    ],
+  },
+  {
+    label: '审批方式:',
+    prop: 'approvalType',
+    component: 'ElSelect',
+    selectOptions: [
+      {
+        label: '会签',
+        value: 0,
+      },
+      {
+        label: '或签',
+        value: 1,
+      },
+    ],
+  },
+  {
+    label: '审批节点顺序:',
+    prop: 'approvalOrder',
+    component: 'ElInputNumber',
+    componentProps: {
+      min: 1,
+    },
+  },
+];
+
+export const APPROVAL_NODE_FORM_DATA = {
+  approvalTemplateId: undefined,
+  nodeDescription: '',
+  approvalType: undefined,
+  approverType: undefined,
+  approvalOrder: undefined,
+};
+
+export const APPROVAL_NODE_FORM_RULES = {
+  nodeDescription: [
+    {
+      required: true,
+      message: '请输入节点描述',
+      trigger: 'blur',
+    },
+  ],
+  approverType: [
+    {
+      required: true,
+      message: '请选择审批人选择方式',
+      trigger: 'change',
+    },
+  ],
+  approvalType: [
+    {
+      required: true,
+      message: '请选择审批方式',
+      trigger: 'change',
+    },
+  ],
+  approvalOrder: [
+    {
+      required: true,
+      message: '请输入审批节点顺序',
+      trigger: 'blur',
+    },
+  ],
+};

+ 88 - 0
src/views/system/approval/config/table.ts

@@ -0,0 +1,88 @@
+/**
+ * 审批管理表格配置
+ */
+import type { TableColumnProps } from '@/types/basic-table';
+
+// 基础表格样式配置
+export const TABLE_OPTIONS = {
+  emptyText: '暂无数据',
+  loading: true,
+  height: 'calc(70vh - 50px)',
+};
+
+export const NODE_TABLE_OPTIONS = {
+  emptyText: '暂无数据',
+  loading: true,
+  height: 'calc(70vh - 220px)',
+};
+
+export const APPROVAL_TABLE_COLUMNS: TableColumnProps[] = [
+  {
+    prop: 'id',
+    label: '序号',
+    align: 'center',
+    width: '150px',
+  },
+  {
+    prop: 'templateName',
+    label: '审批流程名称',
+    minWidth: '200px',
+    align: 'center',
+  },
+  {
+    prop: 'description',
+    label: '审批流程描述',
+    align: 'center',
+    minWidth: '800px',
+  },
+  {
+    prop: 'action',
+    label: '操作',
+    slot: 'action',
+    fixed: 'right',
+    width: '200px',
+    align: 'center',
+  },
+];
+
+export const APPROVAL_NODE_TABLE_COLUMNS: TableColumnProps[] = [
+  {
+    prop: 'approvalOrder',
+    label: '审批顺序',
+    width: '100px',
+    align: 'center',
+  },
+  {
+    prop: 'nodeDescription',
+    label: '节点描述',
+    minWidth: '200px',
+    align: 'center',
+  },
+  {
+    prop: 'approverType',
+    label: '审批人选择方式',
+    width: '100px',
+    align: 'center',
+    slot: 'approverType',
+  },
+  {
+    prop: 'approverNameList',
+    label: '审批人',
+    align: 'center',
+  },
+  {
+    prop: 'approvalType',
+    label: '审批方式',
+    width: '100px',
+    align: 'center',
+    slot: 'approvalType',
+  },
+  {
+    prop: 'action',
+    label: '操作',
+    slot: 'action',
+    fixed: 'right',
+    width: '200px',
+    align: 'center',
+  },
+];

+ 9 - 0
src/views/system/approval/constants.ts

@@ -0,0 +1,9 @@
+export const APPROVER_TYPE_MAP = {
+  0: '固定',
+  1: '自选',
+};
+
+export const APPROVAL_TYPE_MAP = {
+  0: '会签',
+  1: '或签',
+};

+ 33 - 0
src/views/system/approval/types.ts

@@ -0,0 +1,33 @@
+type MakeOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
+
+export interface ApprovalInstanceType {
+  id: number;
+  templateName: string;
+  description?: string;
+  approvalNodeInfoList?: ApprovalNodeInstanceType[];
+}
+
+export interface ApprovalInstanceRuleForm extends MakeOptional<ApprovalInstanceType, 'id'> {}
+
+export interface ApprovalNodeInstanceType {
+  id: number;
+  approvalTemplateId: number;
+  nodeDescription: string;
+  approvalOrder: number;
+  approverType: number; // 审批人选择方式: 0-固定,1-自选
+  approvalType: number; // 审批方式: 0-会签,1-或签
+
+  approverInfoList: {
+    approverId: number;
+    approverName: string;
+  }[];
+
+  approverList?: string;
+  approverNameList?: string;
+}
+
+export interface ApprovalNodeInstanceRuleForm
+  extends MakeOptional<
+    Omit<ApprovalNodeInstanceType, 'approverInfoList' | 'approverNameList'>,
+    'id' | 'approvalTemplateId' | 'approvalOrder' | 'nodeDescription' | 'approverType' | 'approvalType'
+  > {}

+ 3 - 0
src/views/system/approval/utils.ts

@@ -0,0 +1,3 @@
+export function refineNameList(list: any[], key: string) {
+  return list.map((x) => x[key]).join(',');
+}

+ 0 - 18
src/views/system/authorization/Authorization.vue

@@ -1,18 +0,0 @@
-<template>
-  <div class="safety-platform-container">
-    <header class="safety-platform-container__header">
-      <div class="breadcrumb-title"> 审批管理 </div>
-    </header>
-    <main class="safety-platform-container__main">
-      <AuthorizationList />
-    </main>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import AuthorizationList from './components/AuthorizationList.vue';
-</script>
-
-<style lang="scss" scoped>
-  @use '@/styles/page-details-layout.scss' as *;
-</style>

+ 0 - 12
src/views/system/authorization/components/AuthorizationList.vue

@@ -1,12 +0,0 @@
-<template>
-  <div class="authorization-list">
-    <el-button type="primary" @click="handleCreateAuthorizationList" :icon="Plus">添加审批流程</el-button>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { Plus } from '@element-plus/icons-vue';
-  const handleCreateAuthorizationList = () => {};
-</script>
-
-<style scoped></style>

+ 1 - 1
src/views/system/person-group/components/PersonGroupEditDrawer.vue

@@ -81,7 +81,7 @@
   import { addUserGroup, modifyUserGroup, queryUserGroupDetail } from '@/api/system/person-group';
   import { FormRules, FormInstance, ElMessage } from 'element-plus';
   import { useUserStore } from '@/store/modules/user';
-  import PersonGroupFilter from './PersonGroupFilter.vue';
+  import PersonGroupFilter from '@/components/PersonSelector/PersonGroupFilter.vue';
   import { storeToRefs } from 'pinia';
 
   defineProps<{

+ 2 - 1
utils/devProxy/staff/proxy.ts

@@ -3,7 +3,8 @@ import path from 'path';
 
 // staff环境
 const proxyStaff: PROXY_TYPE = {
-  serverHost: 'http://192.168.13.68:8802/',
+  // serverHost: 'http://192.168.13.68:8802/',
+  serverHost: 'http://192.168.22.146:8802/',
   // serverHost: 'http://192.168.22.146:8802/',
   loginHost: 'http://192.168.13.68:7200/login/#/',
   fileUploadHost: 'http://192.168.13.102:9000/',