Selaa lähdekoodia

新增审批界面

695593266@qq.com 1 kuukausi sitten
vanhempi
commit
ea750d2ea1

+ 16 - 0
src/api/bpm/components/demandApplication/index.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request';
+
+const BASE_URL = '/aps/demandapply';
+
+function resolveResponse(res) {
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message || '请求失败'));
+}
+
+/** 获取需求申请单详情 */
+export async function getDetail(id) {
+  const res = await request.get(`${BASE_URL}/getById/${id}`);
+  return resolveResponse(res);
+}

+ 54 - 0
src/views/bpm/handleTask/components/customApproval/detailDialog.vue

@@ -0,0 +1,54 @@
+<template>
+  <div class="custom-approval-detail">
+    <el-descriptions :column="2" border>
+      <el-descriptions-item label="业务编号">
+        {{ businessCode || '-' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="业务类型">
+        {{ businessType || '-' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="业务ID">
+        {{ businessId || '-' }}
+      </el-descriptions-item>
+      <el-descriptions-item label="任务节点">
+        {{ taskDefinitionKey || '-' }}
+      </el-descriptions-item>
+    </el-descriptions>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'CustomApprovalDetail',
+    props: {
+      taskDefinitionKey: {
+        type: String,
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      businessId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      businessCode: {
+        default: ''
+      },
+      processDefinitionId: {
+        default: ''
+      },
+      businessType: {
+        default: ''
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .custom-approval-detail {
+    padding: 10px 0;
+  }
+</style>

+ 173 - 0
src/views/bpm/handleTask/components/customApproval/submit.vue

@@ -0,0 +1,173 @@
+<template>
+  <el-col :span="16" :offset="6" v-loading="isSaveLoading">
+    <el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
+      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+        <el-input
+          type="textarea"
+          v-model="form.reason"
+          placeholder="请输入审批建议"
+        />
+      </el-form-item>
+    </el-form>
+    <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+      <el-button
+        icon="el-icon-edit-outline"
+        type="success"
+        size="mini"
+        v-click-once
+        :loading="isSaveLoading"
+        @click="handleAudit(1)"
+        >通过
+      </el-button>
+
+      <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        v-click-once
+        :loading="isSaveLoading"
+        @click="handleAudit(0)"
+        >驳回
+      </el-button>
+
+      <el-dropdown
+        @command="(command) => handleCommand(command)"
+        style="margin-left: 30px"
+      >
+        <span class="el-dropdown-link">
+          更多<i class="el-icon-arrow-down el-icon--right"></i>
+        </span>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="transfer">转办</el-dropdown-item>
+          <el-dropdown-item command="back">退回</el-dropdown-item>
+          <el-dropdown-item command="cancel">作废</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  import {
+    approveTaskWithVariables,
+    rejectTask,
+    cancelTask
+  } from '@/api/bpm/task';
+
+  export default {
+    name: 'CustomApprovalSubmit',
+    props: {
+      businessId: {
+        default: ''
+      },
+      businessCode: {
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      taskDefinitionKey: {
+        default: ''
+      },
+      fromUser: {
+        default: ''
+      },
+      businessType: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        form: {
+          reason: '同意'
+        },
+        rules: {
+          reason: [
+            {
+              required: true,
+              message: '请输入审批建议',
+              trigger: 'blur'
+            }
+          ]
+        },
+        isSaveLoading: false
+      };
+    },
+    methods: {
+      handleAudit(status) {
+        this.$refs.formRef.validate((valid) => {
+          if (!valid) {
+            return;
+          }
+          this.approveTask(status);
+        });
+      },
+      async approveTask(status) {
+        const API = status ? approveTaskWithVariables : rejectTask;
+        this.isSaveLoading = true;
+        try {
+          const res = await API({
+            id: this.taskId,
+            reason: this.form.reason,
+            variables: {
+              pass: !!status
+            }
+          });
+          if (res.data.code != '-1') {
+            this.$emit('handleAudit', {
+              status,
+              title: status === 0 ? '驳回' : ''
+            });
+          }
+        } finally {
+          this.isSaveLoading = false;
+        }
+      },
+      handleCommand(command) {
+        if (command === 'transfer') {
+          this.$emit('handleUpdateAssignee');
+          return;
+        }
+        if (command === 'back') {
+          this.$emit('handleBackList');
+          return;
+        }
+        if (command === 'cancel') {
+          this.cancelTask();
+        }
+      },
+      cancelTask() {
+        this.$confirm('是否确认作废?', {
+          type: 'warning',
+          cancelButtonText: '取消',
+          confirmButtonText: '确定'
+        })
+          .then(() => {
+            this.isSaveLoading = true;
+            return cancelTask({
+              id: this.id,
+              taskId: this.taskId,
+              reason: this.form.reason,
+              businessId: this.businessId
+            });
+          })
+          .then(() => {
+            this.$emit('handleClose');
+          })
+          .catch((error) => {
+            if (error !== 'cancel') {
+              this.$message.error('流程作废失败');
+            }
+          })
+          .finally(() => {
+            this.isSaveLoading = false;
+          });
+      }
+    }
+  };
+</script>
+
+<style lang="scss"></style>

+ 397 - 0
src/views/bpm/handleTask/components/demandApplication/detailDialog.vue

@@ -0,0 +1,397 @@
+<template>
+  <div class="demand-application-detail" v-loading="loading">
+    <div class="detail-overview">
+      <div class="overview-identity">
+        <div class="overview-icon">
+          <i class="el-icon-document"></i>
+        </div>
+        <div>
+          <div class="overview-label">申请单详情</div>
+          <div class="overview-code">{{ form.applyCode || '-' }}</div>
+        </div>
+      </div>
+      <div class="overview-meta">
+        <div class="meta-item meta-item--unit">
+          <span class="meta-label">申请单位</span>
+          <span class="meta-value meta-value--unit">{{
+            form.applyUnitName || '-'
+          }}</span>
+        </div>
+        <div class="meta-item">
+          <span class="meta-label">明细行数</span>
+          <span class="meta-value meta-value--number">{{ detailCount }}</span>
+        </div>
+        <el-tag :type="approvalStatusType(form.approvalStatus)">
+          {{ approvalStatusLabel(form.approvalStatus) }}
+        </el-tag>
+      </div>
+    </div>
+
+    <section class="detail-section">
+      <headerTitle title="基础信息"></headerTitle>
+      <el-form :model="form" label-width="140px" class="detail-form">
+        <el-row :gutter="20">
+          <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="申请编号:">
+              {{ form.applyCode || '-' }}
+            </el-form-item>
+          </el-col>
+          <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="申请时间:">
+              {{ normalizeDateTime(form.applyTime) || '-' }}
+            </el-form-item>
+          </el-col>
+          <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="申请单位编码:">
+              {{ form.applyUnitCode || '-' }}
+            </el-form-item>
+          </el-col>
+          <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="申请单位名称:">
+              {{ form.applyUnitName || '-' }}
+            </el-form-item>
+          </el-col>
+          <!-- <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="申请用户编码:">
+              {{ form.applyUserCode || '-' }}
+            </el-form-item>
+          </el-col> -->
+          <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form-item label="审批状态:">
+              <el-tag :type="approvalStatusType(form.approvalStatus)">
+                {{ approvalStatusLabel(form.approvalStatus) }}
+              </el-tag>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="备注:">
+              {{ form.remark || '-' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </section>
+
+    <section class="detail-section">
+      <headerTitle title="需求明细"></headerTitle>
+      <ele-pro-table
+        ref="detailTable"
+        :needPage="false"
+        :columns="columns"
+        :toolkit="[]"
+        :datasource="detailList"
+        row-key="id"
+      >
+        <template v-slot:quantity="{ row }">
+          {{ formatQuantity(row) }}
+        </template>
+        <template v-slot:requestDate="{ row }">
+          {{ normalizeDateTime(row.requestDate) || '-' }}
+        </template>
+        <template v-slot:type="{ row }">
+          {{ materialTypeLabel(row.type) }}
+        </template>
+      </ele-pro-table>
+    </section>
+  </div>
+</template>
+
+<script>
+  import { getDetail } from '@/api/bpm/components/demandApplication';
+
+  const APPROVAL_STATUS_OPTIONS = [
+    { label: '未提交', value: 0, type: 'info' },
+    { label: '审核中', value: 1, type: 'warning' },
+    { label: '审核通过', value: 2, type: 'success' },
+    { label: '审核不通过', value: 3, type: 'danger' }
+  ];
+
+  export default {
+    name: 'DemandApplicationDetail',
+    props: {
+      taskDefinitionKey: {
+        type: String,
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      businessId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      businessCode: {
+        default: ''
+      },
+      processDefinitionId: {
+        default: ''
+      },
+      businessType: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        loading: false,
+        form: {},
+        columns: [
+          {
+            columnKey: 'index',
+            type: 'index',
+            label: '序号',
+            width: 55,
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            prop: 'categoryCode',
+            label: '物品编码',
+            minWidth: 150,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryName',
+            label: '物品名称',
+            minWidth: 160,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'rootCategoryLevelId',
+            label: '根级分类ID',
+            minWidth: 135,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'specifications',
+            label: '规格',
+            minWidth: 130,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'modelType',
+            label: '型号',
+            minWidth: 130,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'quantity',
+            label: '申请数量',
+            width: 135,
+            align: 'center',
+            slot: 'quantity'
+          },
+          {
+            prop: 'unit',
+            label: '计量单位',
+            width: 110,
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'requestDate',
+            label: '要求日期',
+            width: 165,
+            align: 'center',
+            slot: 'requestDate'
+          },
+          {
+            prop: 'type',
+            label: '物品类型',
+            width: 115,
+            align: 'center',
+            slot: 'type'
+          }
+        ]
+      };
+    },
+    computed: {
+      detailList() {
+        return Array.isArray(this.form.detailList) ? this.form.detailList : [];
+      },
+      detailCount() {
+        return this.detailList.length;
+      }
+    },
+    created() {
+      this.getDetailData();
+    },
+    methods: {
+      async getDetailData() {
+        if (!this.businessId) return;
+        this.loading = true;
+        try {
+          this.form = (await getDetail(this.businessId)) || {};
+        } catch (error) {
+          this.$message.error(error.message || '需求申请单详情加载失败');
+        } finally {
+          this.loading = false;
+        }
+      },
+      approvalStatusLabel(status) {
+        const option = APPROVAL_STATUS_OPTIONS.find(
+          (item) => item.value === Number(status)
+        );
+        return option ? option.label : '未知状态';
+      },
+      approvalStatusType(status) {
+        const option = APPROVAL_STATUS_OPTIONS.find(
+          (item) => item.value === Number(status)
+        );
+        return option ? option.type : 'info';
+      },
+      normalizeDateTime(value) {
+        if (!value) return '';
+        return String(value)
+          .replace('T', ' ')
+          .replace(/\.\d{1,3}.*$/, '');
+      },
+      materialTypeLabel(type) {
+        return Number(type) === 1 ? '工装' : '默认';
+      },
+      formatQuantity(row) {
+        const quantity =
+          row.quantity || row.quantity === 0 ? row.quantity : '-';
+        return row.unit && quantity !== '-'
+          ? `${quantity} ${row.unit}`
+          : quantity;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .demand-application-detail {
+    min-height: 240px;
+  }
+
+  .detail-overview {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    min-height: 68px;
+    margin-bottom: 12px;
+    padding: 11px 16px;
+    box-sizing: border-box;
+    border: 1px solid #d9e8f5;
+    border-radius: 6px;
+    background: #f8fbff;
+  }
+
+  .overview-identity {
+    display: flex;
+    align-items: center;
+    min-width: 0;
+  }
+
+  .overview-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: 0 0 40px;
+    width: 40px;
+    height: 40px;
+    margin-right: 11px;
+    border-radius: 6px;
+    background: #1684df;
+    color: #fff;
+    font-size: 19px;
+  }
+
+  .overview-label {
+    color: #708196;
+    font-size: 12px;
+    line-height: 18px;
+  }
+
+  .overview-code {
+    overflow: hidden;
+    max-width: 360px;
+    color: #1d3449;
+    font-size: 17px;
+    font-weight: 700;
+    line-height: 24px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+
+  .overview-meta {
+    display: flex;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .meta-item {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-end;
+    min-width: 70px;
+  }
+
+  .meta-item--unit {
+    min-width: 220px;
+    max-width: 420px;
+  }
+
+  .meta-label {
+    color: #98a2b3;
+    font-size: 11px;
+    line-height: 18px;
+  }
+
+  .meta-value {
+    overflow: hidden;
+    max-width: 180px;
+    color: #344054;
+    font-size: 13px;
+    font-weight: 600;
+    line-height: 20px;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+
+  .meta-value--number {
+    color: #1478c9;
+    font-size: 17px;
+  }
+
+  .meta-value--unit {
+    max-width: 420px;
+    text-align: right;
+  }
+
+  .detail-section {
+    margin-bottom: 12px;
+  }
+
+  .detail-form {
+    padding-top: 6px;
+  }
+
+  ::v-deep .detail-form .el-form-item {
+    margin-bottom: 8px;
+  }
+
+  ::v-deep .detail-form .el-form-item__label {
+    color: #53677a;
+    font-weight: 600;
+  }
+
+  @media (max-width: 1000px) {
+    .detail-overview {
+      align-items: flex-start;
+      flex-direction: column;
+    }
+
+    .overview-meta {
+      width: 100%;
+      margin-top: 10px;
+    }
+  }
+</style>

+ 170 - 0
src/views/bpm/handleTask/components/demandApplication/submit.vue

@@ -0,0 +1,170 @@
+<template>
+  <el-col :span="16" :offset="6" v-loading="isSaveLoading">
+    <el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
+      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+        <el-input
+          type="textarea"
+          v-model="form.reason"
+          placeholder="请输入审批建议"
+        />
+      </el-form-item>
+    </el-form>
+    <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+      <el-button
+        icon="el-icon-edit-outline"
+        type="success"
+        size="mini"
+        v-click-once
+        :loading="isSaveLoading"
+        @click="handleAudit(1)"
+        >通过
+      </el-button>
+      <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        v-click-once
+        :loading="isSaveLoading"
+        @click="handleAudit(0)"
+        >驳回
+      </el-button>
+
+      <el-dropdown
+        @command="(command) => handleCommand(command)"
+        style="margin-left: 30px"
+      >
+        <span class="el-dropdown-link">
+          更多<i class="el-icon-arrow-down el-icon--right"></i>
+        </span>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="transfer">转办</el-dropdown-item>
+          <el-dropdown-item command="back">退回</el-dropdown-item>
+          <el-dropdown-item command="cancel">作废</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  import {
+    approveTaskWithVariables,
+    rejectTask,
+    cancelTask
+  } from '@/api/bpm/task';
+
+  export default {
+    name: 'DemandApplicationSubmit',
+    props: {
+      businessId: {
+        default: ''
+      },
+      businessCode: {
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      taskDefinitionKey: {
+        default: ''
+      },
+      fromUser: {
+        default: ''
+      },
+      businessType: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        form: {
+          reason: '同意'
+        },
+        rules: {
+          reason: [
+            {
+              required: true,
+              message: '请输入审批建议',
+              trigger: 'blur'
+            }
+          ]
+        },
+        isSaveLoading: false
+      };
+    },
+    methods: {
+      handleAudit(status) {
+        this.$refs.formRef.validate((valid) => {
+          if (!valid) return;
+          this.approveTask(status);
+        });
+      },
+      async approveTask(status) {
+        const API = status ? approveTaskWithVariables : rejectTask;
+        this.isSaveLoading = true;
+        try {
+          const res = await API({
+            id: this.taskId,
+            reason: this.form.reason,
+            variables: {
+              pass: !!status
+            }
+          });
+          if (res.data.code != '-1') {
+            this.$emit('handleAudit', {
+              status,
+              title: status === 0 ? '驳回' : ''
+            });
+          }
+        } finally {
+          this.isSaveLoading = false;
+        }
+      },
+      handleCommand(command) {
+        if (command === 'transfer') {
+          this.$emit('handleUpdateAssignee');
+          return;
+        }
+        if (command === 'back') {
+          this.$emit('handleBackList');
+          return;
+        }
+        if (command === 'cancel') {
+          this.cancelTask();
+        }
+      },
+      cancelTask() {
+        this.$confirm('是否确认作废?', {
+          type: 'warning',
+          cancelButtonText: '取消',
+          confirmButtonText: '确定'
+        })
+          .then(() => {
+            this.isSaveLoading = true;
+            return cancelTask({
+              id: this.id,
+              taskId: this.taskId,
+              reason: this.form.reason,
+              businessId: this.businessId
+            });
+          })
+          .then(() => {
+            this.$emit('handleClose');
+          })
+          .catch((error) => {
+            if (error !== 'cancel') {
+              this.$message.error('流程作废失败');
+            }
+          })
+          .finally(() => {
+            this.isSaveLoading = false;
+          });
+      }
+    }
+  };
+</script>
+
+<style lang="scss"></style>

+ 3 - 0
src/views/bpm/handleTask/customApproval/detailDialog.vue

@@ -0,0 +1,3 @@
+<script>
+  export { default } from '../components/customApproval/detailDialog.vue';
+</script>

+ 3 - 0
src/views/bpm/handleTask/customApproval/submit.vue

@@ -0,0 +1,3 @@
+<script>
+  export { default } from '../components/customApproval/submit.vue';
+</script>

+ 3 - 0
src/views/bpm/handleTask/demandApplication/detailDialog.vue

@@ -0,0 +1,3 @@
+<script>
+  export { default } from '../components/demandApplication/detailDialog.vue';
+</script>

+ 3 - 0
src/views/bpm/handleTask/demandApplication/submit.vue

@@ -0,0 +1,3 @@
+<script>
+  export { default } from '../components/demandApplication/submit.vue';
+</script>