Procházet zdrojové kódy

feat:优化 system/dept 的代码实现

YunaiV před 4 měsíci
rodič
revize
d96d9da0da

+ 7 - 1
src/pages-system/dept/components/breadcrumb.vue

@@ -80,5 +80,11 @@ function back(): boolean {
   return true
 }
 
-defineExpose({ enter, back })
+/** 重置 */
+function reset() {
+  breadcrumbList.value = []
+  emit('update:modelValue', 0)
+}
+
+defineExpose({ enter, back, reset })
 </script>

+ 125 - 0
src/pages-system/dept/components/search-form.vue

@@ -0,0 +1,125 @@
+<template>
+  <!-- 搜索框入口 -->
+  <wd-search
+    :placeholder="searchPlaceholder"
+    :hide-cancel="true"
+    disabled
+    @click="visible = true"
+  />
+
+  <!-- 搜索弹窗 -->
+  <wd-popup
+    v-model="visible"
+    position="top"
+    custom-style="border-radius: 0 0 24rpx 24rpx;"
+    safe-area-inset-top
+    @close="visible = false"
+  >
+    <view class="p-32rpx">
+      <view class="mb-24rpx text-32rpx text-[#333] font-semibold">
+        搜索部门
+      </view>
+      <view class="mb-24rpx">
+        <view class="mb-12rpx text-28rpx text-[#666]">
+          部门名称
+        </view>
+        <wd-input
+          v-model="formData.name"
+          placeholder="请输入部门名称"
+          clearable
+        />
+      </view>
+      <view class="mb-32rpx">
+        <view class="mb-12rpx text-28rpx text-[#666]">
+          状态
+        </view>
+        <wd-radio-group v-model="formData.status" shape="button" size="medium">
+          <wd-radio :value="-1">
+            全部
+          </wd-radio>
+          <wd-radio
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :value="dict.value"
+          >
+            {{ dict.label }}
+          </wd-radio>
+        </wd-radio-group>
+      </view>
+      <view class="w-full flex justify-center gap-24rpx">
+        <wd-button class="flex-1" plain @click="handleReset">
+          重置
+        </wd-button>
+        <wd-button class="flex-1" type="primary" @click="handleSearch">
+          搜索
+        </wd-button>
+      </view>
+    </view>
+  </wd-popup>
+</template>
+
+<script lang="ts" setup>
+import { computed, reactive, ref, watch } from 'vue'
+import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
+import { DICT_TYPE } from '@/utils/constants'
+
+/** 搜索表单数据 */
+export interface SearchFormData {
+  name?: string
+  status?: number
+}
+
+const props = defineProps<{
+  searchParams?: Partial<SearchFormData> // 初始搜索参数
+}>()
+
+const emit = defineEmits<{
+  'search': [data: SearchFormData]
+  'reset': []
+}>()
+
+const visible = ref(false)
+
+/** 搜索条件 placeholder 拼接 */
+const searchPlaceholder = computed(() => {
+  const conditions: string[] = []
+  if (props.searchParams?.name) {
+    conditions.push(`名称:${props.searchParams.name}`)
+  }
+  if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
+    conditions.push(`状态:${getDictLabel(DICT_TYPE.COMMON_STATUS, props.searchParams.status)}`)
+  }
+  return conditions.length > 0 ? conditions.join(' | ') : '搜索部门'
+})
+
+const formData = reactive<SearchFormData>({
+  name: undefined,
+  status: -1,
+})
+
+/** 监听弹窗打开,同步外部参数 */
+watch(visible, (val) => {
+  if (val && props.searchParams) {
+    formData.name = props.searchParams.name
+    formData.status = props.searchParams.status !== undefined ? props.searchParams.status : -1
+  }
+})
+
+/** 搜索 */
+function handleSearch() {
+  visible.value = false
+  const params = { ...formData }
+  if (params.status === -1) {
+    params.status = undefined
+  }
+  emit('search', params)
+}
+
+/** 重置 */
+function handleReset() {
+  formData.name = undefined
+  formData.status = -1
+  visible.value = false
+  emit('reset')
+}
+</script>

+ 12 - 15
src/pages-system/dept/detail/index.vue

@@ -8,8 +8,8 @@
     />
 
     <!-- 详情内容 -->
