优化财务仪表盘UI与快捷时间筛选
This commit is contained in:
@@ -27,6 +27,9 @@ export async function fetchBackupSchedule() {
|
||||
}
|
||||
|
||||
export async function updateBackupSchedule(payload: BackupSchedule) {
|
||||
const { data } = await apiClient.put<ApiResponse<BackupSchedule>>('/admin/backups/schedule', payload)
|
||||
const { data } = await apiClient.put<ApiResponse<BackupSchedule>>(
|
||||
'/admin/backups/schedule',
|
||||
payload
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -337,7 +337,9 @@ async function handleArbitrate() {
|
||||
result: result.value,
|
||||
remark: remark.value.trim(),
|
||||
amount_cent:
|
||||
isCompletedResult.value && amount.value !== undefined ? yuanToCent(amount.value) : undefined,
|
||||
isCompletedResult.value && amount.value !== undefined
|
||||
? yuanToCent(amount.value)
|
||||
: undefined,
|
||||
actual_coin_consumed_m: isCompletedResult.value ? actualCoinConsumedM.value : undefined,
|
||||
actual_consumable_amount_cent: isCompletedResult.value
|
||||
? yuanToCent(actualConsumableAmountYuan.value)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ interface RiskItem {
|
||||
level: RiskLevel
|
||||
}
|
||||
|
||||
const defaultScreenshotURL = '/api/listings/default-upload-screenshot?v=webp1'
|
||||
const _defaultScreenshotURL = '/api/listings/default-upload-screenshot?v=webp1'
|
||||
const rejectReasonOptions = [
|
||||
'默认截图,需补充真实截图',
|
||||
'账号资产信息不完整',
|
||||
|
||||
@@ -209,10 +209,7 @@ function restoreListState() {
|
||||
if (typeof state.page === 'number' && state.page > 0) {
|
||||
currentPage.value = state.page
|
||||
}
|
||||
if (
|
||||
typeof state.pageSize === 'number' &&
|
||||
[10, 20, 50, 100].includes(state.pageSize)
|
||||
) {
|
||||
if (typeof state.pageSize === 'number' && [10, 20, 50, 100].includes(state.pageSize)) {
|
||||
pageSize.value = state.pageSize
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -78,11 +78,9 @@ async function handleSave() {
|
||||
|
||||
async function handleDelete(item: MohongCategory) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确认删除分类「${item.name}」?其下商品将变为未分类。`,
|
||||
'提示',
|
||||
{ type: 'warning' }
|
||||
)
|
||||
await ElMessageBox.confirm(`确认删除分类「${item.name}」?其下商品将变为未分类。`, '提示', {
|
||||
type: 'warning',
|
||||
})
|
||||
await deleteAdminMohongCategory(item.id)
|
||||
ElMessage.success('已删除')
|
||||
await load()
|
||||
|
||||
@@ -64,7 +64,9 @@ async function uploadQrcode(file: File) {
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h2>撞车配置</h2>
|
||||
<p>全局默认固定二维码与订单复制模板。商品可覆盖默认二维码;支付后用户在订单详情扫码并复制信息联系客服。</p>
|
||||
<p>
|
||||
全局默认固定二维码与订单复制模板。商品可覆盖默认二维码;支付后用户在订单详情扫码并复制信息联系客服。
|
||||
</p>
|
||||
</div>
|
||||
<el-button type="primary" :loading="saving" @click="handleSave">保存配置</el-button>
|
||||
</div>
|
||||
@@ -91,8 +93,9 @@ async function uploadQrcode(file: File) {
|
||||
<div class="hint">
|
||||
可用变量:{{order_no}} {{created_at}}
|
||||
{{items}}(多商品明细) {{product_title}}
|
||||
{{quantity}} {{amount}} {{buyer_name}}
|
||||
{{buyer_phone}} {{unit}}
|
||||
{{quantity}} {{amount}}
|
||||
{{buyer_name}} {{buyer_phone}}
|
||||
{{unit}}
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -128,9 +128,7 @@ function canComplete(row: MohongOrder) {
|
||||
}
|
||||
|
||||
function canCancel(row: MohongOrder) {
|
||||
return (
|
||||
row.status === 'pending_payment' || row.status === 'paid' || row.status === 'receiving'
|
||||
)
|
||||
return row.status === 'pending_payment' || row.status === 'paid' || row.status === 'receiving'
|
||||
}
|
||||
|
||||
function canRefund(row: MohongOrder) {
|
||||
@@ -158,7 +156,13 @@ async function copyText(text: string) {
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<el-input v-model="keyword" clearable placeholder="订单号" style="width: 220px" @keyup.enter="load" />
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
clearable
|
||||
placeholder="订单号"
|
||||
style="width: 220px"
|
||||
@keyup.enter="load"
|
||||
/>
|
||||
<el-select v-model="status" clearable placeholder="状态" style="width: 140px">
|
||||
<el-option label="待支付" value="pending_payment" />
|
||||
<el-option label="已支付" value="paid" />
|
||||
@@ -167,7 +171,7 @@ async function copyText(text: string) {
|
||||
<el-option label="已取消" value="cancelled" />
|
||||
<el-option label="已退款" value="refunded" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click=";(page = 1), load()">查询</el-button>
|
||||
<el-button type="primary" @click=";((page = 1), load())">查询</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="items" border stripe>
|
||||
@@ -262,7 +266,11 @@ async function copyText(text: string) {
|
||||
</div>
|
||||
<div v-if="detail.qrcode_url_snapshot" class="qr-box">
|
||||
<strong>二维码快照</strong>
|
||||
<el-image :src="detail.qrcode_url_snapshot" fit="contain" style="width: 180px; height: 180px" />
|
||||
<el-image
|
||||
:src="detail.qrcode_url_snapshot"
|
||||
fit="contain"
|
||||
style="width: 180px; height: 180px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
@@ -207,7 +207,13 @@ function removeGallery(url: string) {
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<el-input v-model="keyword" clearable placeholder="搜索标题" style="width: 220px" @keyup.enter="load" />
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
clearable
|
||||
placeholder="搜索标题"
|
||||
style="width: 220px"
|
||||
@keyup.enter="load"
|
||||
/>
|
||||
<el-select v-model="categoryId" clearable placeholder="分类" style="width: 140px">
|
||||
<el-option v-for="c in categories" :key="c.id" :label="c.name" :value="c.id" />
|
||||
</el-select>
|
||||
@@ -216,7 +222,7 @@ function removeGallery(url: string) {
|
||||
<el-option label="上架中" value="on_sale" />
|
||||
<el-option label="已下架" value="off_sale" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click=";(page = 1), load()">查询</el-button>
|
||||
<el-button type="primary" @click=";((page = 1), load())">查询</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="items" border stripe>
|
||||
@@ -273,7 +279,12 @@ function removeGallery(url: string) {
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="分类">
|
||||
<el-select v-model="form.category_id" clearable placeholder="选择分类" style="width: 100%">
|
||||
<el-select
|
||||
v-model="form.category_id"
|
||||
clearable
|
||||
placeholder="选择分类"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="c in categories" :key="c.id" :label="c.name" :value="c.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -288,7 +299,11 @@ function removeGallery(url: string) {
|
||||
style="width: 80px; height: 80px; border-radius: 8px"
|
||||
fit="cover"
|
||||
/>
|
||||
<el-upload :show-file-list="false" accept="image/*" :before-upload="(f: File) => uploadImage(f, 'cover')">
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
accept="image/*"
|
||||
:before-upload="(f: File) => uploadImage(f, 'cover')"
|
||||
>
|
||||
<el-button :icon="Upload">上传封面</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
@@ -299,7 +314,11 @@ function removeGallery(url: string) {
|
||||
<el-image :src="url" fit="cover" />
|
||||
<button type="button" @click="removeGallery(url)">×</button>
|
||||
</div>
|
||||
<el-upload :show-file-list="false" accept="image/*" :before-upload="(f: File) => uploadImage(f, 'gallery')">
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
accept="image/*"
|
||||
:before-upload="(f: File) => uploadImage(f, 'gallery')"
|
||||
>
|
||||
<el-button :icon="Upload">添加图片</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
@@ -331,7 +350,11 @@ function removeGallery(url: string) {
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专属二维码">
|
||||
<el-switch v-model="form.use_custom_qrcode" active-text="覆盖默认" inactive-text="用默认" />
|
||||
<el-switch
|
||||
v-model="form.use_custom_qrcode"
|
||||
active-text="覆盖默认"
|
||||
inactive-text="用默认"
|
||||
/>
|
||||
<div v-if="form.use_custom_qrcode" class="upload-row" style="margin-top: 8px">
|
||||
<el-image
|
||||
v-if="form.qrcode_image_url"
|
||||
|
||||
@@ -234,10 +234,20 @@ function statusType(status: string) {
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker v-model="filters.start_date" class="full-control" type="date" value-format="YYYY-MM-DD" />
|
||||
<el-date-picker
|
||||
v-model="filters.start_date"
|
||||
class="full-control"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="filters.end_date" class="full-control" type="date" value-format="YYYY-MM-DD" />
|
||||
<el-date-picker
|
||||
v-model="filters.end_date"
|
||||
class="full-control"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="filters.status" clearable placeholder="全部状态" class="full-control">
|
||||
@@ -249,7 +259,12 @@ function statusType(status: string) {
|
||||
<el-input v-model="filters.category" clearable placeholder="按类别精确筛选" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="filters.keyword" clearable placeholder="单号、收款方或用途" @keyup.enter="search" />
|
||||
<el-input
|
||||
v-model="filters.keyword"
|
||||
clearable
|
||||
placeholder="单号、收款方或用途"
|
||||
@keyup.enter="search"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -264,13 +279,17 @@ function statusType(status: string) {
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开支金额" min-width="135" align="right">
|
||||
<template #default="{ row }"><strong>{{ money(row.amount_cent) }}</strong></template>
|
||||
<template #default="{ row }"
|
||||
><strong>{{ money(row.amount_cent) }}</strong></template
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="开支时间" min-width="175">
|
||||
<template #default="{ row }">{{ formatDateTime(row.occurred_at) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="105" align="center">
|
||||
<template #default="{ row }"><el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag></template>
|
||||
<template #default="{ row }"
|
||||
><el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag></template
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="录入人" min-width="120">
|
||||
<template #default="{ row }">{{ row.created_by_name || '-' }}</template>
|
||||
@@ -280,7 +299,9 @@ function statusType(status: string) {
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="145" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" :icon="View" @click="selectedExpense = row">详情</el-button>
|
||||
<el-button link type="primary" :icon="View" @click="selectedExpense = row"
|
||||
>详情</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="row.status === 'paid' && canManage"
|
||||
link
|
||||
@@ -304,60 +325,148 @@ function statusType(status: string) {
|
||||
@page-change="loadItems"
|
||||
/>
|
||||
|
||||
<el-dialog v-model="createVisible" title="新增运营开支" width="560px" :close-on-click-modal="false">
|
||||
<el-dialog
|
||||
v-model="createVisible"
|
||||
title="新增运营开支"
|
||||
width="560px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form class="expense-form" label-position="top" @submit.prevent="submitExpense">
|
||||
<el-form-item label="开支类别" required>
|
||||
<el-input v-model="createForm.category" maxlength="50" placeholder="例如:推广投放、办公采购" />
|
||||
<el-input
|
||||
v-model="createForm.category"
|
||||
maxlength="50"
|
||||
placeholder="例如:推广投放、办公采购"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="收款方" required>
|
||||
<el-input v-model="createForm.payee_name" maxlength="100" placeholder="姓名或单位名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开支金额" required>
|
||||
<el-input-number v-model="createForm.amount_yuan" class="full-control" :min="0.01" :precision="2" :step="100" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="createForm.amount_yuan"
|
||||
class="full-control"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
:step="100"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开支时间" required>
|
||||
<el-date-picker v-model="createForm.occurred_at" class="full-control" type="datetime" placeholder="选择开支时间" />
|
||||
<el-date-picker
|
||||
v-model="createForm.occurred_at"
|
||||
class="full-control"
|
||||
type="datetime"
|
||||
placeholder="选择开支时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="expense-form-wide" label="开支用途" required>
|
||||
<el-input v-model="createForm.remark" type="textarea" :rows="3" maxlength="500" show-word-limit placeholder="填写开支用途" />
|
||||
<el-input
|
||||
v-model="createForm.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="填写开支用途"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="expense-form-wide" label="开支凭证(选填)">
|
||||
<div v-if="createForm.voucher_url" class="voucher-preview">
|
||||
<AuthImage :source="createForm.voucher_url" :admin="true" fit="cover" :preview-src-list="[createForm.voucher_url]" :image-style="{ width: '104px', height: '104px', borderRadius: '6px' }" />
|
||||
<el-button class="voucher-remove" circle plain type="danger" :icon="CircleClose" title="移除凭证" @click="createForm.voucher_url = ''" />
|
||||
<AuthImage
|
||||
:source="createForm.voucher_url"
|
||||
:admin="true"
|
||||
fit="cover"
|
||||
:preview-src-list="[createForm.voucher_url]"
|
||||
:image-style="{ width: '104px', height: '104px', borderRadius: '6px' }"
|
||||
/>
|
||||
<el-button
|
||||
class="voucher-remove"
|
||||
circle
|
||||
plain
|
||||
type="danger"
|
||||
:icon="CircleClose"
|
||||
title="移除凭证"
|
||||
@click="createForm.voucher_url = ''"
|
||||
/>
|
||||
</div>
|
||||
<el-upload v-else :show-file-list="false" :http-request="uploadVoucher" accept="image/jpeg,image/png,image/webp">
|
||||
<el-upload
|
||||
v-else
|
||||
:show-file-list="false"
|
||||
:http-request="uploadVoucher"
|
||||
accept="image/jpeg,image/png,image/webp"
|
||||
>
|
||||
<el-button :icon="UploadFilled" :loading="voucherUploading">上传凭证</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="createSaving" @click="createVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="createSaving" :disabled="voucherUploading" @click="submitExpense">确认记账</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="createSaving"
|
||||
:disabled="voucherUploading"
|
||||
@click="submitExpense"
|
||||
>确认记账</el-button
|
||||
>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :model-value="!!selectedExpense" title="运营开支详情" width="620px" @update:model-value="selectedExpense = null">
|
||||
<el-dialog
|
||||
:model-value="!!selectedExpense"
|
||||
title="运营开支详情"
|
||||
width="620px"
|
||||
@update:model-value="selectedExpense = null"
|
||||
>
|
||||
<el-descriptions v-if="selectedExpense" :column="2" border>
|
||||
<el-descriptions-item label="开支单号">{{ selectedExpense.expense_no }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态"><el-tag :type="statusType(selectedExpense.status)">{{ statusLabel(selectedExpense.status) }}</el-tag></el-descriptions-item>
|
||||
<el-descriptions-item label="开支单号">{{
|
||||
selectedExpense.expense_no
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态"
|
||||
><el-tag :type="statusType(selectedExpense.status)">{{
|
||||
statusLabel(selectedExpense.status)
|
||||
}}</el-tag></el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="开支类别">{{ selectedExpense.category }}</el-descriptions-item>
|
||||
<el-descriptions-item label="收款方">{{ selectedExpense.payee_name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开支金额"><strong>{{ money(selectedExpense.amount_cent) }}</strong></el-descriptions-item>
|
||||
<el-descriptions-item label="开支时间">{{ formatDateTime(selectedExpense.occurred_at) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="录入人">{{ selectedExpense.created_by_name || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="录入时间">{{ formatDateTime(selectedExpense.created_at) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开支用途" :span="2">{{ selectedExpense.remark }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开支金额"
|
||||
><strong>{{ money(selectedExpense.amount_cent) }}</strong></el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="开支时间">{{
|
||||
formatDateTime(selectedExpense.occurred_at)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="录入人">{{
|
||||
selectedExpense.created_by_name || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="录入时间">{{
|
||||
formatDateTime(selectedExpense.created_at)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="开支用途" :span="2">{{
|
||||
selectedExpense.remark
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="selectedExpense.voucher_url" label="开支凭证" :span="2">
|
||||
<AuthImage :source="selectedExpense.voucher_url" :admin="true" fit="cover" :preview-src-list="[selectedExpense.voucher_url]" :image-style="{ width: '140px', height: '140px', borderRadius: '6px' }" />
|
||||
<AuthImage
|
||||
:source="selectedExpense.voucher_url"
|
||||
:admin="true"
|
||||
fit="cover"
|
||||
:preview-src-list="[selectedExpense.voucher_url]"
|
||||
:image-style="{ width: '140px', height: '140px', borderRadius: '6px' }"
|
||||
/>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="selectedExpense.status === 'voided'" label="作废信息" :span="2">
|
||||
{{ selectedExpense.voided_by_name || '-' }} · {{ formatDateTime(selectedExpense.voided_at) }} · {{ selectedExpense.void_reason || '-' }}
|
||||
{{ selectedExpense.voided_by_name || '-' }} ·
|
||||
{{ formatDateTime(selectedExpense.voided_at) }} · {{ selectedExpense.void_reason || '-' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template #footer>
|
||||
<el-button @click="selectedExpense = null">关闭</el-button>
|
||||
<el-button v-if="selectedExpense?.status === 'paid' && canManage" type="danger" :icon="CircleClose" :loading="actionID === selectedExpense.id" @click="handleVoid(selectedExpense)">作废记录</el-button>
|
||||
<el-button
|
||||
v-if="selectedExpense?.status === 'paid' && canManage"
|
||||
type="danger"
|
||||
:icon="CircleClose"
|
||||
:loading="actionID === selectedExpense.id"
|
||||
@click="handleVoid(selectedExpense)"
|
||||
>作废记录</el-button
|
||||
>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user