审核流程

main
panliang 2024-04-27 23:09:15 +08:00
parent 2e7bd9d7d0
commit 57aa557e2b
10 changed files with 170 additions and 214 deletions

View File

@ -9,65 +9,79 @@ export default {
// }, // },
{ {
title: '所属门店', title: '所属门店',
dataIndex: 'taskable.store.title', dataIndex: 'check.subject.store.title',
// borderBottom: false, // borderBottom: false,
// labelPosition: 'top' // labelPosition: 'top'
}, },
{ {
title: '电话号码', title: '电话号码',
dataIndex: '', dataIndex: 'check.subject.store_master.phone',
}, },
{ {
title: '申请时间', title: '申请时间',
dataIndex: 'created_at', dataIndex: 'check.subject.created_at',
format: timeFormat, format: timeFormat,
}, },
{ {
title: '清洁范围', title: '清洁范围',
dataIndex: 'taskable.description', dataIndex: 'check.subject.description',
labelPosition: 'top', labelPosition: 'top',
}, },
{ {
title: '清洁结果', title: '清洁结果',
dataIndex: 'taskable.photos', dataIndex: 'check.subject.photos',
type: 'album', type: 'album',
}, },
], ],
params: { include: 'check.subject.task,check.subject.storeMaster,check.subject.store' }
}, },
reimbursements: { reimbursements: {
params: { params: {
include: 'employee,store,type', include: 'check.subject.type,check.subject.employee,check.subject.store',
}, },
data: [ data: [
{ {
title: '审核状态', title: "申请人",
dataIndex: 'workflow_check.check_status_text', dataIndex: "check.subject.employee.name"
}, },
{ {
title: '未通过理由', title: "所属门店",
dataIndex: 'workflow_check.check_remarks', dataIndex: "check.subject.store.title"
isShow: (item) => { },
return item?.workflow_check?.check_status == 4 {
}, title: "电话号码",
dataIndex: "check.subject.employee.phone"
},
{
title: "申请时间",
dataIndex: "check.subject.created_at_format"
}, },
{ {
title: '报销分类', title: '报销分类',
dataIndex: 'type.name', dataIndex: 'check.subject.type.name',
}, },
{ {
title: '报销金额', title: '报销金额',
dataIndex: 'expense', dataIndex: 'check.subject.expense',
}, },
{ {
title: '报销原因', title: '报销原因',
dataIndex: 'reason', dataIndex: 'check.subject.reason',
labelPosition: 'top', labelPosition: 'top',
}, },
{ {
title: '报销凭证', title: '报销凭证',
dataIndex: 'photos', dataIndex: 'check.subject.photos',
type: 'album', type: 'album',
}, },
{
title: '未通过原因',
dataIndex: 'remarks',
labelPosition: 'top',
isShow: (item) => {
return item?.check_status == 4
},
},
] ]
} }
} }

View File

