Browse Source

修改流程申请审核管理的bug

master
王泽彦 10 months ago
parent
commit
4588ea879b
  1. 10
      admin/src/app/api/school_approval/process.ts
  2. 21
      admin/src/app/views/school_approval/config/index.vue
  3. 178
      admin/src/app/views/school_approval/process/index.vue
  4. 37
      admin/src/utils/request.ts
  5. 10
      niucloud/app/adminapi/controller/school_approval/Process.php
  6. 2
      niucloud/app/service/school_approval/SchoolApprovalProcessService.php

10
admin/src/app/api/school_approval/process.ts

@ -5,7 +5,7 @@ import request from '@/utils/request'
* @param params
*/
export function getProcessList(params?: Record<string, any>) {
return request.get({ url: '/school_approval/process/lists', params })
return request.get('/school_approval/process/lists', { params })
}
/**
@ -13,7 +13,7 @@ export function getProcessList(params?: Record<string, any>) {
* @param params
*/
export function getProcessInfo(params: { id: number }) {
return request.get({ url: '/school_approval/process/info', params })
return request.get('/school_approval/process/info', { params })
}
/**
@ -21,7 +21,7 @@ export function getProcessInfo(params: { id: number }) {
* @param params
*/
export function createProcess(params: any) {
return request.post({ url: '/school_approval/process/create', data: params })
return request.post('/school_approval/process/create', params)
}
/**
@ -29,7 +29,7 @@ export function createProcess(params: any) {
* @param params
*/
export function approveProcess(params: { process_id: number; status: string; remarks?: string }) {
return request.post({ url: '/school_approval/process/approve', data: params })
return request.post('/school_approval/process/approve', params)
}
/**
@ -37,5 +37,5 @@ export function approveProcess(params: { process_id: number; status: string; rem
* @param params
*/
export function cancelProcess(params: { process_id: number }) {
return request.post({ url: '/school_approval/process/cancel', data: params })
return request.post('/school_approval/process/cancel', params)
}

21
admin/src/app/views/school_approval/config/index.vue

