babyhealth/pages/function/function.vue
2026-02-06 20:21:10 +08:00

554 lines
12 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="function-page">
<!-- 统一顶部导航 -->
<view class="unified-header">
<view class="header-content">
<view class="header-left">
<!-- <i class="fas fa-search header-icon" @click="handleSearch"></i> -->
</view>
<view class="header-title">功能</view>
<view class="header-right">
<!-- <i class="fas fa-bell header-icon" @click="handleNotification">
<view class="badge" v-if="unreadCount > 0">{{ unreadCount }}</view>
</i> -->
</view>
</view>
</view>
<!-- 最近使用 -->
<view class="recent-section" v-if="recentFunctions.length > 0">
<view class="section-title">最近使用</view>
<view class="recent-functions">
<view
class="recent-item"
v-for="(func, index) in recentFunctions"
:key="index"
@click="handleFunction(func)"
>
<view class="recent-icon">
<i
class="icon-text"
:class="func.icon"
:style="{ color: func.color }"
></i>
</view>
<text class="recent-label">{{ func.label }}</text>
</view>
</view>
</view>
<!-- 分类导航 -->
<view class="category-tabs">
<scroll-view scroll-x class="tabs-scroll">
<view class="tabs">
<view
class="tab-item"
:class="{ active: activeCategory === category.key }"
v-for="category in categories"
:key="category.key"
@click="switchCategory(category.key)"
>
<text>{{ category.label }}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 功能列表 -->
<scroll-view scroll-y class="unified-content">
<view class="function-list">
<view
class="function-group"
v-for="(group, groupIndex) in currentFunctions"
:key="groupIndex"
>
<view class="group-functions">
<view
class="function-item"
v-for="(func, funcIndex) in group.functions"
:key="funcIndex"
@click="handleFunction(func)"
>
<view class="function-icon">
<i
class="icon-text"
:class="func.icon"
:style="{ color: func.color }"
></i>
</view>
<view class="function-content">
<text class="function-name">{{ func.name }}</text>
<text class="function-desc">{{ func.description }}</text>
</view>
<view class="function-arrow">
<text class="arrow-icon"></text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { ref, reactive, computed } from "vue";
// 图标
const FA = {
clock: "fas fa-clock",
route: "fas fa-route",
calendar: "fas fa-calendar-alt",
tasks: "fas fa-tasks",
sync: "fas fa-sync-alt",
money: "fas fa-money-bill-wave",
file: "fas fa-file-alt",
userFriends: "fas fa-user-friends",
folder: "fas fa-folder-open",
chatBar: "far fa-chart-bar",
};
export default {
setup() {
// 响应式数据
const activeCategory = ref("datas");
const unreadCount = ref(2);
// 分类数据
const categories = reactive([
{ key: "datas", label: "业务数据" },
{ key: "hr", label: "人事管理" },
{ key: "finance", label: "财务报销" },
{ key: "work", label: "工作协同" },
{ key: "resource", label: "资源管理" },
]);
// 最近使用功能
const recentFunctions = reactive([
{ icon: FA.calendar, color: "#FF6B6B", label: "请假", action: "leave" },
{
icon: FA.money,
color: "#4ECDC4",
label: "报销",
action: "reimbursement",
},
{ icon: FA.route, color: "#45B7D1", label: "打卡", action: "checkin" },
]);
// 功能数据
const functionData = reactive({
datas: [
{
functions: [
{
name: "业务数据",
description: "查看业务数据",
icon: FA.chatBar,
color: "#0081ff",
action: "businessData",
},
{
name: "业务审批",
description: "审批相关业务流程",
icon: "fas fa-check-circle",
color: "#0081ff",
action: "approval",
},
],
},
],
hr: [
{
functions: [
{
name: "考勤打卡",
description: "支持定位打卡、WiFi打卡",
icon: FA.route,
color: "#0081ff",
action: "attendance",
},
{
name: "请假申请",
description: "选择类型、日期、理由,附附件",
icon: FA.calendar,
color: "#0081ff",
action: "leave",
},
{
name: "加班申请",
description: "申请加班,记录加班时长",
icon: FA.tasks,
color: "#0081ff",
action: "overtime",
},
{
name: "调休记录",
description: "查看调休申请和记录",
icon: FA.sync,
color: "#0081ff",
action: "compensatory",
},
],
},
],
finance: [
{
functions: [
{
name: "报销提交",
description: "选择报销类型、上传发票、填写金额",
icon: FA.money,
color: "#0081ff",
action: "reimbursement",
},
{
name: "报销进度",
description: "查看报销申请进度",
icon: FA.file,
color: "#0081ff",
action: "reimbursement-progress",
},
{
name: "报销历史",
description: "查看历史报销记录",
icon: FA.tasks,
color: "#0081ff",
action: "reimbursement-history",
},
],
},
],
work: [
{
functions: [
{
name: "待办任务",
description: "关联项目、设置截止时间",
icon: FA.tasks,
color: "#0081ff",
action: "todo",
},
{
name: "已办任务",
description: "查看已完成的任务",
icon: FA.tasks,
color: "#0081ff",
action: "completed",
},
{
name: "会议预订",
description: "选择会议室、邀请参会人",
icon: FA.calendar,
color: "#0081ff",
action: "meeting",
},
],
},
],
resource: [
{
functions: [
{
name: "客户目录",
description: "按行业、区域分类,显示联系方式",
icon: FA.userFriends,
color: "#0081ff",
action: "customer",
},
{
name: "企业文件库",
description: "按部门权限查看,支持在线预览",
icon: FA.folder,
color: "#0081ff",
action: "files",
},
],
},
],
});
// 计算当前分类的功能
const currentFunctions = computed(() => {
return functionData[activeCategory.value] || [];
});
// 方法
const handleSearch = () => {
uni.showToast({
title: "搜索功能",
});
};
//跳转通知页面
const handleNotification = () => {
uni.switchTab({
url: "/pages/message/message",
});
};
const switchCategory = (category) => {
activeCategory.value = category;
};
const handleFunction = (func) => {
//跳转业务数据页面
if (func.action === "businessData") {
uni.navigateTo({
url: "/pages/businessDatas/index",
});
return;
}
//跳转到业务审批界面
if (func.action === "approval") {
uni.navigateTo({
url: "/pages/tasks/approval",
});
return;
}
//跳转任务页面
if (func.action === "todo") {
uni.navigateTo({
url: "/pages/tasks/index",
});
return;
}
//跳转考勤页面
if (func.action === "attendance") {
uni.navigateTo({
url: "/pages/hr/attendance/index",
});
return;
}
uni.showToast({
title: `功能开发中...`,
});
};
return {
activeCategory,
unreadCount,
categories,
recentFunctions,
currentFunctions,
handleSearch,
handleNotification,
switchCategory,
handleFunction,
};
},
};
</script>
<style lang="scss" scoped>
.function-page {
height: 100vh;
background-color: var(--background);
position: relative;
padding-top: calc(var(--status-bar-height) + 88rpx);
}
/* 支持安全区域的设备 */
@supports (padding: max(0px)) {
.function-page {
padding-top: calc(
var(--status-bar-height) + 88rpx + env(safe-area-inset-top)
);
}
}
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
}
.search-box {
flex: 1;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 25rpx;
padding: 15rpx 20rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
}
.search-placeholder {
color: rgba(255, 255, 255, 0.8);
font-size: 28rpx;
margin-left: 10rpx;
}
.notification {
position: relative;
padding: 10rpx;
}
.recent-section {
background: var(--white);
padding: 30rpx;
border-bottom: 1rpx solid var(--border-light);
}
.section-title {
font-size: 28rpx;
font-weight: 600;
color: var(--text-color);
margin-bottom: 20rpx;
}
.recent-functions {
display: flex;
gap: 30rpx;
}
.recent-item {
display: flex;
flex-direction: column;
align-items: center;
}
.recent-icon {
margin-bottom: 10rpx;
}
.recent-label {
font-size: 24rpx;
color: var(--text-secondary);
}
.category-tabs {
background: var(--white);
border-bottom: 1rpx solid var(--border-light);
}
.tabs-scroll {
white-space: nowrap;
width: 100%;
}
.tabs {
display: flex;
padding: 0 30rpx;
min-width: max-content;
}
.tab-item {
padding: 30rpx 20rpx;
font-size: 28rpx;
color: var(--text-secondary);
white-space: nowrap;
position: relative;
flex-shrink: 0;
min-width: max-content;
}
.tab-item.active {
color: var(--primary-color);
font-weight: 600;
}
.tab-item.active::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: var(--primary-color);
border-radius: 2rpx;
}
.page-content {
height: calc(100vh - 300rpx);
}
.function-list {
padding: 30rpx;
}
.function-group {
margin-bottom: 40rpx;
}
.group-title {
font-size: 30rpx;
font-weight: 600;
color: var(--text-color);
margin-bottom: 20rpx;
}
.group-functions {
background: var(--white);
border-radius: 16rpx;
overflow: hidden;
box-shadow: var(--shadow);
}
.function-item {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid var(--border-light);
}
.function-item:last-child {
border-bottom: none;
}
.function-icon {
margin-right: 20rpx;
}
.function-content {
flex: 1;
}
.function-name {
font-size: 30rpx;
font-weight: 600;
color: var(--text-color);
margin-bottom: 8rpx;
display: block;
}
.function-desc {
font-size: 24rpx;
color: var(--text-secondary);
}
.function-arrow {
margin-left: 20rpx;
}
.search-icon,
.notification-icon {
font-size: 32rpx;
margin-right: 10rpx;
color: var(--white);
}
.badge {
position: absolute;
top: 0rpx;
right: 15rpx;
background-color: var(--error);
color: var(--white);
font-size: 20rpx;
padding: 2rpx 8rpx;
border-radius: 50%;
// min-width: 30rpx;
text-align: center;
line-height: 1.2;
}
.icon-text {
font-size: 40rpx;
}
.arrow-icon {
font-size: 32rpx;
color: var(--text-muted);
}
</style>