feat: 审计页面新增提交与审核日期范围筛选,并优化发票列表凭证展示及上传逻辑。
This commit is contained in:
parent
def0d75840
commit
d9c6150ae1
@ -92,11 +92,11 @@ const handleUploadFinish = ({ file, event }) => {
|
|||||||
try {
|
try {
|
||||||
const res = JSON.parse(event.target.response)
|
const res = JSON.parse(event.target.response)
|
||||||
// 只要返回了 url 字段,就认为上传成功
|
// 只要返回了 url 字段,就认为上传成功
|
||||||
if (res.url) {
|
if (res.code === 200 && res.data?.url) {
|
||||||
// 显式查找 fileList 中的文件对象进行更新,确保响应式
|
// 显式查找 fileList 中的文件对象进行更新,确保响应式
|
||||||
const targetFile = fileList.value.find(f => f.id === file.id) || file
|
const targetFile = fileList.value.find(f => f.id === file.id) || file
|
||||||
targetFile.url = res.url
|
targetFile.url = res.data.url
|
||||||
targetFile.name = res.filename || targetFile.name
|
targetFile.name = res.data.filename || targetFile.name
|
||||||
targetFile.status = 'finished' // 手动标记为完成
|
targetFile.status = 'finished' // 手动标记为完成
|
||||||
|
|
||||||
// 更新 formData.attachments
|
// 更新 formData.attachments
|
||||||
|
|||||||
@ -70,12 +70,9 @@ const renderInvoiceType = (type) => {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
key: 'receiptId',
|
key: 'id',
|
||||||
width: 80,
|
width: 80,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
|
||||||
return row.receipt?.id || '-'
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '提交时间',
|
title: '提交时间',
|
||||||
@ -88,38 +85,25 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '付款凭证',
|
title: '付款凭证',
|
||||||
key: 'receipt',
|
key: 'receipts',
|
||||||
width: 140,
|
width: 140,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
const list = Array.isArray(row.receipt) ? row.receipt : row.receipt ? [row.receipt] : []
|
const list = Array.isArray(row.receipts) ? row.receipts : []
|
||||||
const urls = list
|
const urls = list.map((item) => item?.url).filter(Boolean)
|
||||||
.map((item) => (typeof item === 'string' ? item : item?.url))
|
|
||||||
.filter(Boolean)
|
|
||||||
if (!urls.length) return '-'
|
if (!urls.length) return '-'
|
||||||
return h(
|
return h(
|
||||||
'div',
|
'div',
|
||||||
{ style: 'display:flex; gap:6px; justify-content:center;' },
|
{ style: 'display:flex; gap:6px; justify-content:center; align-items: center;' },
|
||||||
urls.slice(0, 3).map((url, idx) =>
|
urls.slice(0, 3).map((url, idx) =>
|
||||||
h(
|
h('img', {
|
||||||
'a',
|
src: url,
|
||||||
{
|
style:
|
||||||
href: url,
|
'width:40px;height:40px;object-fit:cover;border-radius:4px;border:1px solid #e5e6eb;cursor:pointer;',
|
||||||
target: '_blank',
|
alt: '付款凭证',
|
||||||
rel: 'noopener noreferrer',
|
onClick: () => window.open(url, '_blank'),
|
||||||
key: `${url}-${idx}`,
|
})
|
||||||
style: 'display:inline-block',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
default: () =>
|
|
||||||
h('img', {
|
|
||||||
src: url,
|
|
||||||
style:
|
|
||||||
'width:46px;height:46px;object-fit:cover;border-radius:4px;border:1px solid #e5e6eb;',
|
|
||||||
alt: '付款凭证',
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -230,22 +214,11 @@ const columns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
// 开票按钮:未开票可编辑,其余只读
|
// 开票按钮:未开票可编辑,其余只读
|
||||||
async function handleInvoice(row) {
|
function handleInvoice(row) {
|
||||||
const editable = row.status === 'pending'
|
const editable = row.status === 'pending'
|
||||||
invoiceModalMode.value = editable ? 'send' : 'view'
|
invoiceModalMode.value = editable ? 'send' : 'view'
|
||||||
|
currentInvoice.value = row
|
||||||
invoiceModalVisible.value = true
|
invoiceModalVisible.value = true
|
||||||
await fetchDetail(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchDetail(row) {
|
|
||||||
try {
|
|
||||||
const id = row?.receipt?.id || row.id
|
|
||||||
const { data } = await api.getInvoiceById({ id })
|
|
||||||
currentInvoice.value = data || row
|
|
||||||
} catch (error) {
|
|
||||||
currentInvoice.value = row
|
|
||||||
$message.error(error?.message || '获取详情失败')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确认发送邮件
|
// 确认发送邮件
|
||||||
@ -253,6 +226,7 @@ async function fetchDetail(row) {
|
|||||||
async function handleInvoiceConfirm(formData) {
|
async function handleInvoiceConfirm(formData) {
|
||||||
try {
|
try {
|
||||||
const payload = {
|
const payload = {
|
||||||
|
receipt_id: formData.id,
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
subject: formData.email, // 用户要求 subject 传 email
|
subject: formData.email, // 用户要求 subject 传 email
|
||||||
body: formData.content, // 映射 content -> body
|
body: formData.content, // 映射 content -> body
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { h, onMounted, ref, watch } from 'vue'
|
import { h, onMounted, ref, watch } from 'vue'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import {
|
import {
|
||||||
NButton,
|
NButton,
|
||||||
@ -29,6 +30,30 @@ const router = useRouter()
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const $table = ref(null)
|
const $table = ref(null)
|
||||||
const queryItems = ref({})
|
const queryItems = ref({})
|
||||||
|
const submittedDateRange = ref(null)
|
||||||
|
const auditedDateRange = ref(null)
|
||||||
|
|
||||||
|
const handleSubmittedDateRangeChange = (val) => {
|
||||||
|
if (val && val.length === 2) {
|
||||||
|
queryItems.value.submitted_start = dayjs(val[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
queryItems.value.submitted_end = dayjs(val[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
} else {
|
||||||
|
queryItems.value.submitted_start = null
|
||||||
|
queryItems.value.submitted_end = null
|
||||||
|
}
|
||||||
|
$table.value?.handleSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAuditedDateRangeChange = (val) => {
|
||||||
|
if (val && val.length === 2) {
|
||||||
|
queryItems.value.audited_start = dayjs(val[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
queryItems.value.audited_end = dayjs(val[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
} else {
|
||||||
|
queryItems.value.audited_start = null
|
||||||
|
queryItems.value.audited_end = null
|
||||||
|
}
|
||||||
|
$table.value?.handleSearch()
|
||||||
|
}
|
||||||
|
|
||||||
// 列表与详情公共方法
|
// 列表与详情公共方法
|
||||||
const renderStatus = (status) => {
|
const renderStatus = (status) => {
|
||||||
@ -48,24 +73,24 @@ const columns = [
|
|||||||
{ title: '编号', key: 'id', width: 80, align: 'center' },
|
{ title: '编号', key: 'id', width: 80, align: 'center' },
|
||||||
{
|
{
|
||||||
title: '手机号',
|
title: '手机号',
|
||||||
key: 'phone',
|
key: 'user_phone',
|
||||||
width: 120,
|
width: 120,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: { tooltip: true },
|
ellipsis: { tooltip: true },
|
||||||
render(row) {
|
render(row) {
|
||||||
return row.phone || row.user_phone || row.user?.phone || '-'
|
return row.user_phone || row.user?.phone || '-'
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '微信号',
|
|
||||||
key: 'wechat',
|
|
||||||
width: 120,
|
|
||||||
align: 'center',
|
|
||||||
ellipsis: { tooltip: true },
|
|
||||||
render(row) {
|
|
||||||
return row.wechat || row.user_wechat || row.user?.wechat || '-'
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// title: '微信号',
|
||||||
|
// key: 'wechat',
|
||||||
|
// width: 120,
|
||||||
|
// align: 'center',
|
||||||
|
// ellipsis: { tooltip: true },
|
||||||
|
// render(row) {
|
||||||
|
// return row.wechat || row.user_wechat || row.user?.wechat || '-'
|
||||||
|
// },
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
title: '评估结果',
|
title: '评估结果',
|
||||||
key: 'valuation_result',
|
key: 'valuation_result',
|
||||||
@ -300,7 +325,7 @@ watch(
|
|||||||
@keypress.enter="$table?.handleSearch()"
|
@keypress.enter="$table?.handleSearch()"
|
||||||
/>
|
/>
|
||||||
</QueryBarItem>
|
</QueryBarItem>
|
||||||
<QueryBarItem label="微信号" :label-width="80">
|
<!-- <QueryBarItem label="微信号" :label-width="80">
|
||||||
<NInput
|
<NInput
|
||||||
v-model:value="queryItems.wechat"
|
v-model:value="queryItems.wechat"
|
||||||
clearable
|
clearable
|
||||||
@ -309,25 +334,25 @@ watch(
|
|||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
@keypress.enter="$table?.handleSearch()"
|
@keypress.enter="$table?.handleSearch()"
|
||||||
/>
|
/>
|
||||||
</QueryBarItem>
|
</QueryBarItem> -->
|
||||||
<QueryBarItem label="提交时间" :label-width="80">
|
<QueryBarItem label="提交时间" :label-width="80">
|
||||||
<NDatePicker
|
<NDatePicker
|
||||||
v-model:value="queryItems.created_at"
|
v-model:value="submittedDateRange"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
clearable
|
clearable
|
||||||
placeholder="请选择提交时间"
|
placeholder="请选择提交时间"
|
||||||
style="width: 280px"
|
style="width: 280px"
|
||||||
@update:value="$table?.handleSearch()"
|
@update:value="handleSubmittedDateRangeChange"
|
||||||
/>
|
/>
|
||||||
</QueryBarItem>
|
</QueryBarItem>
|
||||||
<QueryBarItem label="审核时间" :label-width="80">
|
<QueryBarItem label="审核时间" :label-width="80">
|
||||||
<NDatePicker
|
<NDatePicker
|
||||||
v-model:value="queryItems.reviewed_at"
|
v-model:value="auditedDateRange"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
clearable
|
clearable
|
||||||
placeholder="请选择审核时间"
|
placeholder="请选择审核时间"
|
||||||
style="width: 280px"
|
style="width: 280px"
|
||||||
@update:value="$table?.handleSearch()"
|
@update:value="handleAuditedDateRangeChange"
|
||||||
/>
|
/>
|
||||||
</QueryBarItem>
|
</QueryBarItem>
|
||||||
<QueryBarItem label="状态" :label-width="80">
|
<QueryBarItem label="状态" :label-width="80">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user