@ -2,11 +2,7 @@
<view> <view>
<CuNavbar title="审核详情"> <CuNavbar title="审核详情">
<template #right> <template #right>
<view <view class="text-sm text-white" @click="goPath(`/pages/audits/log?id=${data.check_id}`)"></view>
class="text-sm text-white"
@click="goPath(`/pages/audits/log?id=${id}&type=${type}`)"
>审核流程</view
>
</template> </template>
</CuNavbar> </CuNavbar>
<view class="px-base mt-30rpx"> <view class="px-base mt-30rpx">
@ -74,20 +70,11 @@ const modelOptions = reactive({
const onConfirm = async () => { const onConfirm = async () => {
try { try {
await http.post( await http.post(`/workflow/${id.value}/check`, {
`/workflow/${id.value}/check`, status: !modelOptions.isValue,
{ remarks: modelOptions.isValue ? value.value : '',
subject_type: type.value, })
status: !modelOptions.isValue, // uni.$emit('audits:onRefresh')
remarks: modelOptions.isValue ? value.value : '',
},
{
header: {
Accept: 'application/json',
},
}
)
uni.$emit('audits:onRefresh')
uni.navigateBack() uni.navigateBack()
} catch (error) {} } catch (error) {}
} }
@ -124,7 +111,6 @@ const getData = async () => {
}) })
data.value = resData.data data.value = resData.data
checkable.value = resData.checkable checkable.value = resData.checkable
console.log(resData)
} }
const goPath = (url) => { const goPath = (url) => {

View File

@ -21,7 +21,6 @@
<view> {{ item.check_user ? item.check_user.name : item.check_name }}</view> <view> {{ item.check_user ? item.check_user.name : item.check_name }}</view>
</view> </view>
<view <view
v-if="item.checked_at"
class="text-24rpx" class="text-24rpx"
:style="{ :style="{
color: statusFun(item.check_status, 'statusExpense', 'color'), color: statusFun(item.check_status, 'statusExpense', 'color'),
@ -51,9 +50,7 @@ const list = ref([])
// const currentStop = computed(()=>list.value.filter(e=>e.check_status>=3)) // const currentStop = computed(()=>list.value.filter(e=>e.check_status>=3))
onLoad((options) => { onLoad((options) => {
http http
.get(`/workflow/${options.id}/logs`, { .get(`/workflow/${options.id}/logs`)
params: { subject_type: options.type },
})
.then((res) => { .then((res) => {
list.value = res list.value = res
}) })

View File

@ -41,15 +41,24 @@ const actionlist = ref([
const colums = [ const colums = [
{ {
title: '审核状态', title: "审核状态",
dataIndex: 'workflow_check.check_status_text', dataIndex: "workflow_check.check_status_text",
}, },
{ {
title: '未通过理由', title: "申请人",
dataIndex: 'workflow_check.check_remarks', dataIndex: "employee.name"
isShow: (item) => { },
return item?.workflow_check?.check_status == 4 {
}, title: "所属门店",
dataIndex: "store.title"
},
{
title: "电话号码",
dataIndex: "employee.phone"
},
{
title: "申请时间",
dataIndex: "created_at_format"
}, },
{ {
title: '报销分类', title: '报销分类',
@ -69,6 +78,14 @@ const colums = [
dataIndex: 'photos', dataIndex: 'photos',
type: 'album', type: 'album',
}, },
{
title: '未通过原因',
dataIndex: 'remarks',
labelPosition: 'top',
isShow: (item) => {
return item?.check_status == 4
},
},
] ]
const actionSheet = ref(null) const actionSheet = ref(null)
const data = ref(null) const data = ref(null)

View File

@ -2,11 +2,7 @@
<view> <view>
<CuNavbar title="报销管理"> <CuNavbar title="报销管理">
<template #right> <template #right>
<view <view @click="goPath('/pages/expense-account/submit')" class="text-24rpx text-white">申请</view>
@click="goPath('/pages/expense-account/submit')"
class="text-24rpx text-white"
>申请</view
>
</template> </template>
</CuNavbar> </CuNavbar>
<uv-sticky bgColor="#fff"> <uv-sticky bgColor="#fff">
@ -29,8 +25,25 @@
> >
<template v-slot="{ list }"> <template v-slot="{ list }">
<view class="space-y-15rpx p-base"> <view class="space-y-15rpx p-base">
<view v-for="item in list" :key="item.id"> <view v-for="item in list" :key="item.id" class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx" @click="applyDetail(item)">
<Item :item="item" /> <view class="flex items-center justify-between">
<view class="text-30rpx"> {{ item.type?.name }} </view>
<view :style="{color: statusFun(item.workflow_check?.check_status,'statusExpense','color'),}" class="text-24rpx">{{ item.workflow_check?.check_status_text }}</view>
</view>
<view class="text-24rpx text-hex-999999 flex">
<view class="w-140rpx">报销金额</view>
<view class="text-primary">{{ item.expense }}</view>
</view>
<view class="text-24rpx text-hex-999999 flex">
<view class="w-140rpx">报销时间</view>
<view class="text-hex-333">{{ timeFormat(item.created_at) }}</view>
</view>
<view class="text-24rpx text-hex-999999">
<view class="">
<text class="w-140rpx inline-block">报销原因:</text>
<text class="text-hex-333 leading-27rpx">{{ item.reason }}</text>
</view>
</view>
</view> </view>
</view> </view>
</template> </template>
@ -45,13 +58,27 @@
> >
<template v-slot="{ list }"> <template v-slot="{ list }">
<view class="space-y-15rpx p-base"> <view class="space-y-15rpx p-base">
<view v-for="item in list" :key="item.id"> <view v-for="item in list" :key="item.id" class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx" @click="checkDetail(item)">
<Item <view class="flex items-center justify-between">
:item="item" <view class="text-30rpx"> {{ item.check.subject.type.name }} </view>
:type="tabList[1].params.subject_type" <view :style="{color: statusFun(item.check_status,'statusExpense','color'),}" class="text-24rpx">{{ item.check_status_text }}</view>
status="statusExpense" </view>
/> </view <view class="text-24rpx text-hex-999999 flex">
></view> <view class="w-140rpx">报销金额</view>
<view class="text-primary">{{ item.check.subject.expense }}</view>
</view>
<view class="text-24rpx text-hex-999999 flex">
<view class="w-140rpx">报销时间</view>
<view class="text-hex-333">{{ timeFormat(item.check.subject.created_at) }}</view>
</view>
<view class="text-24rpx text-hex-999999">
<view class="">
<text class="w-140rpx inline-block">报销原因:</text>
<text class="text-hex-333 leading-27rpx">{{ item.check.subject.reason }}</text>
</view>
</view>
</view>
</view>
</template> </template>
</MescrollItem> </MescrollItem>
</view> </view>
@ -63,7 +90,8 @@ import { ref } from 'vue'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app' import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescrollMore from '@/uni_modules/mescroll-uni/hooks/useMescrollMore.js' import useMescrollMore from '@/uni_modules/mescroll-uni/hooks/useMescrollMore.js'
import MescrollItem from '@/components/mescroll-api/more.vue' import MescrollItem from '@/components/mescroll-api/more.vue'
import Item from './item.vue' import { timeFormat } from '@climblee/uv-ui/libs/function'
import statusFun from '@/utils/status'
const mescrollItem0 = ref(null) const mescrollItem0 = ref(null)
const mescrollItem1 = ref(null) const mescrollItem1 = ref(null)
@ -83,7 +111,7 @@ const tabList = ref([
{ {
name: '报销审核', name: '报销审核',
apiUrl: '/workflow', apiUrl: '/workflow',
params: { subject_type: 'reimbursements', include: 'employee,store,type' }, params: { subject_type: 'reimbursements', include: 'check.subject.type' },
}, },
]) ])
@ -97,4 +125,16 @@ const goPath = (url) => {
url, url,
}) })
} }
const applyDetail = (item) => {
uni.navigateTo({
url: `/pages/expense-account/detail?id=${item.id}`
})
}
const checkDetail = (item) => {
uni.navigateTo({
url: `/pages/audits/detail?id=${item.id}&type=${item.check.subject_type}`
})
}
</script> </script>

View File

@ -1,61 +0,0 @@
<template>
<view
class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx"
@click="detail(item)"
>
<view class="flex items-center justify-between">
<view class="text-30rpx"> {{ item.type?.name }} </view>
<view
:style="[
{
color: statusFun(
item.workflow_check?.check_status,
status || 'statusExpense',
'color'
),
},
]"
class="text-24rpx"
>{{ item.workflow_check?.check_status_text }}</view
>
</view>
<view class="text-24rpx text-hex-999999 flex">
<view class="w-140rpx">报销金额</view>
<view class="text-primary">{{ item.expense }}</view>
</view>
<view class="text-24rpx text-hex-999999 flex">
<view class="w-140rpx">报销时间</view>
<view class="text-hex-333">{{ timeFormat(item.created_at) }}</view>
</view>
<view class="text-24rpx text-hex-999999">
<view class="">
<text class="w-140rpx inline-block">报销原因:</text>
<text class="text-hex-333 leading-27rpx">{{ item.reason }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { timeFormat } from '@climblee/uv-ui/libs/function'
import statusFun from '@/utils/status'
const emits = defineEmits(['click'])
const props = defineProps({
item: Object,
type: String,
status: String,
})
const detail = (item) => {
let url
if (props.type) {
url = `/pages/audits/detail?id=${props.item.id}&type=${props.type}`
} else {
url = `/pages/expense-account/detail?id=${props.item.id}`
}
uni.navigateTo({
url: url,
})
}
</script>

View File

@ -1,70 +0,0 @@
<template>
<view
class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx"
@click.stop="onClick"
>
<view class="flex items-center justify-between">
<view class="text-30rpx">{{ item.name }}</view>
<view
:style="{
color: statusFun(
item.taskable.status,
isCheck ? 'task_hygienes' : item.taskable_type,
'color'
),
}"
class="text-24rpx"
>{{
statusFun(
item.taskable.status,
isCheck ? 'task_hygienes' : item.taskable_type,
'name'
)
}}</view
>
</view>
<view class="text-24rpx text-hex-999999">
任务时间{{ timeFormat(item.start_at, 'yyyy年mm月dd日') }} -
{{ timeFormat(item.end_at, 'yyyy年mm月dd日') }}
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
import statusFun from '@/utils/status'
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
const props = defineProps({
item: Object,
isCheck: Boolean,
type: String,
})
const onClick = () => {
const type = props.item.taskable_type
const { status } = props.item.taskable
let url
if (props.isCheck) {
url = `/pages/audits/detail?id=${props.item.id}&type=${type}`
} else {
if (type === 'task_hygienes') {
if (status === 2 || status == 4) {
url = `/pages/task/task_hygienes_submit?id=${props.item.id}`
} else {
url = `/pages/task/detail?id=${props.item.id}`
}
} else if (type === 'task_ledgers') {
url = `/pages/task/${type}_submit?id=${props.item.id}`
}
}
uni.navigateTo({
url: url,
})
}
const onTask = (e) => {
const type = props.item.taskable_type
uni.navigateTo({
url: `/pages/task/${type}_submit?id=${props.item.id}`,
})
}
</script>

View File

@ -57,7 +57,7 @@ import { timeFormat } from '@climblee/uv-ui/libs/function'
const baseColums = [ const baseColums = [
{ {
title: '申请人', title: '申请人',
dataIndex: 'name', dataIndex: 'taskable.store_master.name',
}, },
{ {
title: '所属门店', title: '所属门店',
@ -65,7 +65,7 @@ const baseColums = [
}, },
{ {
title: '电话号码', title: '电话号码',
dataIndex: '', dataIndex: 'taskable.store_master.phone',
}, },
{ {
title: '申请时间', title: '申请时间',

View File

@ -22,8 +22,15 @@
> >
<template v-slot="{ list }"> <template v-slot="{ list }">
<view class="space-y-15rpx p-base"> <view class="space-y-15rpx p-base">
<view v-for="(item, i) in list" :key="i"> <view v-for="item in list" :key="item.id" class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx" @click.stop="applyClick(item)">
<Item :item="item"></Item> <view class="flex items-center justify-between">
<view class="text-30rpx">{{ item.name }}</view>
<view class="text-24rpx" :style="{color: statusFun(item.taskable.status, 'task_hygienes' ,'color')}">{{ item.taskable.status_text }}</view>
</view>
<view class="text-24rpx text-hex-999999">
任务时间{{ timeFormat(item.start_at, 'yyyy年mm月dd日') }} -
{{ timeFormat(item.end_at, 'yyyy年mm月dd日') }}
</view>
</view> </view>
</view> </view>
</template> </template>
@ -38,12 +45,15 @@
> >
<template v-slot="{ list }"> <template v-slot="{ list }">
<view class="space-y-15rpx p-base"> <view class="space-y-15rpx p-base">
<view v-for="(item, i) in list" :key="i"> <view v-for="item in list" :key="item.id" class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx" @click.stop="checkClick(item)">
<Item <view class="flex items-center justify-between">
:item="item" <view class="text-30rpx">{{ item.check.subject.task.name }}</view>
isCheck <view class="text-24rpx" :style="{color: statusFun(item.check_status, 'statusExpense' ,'color')}">{{ item.check_status_text }}</view>
:type="tabList[1].params.subject_type" </view>
></Item> <view class="text-24rpx text-hex-999999">
任务时间{{ timeFormat(item.check.subject.task.start_at, 'yyyy年mm月dd日') }} -
{{ timeFormat(item.check.subject.task.end_at, 'yyyy年mm月dd日') }}
</view>
</view> </view>
</view> </view>
</template> </template>
@ -53,10 +63,11 @@
<script setup> <script setup>
import CuNavbar from '@/components/cu-navbar/index' import CuNavbar from '@/components/cu-navbar/index'
import { computed, reactive, ref } from 'vue' import { computed, reactive, ref } from 'vue'
import Item from './components/item.vue'
import { onPageScroll, onReachBottom, onShow } from '@dcloudio/uni-app' import { onPageScroll, onReachBottom, onShow } from '@dcloudio/uni-app'
import useMescrollMore from '@/uni_modules/mescroll-uni/hooks/useMescrollMore.js' import useMescrollMore from '@/uni_modules/mescroll-uni/hooks/useMescrollMore.js'
import MescrollItem from '@/components/mescroll-api/more.vue' import MescrollItem from '@/components/mescroll-api/more.vue'
import statusFun from '@/utils/status'
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
const mescrollItem0 = ref(null) const mescrollItem0 = ref(null)
const mescrollItem1 = ref(null) const mescrollItem1 = ref(null)
@ -76,7 +87,8 @@ const tabList = ref([
name: '任务审核', name: '任务审核',
apiUrl: '/workflow', apiUrl: '/workflow',
params: { params: {
subject_type: 'task_hygienes' subject_type: 'task_hygienes',
include: 'check.subject.task'
}, },
}, },
]) ])
@ -85,4 +97,24 @@ const tabChange = ({ index }) => {
tabIndex.value = index tabIndex.value = index
scrollToLastY() scrollToLastY()
} }
const applyClick = (item) => {
const type = item.taskable_type
const status = item.taskable.status
let url
if (status === 2 || status == 4) {
url = `/pages/task/${type}_submit?id=${item.id}`
} else {
url = `/pages/task/detail?id=${item.id}`
}
uni.navigateTo({
url: url,
})
}
const checkClick = (item) => {
uni.navigateTo({
url: `/pages/audits/detail?id=${item.id}&type=${item.check.subject_type}`,
})
}
</script> </script>

View File

@ -21,14 +21,15 @@
</uv-form-item> </uv-form-item>
<uv-line color="#f5f5f5"></uv-line> <uv-line color="#f5f5f5"></uv-line>
<uv-form-item <uv-form-item
label="报销凭证" label="清洁结果"
labelPosition="top" labelPosition="top"
prop="photos" prop="photos"
required required
> >
<template #right>{{ form.photos.length }} / {{ maxCount }}</template>
<view class="w-full mt-15rpx"> <view class="w-full mt-15rpx">
<uv-upload <uv-upload
:maxCount="9" :maxCount="maxCount"
multiple multiple
:fileList="form.photos" :fileList="form.photos"
@afterRead="afterRead" @afterRead="afterRead"
@ -65,12 +66,13 @@ const form = reactive({
description: '', description: '',
photos: [], photos: [],
}) })
const maxCount = ref(9)
const rules = reactive({ const rules = reactive({
description: [{ required: true, message: '请输入清洁范围' }], description: [{ required: true, message: '请输入清洁范围' }],
photos: { photos: {
type: 'array', type: 'array',
required: true, required: true,
message: '请上传报销凭证', message: '请上传清洁结果',
}, },
}) })
onLoad((options) => { onLoad((options) => {
@ -80,6 +82,8 @@ onLoad((options) => {
const submit = () => { const submit = () => {
formRef.value.validate().then((res) => { formRef.value.validate().then((res) => {
modalRef.value.open() modalRef.value.open()
}).catch(error => {
console.log(error)
}) })
} }
@ -90,9 +94,6 @@ const onSubmit = async () => {
await http.request({ await http.request({
url: `/tasks/${id.value}/submit`, url: `/tasks/${id.value}/submit`,
method: 'POST', method: 'POST',
header: {
Accept: 'application/json',
},
data: { data: {
task_hygiene: { task_hygiene: {
description: form.description, description: form.description,
@ -105,7 +106,7 @@ const onSubmit = async () => {
icon: 'none', icon: 'none',
}) })
formRef.value.resetFields() formRef.value.resetFields()
uni.$emit('task:submit', resData) uni.$emit('task:submit')
uni.navigateBack() uni.navigateBack()
} catch (error) { } catch (error) {
console.log(error) console.log(error)