121 lines
4.2 KiB
Vue
121 lines
4.2 KiB
Vue
<template>
|
|
<view class="page">
|
|
<fy-header :title="title" back />
|
|
<view v-if="!allowed" class="deny">当前账号没有「{{ title }}」查看权限</view>
|
|
<view v-else>
|
|
<scroll-view scroll-x class="tabs">
|
|
<text v-for="t in tabs" :key="t.id" class="tab" :class="{ on: tab === t.id }" @click="switchTab(t)">{{ t.title }}</text>
|
|
</scroll-view>
|
|
<view v-if="loading" class="empty">加载中…</view>
|
|
<view v-else-if="!rows.length" class="empty">暂无数据</view>
|
|
<view v-for="r in rows" :key="r.id || r.no || r.code" class="card item">
|
|
<text class="t">{{ titleOf(r) }}</text>
|
|
<text class="s">{{ subOf(r) }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import FyHeader from '../../components/fy-header.vue'
|
|
import { store } from '../../utils/store.js'
|
|
import { ERP_MODULES, ERP_TABS } from '../../utils/catalog.js'
|
|
import { asList, firstText } from '../../utils/format.js'
|
|
import { oaGet } from '../../utils/api.js'
|
|
import { canMenu } from '../../utils/perms.js'
|
|
|
|
export default {
|
|
components: { FyHeader },
|
|
data() {
|
|
return { id: '', tab: '', rows: [], loading: false }
|
|
},
|
|
computed: {
|
|
meta() { return ERP_MODULES.find((m) => m.id === this.id) || { title: '业务', menu: this.id } },
|
|
title() { return this.meta.title },
|
|
allowed() { return store.can(this.meta.menu || this.id, 'view') },
|
|
tabs() {
|
|
const all = ERP_TABS[this.id] || [{ id: 'all', title: '全部' }]
|
|
return all.filter((t) => canMenu(store.menus, this.id, t.action || 'view', !!(store.me && store.me.isSuper)))
|
|
}
|
|
},
|
|
onLoad(q) {
|
|
this.id = q.id || 'bidding'
|
|
const first = this.tabs[0]
|
|
this.tab = first ? first.id : ''
|
|
if (this.allowed) this.load()
|
|
},
|
|
methods: {
|
|
switchTab(t) {
|
|
this.tab = t.id
|
|
this.load()
|
|
},
|
|
titleOf(r) {
|
|
return firstText(r, ['title', 'name', 'project', 'code', 'no', 'realName', 'customer'], '记录')
|
|
},
|
|
subOf(r) {
|
|
return firstText(r, ['status', 'stage', 'owner', 'dept', 'submitter', 'createdAt'], '')
|
|
},
|
|
async load() {
|
|
this.loading = true
|
|
try {
|
|
this.rows = asList(await oaGet(this.path(), store.token))
|
|
} catch (_) {
|
|
this.rows = []
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
path() {
|
|
const id = this.id
|
|
const tab = this.tab
|
|
if (id === 'bidding') {
|
|
if (tab === 'stats') return '/bid/registries'
|
|
return '/bid/cases'
|
|
}
|
|
if (id === 'project') {
|
|
if (tab === 'workhours') return '/project/hours'
|
|
if (tab === 'accept') return '/project/accepts'
|
|
return '/project/projects'
|
|
}
|
|
if (id === 'finance') return `/finance/bills?type=${tab === 'ledger' ? '' : tab}`
|
|
if (id === 'hr') {
|
|
if (tab === 'org') return '/org/depts'
|
|
if (tab === 'attendance') return '/hr/attendance'
|
|
if (tab === 'salary') return '/hr/payroll'
|
|
if (tab === 'notice') return '/announcements'
|
|
return '/hr/staff'
|
|
}
|
|
if (id === 'contracts') return `/contracts?kind=${tab}`
|
|
if (id === 'seals') {
|
|
if (tab === 'qualification') return '/seals/qualifications'
|
|
if (tab === 'borrow') return '/seals/borrows'
|
|
if (tab === 'manage') return '/seals'
|
|
return '/seals/logs'
|
|
}
|
|
if (id === 'crm') {
|
|
if (tab === 'opportunity') return '/crm/opportunities'
|
|
if (tab === 'pool') return '/crm/pool'
|
|
return '/crm/customers'
|
|
}
|
|
if (id === 'system') {
|
|
if (tab === 'attend') return '/system/attend-rules'
|
|
if (tab === 'logs') return '/system/logs'
|
|
if (tab === 'online') return '/system/online'
|
|
return '/system/perm-grants'
|
|
}
|
|
return '/dashboard/overview'
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.tabs { white-space: nowrap; padding: 16rpx 16rpx 0; }
|
|
.tab { display: inline-block; padding: 12rpx 20rpx; font-size: 24rpx; color: #6B7280; }
|
|
.tab.on { color: #1677FF; font-weight: 700; border-bottom: 4rpx solid #1677FF; }
|
|
.item { margin: 16rpx 24rpx; padding: 24rpx; }
|
|
.t { display: block; font-weight: 600; font-size: 28rpx; }
|
|
.s { font-size: 22rpx; color: #6B7280; }
|
|
.empty, .deny { padding: 80rpx 40rpx; text-align: center; color: #6B7280; }
|
|
</style>
|