forked from jiaoly/financial_system
feat: add realtime attendance and monthly payroll menus
This commit is contained in:
parent
a846ea5070
commit
dc74a618f7
@ -12,6 +12,12 @@ PERMISSION_PAYROLL_EXCEL_CALCULATE = "payroll:excel:calculate"
|
|||||||
PERMISSION_PAYROLL_DINGTALK_CALCULATE = "payroll:dingtalk:calculate"
|
PERMISSION_PAYROLL_DINGTALK_CALCULATE = "payroll:dingtalk:calculate"
|
||||||
PERMISSION_PAYROLL_JOB_VIEW = "payroll:job:view"
|
PERMISSION_PAYROLL_JOB_VIEW = "payroll:job:view"
|
||||||
PERMISSION_PAYROLL_FILE_DOWNLOAD = "payroll:file:download"
|
PERMISSION_PAYROLL_FILE_DOWNLOAD = "payroll:file:download"
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_VIEW = "attendance:realtime:view"
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_SYNC = "attendance:realtime:sync"
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_VIEW = "monthly_payroll:view"
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_CALCULATE = "monthly_payroll:calculate"
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_LOCK = "monthly_payroll:lock"
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_EXPORT = "monthly_payroll:export"
|
||||||
PERMISSION_USER_CREATE = "user:create"
|
PERMISSION_USER_CREATE = "user:create"
|
||||||
PERMISSION_USER_LIST = "user:list"
|
PERMISSION_USER_LIST = "user:list"
|
||||||
PERMISSION_OPERATION_LOG_VIEW = "operation_log:view"
|
PERMISSION_OPERATION_LOG_VIEW = "operation_log:view"
|
||||||
@ -38,6 +44,8 @@ class MenuPermission:
|
|||||||
|
|
||||||
|
|
||||||
MENUS = {
|
MENUS = {
|
||||||
|
"attendance_realtime": MenuPermission(code="attendance_realtime", name="实时考勤", path="/attendance/realtime"),
|
||||||
|
"monthly_payroll": MenuPermission(code="monthly_payroll", name="月度核算", path="/payroll/monthly"),
|
||||||
"payroll": MenuPermission(code="payroll", name="工资计算", path="/payroll"),
|
"payroll": MenuPermission(code="payroll", name="工资计算", path="/payroll"),
|
||||||
"jobs": MenuPermission(code="jobs", name="计算记录", path="/payroll/jobs"),
|
"jobs": MenuPermission(code="jobs", name="计算记录", path="/payroll/jobs"),
|
||||||
"employees": MenuPermission(code="employees", name="员工维护", path="/system/employees"),
|
"employees": MenuPermission(code="employees", name="员工维护", path="/system/employees"),
|
||||||
@ -52,6 +60,8 @@ MENUS = {
|
|||||||
|
|
||||||
ROLE_MENU_CODES = {
|
ROLE_MENU_CODES = {
|
||||||
ROLE_SUPERUSER: (
|
ROLE_SUPERUSER: (
|
||||||
|
"attendance_realtime",
|
||||||
|
"monthly_payroll",
|
||||||
"payroll",
|
"payroll",
|
||||||
"jobs",
|
"jobs",
|
||||||
"employees",
|
"employees",
|
||||||
@ -64,6 +74,8 @@ ROLE_MENU_CODES = {
|
|||||||
"operation_logs",
|
"operation_logs",
|
||||||
),
|
),
|
||||||
ROLE_MANAGER: (
|
ROLE_MANAGER: (
|
||||||
|
"attendance_realtime",
|
||||||
|
"monthly_payroll",
|
||||||
"payroll",
|
"payroll",
|
||||||
"jobs",
|
"jobs",
|
||||||
"employees",
|
"employees",
|
||||||
@ -74,11 +86,17 @@ ROLE_MENU_CODES = {
|
|||||||
"configs",
|
"configs",
|
||||||
"operation_logs",
|
"operation_logs",
|
||||||
),
|
),
|
||||||
ROLE_VIEWER: ("jobs", "reports"),
|
ROLE_VIEWER: ("attendance_realtime", "jobs", "reports"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ROLE_OPERATION_PERMISSIONS = {
|
ROLE_OPERATION_PERMISSIONS = {
|
||||||
ROLE_SUPERUSER: (
|
ROLE_SUPERUSER: (
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_VIEW,
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_SYNC,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_VIEW,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_CALCULATE,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_LOCK,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_EXPORT,
|
||||||
PERMISSION_PAYROLL_EXCEL_CALCULATE,
|
PERMISSION_PAYROLL_EXCEL_CALCULATE,
|
||||||
PERMISSION_PAYROLL_DINGTALK_CALCULATE,
|
PERMISSION_PAYROLL_DINGTALK_CALCULATE,
|
||||||
PERMISSION_PAYROLL_JOB_VIEW,
|
PERMISSION_PAYROLL_JOB_VIEW,
|
||||||
@ -99,6 +117,12 @@ ROLE_OPERATION_PERMISSIONS = {
|
|||||||
PERMISSION_REPORT_VIEW,
|
PERMISSION_REPORT_VIEW,
|
||||||
),
|
),
|
||||||
ROLE_MANAGER: (
|
ROLE_MANAGER: (
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_VIEW,
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_SYNC,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_VIEW,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_CALCULATE,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_LOCK,
|
||||||
|
PERMISSION_MONTHLY_PAYROLL_EXPORT,
|
||||||
PERMISSION_PAYROLL_EXCEL_CALCULATE,
|
PERMISSION_PAYROLL_EXCEL_CALCULATE,
|
||||||
PERMISSION_PAYROLL_DINGTALK_CALCULATE,
|
PERMISSION_PAYROLL_DINGTALK_CALCULATE,
|
||||||
PERMISSION_PAYROLL_JOB_VIEW,
|
PERMISSION_PAYROLL_JOB_VIEW,
|
||||||
@ -117,6 +141,7 @@ ROLE_OPERATION_PERMISSIONS = {
|
|||||||
PERMISSION_REPORT_VIEW,
|
PERMISSION_REPORT_VIEW,
|
||||||
),
|
),
|
||||||
ROLE_VIEWER: (
|
ROLE_VIEWER: (
|
||||||
|
PERMISSION_ATTENDANCE_REALTIME_VIEW,
|
||||||
PERMISSION_PAYROLL_JOB_VIEW,
|
PERMISSION_PAYROLL_JOB_VIEW,
|
||||||
PERMISSION_PAYROLL_FILE_DOWNLOAD,
|
PERMISSION_PAYROLL_FILE_DOWNLOAD,
|
||||||
PERMISSION_REPORT_VIEW,
|
PERMISSION_REPORT_VIEW,
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import {
|
|||||||
Banknote,
|
Banknote,
|
||||||
BadgeDollarSign,
|
BadgeDollarSign,
|
||||||
Building2,
|
Building2,
|
||||||
|
Calculator,
|
||||||
|
CalendarClock,
|
||||||
ClipboardList,
|
ClipboardList,
|
||||||
FileChartColumn,
|
FileChartColumn,
|
||||||
LayoutDashboard,
|
LayoutDashboard,
|
||||||
@ -35,6 +37,8 @@ const auth = useAuthStore();
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const backendIconMap = {
|
const backendIconMap = {
|
||||||
|
attendance_realtime: CalendarClock,
|
||||||
|
monthly_payroll: Calculator,
|
||||||
payroll: Banknote,
|
payroll: Banknote,
|
||||||
jobs: ClipboardList,
|
jobs: ClipboardList,
|
||||||
employees: UserCog,
|
employees: UserCog,
|
||||||
|
|||||||
@ -8,9 +8,11 @@ import DashboardView from "../views/DashboardView.vue";
|
|||||||
import EmployeesView from "../views/EmployeesView.vue";
|
import EmployeesView from "../views/EmployeesView.vue";
|
||||||
import JobsView from "../views/JobsView.vue";
|
import JobsView from "../views/JobsView.vue";
|
||||||
import LoginView from "../views/LoginView.vue";
|
import LoginView from "../views/LoginView.vue";
|
||||||
|
import MonthlyPayrollView from "../views/MonthlyPayrollView.vue";
|
||||||
import OperationLogsView from "../views/OperationLogsView.vue";
|
import OperationLogsView from "../views/OperationLogsView.vue";
|
||||||
import OrganizationView from "../views/OrganizationView.vue";
|
import OrganizationView from "../views/OrganizationView.vue";
|
||||||
import PayrollView from "../views/PayrollView.vue";
|
import PayrollView from "../views/PayrollView.vue";
|
||||||
|
import RealtimeAttendanceView from "../views/RealtimeAttendanceView.vue";
|
||||||
import ReportsView from "../views/ReportsView.vue";
|
import ReportsView from "../views/ReportsView.vue";
|
||||||
import SalaryProfilesView from "../views/SalaryProfilesView.vue";
|
import SalaryProfilesView from "../views/SalaryProfilesView.vue";
|
||||||
import UsersView from "../views/UsersView.vue";
|
import UsersView from "../views/UsersView.vue";
|
||||||
@ -44,6 +46,18 @@ const router = createRouter({
|
|||||||
name: "dashboard",
|
name: "dashboard",
|
||||||
component: DashboardView,
|
component: DashboardView,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "attendance/realtime",
|
||||||
|
name: "attendance-realtime",
|
||||||
|
component: RealtimeAttendanceView,
|
||||||
|
meta: { permission: "attendance:realtime:view" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "payroll/monthly",
|
||||||
|
name: "monthly-payroll",
|
||||||
|
component: MonthlyPayrollView,
|
||||||
|
meta: { permission: "monthly_payroll:view" },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "payroll",
|
path: "payroll",
|
||||||
name: "payroll",
|
name: "payroll",
|
||||||
@ -137,6 +151,12 @@ router.beforeEach(async (to) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function firstAllowedPath(permissions: string[]): string {
|
function firstAllowedPath(permissions: string[]): string {
|
||||||
|
if (permissions.includes("attendance:realtime:view")) {
|
||||||
|
return "/attendance/realtime";
|
||||||
|
}
|
||||||
|
if (permissions.includes("monthly_payroll:view")) {
|
||||||
|
return "/payroll/monthly";
|
||||||
|
}
|
||||||
if (permissions.includes("payroll:excel:calculate")) {
|
if (permissions.includes("payroll:excel:calculate")) {
|
||||||
return "/payroll";
|
return "/payroll";
|
||||||
}
|
}
|
||||||
|
|||||||
48
frontend/src/views/MonthlyPayrollView.vue
Normal file
48
frontend/src/views/MonthlyPayrollView.vue
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Calculator, FileSpreadsheet, LockKeyhole, Upload } from "@lucide/vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="view-stack">
|
||||||
|
<header class="page-header">
|
||||||
|
<div>
|
||||||
|
<h1>月度核算</h1>
|
||||||
|
<p>按工资月份完成导入、计算、复核、锁定和导出。</p>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="secondary-button" type="button" disabled>
|
||||||
|
<Upload :size="18" aria-hidden="true" />
|
||||||
|
<span>导入 Excel</span>
|
||||||
|
</button>
|
||||||
|
<button class="primary-button" type="button" disabled>
|
||||||
|
<Calculator :size="18" aria-hidden="true" />
|
||||||
|
<span>同步并计算</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<div>
|
||||||
|
<h2>核算流程</h2>
|
||||||
|
<p>数据导入 -> 考勤转换 -> 异常处理 -> 工资计算 -> 复核锁定</p>
|
||||||
|
</div>
|
||||||
|
<span class="status-chip neutral">草稿</span>
|
||||||
|
</div>
|
||||||
|
<div class="empty-state">
|
||||||
|
<FileSpreadsheet :size="38" aria-hidden="true" />
|
||||||
|
<p>月度核算中心已接入菜单,下一阶段接入月度计算、异常清单和锁定逻辑。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<div>
|
||||||
|
<h2>锁定规则</h2>
|
||||||
|
<p>锁定后本月工资不可重新计算,仅允许导出。</p>
|
||||||
|
</div>
|
||||||
|
<LockKeyhole :size="22" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
38
frontend/src/views/RealtimeAttendanceView.vue
Normal file
38
frontend/src/views/RealtimeAttendanceView.vue
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { CalendarClock, CloudCog, RefreshCw } from "@lucide/vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="view-stack">
|
||||||
|
<header class="page-header">
|
||||||
|
<div>
|
||||||
|
<h1>实时考勤</h1>
|
||||||
|
<p>查看今日打卡状态,并预估本月薪资进度。</p>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="secondary-button" type="button" disabled>
|
||||||
|
<RefreshCw :size="18" aria-hidden="true" />
|
||||||
|
<span>刷新</span>
|
||||||
|
</button>
|
||||||
|
<button class="primary-button" type="button" disabled>
|
||||||
|
<CloudCog :size="18" aria-hidden="true" />
|
||||||
|
<span>同步钉钉</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<div>
|
||||||
|
<h2>今日考勤与薪资预估</h2>
|
||||||
|
<p>预估金额,最终以月度核算锁定结果为准。</p>
|
||||||
|
</div>
|
||||||
|
<span class="status-chip neutral">待接入</span>
|
||||||
|
</div>
|
||||||
|
<div class="empty-state">
|
||||||
|
<CalendarClock :size="38" aria-hidden="true" />
|
||||||
|
<p>实时考勤看板已接入菜单,下一阶段接入钉钉同步和薪资预估数据。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Loading…
Reference in New Issue
Block a user