-    <view class="p-24rpx pb-200rpx">
-      <wd-cell-group custom-class="cell-group" border>
+    <view>
+      <wd-cell-group border>
         <wd-cell title="部门名称" :value="formData?.name || '-'" />
         <wd-cell title="上级部门" :value="getParentName() || '-'" />
         <wd-cell title="负责人" :value="getLeaderName() || '-'" />
@@ -24,7 +24,7 @@
     </view>
 
     <!-- 底部操作按钮 -->
-    <view class="safe-area-inset-bottom fixed bottom-0 left-0 right-0 bg-white p-24rpx">
+    <view class="fixed bottom-0 left-0 right-0 bg-white p-24rpx">
       <view class="w-full flex gap-24rpx">
         <wd-button class="flex-1" type="warning" @click="handleEdit">
           编辑
@@ -44,11 +44,12 @@ import { onMounted, ref } from 'vue'
 import { useToast } from 'wot-design-uni'
 import { deleteDept, getDept, getSimpleDeptList } from '@/api/system/dept'
 import { getSimpleUserList } from '@/api/system/user'
+import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
 import { formatDateTime } from '@/utils/date'
 
 const props = defineProps<{
-  id: number
+  id: number | any
 }>()
 
 definePage({
@@ -66,7 +67,7 @@ const userList = ref<User[]>([]) // 用户列表
 
 /** 返回上一页 */
 function handleBack() {
-  uni.navigateBack()
+  navigateBackPlus()
 }
 
 /** 获取上级部门名称 */
@@ -92,7 +93,12 @@ async function getDetail() {
   if (!props.id) {
     return
   }
-  formData.value = await getDept(props.id)
+  toast.loading('加载中...')
+  try {
+    formData.value = await getDept(props.id)
+  } finally {
+    toast.close()
+  }
 }
 
 /** 编辑部门 */
@@ -140,13 +146,4 @@ onMounted(async () => {
 </script>
 
 <style lang="scss" scoped>
-:deep(.cell-group) {
-  border-radius: 12rpx;
-  overflow: hidden;
-  box-shadow: 0 3rpx 8rpx rgba(24, 144, 255, 0.06);
-}
-
-.safe-area-inset-bottom {
-  padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
-}
 </style>

+ 3 - 12
src/pages-system/dept/form/index.vue

@@ -8,9 +8,9 @@
     />
 
     <!-- 表单区域 -->
-    <view class="p-24rpx">
+    <view>
       <wd-form ref="formRef" :model="formData" :rules="formRules">
-        <wd-cell-group custom-class="cell-group" border>
+        <wd-cell-group border>
           <wd-cell
             title="上级部门"
             title-width="180rpx"
@@ -110,7 +110,7 @@ import { getSimpleUserList } from '@/api/system/user'
 import { CommonStatusEnum } from '@/utils/constants'
 
 const props = defineProps<{
-  id?: number
+  id?: number | any
   parentId?: number
 }>()
 
@@ -246,13 +246,4 @@ onMounted(async () => {
 </script>
 
 <style lang="scss" scoped>
-:deep(.cell-group) {
-  border-radius: 12rpx;
-  overflow: hidden;
-  box-shadow: 0 3rpx 8rpx rgba(24, 144, 255, 0.06);
-}
-
-.safe-area-inset-bottom {
-  padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
-}
 </style>

+ 38 - 8
src/pages-system/dept/index.vue

@@ -7,6 +7,13 @@
       @click-left="handleBack"
     />
 
+    <!-- 搜索组件 -->
+    <SearchForm
+      :search-params="queryParams"
+      @search="handleQuery"
+      @reset="handleReset"
+    />
+
     <!-- 面包屑导航 -->
     <Breadcrumb ref="breadcrumbRef" v-model="currentParentId" />
 
@@ -55,24 +62,27 @@
     </view>
 
     <!-- 新增按钮 -->
-    <view
-      class="fixed bottom-100rpx right-32rpx z-10 h-100rpx w-100rpx flex items-center justify-center rounded-full bg-[#1890ff] shadow-lg"
+    <wd-fab
+      position="right-bottom"
+      type="primary"
+      :expandable="false"
       @click="handleAdd"
-    >
-      <wd-icon name="add" size="24px" color="#fff" />
-    </view>
+    />
   </view>
 </template>
 
 <script lang="ts" setup>
+import type { SearchFormData } from './components/search-form.vue'
 import type { Dept } from '@/api/system/dept'
 import type { User } from '@/api/system/user'
-import { computed, onMounted, ref } from 'vue'
+import { computed, onMounted, reactive, ref } from 'vue'
 import { getDeptList } from '@/api/system/dept'
 import { getSimpleUserList } from '@/api/system/user'
+import { navigateBackPlus } from '@/utils'
 import { DICT_TYPE } from '@/utils/constants'
 import { findChildren, handleTree } from '@/utils/tree'
 import Breadcrumb from './components/breadcrumb.vue'
+import SearchForm from './components/search-form.vue'
 
 definePage({
   style: {
@@ -94,10 +104,15 @@ const currentList = computed(() => {
 }) // 当前层级的部门列表
 const breadcrumbRef = ref<InstanceType<typeof Breadcrumb>>()
 
+const queryParams = reactive<SearchFormData>({
+  name: undefined,
+  status: undefined,
+})
+
 /** 返回上一页或上一层级 */
 function handleBack() {
   if (!breadcrumbRef.value?.back()) {
-    uni.navigateBack()
+    navigateBackPlus()
   }
 }
 
@@ -119,13 +134,28 @@ function handleEnterChildren(item: Dept) {
 async function getList() {
   loading.value = true
   try {
-    const data = await getDeptList()
+    const data = await getDeptList(queryParams)
     list.value = handleTree(data)
   } finally {
     loading.value = false
   }
 }
 
+/** 搜索按钮操作 */
+function handleQuery(data?: SearchFormData) {
+  queryParams.name = data?.name
+  queryParams.status = data?.status
+  // 重置面包屑
+  currentParentId.value = 0
+  breadcrumbRef.value?.reset()
+  getList()
+}
+
+/** 重置按钮操作 */
+function handleReset() {
+  handleQuery()
+}
+
 /** 新增部门 */
 function handleAdd() {
   uni.navigateTo({

+ 9 - 6
src/pages-system/post/components/search-form.vue

@@ -47,11 +47,12 @@
           <wd-radio :value="-1">
             全部
           </wd-radio>
-          <wd-radio :value="0">
-            启用
-          </wd-radio>
-          <wd-radio :value="1">
-            禁用
+          <wd-radio
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :value="dict.value"
+          >
+            {{ dict.label }}
           </wd-radio>
         </wd-radio-group>
       </view>
@@ -69,6 +70,8 @@
 
 <script lang="ts" setup>
 import { computed, reactive, ref, watch } from 'vue'
+import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
+import { DICT_TYPE } from '@/utils/constants'
 
 /** 搜索表单数据 */
 export interface SearchFormData {
@@ -98,7 +101,7 @@ const searchPlaceholder = computed(() => {
     conditions.push(`编码:${props.searchParams.code}`)
   }
   if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
-    conditions.push(`状态:${props.searchParams.status === 0 ? '启用' : '禁用'}`)
+    conditions.push(`状态:${getDictLabel(DICT_TYPE.COMMON_STATUS, props.searchParams.status)}`)
   }
   return conditions.length > 0 ? conditions.join(' | ') : '搜索岗位'
 })

+ 9 - 6
src/pages-system/role/components/search-form.vue

@@ -47,11 +47,12 @@
           <wd-radio :value="-1">
             全部
           </wd-radio>
-          <wd-radio :value="0">
-            启用
-          </wd-radio>
-          <wd-radio :value="1">
-            禁用
+          <wd-radio
+            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :value="dict.value"
+          >
+            {{ dict.label }}
           </wd-radio>
         </wd-radio-group>
       </view>
@@ -69,6 +70,8 @@
 
 <script lang="ts" setup>
 import { computed, reactive, ref, watch } from 'vue'
+import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
+import { DICT_TYPE } from '@/utils/constants'
 
 /** 搜索表单数据 */
 export interface SearchFormData {
@@ -98,7 +101,7 @@ const searchPlaceholder = computed(() => {
     conditions.push(`标识:${props.searchParams.code}`)
   }
   if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
-    conditions.push(`状态:${props.searchParams.status === 0 ? '启用' : '禁用'}`)
+    conditions.push(`状态:${getDictLabel(DICT_TYPE.COMMON_STATUS, props.searchParams.status)}`)
   }
   return conditions.length > 0 ? conditions.join(' | ') : '搜索角色'
 })