index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <view class="bills-page">
  3. <!-- 整页分区宫格:所有域一次铺开,上下滚动看全,无需左右滑 -->
  4. <view v-for="group in billGroups" :id="'pkg-' + group.pkg" :key="group.pkg" class="card">
  5. <view class="card__head">
  6. <text class="card__title">{{ group.icon }} {{ group.title }}</text>
  7. <text class="card__count">{{ group.modules.length }} 项</text>
  8. </view>
  9. <view class="grid">
  10. <view v-for="m in group.modules" :key="m.key" class="grid__item">
  11. <ModuleGridCell :title="m.title" :color="domainColor(group.pkg)" @click="openModule(m)" />
  12. </view>
  13. </view>
  14. </view>
  15. <!-- 右侧域索引:点击直达对应分区 -->
  16. <view v-if="billGroups.length > 3" class="side-index">
  17. <view
  18. v-for="g in billGroups"
  19. :key="g.pkg"
  20. class="side-index__item"
  21. @click="scrollToGroup(g.pkg)"
  22. >
  23. <text class="side-index__text">{{ g.title.slice(0, 2) }}</text>
  24. </view>
  25. </view>
  26. </view>
  27. </template>
  28. <script setup lang="ts">
  29. /**
  30. * 单据页:业务域分区宫格目录(注册表驱动,菜单权限过滤,剔除报表中心)
  31. * 右侧域索引快速定位;待办总数同步「单据」tab 角标。
  32. */
  33. import { computed } from 'vue'
  34. import { onShow } from '@dcloudio/uni-app'
  35. import type { ModuleConfig } from '@/modules/registry'
  36. import { useMenuStore } from '@/store/modules/menu'
  37. import { useTodoStore } from '@/store/modules/todo'
  38. import { requireLogin } from '@/utils/auth'
  39. import { moduleListPage } from '@/constants/routes'
  40. import { domainColor } from '@/modules/domainStyle'
  41. import ModuleGridCell from '@/components/common/ModuleGridCell.vue'
  42. const menuStore = useMenuStore()
  43. const todoStore = useTodoStore()
  44. // 单据页展示的域(菜单权限驱动,排除报表中心——报表从工作台进入)
  45. const billGroups = computed(() => menuStore.visibleBillGroups)
  46. onShow(() => {
  47. requireLogin()
  48. menuStore.ensureMenus().catch(() => {})
  49. todoStore
  50. .ensureTodos()
  51. .then(() => todoStore.syncTabBadge())
  52. .catch(() => {})
  53. })
  54. function scrollToGroup(pkg: string) {
  55. uni.pageScrollTo({ selector: `#pkg-${pkg}`, duration: 200, offsetTop: -16 })
  56. }
  57. function openModule(m: ModuleConfig) {
  58. if (!menuStore.isModuleAllowed(m.key)) {
  59. uni.showToast({ title: '无该功能权限', icon: 'none' })
  60. return
  61. }
  62. uni.navigateTo({ url: `${moduleListPage(m.pkg)}?module=${m.key}` })
  63. }
  64. </script>
  65. <style lang="scss" scoped>
  66. .bills-page {
  67. min-height: 100vh;
  68. background: #f2f5fa;
  69. padding-bottom: 40rpx;
  70. }
  71. .card {
  72. margin: 24rpx 24rpx 0;
  73. background: #fff;
  74. border-radius: 16rpx;
  75. padding: 24rpx;
  76. &__head {
  77. display: flex;
  78. align-items: center;
  79. justify-content: space-between;
  80. margin-bottom: 8rpx;
  81. }
  82. &__title {
  83. font-size: 28rpx;
  84. font-weight: 600;
  85. color: #303133;
  86. }
  87. &__count {
  88. font-size: 22rpx;
  89. color: #909399;
  90. }
  91. }
  92. .grid {
  93. display: flex;
  94. flex-wrap: wrap;
  95. &__item {
  96. width: 25%;
  97. }
  98. }
  99. .side-index {
  100. position: fixed;
  101. right: 8rpx;
  102. top: 50%;
  103. transform: translateY(-50%);
  104. background: rgba(255, 255, 255, 0.92);
  105. border-radius: 24rpx;
  106. padding: 8rpx 0;
  107. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
  108. z-index: 20;
  109. &__item {
  110. padding: 10rpx 16rpx;
  111. display: flex;
  112. justify-content: center;
  113. &:active {
  114. opacity: 0.6;
  115. }
  116. }
  117. &__text {
  118. font-size: 22rpx;
  119. color: #606266;
  120. }
  121. }
  122. </style>