228 lines
5.5 KiB
Vue
228 lines
5.5 KiB
Vue
<template>
|
|
<view class="px-base">
|
|
<CuNavbar title="报销申请"> </CuNavbar>
|
|
<view class="space-y-base mt-base">
|
|
<view class="card-shadow bg-white rounded-19rpx px-base">
|
|
<uv-form
|
|
labelWidth="160rpx"
|
|
:model="form"
|
|
:rules="rules"
|
|
errorType="toast"
|
|
ref="formRef"
|
|
labelPosition="left"
|
|
>
|
|
<uv-form-item label="报销分类" required prop="reimbursement_type_id">
|
|
<view
|
|
@click="openType"
|
|
keyName="name"
|
|
class="h-full w-full flex justify-end"
|
|
>
|
|
{{ type.name }}
|
|
<uv-icon name="arrow-right"></uv-icon>
|
|
</view>
|
|
</uv-form-item>
|
|
<uv-line color="#f5f5f5"></uv-line>
|
|
<uv-form-item label="报销金额" required prop="expense">
|
|
<uv-input
|
|
:border="`none`"
|
|
placeholder="请输入报销金额"
|
|
type="digit"
|
|
input-align="right"
|
|
v-model="form.expense"
|
|
></uv-input>
|
|
</uv-form-item>
|
|
<uv-line color="#f5f5f5"></uv-line>
|
|
<uv-form-item
|
|
label="报销原因"
|
|
required
|
|
prop="reason"
|
|
labelPosition="top"
|
|
>
|
|
<uv-textarea
|
|
:border="`none`"
|
|
v-model="form.reason"
|
|
placeholder="请输入报销原因"
|
|
:customStyle="{ padding: '0' }"
|
|
></uv-textarea>
|
|
</uv-form-item>
|
|
<uv-line color="#f5f5f5"></uv-line>
|
|
<uv-form-item label="报销凭证" prop="photos" required>
|
|
<view class="text-right w-full text-hex-999"
|
|
>{{ form.photos.length }}/9</view
|
|
>
|
|
</uv-form-item>
|
|
<view class="w-full">
|
|
<uv-upload
|
|
:maxCount="9"
|
|
multiple
|
|
:fileList="form.photos"
|
|
@afterRead="afterRead"
|
|
@delete="deletePic"
|
|
name="photos"
|
|
></uv-upload>
|
|
</view>
|
|
</uv-form>
|
|
</view>
|
|
</view>
|
|
<view class="mt-100rpx">
|
|
<uv-button type="primary" @click="submit">提交</uv-button>
|
|
</view>
|
|
|
|
<uv-picker
|
|
ref="typeRef"
|
|
keyName="name"
|
|
:columns="[typeList]"
|
|
@confirm="typeConfirm"
|
|
></uv-picker>
|
|
|
|
<uv-modal
|
|
ref="modalRef"
|
|
title="提示"
|
|
content="确定提交报销申请?"
|
|
@confirm="onSubmit"
|
|
:showCancelButton="true"
|
|
></uv-modal>
|
|
</view>
|
|
</template>
|
|
<script setup>
|
|
import CuNavbar from '@/components/cu-navbar/index'
|
|
import Cell from '@/components/cell/index'
|
|
import { ref, reactive } from 'vue'
|
|
import { http } from '@/utils/request'
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
const typeRef = ref(null)
|
|
const typeList = ref([])
|
|
const type = ref({})
|
|
const modalRef = ref(null)
|
|
const formRef = ref(null)
|
|
const loading = ref(false)
|
|
const form = reactive({
|
|
reimbursement_type_id: '',
|
|
expense: '',
|
|
reason: '',
|
|
photos: [],
|
|
})
|
|
const rules = reactive({
|
|
reimbursement_type_id: [
|
|
{
|
|
required: true,
|
|
message: '请选择报销分类',
|
|
},
|
|
],
|
|
expense: [
|
|
{ required: true, message: '请输入报销金额' },
|
|
{
|
|
required: true,
|
|
type: 'number',
|
|
min: 0.01,
|
|
max: 22,
|
|
message: '报销金额不能小于0.01',
|
|
},{
|
|
validator: (rule, value) => {
|
|
return value > 0
|
|
},
|
|
message: '报销金额不能小于0',
|
|
}
|
|
],
|
|
reason: [{ required: true, message: '请输入报销原因' }],
|
|
photos: {
|
|
type: 'array',
|
|
required: true,
|
|
message: '请上传报销凭证',
|
|
},
|
|
})
|
|
|
|
onLoad(() => {
|
|
getTypes()
|
|
})
|
|
|
|
const submit = () => {
|
|
formRef.value.validate().then((res) => {
|
|
modalRef.value.open()
|
|
})
|
|
}
|
|
const onSubmit = async () => {
|
|
if (loading.value) return
|
|
loading.value = true
|
|
try {
|
|
const resData = await http.post('/reimbursements', {
|
|
reimbursement_type_id: form.reimbursement_type_id,
|
|
expense: form.expense,
|
|
reason: form.reason,
|
|
photos: form.photos.map((item) => item.url),
|
|
})
|
|
uni.showToast({
|
|
title: '提交成功',
|
|
icon: 'none',
|
|
})
|
|
formRef.value.resetFields()
|
|
uni.$emit('ex:submit', resData)
|
|
uni.navigateBack()
|
|
} catch (error) {
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const afterRead = async (event) => {
|
|
let lists = [].concat(event.file)
|
|
let fileListLen = form[event.name].length
|
|
|
|
lists.map((item) => {
|
|
form[event.name].push({
|
|
...item,
|
|
status: 'uploading',
|
|
message: '上传中',
|
|
})
|
|
})
|
|
for (let i = 0; i < lists.length; i++) {
|
|
const result = await uploadFilePromise(lists[i].url)
|
|
let item = form[event.name][fileListLen]
|
|
form[event.name].splice(
|
|
fileListLen,
|
|
1,
|
|
Object.assign(item, {
|
|
status: 'success',
|
|
message: '',
|
|
url: result,
|
|
})
|
|
)
|
|
fileListLen++
|
|
}
|
|
}
|
|
|
|
const uploadFilePromise = (url) => {
|
|
return new Promise((resolve, reject) => {
|
|
http
|
|
.upload('/fileupload', {
|
|
filePath: url,
|
|
name: 'file',
|
|
})
|
|
.then((res) => {
|
|
resolve(res.url)
|
|
})
|
|
.catch((err) => {
|
|
reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
const deletePic = (event) => {
|
|
form[event.name].splice(event.index, 1)
|
|
}
|
|
const getTypes = () => {
|
|
http.get('/keyword?parent_key=reimbursement_type').then((res) => {
|
|
typeList.value = res
|
|
})
|
|
}
|
|
|
|
const typeConfirm = ({ value }) => {
|
|
type.value = value[0]
|
|
form.reimbursement_type_id = type.value.id
|
|
}
|
|
|
|
const openType = () => {
|
|
typeRef.value.open()
|
|
}
|
|
</script>
|