288 lines
9.6 KiB
Vue
288 lines
9.6 KiB
Vue
<template>
|
|
<div class="personal-account-cost-page">
|
|
<el-card class="!border-none mb-4" shadow="never">
|
|
<div class="flex flex-wrap">
|
|
<div class="w-1/2 md:w-1/3">
|
|
<div class="leading-10">当前筛选天数</div>
|
|
<div class="text-4xl">{{ pager.extend.days_count ?? 0 }}</div>
|
|
</div>
|
|
<div class="w-1/2 md:w-1/3">
|
|
<div class="leading-10">累计账户消耗 (元)</div>
|
|
<div class="text-4xl">¥{{ pager.extend.total_amount ?? '0.00' }}</div>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
|
|
<el-card class="!border-none" shadow="never">
|
|
<el-form :inline="true" :model="queryParams" class="stats-filter-form">
|
|
<list-time-filter
|
|
v-model:time-type="time_type"
|
|
v-model:date-range="dateRange"
|
|
@time-type-change="onTimeTypeChange"
|
|
@custom-change="onCustomDateChange"
|
|
/>
|
|
|
|
<el-form-item label="部门">
|
|
<el-tree-select
|
|
v-model="queryParams.dept_id"
|
|
:data="deptOptions"
|
|
node-key="id"
|
|
:props="deptTreeProps"
|
|
:default-expand-all="true"
|
|
check-strictly
|
|
placeholder="全部部门"
|
|
clearable
|
|
filterable
|
|
class="w-[220px]"
|
|
@change="handleQuery"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="自媒体来源">
|
|
<media-source-select
|
|
v-model="queryParams.media_source"
|
|
:options="mediaSourceOptions"
|
|
:loading="mediaSourceLoading"
|
|
placeholder="全部来源"
|
|
:allow-create="false"
|
|
select-class="w-[220px]"
|
|
@change="handleQuery"
|
|
@visible-change="onMediaSourceDropdownVisible"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item class="w-[280px]" label="备注/录入人">
|
|
<el-input
|
|
v-model="queryParams.remark"
|
|
placeholder="备注 / 创建人"
|
|
clearable
|
|
@keyup.enter="handleQuery"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" :loading="pager.loading" @click="handleQuery">查询</el-button>
|
|
<el-button @click="handleReset">重置</el-button>
|
|
<el-button v-if="selfInputPath" class="ml-2" @click="goSelfInput">返回统计</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-card>
|
|
|
|
<el-card class="!border-none mt-4" shadow="never">
|
|
<div>
|
|
<el-button v-perms="['stats.personal_account_cost/add']" type="primary" @click="handleAdd">
|
|
<template #icon>
|
|
<icon name="el-icon-Plus" />
|
|
</template>
|
|
新增
|
|
</el-button>
|
|
</div>
|
|
|
|
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
|
|
<el-table-column label="日期" prop="cost_date" min-width="120" />
|
|
<el-table-column label="自媒体来源" prop="media_source" min-width="160" show-overflow-tooltip />
|
|
<el-table-column label="账户消耗" min-width="120">
|
|
<template #default="{ row }">¥{{ row.amount }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="备注" prop="remark" min-width="200" show-overflow-tooltip />
|
|
<el-table-column label="录入人" prop="creator_name" min-width="100" />
|
|
<el-table-column label="部门" prop="dept_name" min-width="140">
|
|
<template #default="{ row }">
|
|
<el-tooltip
|
|
v-if="row.dept_path"
|
|
:content="row.dept_path"
|
|
placement="top"
|
|
effect="dark"
|
|
>
|
|
<span class="dept-cell">{{ row.dept_name || '未分配' }}</span>
|
|
</el-tooltip>
|
|
<span v-else-if="row.dept_name">{{ row.dept_name }}</span>
|
|
<span v-else class="text-gray-400">未分配</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="最后修改人" prop="updater_name" min-width="100" />
|
|
<el-table-column label="更新时间" prop="update_time" min-width="180" />
|
|
<el-table-column label="操作" width="160" fixed="right">
|
|
<template #default="{ row }">
|
|
<el-button
|
|
v-perms="['stats.personal_account_cost/edit']"
|
|
type="primary"
|
|
link
|
|
@click="handleEdit(row)"
|
|
>
|
|
编辑
|
|
</el-button>
|
|
<el-button
|
|
v-perms="['stats.personal_account_cost/delete']"
|
|
type="danger"
|
|
link
|
|
@click="handleDelete(row.id)"
|
|
>
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="flex justify-end mt-4">
|
|
<pagination v-model="pager" @change="getLists" />
|
|
</div>
|
|
</el-card>
|
|
|
|
<cost-edit-popup
|
|
v-if="showEdit"
|
|
ref="editRef"
|
|
:media-source-options="mediaSourceOptions"
|
|
:media-source-loading="mediaSourceLoading"
|
|
@success="handleCostSuccess"
|
|
@close="showEdit = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup name="personalAccountCost">
|
|
import { personalAccountCostDelete, personalAccountCostLists } from '@/api/self_input_stats'
|
|
import { deptAll } from '@/api/org/department'
|
|
import { usePaging } from '@/hooks/usePaging'
|
|
import { getRoutePath } from '@/router'
|
|
import feedback from '@/utils/feedback'
|
|
|
|
import CostEditPopup from './cost-edit.vue'
|
|
import MediaSourceSelect from './MediaSourceSelect.vue'
|
|
import { useMediaSourceOptions } from './useMediaSourceOptions'
|
|
import ListTimeFilter from '@/components/list-time-filter/index.vue'
|
|
import { useListTimeFilter } from '@/hooks/useListTimeFilter'
|
|
|
|
const router = useRouter()
|
|
const editRef = shallowRef<InstanceType<typeof CostEditPopup>>()
|
|
const showEdit = ref(false)
|
|
const deptOptions = ref<any[]>([])
|
|
const {
|
|
mediaSourceOptions,
|
|
mediaSourceLoading,
|
|
loadMediaSourceOptions,
|
|
refreshMediaSourceOptions,
|
|
} = useMediaSourceOptions()
|
|
|
|
const deptTreeProps = {
|
|
value: 'id',
|
|
label: 'name',
|
|
children: 'children',
|
|
}
|
|
|
|
const selfInputPath = computed(() => getRoutePath('stats.self_input/overview') || '')
|
|
|
|
const goSelfInput = () => {
|
|
if (selfInputPath.value) {
|
|
router.push(selfInputPath.value)
|
|
}
|
|
}
|
|
|
|
const queryParams = reactive({
|
|
media_source: '',
|
|
dept_id: undefined as number | undefined,
|
|
remark: '',
|
|
})
|
|
|
|
const {
|
|
time_type,
|
|
dateRange,
|
|
resolve,
|
|
handleTimeTypeChange,
|
|
handleCustomDateChange,
|
|
resetTimeFilter,
|
|
} = useListTimeFilter('today')
|
|
|
|
const { pager, getLists, resetPage } = usePaging({
|
|
fetchFun: async (params: Record<string, any>) => {
|
|
const [start_date, end_date] = resolve()
|
|
return personalAccountCostLists({
|
|
...params,
|
|
start_date,
|
|
end_date,
|
|
})
|
|
},
|
|
params: queryParams,
|
|
})
|
|
|
|
const handleQuery = () => {
|
|
pager.page = 1
|
|
getLists()
|
|
}
|
|
|
|
const onTimeTypeChange = () => handleTimeTypeChange(handleQuery)
|
|
const onCustomDateChange = () => handleCustomDateChange(handleQuery)
|
|
|
|
const handleReset = () => {
|
|
resetTimeFilter()
|
|
queryParams.media_source = ''
|
|
queryParams.dept_id = undefined
|
|
queryParams.remark = ''
|
|
pager.page = 1
|
|
pager.size = 15
|
|
getLists()
|
|
}
|
|
|
|
const onMediaSourceDropdownVisible = (visible: boolean) => {
|
|
if (visible) {
|
|
refreshMediaSourceOptions()
|
|
}
|
|
}
|
|
|
|
const handleCostSuccess = async () => {
|
|
await refreshMediaSourceOptions()
|
|
getLists()
|
|
}
|
|
|
|
const handleAdd = async () => {
|
|
await refreshMediaSourceOptions()
|
|
showEdit.value = true
|
|
await nextTick()
|
|
editRef.value?.open('add')
|
|
}
|
|
|
|
const handleEdit = async (row: Record<string, any>) => {
|
|
showEdit.value = true
|
|
await nextTick()
|
|
editRef.value?.open('edit')
|
|
editRef.value?.setFormData(row)
|
|
}
|
|
|
|
const handleDelete = async (id: number) => {
|
|
await feedback.confirm('确定删除该账户消耗记录?')
|
|
await personalAccountCostDelete({ id })
|
|
getLists()
|
|
}
|
|
|
|
const loadDeptOptions = async () => {
|
|
try {
|
|
const res = await deptAll({ apply_data_scope: 1 })
|
|
if (Array.isArray(res)) {
|
|
deptOptions.value = res
|
|
}
|
|
} catch (e) {
|
|
deptOptions.value = []
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
loadDeptOptions()
|
|
loadMediaSourceOptions()
|
|
await getLists()
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.personal-account-cost-page {
|
|
padding: 20px;
|
|
}
|
|
|
|
.stats-filter-form {
|
|
:deep(.el-form-item) {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
.dept-cell {
|
|
cursor: help;
|
|
border-bottom: 1px dashed #c0c4cc;
|
|
}
|
|
</style>
|