@ -125,7 +125,8 @@
添加节点
</el-button>
</div>
<div v-if="state.dialog.form.nodes.length === 0" class="text-gray-400 text-center py-20px border border-dashed rounded">
<div v-if="state.dialog.form.nodes.length === 0"
class="text-gray-400 text-center py-20px border border-dashed rounded">
暂无审批节点请点击添加
</div>
<div v-else class="node-list">
@ -272,7 +273,14 @@
<script lang="ts" setup>
import {reactive, ref, onMounted} from 'vue'
import {ElMessage, ElMessageBox, FormInstance} from 'element-plus'
import { getConfigList, getConfigInfo, addConfig, editConfig, deleteConfig, changeConfigStatus } from '@/app/api/school_approval/config'
import {
getConfigList,
getConfigInfo,
addConfig,
editConfig,
deleteConfig,
changeConfigStatus
} from '@/app/api/school_approval/config'
// draggable使
// import draggable from 'vuedraggable'
@ -501,7 +509,8 @@ function handleDelete(row: any) {
console.error(error)
}
})
.catch(() => {})
.catch(() => {
})
}
//
@ -613,9 +622,15 @@ onMounted(() => {
</script>
<style lang="scss" scoped>
.node-list {
margin-left: 10px;
}
.node-item {
background-color: #f9f9f9;
transition: all 0.3s;
padding: 10px;
margin-top: 10px;
&:hover {
background-color: #f2f2f2;

178
admin/src/app/views/school_approval/process/index.vue

@ -5,14 +5,14 @@
<div>
<el-button type="primary" @click="handleCreate">
<icon name="add" class="mr-5px" />
{{ $t('approval.process.create') }}
{{ '创建' }}
</el-button>
</div>
<div class="flex items-center">
<el-input
v-model="state.searchParams.process_name"
class="w-200px mr-15px"
:placeholder="$t('approval.process.searchPlaceholder')"
class="w-200 mr-15"
:placeholder="'搜索'"
clearable
@keyup.enter="handleSearch"
@clear="handleSearch"
@ -20,29 +20,29 @@
<el-select
v-model="state.searchParams.approval_status"
class="w-150px mr-15px"
:placeholder="$t('approval.process.statusPlaceholder')"
:placeholder="'状态'"
clearable
@change="handleSearch"
>
<el-option :label="$t('approval.process.pending')" value="pending" />
<el-option :label="$t('approval.process.approved')" value="approved" />
<el-option :label="$t('approval.process.rejected')" value="rejected" />
<el-option :label="'待审批'" value="pending" />
<el-option :label="'已审批'" value="approved" />
<el-option :label="'已拒绝'" value="rejected" />
</el-select>
<el-button type="primary" @click="handleSearch">
<icon name="search" class="mr-5px" />
{{ $t('common.search') }}
{{ '搜索' }}
</el-button>
<el-button @click="handleReset">
<icon name="refresh-right" class="mr-5px" />
{{ $t('common.reset') }}
{{ '重置' }}
</el-button>
</div>
</div>
<el-tabs v-model="state.activeTab" class="mt-15px" @tab-click="handleTabChange">
<el-tab-pane :label="$t('approval.process.all')" name="all" />
<el-tab-pane :label="$t('approval.process.myCreate')" name="myCreate" />
<el-tab-pane :label="$t('approval.process.myApproval')" name="myApproval" />
<el-tab-pane :label="'全部'" name="all" />
<el-tab-pane :label="'我创建的'" name="myCreate" />
<el-tab-pane :label="'我审批的'" name="myApproval" />
</el-tabs>
<el-table
@ -50,22 +50,22 @@
:data="state.processList"
:header-cell-style="{ background: '#fafafa', color: '#606266' }"
>
<el-table-column :label="$t('approval.process.id')" prop="id" width="80" />
<el-table-column :label="$t('approval.process.processName')" prop="process_name" min-width="180" />
<el-table-column :label="$t('approval.process.applicantId')" prop="applicant_id" width="100" />
<el-table-column :label="$t('approval.process.applicationTime')" prop="application_time" width="180" />
<el-table-column :label="$t('approval.process.currentApproverId')" prop="current_approver_id" width="100" />
<el-table-column :label="$t('approval.process.approvalStatus')" prop="approval_status" width="100">
<el-table-column :label="'ID'" prop="id" width="80" />
<el-table-column :label="'流程名称'" prop="process_name" min-width="180" />
<el-table-column :label="'申请人ID'" prop="applicant_id" width="100" />
<el-table-column :label="'申请时间'" prop="application_time" width="180" />
<el-table-column :label="'当前审批人ID'" prop="current_approver_id" width="100" />
<el-table-column :label="'审批状态'" prop="approval_status" width="100">
<template #default="{ row }">
<el-tag :type="getStatusType(row.approval_status)">
{{ getStatusText(row.approval_status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('common.action')" width="180" fixed="right">
<el-table-column :label="'操作'" width="180" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="handleDetail(row)">
{{ $t('common.detail') }}
{{ '详情' }}
</el-button>
<el-button
v-if="row.approval_status === 'pending' && row.applicant_id === state.userInfo.uid"
@ -73,7 +73,7 @@
link
@click="handleCancel(row)"
>
{{ $t('approval.process.cancel') }}
{{ '取消' }}
</el-button>
<el-button
v-if="row.approval_status === 'pending' && row.current_approver_id === state.userInfo.uid"
@ -81,7 +81,7 @@
link
@click="handleApprove(row)"
>
{{ $t('approval.process.approve') }}
{{ '审批' }}
</el-button>
</template>
</el-table-column>
@ -103,7 +103,7 @@
<!-- 创建审批弹窗 -->
<el-dialog
v-model="state.createDialog.visible"
:title="$t('approval.process.create')"
:title="'创建审批'"
width="600px"
:close-on-click-modal="false"
:destroy-on-close="true"
@ -114,17 +114,17 @@
:rules="state.createDialog.rules"
label-width="120px"
>
<el-form-item :label="$t('approval.process.processName')" prop="process_name">
<el-form-item :label="'流程名称'" prop="process_name">
<el-input
v-model="state.createDialog.form.process_name"
:placeholder="$t('approval.process.processNamePlaceholder')"
:placeholder="'请输入流程名称'"
/>
</el-form-item>
<el-form-item :label="$t('approval.process.configId')" prop="config_id">
<el-form-item :label="'审批流配置'" prop="config_id">
<el-select
v-model="state.createDialog.form.config_id"
class="w-full"
:placeholder="$t('approval.process.configIdPlaceholder')"
:placeholder="'请选择审批流配置'"
>
<el-option
v-for="item in state.configOptions"
@ -134,19 +134,19 @@
/>
</el-select>
</el-form-item>
<el-form-item :label="$t('approval.process.remarks')" prop="remarks">
<el-form-item :label="'备注'" prop="remarks">
<el-input
v-model="state.createDialog.form.remarks"
type="textarea"
:rows="3"
:placeholder="$t('approval.process.remarksPlaceholder')"
:placeholder="'请输入备注'"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="state.createDialog.visible = false">{{ $t('common.cancel') }}</el-button>
<el-button @click="state.createDialog.visible = false">{{ '取消' }}</el-button>
<el-button type="primary" :loading="state.createDialog.loading" @click="handleCreateSubmit">
{{ $t('common.confirm') }}
{{ '确认' }}
</el-button>
</template>
</el-dialog>
@ -154,7 +154,7 @@
<!-- 审批弹窗 -->
<el-dialog
v-model="state.approveDialog.visible"
:title="$t('approval.process.approve')"
:title="'审批'"
width="500px"
:close-on-click-modal="false"
:destroy-on-close="true"
@ -165,25 +165,25 @@
:rules="state.approveDialog.rules"
label-width="80px"
>
<el-form-item :label="$t('approval.process.status')" prop="status">
<el-form-item :label="'审批状态'" prop="status">
<el-radio-group v-model="state.approveDialog.form.status">
<el-radio label="approved">{{ $t('approval.process.approved') }}</el-radio>
<el-radio label="rejected">{{ $t('approval.process.rejected') }}</el-radio>
<el-radio label="approved">{{ '已审批' }}</el-radio>
<el-radio label="rejected">{{ '已拒绝' }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('approval.process.remarks')" prop="remarks">
<el-form-item :label="'备注'" prop="remarks">
<el-input
v-model="state.approveDialog.form.remarks"
type="textarea"
:rows="3"
:placeholder="$t('approval.process.remarksPlaceholder')"
:placeholder="'请输入备注'"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="state.approveDialog.visible = false">{{ $t('common.cancel') }}</el-button>
<el-button @click="state.approveDialog.visible = false">{{ '取消' }}</el-button>
<el-button type="primary" :loading="state.approveDialog.loading" @click="handleApproveSubmit">
{{ $t('common.confirm') }}
{{ '确认' }}
</el-button>
</template>
</el-dialog>
@ -191,41 +191,41 @@
<!-- 详情弹窗 -->
<el-dialog
v-model="state.detailDialog.visible"
:title="$t('approval.process.detail')"
:title="'审批详情'"
width="800px"
:destroy-on-close="true"
>
<el-descriptions :column="1" border>
<el-descriptions-item :label="$t('approval.process.id')">
<el-descriptions-item :label="'ID'">
{{ state.detailDialog.info.id }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.processName')">
<el-descriptions-item :label="'流程名称'">
{{ state.detailDialog.info.process_name }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.applicantId')">
<el-descriptions-item :label="'申请人ID'">
{{ state.detailDialog.info.applicant_id }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.applicationTime')">
<el-descriptions-item :label="'申请时间'">
{{ state.detailDialog.info.application_time }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.currentApproverId')">
<el-descriptions-item :label="'当前审批人ID'">
{{ state.detailDialog.info.current_approver_id }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.approvalStatus')">
<el-descriptions-item :label="'审批状态'">
<el-tag :type="getStatusType(state.detailDialog.info.approval_status)">
{{ getStatusText(state.detailDialog.info.approval_status) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.approvalTime')">
<el-descriptions-item :label="'审批时间'">
{{ state.detailDialog.info.approval_time || '-' }}
</el-descriptions-item>
<el-descriptions-item :label="$t('approval.process.remarks')">
<el-descriptions-item :label="'备注'">
{{ state.detailDialog.info.remarks || '-' }}
</el-descriptions-item>
</el-descriptions>
<div class="mt-20px">
<div class="font-bold text-16px mb-10px">{{ $t('approval.process.participants') }}</div>
<div class="font-bold text-16px mb-10px">{{ '参与者' }}</div>
<el-timeline>
<el-timeline-item
v-for="(node, index) in state.detailDialog.info.participants"
@ -234,22 +234,22 @@
:color="getNodeColor(node.status)"
>
<div class="font-bold mb-5px">
{{ $t('approval.process.participantLabel', { index: index + 1 }) }}
{{ '参与者' + (index + 1) }}
</div>
<div class="text-gray-500">
{{ $t('approval.process.participantId') }}{{ node.participant_id }}
{{ '参与者ID' }}{{ node.participant_id }}
</div>
<div class="text-gray-500">
{{ $t('approval.process.sequence') }}{{ node.sequence }}
{{ '顺序' }}{{ node.sequence }}
</div>
<div class="text-gray-500">
{{ $t('approval.process.status') }}{{ getStatusText(node.status) }}
{{ '状态' }}{{ getStatusText(node.status) }}
</div>
<div class="text-gray-500">
{{ $t('approval.process.signType') }}{{ node.sign_type === 'or_sign' ? $t('approval.process.orSign') : $t('approval.process.andSign') }}
{{ '签名类型' }}{{ node.sign_type === 'or_sign' ? '或签名' : '和签名' }}
</div>
<div class="text-gray-500">
{{ $t('approval.process.remarks') }}{{ node.remarks || '-' }}
{{ '备注' }}{{ node.remarks || '-' }}
</div>
</el-timeline-item>
</el-timeline>
@ -263,23 +263,39 @@ import { reactive, ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus'
import { getProcessList, getProcessInfo, createProcess, approveProcess, cancelProcess } from '@/app/api/school_approval/process'
import { getConfigList } from '@/app/api/school_approval/config'
import { useI18n } from 'vue-i18n'
// import { useI18n } from 'vue-i18n'
// import { useUserInfo } from '@/stores/userInfo'
const { t } = useI18n()
// const { t } = useI18n()
// const userInfo = useUserInfo()
//
const createFormRef = ref<FormInstance>()
const approveFormRef = ref<FormInstance>()
// script
interface ConfigOption {
label: string;
value: number;
}
interface Participant {
participant_id: number;
sequence: number;
status: string;
sign_type: string;
remarks?: string;
}
//
const state = reactive({
loading: false,
processList: [],
total: 0,
activeTab: 'all',
userInfo: null,
userInfo: {
uid: 1 // IDstore
},
searchParams: {
page: 1,
limit: 10,
@ -288,7 +304,7 @@ const state = reactive({
applicant_id: 0,
approver_id: 0
},
configOptions: [], //
configOptions: [] as ConfigOption[], //
createDialog: {
visible: false,
loading: false,
@ -299,10 +315,10 @@ const state = reactive({
},
rules: {
process_name: [
{ required: true, message: t('approval.process.processNameRequired'), trigger: 'blur' }
{ required: true, message: '请输入流程名称', trigger: 'blur' }
],
config_id: [
{ required: true, message: t('approval.process.configIdRequired'), trigger: 'change' }
{ required: true, message: '请选择审批流配置', trigger: 'change' }
]
}
},
@ -316,13 +332,23 @@ const state = reactive({
},
rules: {
status: [
{ required: true, message: t('approval.process.statusRequired'), trigger: 'change' }
{ required: true, message: '请选择审批状态', trigger: 'change' }
]
}
},
detailDialog: {
visible: false,
info: {}
info: {
id: 0,
process_name: '',
applicant_id: 0,
application_time: '',
current_approver_id: 0,
approval_status: '',
approval_time: '',
remarks: '',
participants: [] as Participant[] //
}
}
})
@ -394,11 +420,11 @@ function handleTabChange() {
async function getConfigOptions() {
try {
const res = await getConfigList({ status: 1 })
state.configOptions = res.data.list.map((item: any) => {
state.configOptions = (res.data.list || []).map((item: any) => {
return {
label: item.config_name,
value: item.id
}
label: item.config_name || '',
value: item.id || 0
} as ConfigOption
})
} catch (error) {
console.error(error)
@ -425,7 +451,7 @@ async function handleCreateSubmit() {
state.createDialog.loading = true
try {
await createProcess(state.createDialog.form)
ElMessage.success(t('approval.process.createSuccess'))
ElMessage.success('创建成功')
state.createDialog.visible = false
getList()
} catch (error) {
@ -460,7 +486,7 @@ async function handleApproveSubmit() {
status: state.approveDialog.form.status,
remarks: state.approveDialog.form.remarks
})
ElMessage.success(t('approval.process.approveSuccess'))
ElMessage.success('审批成功')
state.approveDialog.visible = false
getList()
} catch (error) {
@ -473,15 +499,15 @@ async function handleApproveSubmit() {
//
function handleCancel(row: any) {
ElMessageBox.confirm(t('approval.process.confirmCancel'), t('common.warning'), {
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
ElMessageBox.confirm('确认取消审批?', '警告', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
try {
await cancelProcess({ process_id: row.id })
ElMessage.success(t('approval.process.cancelSuccess'))
ElMessage.success('取消成功')
getList()
} catch (error) {
console.error(error)
@ -514,9 +540,9 @@ function getStatusType(status: string) {
//
function getStatusText(status: string) {
const map: Record<string, string> = {
pending: t('approval.process.pending'),
approved: t('approval.process.approved'),
rejected: t('approval.process.rejected')
pending: '待审批',
approved: '已审批',
rejected: '已拒绝'
}
return map[status] || status
}

37
admin/src/utils/request.ts

@ -8,7 +8,6 @@ import type {
import { getToken, isUrl } from './common'
import { ElMessage } from 'element-plus'
import type { MessageParams } from 'element-plus'
import { t } from '@/lang'
import useUserStore from '@/stores/modules/user'
import storage from '@/utils/storage'
@ -172,13 +171,13 @@ class Request {
const errStatus = err.response.status
switch (errStatus) {
case 400:
errMessage = t('axios.400')
errMessage = '请求错误'
break
case 401:
errMessage = t('axios.401')
errMessage = '未授权,请登录'
break
case 403:
errMessage = t('axios.403')
errMessage = '拒绝访问'
break
case 404:
let baseURL = '';
@ -191,38 +190,38 @@ class Request {
} catch (e) {
baseURL = location.origin;
}
errMessage = baseURL + t('axios.baseUrlError')
errMessage = baseURL + '请求地址出错'
break
case 405:
errMessage = t('axios.405')
errMessage = '请求方法未允许'
break
case 408:
errMessage = t('axios.408')
errMessage = '请求超时'
break
case 409:
errMessage = t('axios.409')
errMessage = '资源冲突'
break
case 500:
errMessage = t('axios.500')
errMessage = '服务器内部错误'
break
case 501:
errMessage = t('axios.501')
errMessage = '服务未实现'
break
case 502:
errMessage = t('axios.502')
errMessage = '网关错误'
break
case 503:
errMessage = t('axios.503')
errMessage = '服务不可用'
break
case 504:
errMessage = t('axios.504')
errMessage = '网关超时'
break
case 505:
errMessage = t('axios.505')
errMessage = 'HTTP版本不受支持'
break
}
}
err.message.includes('timeout') && (errMessage = t('axios.timeout'))
err.message.includes('timeout') && (errMessage = '请求超时')
if (err.code == 'ERR_NETWORK') {
let baseURL = '';
try {
@ -234,7 +233,7 @@ class Request {
} catch (e) {
baseURL = location.origin;
}
errMessage = baseURL + t('axios.baseUrlError')
errMessage = baseURL + '请求地址出错'
}
errMessage &&
this.showElMessage({
@ -256,7 +255,11 @@ class Request {
private messageCache = new Map()
private showElMessage(options: MessageParams) {
const cacheKey = options.message
// 处理类型问题,安全地获取消息
const message = typeof options === 'string' ? options : (options as any).message;
if (!message) return;
const cacheKey = message;
const cachedMessage = this.messageCache.get(cacheKey)
if (!cachedMessage || Date.now() - cachedMessage.timestamp > 5000) {

10
niucloud/app/adminapi/controller/school_approval/Process.php

@ -58,7 +58,7 @@ class Process extends BaseAdminController
$where[] = ['approval_status', '=', 'pending'];
}
$data = $this->service->getList($where, $page, $limit);
$data = $this->service->getList($where, (int)$page, (int)$limit);
return success($data);
}
@ -73,7 +73,7 @@ class Process extends BaseAdminController
return fail('参数错误');
}
$info = $this->service->getInfo($id);
$info = $this->service->getInfo((int)$id);
if (empty($info)) {
return fail('审批流程不存在');
}
@ -99,7 +99,7 @@ class Process extends BaseAdminController
}
// 设置申请人ID
$data['applicant_id'] = $this->user_info['uid'];
$data['applicant_id'] = $this->request->uid();
try {
$process_id = $this->service->create($data, $config_id);
@ -127,7 +127,7 @@ class Process extends BaseAdminController
}
try {
$result = $this->service->approve($process_id, $this->user_info['uid'], $status, $remarks);
$result = $this->service->approve((int)$process_id, $this->request->uid(), $status, $remarks);
return success($result);
} catch (\Exception $e) {
return fail($e->getMessage());
@ -146,7 +146,7 @@ class Process extends BaseAdminController
}
try {
$result = $this->service->cancel($process_id, $this->user_info['uid']);
$result = $this->service->cancel($process_id, $this->request->uid());
return success($result);
} catch (\Exception $e) {
return fail($e->getMessage());

2
niucloud/app/service/school_approval/SchoolApprovalProcessService.php

@ -81,7 +81,7 @@ class SchoolApprovalProcessService
$process = [
'process_name' => $data['process_name'],
'applicant_id' => $data['applicant_id'],
'application_time' => time(),
'application_time' => date("Y-m-d H:i:s"),
'current_approver_id' => 0, // 初始时为0,后面会更新
'approval_status' => SchoolApprovalProcess::STATUS_PENDING,
'remarks' => $data['remarks'] ?? ''

Loading…
Cancel
Save