wui-components-v2 1.1.35 → 1.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -197,7 +197,7 @@ function closeMoreButn() {
197
197
  }
198
198
 
199
199
  // 点击更多按钮
200
- function select({ item }) {
200
+ function select({ item }: { item: any }) {
201
201
  message.confirm({
202
202
  msg: `确定${item.title}操作吗?`,
203
203
  title: '提示',
@@ -225,9 +225,16 @@ function select({ item }) {
225
225
  {{ subitem.title }}
226
226
  </wd-button>
227
227
  </view> -->
228
- <wd-button v-if="morebutns.length > 0" size="small" type="info" @click="() => { showMoreButn = true }">
229
- 更多
230
- </wd-button>
228
+ <view>
229
+ <wd-button v-if="morebutns.length > 3" size="small" type="info" @click="() => { showMoreButn = true }">
230
+ 更多
231
+ </wd-button>
232
+ <view v-else>
233
+ <wd-button v-for="subitem in morebutns" :key="subitem.id" plain size="small" @click="() => { select({ item: subitem }) }">
234
+ {{ subitem.title }}
235
+ </wd-button>
236
+ </view>
237
+ </view>
231
238
 
232
239
  <wd-button v-if="props.item.buttons.includes('dtmplEdit')" size="small" @click="edit()">
233
240
  编辑
@@ -238,9 +245,9 @@ function select({ item }) {
238
245
  <wd-button v-if="props.item.buttons.includes('singleDelete')" size="small" type="error" @click="del()">
239
246
  删除
240
247
  </wd-button>
241
- <ActionPopup
248
+ <ActionPopup
242
249
  v-model:show="actionItemShow" :enum-column="props.enumColumn" :zpaging="props.zpaging"
243
- :field-group="actionItem" :code="props.code"
250
+ :field-group="actionItem" :code="props.code"
244
251
  />
245
252
  <!-- 更多按钮 -->
246
253
  <wd-action-sheet v-model="showMoreButn" :actions="morebutns" @close="closeMoreButn" @select="select" />
@@ -0,0 +1,77 @@
1
+ <script lang="ts" setup>
2
+ import { ref ,defineProps,defineEmits,onMounted,computed} from 'vue'
3
+ import { useEnums } from '../../composables/useEnumes'
4
+ import type { Config, Entities, Enums } from '../../type'
5
+ import {pageConfig } from '../../api/page'
6
+ defineOptions({
7
+ name: 'EnumeSelectControl',
8
+ })
9
+
10
+ const props = defineProps<{
11
+ sourceId: string
12
+ id:string
13
+ label?:string
14
+ title?:string
15
+ modelValue:string
16
+ placeholder?:string
17
+ disabled?:boolean
18
+ required?:boolean
19
+ rules?:any
20
+ zIndex?:number
21
+ type:'checkbox'|'radio'
22
+ }>()
23
+ const emits=defineEmits(['update:modelValue'])
24
+
25
+ const config=ref<Config>()
26
+ const { enumColumn,getEnums }= useEnums({ config })
27
+ async function getPageConfig() {
28
+ try {
29
+ const res = await pageConfig(props.sourceId)
30
+
31
+ if (res.ltmplConfig) {
32
+ config.value = res.ltmplConfig
33
+ getEnums()
34
+ }
35
+ }
36
+ catch (error) {
37
+ console.log(error)
38
+ }
39
+ }
40
+
41
+ const comEnums=computed(()=>{
42
+ const mstrucId=config.value?.criterias?.find((item)=>item.sourceId===props.id)?.mstrucId
43
+
44
+ if(mstrucId)return enumColumn.value[mstrucId]?.map((item)=>{
45
+ return {
46
+ id:item.id,
47
+ label:item.title,
48
+ value:`${item.id}@R@${item.value}`
49
+ }
50
+ })
51
+
52
+ return []
53
+
54
+ })
55
+
56
+ onMounted(()=>{
57
+ getPageConfig()
58
+ })
59
+
60
+ const confirm=(event:any)=>{
61
+ emits('update:modelValue',event.value)
62
+ }
63
+ </script>
64
+
65
+ <script lang="ts">
66
+ export default {
67
+ options: {
68
+ virtualHost: true,
69
+ addGlobalClass: true,
70
+ styleIsolation: 'shared',
71
+ },
72
+ }
73
+ </script>
74
+
75
+ <template>
76
+ <wd-select-picker :title="props.title" :placeholder="props.placeholder" :disabled="props.disabled" :required="props.required" :rules="props.rules" :zIndex="props.zIndex" :type="$props.type" :modelValue="modelValue" :label="props.label" @confirm="confirm" :columns="comEnums"></wd-select-picker>
77
+ </template>
@@ -36,6 +36,7 @@ const groups = ref<Groups>({
36
36
  relationNames: [],
37
37
  readOnly: false,
38
38
  displayConfig: [],
39
+
39
40
  })
40
41
  const loading = ref(false)
41
42
  // 折叠面板
@@ -133,7 +134,7 @@ async function getDetailData() {
133
134
  <view v-for="(field, subindex) in data.arrayMap[group.id]" :key="field.code">
134
135
  <foldCard :index="subindex" :enum-column="{}" :groups="group" :source-id="sourceId" :columns="group.fields" model="complex" :data="field">
135
136
  <template #buttons>
136
- <CardBotomButtons :source-id="group.id" :item="groups" :code="field.code" :data="data" />
137
+ <CardBotomButtons :primary-column="group.primaryColumn || { controlType: '', extControlType: '', sourceId: '', mstrucId: '' }" :source-id="group.id" :item="groups" :code="field.code" :data="data" />
137
138
  </template>
138
139
  </foldCard>
139
140
  </view>
@@ -141,5 +142,6 @@ async function getDetailData() {
141
142
  </wd-collapse-item>
142
143
  </wd-collapse>
143
144
  </view>
145
+ <slot name="botombuttons" />
144
146
  </view>
145
147
  </template>
@@ -1,23 +1,23 @@
1
1
  <script lang="ts" setup>
2
2
  import { defineOptions, defineProps, onMounted, onUnmounted, ref } from 'vue'
3
3
  import { onLoad } from '@dcloudio/uni-app'
4
- import { enums, listData, pageConfig, pageKey } from '../../api/page'
4
+ import {listData, pageConfig, pageKey } from '../../api/page'
5
5
  import foldCard from '../fold-card/fold-card.vue'
6
- import type { Config, Entities, Enums } from '../../type'
6
+ import type { Config, Entities } from '../../type'
7
7
  import Search from '../search/search.vue'
8
8
  import ListTopButtons from '../list-top-buttons/list-top-buttons.vue'
9
9
  import CardBotomButtons from '../card-botom-buttons/card-botom-buttons.vue'
10
10
  import { generateHighResolutionID } from '../../utils/index'
11
11
  import productCard from '../product-card/product-card.vue'
12
12
  import tabSearch from '../tab-search/tab-search.vue'
13
- import ControlTypeSupportor from '../../utils/control-type-supportor'
14
-
13
+ import {useEnums} from '../../composables/useEnumes'
15
14
  defineOptions({
16
15
  name: 'WuiList',
17
16
  })
18
17
  defineProps<{
19
18
  detailButtonHandle?: (data: Entities) => void
20
19
  }>()
20
+
21
21
  const Zpaging = ref<any>(null)
22
22
  const config = ref<Config>({
23
23
  buttons: [],
@@ -57,13 +57,13 @@ const config = ref<Config>({
57
57
  displayConfig: [],
58
58
  showType: 'table',
59
59
  })
60
+ const { getEnums, enumColumn} = useEnums({ config })
60
61
  const sourceId = ref('')
61
62
  const datas = ref<Entities[]>([])
62
63
  const pageTitle = ref('')
63
64
  const searchData = ref('')
64
65
  const tabSearchData = ref('')
65
66
  const pageType = ref('')
66
- const enumColumn = ref<Enums>({})
67
67
  const mainCode = ref('')
68
68
  const addEvent = generateHighResolutionID()// 全局事件名称
69
69
  onLoad((option: any) => {
@@ -143,40 +143,6 @@ async function queryList(pageNo: number, pageSize: number) {
143
143
  }
144
144
  }
145
145
 
146
- // 获取枚举
147
- async function getEnums() {
148
- try {
149
- const params: string[] = []
150
- const criterias = config.value?.criterias ?? []
151
- const columns = config.value.columns ?? []
152
- const writes = config.value.rowActions?.reduce((acc: any, cur: any) => {
153
- return [...acc, ...cur.writes]
154
- }, []) || []
155
- columns.forEach((item: any) => {
156
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
157
- params.push(`mstrucIds=${item.mstrucId}`)
158
- }
159
- })
160
- criterias.forEach((item: any) => {
161
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
162
- params.push(`mstrucIds=${item.mstrucId}`)
163
- }
164
- })
165
- writes.forEach((item: any) => {
166
- if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
167
- params.push(`mstrucIds=${item.mstrucId}`)
168
- }
169
- })
170
- if (!params.length)
171
- return
172
- const res = await enums(params.join('&'))
173
- enumColumn.value = res.enumMap || {}
174
- }
175
- catch (error) {
176
- console.log('error:', error)
177
- }
178
- }
179
-
180
146
  function submitSearch(data: any) {
181
147
  searchData.value = data
182
148
  // for (const key in data) {
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ import { defineOptions, ref } from 'vue'
3
+ import { onLoad } from '@dcloudio/uni-app'
4
+ import wuiDetailsPage from '../wui-details-page/wui-details-page.vue'
5
+ import cardBotomButtons from '../card-botom-buttons/card-botom-buttons.vue'
6
+
7
+ defineOptions({
8
+ name: 'NotifyHandle',
9
+ })
10
+ const item = ref<any>(null)
11
+ const sourceId = ref<any>(null)
12
+ const pagedata = ref<any>(null)
13
+ const rowActions = ref<any>(null)
14
+ const actions = ref<any>(null)
15
+ const ractions = ref<any>(null)
16
+ const primaryColumn = ref<any>(null)
17
+ const enumColumn = ref<any>(null)
18
+ onLoad(() => {
19
+ console.log('load')
20
+ uni.$on('notify-click', (data: any) => {
21
+ console.log(data, 'kkkk')
22
+ item.value = data.item
23
+ sourceId.value = data.sourceId
24
+ pagedata.value = data.data
25
+ rowActions.value = data.rowActions
26
+ actions.value = data.actions
27
+ ractions.value = data.ractions
28
+ primaryColumn.value = data.primaryColumn
29
+ enumColumn.value = data.enumColumn
30
+ })
31
+ })
32
+ onUnload(() => {
33
+ console.log('unload')
34
+ uni.$off('notify-click')
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <view>
40
+ <wuiDetailsPage>
41
+ <template #botombuttons>
42
+ <view class="flex justify-end bg-#ffff p-4">
43
+ <cardBotomButtons v-if="sourceId" :item="item" :source-id="sourceId" :code="pagedata.code" :data="pagedata" :row-actions="rowActions" :actions="actions" :ractions="ractions" :primary-column="primaryColumn" />
44
+ </view>
45
+ </template>
46
+ </wuiDetailsPage>
47
+ <view />
48
+ </view>
49
+ </template>
50
+
51
+ <style scoped>
52
+
53
+ </style>
@@ -1,11 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, defineOptions, watch } from 'vue'
3
3
  import { useRouter } from 'uni-mini-router'
4
- import { listData, pageConfig, pageKey } from '../../api/page'
4
+ import { enums, listData, pageConfig, pageKey } from '../../api/page'
5
5
  import { useSectionMenus } from '../../composables/useSectionMenus'
6
6
  import { formatItemData } from '../../utils'
7
7
  import ControlTypeSupportor from '../../utils/control-type-supportor'
8
- import { useLanguageStore } from '../../store/language'
8
+ import { useLanguageStore } from '../../store/language'
9
+ import type { Config, Entities, Enums } from '../../type'
9
10
 
10
11
  defineOptions({
11
12
  name: 'WuiNotifyInfo',
@@ -20,22 +21,27 @@ const { rightSidebar01, rightSidebar02 } = useSectionMenus()
20
21
  // default: return BellIcon
21
22
  // }
22
23
  // }
24
+ const dtmplConfig = ref<{ [key: string]: Config }>({})
25
+ const enumColumn = ref<{ [key: string]: Enums }>({})
26
+ interface Data {
27
+ type: 'system'
28
+ read: boolean
29
+ id: string
30
+ primaryColumn: string
31
+ primaryColumnLabel: string
32
+ secondColumn: string
33
+ secondColumnLabel: string
34
+ primaryColumnLabelConfig: any
35
+ primaryColumnConfig: any
36
+ secondColumnConfig: any
37
+ secondColumnLabelConfig: any
38
+ sourceid: string
39
+ data: Entities
40
+ }
23
41
  interface Notification {
24
42
  id: string
25
43
  title: string
26
- data: {
27
- type: 'system'
28
- read: boolean
29
- id: string
30
- primaryColumn: string
31
- primaryColumnLabel: string
32
- secondColumn: string
33
- secondColumnLabel: string
34
- primaryColumnLabelConfig: any
35
- primaryColumnConfig: any
36
- secondColumnConfig: any
37
- secondColumnLabelConfig: any
38
- }[]
44
+ data: Data[]
39
45
  }
40
46
  const router = useRouter()
41
47
  const notifications = ref<Notification[] | null>([])
@@ -57,17 +63,51 @@ const sources = computed(() => {
57
63
  }
58
64
  })
59
65
  })
60
-
66
+ // 获取枚举
67
+ async function getEnums(sourceId: string, config: Config) {
68
+ try {
69
+ const params: string[] = []
70
+ const criterias = config?.criterias ?? []
71
+ const columns = config?.columns ?? []
72
+ const writes = config?.rowActions?.reduce((acc: any, cur: any) => {
73
+ return [...acc, ...cur.writes]
74
+ }, []) || []
75
+ columns.forEach((item: any) => {
76
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
77
+ params.push(`mstrucIds=${item.mstrucId}`)
78
+ }
79
+ })
80
+ criterias.forEach((item: any) => {
81
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
82
+ params.push(`mstrucIds=${item.mstrucId}`)
83
+ }
84
+ })
85
+ writes.forEach((item: any) => {
86
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
87
+ params.push(`mstrucIds=${item.mstrucId}`)
88
+ }
89
+ })
90
+ if (!params.length)
91
+ return
92
+ const res = await enums(params.join('&'))
93
+ enumColumn.value[sourceId] = res.enumMap || {}
94
+ }
95
+ catch (error) {
96
+ console.log('error:', error)
97
+ }
98
+ }
61
99
  // 获取数据
62
100
  async function queryList(source: { id: string, title: string }): Promise<Notification | null> {
63
101
  try {
64
102
  const res = await pageConfig(source.id)
103
+ dtmplConfig.value[source.id] = res.ltmplConfig
104
+ getEnums(source.id, res.ltmplConfig)
65
105
  const res1 = await pageKey(source.id, '', '')// 获取key
66
106
  const data = await listData(res1.key, 1, 10)// 获取数据
67
107
  return {
68
108
  id: source.id,
69
109
  title: source.title,
70
- data: data.entities.map((item: any) => {
110
+ data: data.entities.map((item: Entities) => {
71
111
  return {
72
112
  type: 'system',
73
113
  read: false,
@@ -81,6 +121,7 @@ async function queryList(source: { id: string, title: string }): Promise<Notific
81
121
  secondColumnConfig: res.ltmplConfig.secondColumn,
82
122
  secondColumnLabel: item.fieldMap[res.ltmplConfig.secondColumnLabel?.sourceId] || '',
83
123
  secondColumnLabelConfig: res.ltmplConfig.secondColumnLabel,
124
+ data: item,
84
125
  }
85
126
  }),
86
127
  }
@@ -127,8 +168,22 @@ function gotoPage(item: Notification) {
127
168
  }
128
169
 
129
170
  // 跳转详情页面
130
- function gotoDetailPage(item: any) {
131
- router.push(`/pages/details-page/index?sourceId=${item.sourceid}&id=${item.id}&title=`)
171
+ function gotoDetailPage(item: Data) {
172
+ router.push(`/pages/notify-handle/index?sourceId=${item.sourceid}&id=${item.id}&title=`)
173
+
174
+ // 延迟发送,确保事件被发送
175
+ setTimeout(() => {
176
+ uni.$emit('notify-click', {
177
+ item: dtmplConfig.value[item.sourceid],
178
+ sourceId: item.sourceid,
179
+ data: item.data,
180
+ rowActions: dtmplConfig.value[item.sourceid]?.rowActions,
181
+ actions: dtmplConfig.value[item.sourceid]?.actions,
182
+ ractions: dtmplConfig.value[item.sourceid]?.ractions,
183
+ primaryColumn: dtmplConfig.value[item.sourceid]?.primaryColumn,
184
+ enumColumn: enumColumn.value[item.sourceid],
185
+ })
186
+ }, 100)
132
187
  }
133
188
  </script>
134
189
 
@@ -147,37 +202,39 @@ function gotoDetailPage(item: any) {
147
202
  {{ languageStore.t('查看全部') }}
148
203
  </view>
149
204
  </view>
150
- <button
151
- v-for="item in notification.data"
152
- :key="item.id"
205
+ <button
206
+ v-for="item in notification.data" :key="item.id"
153
207
  class="w-full flex cursor-pointer items-start gap-3 rounded-xl bg-white p-4 text-left shadow-[0_4px_16px_rgba(99,102,241,0.1)] transition-all duration-200 .dark:bg-black hover:shadow-md"
154
- :class="{ 'opacity-60': item.read }"
155
- @click="handleNotificationClick(item)"
208
+ :class="{ 'opacity-60': item.read }" @click="handleNotificationClick(item)"
156
209
  >
157
- <view
210
+ <view
158
211
  :class="getIconColor(item.type)"
159
- class="h-10 w-10 flex flex-shrink-0 items-center justify-center rounded-full"
212
+ class="h-10 w-10 flex flex-shrink-0 items-center justify-center rounded-full"
160
213
  >
161
214
  <wd-icon name="notification" size="40rpx" color="#fff" />
162
215
  </view>
163
216
 
164
217
  <view class="min-w-0 flex-1">
165
218
  <view class="flex justify-between gap-1">
166
- <span class="text-sm text-slate-800 font-medium .dark:text-white">{{ formatItemData(item.primaryColumn, ControlTypeSupportor.getControlType(item.primaryColumnConfig)) }}</span>
167
- <span class="whitespace-nowrap text-xs text-slate-400 .dark:text-white">{{ formatItemData(item.primaryColumnLabel, ControlTypeSupportor.getControlType(item.primaryColumnLabelConfig)) }}</span>
219
+ <span class="text-sm text-slate-800 font-medium .dark:text-white">{{ formatItemData(item.primaryColumn,
220
+ ControlTypeSupportor.getControlType(item.primaryColumnConfig)) }}</span>
221
+ <span class="whitespace-nowrap text-xs text-slate-400 .dark:text-white">{{
222
+ formatItemData(item.primaryColumnLabel,
223
+ ControlTypeSupportor.getControlType(item.primaryColumnLabelConfig)) }}</span>
168
224
  </view>
169
225
  <p class="line-clamp-2 mt-1 text-sm text-slate-500 .dark:text-white">
170
226
  <text class="mr-1">
171
- {{ formatItemData(item.secondColumn, ControlTypeSupportor.getControlType(item.secondColumnConfig || {})) }}
227
+ {{ formatItemData(item.secondColumn, ControlTypeSupportor.getControlType(item.secondColumnConfig || {}))
228
+ }}
229
+ </text>
230
+ <text>
231
+ {{ formatItemData(item.secondColumnLabel,
232
+ ControlTypeSupportor.getControlType(item.secondColumnLabelConfig || {})) }}
172
233
  </text>
173
- <text> {{ formatItemData(item.secondColumnLabel, ControlTypeSupportor.getControlType(item.secondColumnLabelConfig || {})) }}</text>
174
234
  </p>
175
235
  </view>
176
236
 
177
- <view
178
- v-if="!item.read"
179
- class="mt-2 h-2 w-2 flex-shrink-0 rounded-full bg-indigo-500"
180
- />
237
+ <view v-if="!item.read" class="mt-2 h-2 w-2 flex-shrink-0 rounded-full bg-indigo-500" />
181
238
  </button>
182
239
  </view>
183
240
  </view>
@@ -41,7 +41,7 @@ defineExpose({ addToHistory })
41
41
  <view v-if="modelValue.length > 0" class="mt-4">
42
42
  <view class="mb-3 flex items-center justify-between">
43
43
  <view class="flex items-center gap-2">
44
- <ClockIcon class="h-4 w-4 text-slate-400" />
44
+ <!-- <ClockIcon class="h-4 w-4 text-slate-400" /> -->
45
45
  <view class="text-sm text-slate-600 font-medium">
46
46
  搜索历史
47
47
  </view>
@@ -62,7 +62,8 @@ defineExpose({ addToHistory })
62
62
  >
63
63
  <!-- <MagnifyingGlassCircleIcon class="h-3.5 w-3.5" /> -->
64
64
  <view>{{ keyword }}</view>
65
- <wd-icon name="close-normal" size="16px" class="flex items-center" @click.stop="removeFromHistory(keyword)" />
65
+ <wd-icon name="close-normal" size="16px" class="flex items-center" @click.stop="removeFromHistory(keyword)" />
66
+ <!-- <wd-icon name="close-bold" size="22px" @click.stop="removeFromHistory(keyword)" ></wd-icon> -->
66
67
  </view>
67
68
  </view>
68
69
  </view>
@@ -1,61 +1,101 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, defineOptions, onMounted, ref } from 'vue'
3
- // import { useRouter } from 'vue-router'
3
+ import { useRouter } from 'uni-mini-router'
4
+ import { useMenus } from '../../composables/useMenus'
5
+ import type { MenuItem } from '../../composables/useMenus'
6
+ import { useGlobalToast } from '../../composables/useGlobalToast'
7
+ import { menu } from '../../api/menu'
4
8
  import SearchHistory from './components/SearchBar.vue'
5
9
 
6
10
  defineOptions({
7
11
  name: 'WuiSearchHistoryBabbar',
8
12
  })
9
- // const router = useRouter()
10
- const allMenus: any = [
11
- { id: 1, label: '打卡', icon: 'clock', color: 'bg-blue-500', description: '上下班打卡签到' },
12
- { id: 2, label: '报销', icon: 'document-text', color: 'bg-green-500', description: '提交报销单据' },
13
- { id: 3, label: '审批', icon: 'check-circle', color: 'bg-purple-500', description: '审批流程管理' },
14
- { id: 4, label: '日程', icon: 'calendar', color: 'bg-orange-500', description: '查看和安排日程' },
15
- { id: 5, label: '通讯录', icon: 'user-group', color: 'bg-indigo-500', description: '企业通讯录' },
16
- { id: 6, label: '更多', icon: 'ellipsis-horizontal', color: 'bg-slate-500', description: '更多应用' },
17
- { id: 7, label: '请假', icon: 'arrow-right-circle', color: 'bg-rose-500', description: '申请请假' },
18
- { id: 8, label: '考勤', icon: 'clipboard-check', color: 'bg-cyan-500', description: '考勤记录查询' },
19
- { id: 9, label: '会议', icon: 'video-camera', color: 'bg-violet-500', description: '会议室预约' },
20
- { id: 10, label: '文档', icon: 'folder', color: 'bg-amber-500', description: '文档管理中心' },
21
- { id: 11, label: '项目管理', icon: 'chart-bar', color: 'bg-emerald-500', description: '项目进度管理' },
22
- { id: 12, label: 'CRM', icon: 'user-circle', color: 'bg-pink-500', description: '客户关系管理' },
23
- { id: 13, label: '人力资源', icon: 'identification', color: 'bg-teal-500', description: 'HR管理' },
24
- { id: 14, label: '财务管理', icon: 'banknotes', color: 'bg-lime-500', description: '财务相关操作' },
25
- { id: 15, label: '资产管理', icon: 'cube', color: 'bg-fuchsia-500', description: '企业资产管理' },
26
- { id: 16, label: '公告', icon: 'megaphone', color: 'bg-red-500', description: '公司公告通知' },
27
- { id: 17, label: '任务', icon: 'check-badge', color: 'bg-sky-500', description: '任务分配与跟踪' },
28
- { id: 18, label: '笔记', icon: 'pencil-square', color: 'bg-yellow-500', description: '个人笔记' },
29
- { id: 19, label: '邮件', icon: 'envelope', color: 'bg-blue-600', description: '企业邮件' },
30
- { id: 20, label: '云盘', icon: 'cloud', color: 'bg-indigo-600', description: '云端文件存储' },
31
- { id: 21, label: '设置', icon: 'cog-6-tooth', color: 'bg-gray-500', description: '个人设置' },
32
- ]
13
+
14
+ const { gotoPage, filtermenu, menuList } = useMenus()
15
+ const router = useRouter()
16
+ const toast = useGlobalToast()
17
+
18
+ function queryList() {
19
+ // 此处请求仅为演示,请替换为自己项目中的请求
20
+ menu().then((res: any) => {
21
+ if (!res?.blocks?.length) {
22
+ toast.warning('暂无权限,请重新登录或联系管理员')
23
+ setTimeout(() => {
24
+ router.replaceAll('/pages/login/index')
25
+ }, 1000)
26
+ }
27
+ else {
28
+ menuList.value = res?.blocks
29
+ }
30
+ }).catch((res: any) => {
31
+ console.log(res)
32
+ })
33
+ }
34
+
35
+ /**
36
+ * 提取树形结构中最深层的数据节点
37
+ * @param treeData - 树形结构数据
38
+ * @param childrenKey - 子节点的键名,默认为 'children'
39
+ * @returns 最深层节点组成的数组
40
+ */
41
+ function extractDeepestNodes<T>(
42
+ treeData: T[],
43
+ childrenKey: string = 'children',
44
+ ): T[] {
45
+ const result: T[] = []
46
+
47
+ /**
48
+ * 递归遍历树节点
49
+ */
50
+ function traverse(nodes: T[], depth: number = 0) {
51
+ for (const node of nodes) {
52
+ // 检查当前节点是否有子节点
53
+ const children = (node as any)[childrenKey]
54
+
55
+ if (children && Array.isArray(children) && children.length > 0) {
56
+ // 如果有子节点,继续深入
57
+ traverse(children, depth + 1)
58
+ }
59
+ else {
60
+ // 如果没有子节点,这是最深层的节点,添加到结果中
61
+ result.push(node)
62
+ }
63
+ }
64
+ }
65
+
66
+ traverse(treeData)
67
+ return result
68
+ }
69
+
70
+ const a = computed(() => {
71
+ return extractDeepestNodes(filtermenu.value, 'items')
72
+ })
33
73
 
34
74
  const searchQuery = ref('')
35
75
  const searchHistory = ref<string[]>([])
36
76
  const inputRef = ref<HTMLInputElement | null>(null)
37
77
 
38
- const filteredMenus = computed(() => {
78
+ const filteredMenus = computed<MenuItem[]>(() => {
39
79
  if (!searchQuery.value.trim()) {
40
- return allMenus
80
+ return a.value
41
81
  }
42
82
  const query = searchQuery.value.toLowerCase().trim()
43
- return allMenus.filter(menu =>
44
- menu.label.toLowerCase().includes(query)
45
- || (menu.description && menu.description.toLowerCase().includes(query)),
83
+ return a.value.filter(menu =>
84
+ menu.title.toLowerCase().includes(query)
85
+ || (menu.tip && menu.tip.toLowerCase().includes(query)),
46
86
  )
47
87
  })
48
88
 
49
- function highlightedLabel(menu: any) {
50
- if (!searchQuery.value.trim())
51
- return menu.label
89
+ function highlightedLabel(menu: MenuItem) {
90
+ if (!searchQuery.value.trim())
91
+ return menu.title
52
92
  const query = searchQuery.value.toLowerCase().trim()
53
- const index = menu.label.toLowerCase().indexOf(query)
54
- if (index === -1)
55
- return menu.label
56
- const before = menu.label.substring(0, index)
57
- const match = menu.label.substring(index, index + query.length)
58
- const after = menu.label.substring(index + query.length)
93
+ const index = menu.title.toLowerCase().indexOf(query)
94
+ if (index === -1)
95
+ return menu.title
96
+ const before = menu.title.substring(0, index)
97
+ const match = menu.title.substring(index, index + query.length)
98
+ const after = menu.title.substring(index + query.length)
59
99
  return `${before}<mark class="bg-yellow-200 text-yellow-800 rounded px-0.5">${match}</mark>${after}`
60
100
  }
61
101
 
@@ -65,18 +105,18 @@ function highlightedLabel(menu: any) {
65
105
 
66
106
  function handleClear() {
67
107
  searchQuery.value = ''
68
- inputRef.value?.focus()
108
+ inputRef?.value?.focus()
69
109
  }
70
110
 
71
- function handleMenuClick(menu: any) {
111
+ function handleMenuClick(menu: MenuItem) {
72
112
  if (searchQuery.value.trim()) {
73
113
  addToHistory(searchQuery.value.trim())
74
114
  }
75
- console.log('Menu clicked:', menu.label)
115
+ gotoPage(menu)
76
116
  }
77
117
 
78
118
  function addToHistory(keyword: string) {
79
- if (!keyword.trim())
119
+ if (!keyword.trim())
80
120
  return
81
121
  const current = [...searchHistory.value]
82
122
  const index = current.indexOf(keyword)
@@ -96,16 +136,16 @@ function handleSelectHistory(keyword: string) {
96
136
  }
97
137
 
98
138
  onMounted(() => {
139
+ queryList()
99
140
  const saved = localStorage.getItem('searchHistory')
100
141
  if (saved) {
101
142
  try {
102
143
  searchHistory.value = JSON.parse(saved)
103
- }
144
+ }
104
145
  catch {
105
146
  searchHistory.value = []
106
147
  }
107
148
  }
108
- inputRef.value?.focus()
109
149
  })
110
150
  </script>
111
151
 
@@ -113,7 +153,7 @@ onMounted(() => {
113
153
  <view class="min-h-screen bg-slate-50">
114
154
  <view class="sticky top-0 z-10 bg-white shadow-sm">
115
155
  <view class="flex items-center gap-3 px-4 py-3">
116
- <view class="h-11 flex flex-1 items-center rounded-xl bg-slate-100 px-4">
156
+ <view class="h-11 flex flex-1 items-center rounded-xl bg-slate-100 px-4">
117
157
  <input
118
158
  ref="inputRef"
119
159
  v-model="searchQuery"
@@ -126,7 +166,7 @@ onMounted(() => {
126
166
  class="cursor-pointer rounded-full p-1 transition-colors hover:bg-slate-200"
127
167
  @click="handleClear"
128
168
  >
129
- <XMarkIcon class="h-4 w-4 text-slate-400" />
169
+ <wd-icon name="close-circle-filled" size="22px" color="#ccc" />
130
170
  </view>
131
171
  </view>
132
172
  </view>
@@ -139,24 +179,24 @@ onMounted(() => {
139
179
  />
140
180
 
141
181
  <view v-if="filteredMenus.length === 0" class="mt-6">
142
- <p class="text-center text-sm text-slate-400">
143
- 未找到相关菜单
182
+ <p class="text-center text-sm text-slate-400">
183
+ 未找到相关菜单
144
184
  </p>
145
185
  </view>
146
186
 
147
187
  <view v-else class="mt-4">
148
- <p class="mb-3 text-xs text-slate-400">
149
- {{ searchQuery.trim() ? `找到 ${filteredMenus.length} 个相关菜单` : '全部菜单' }}
188
+ <p class="mb-3 text-xs text-slate-400">
189
+ {{ searchQuery.trim() ? `找到 ${filteredMenus.length} 个相关菜单` : '全部菜单' }}
150
190
  </p>
151
191
  <view class="space-y-2">
152
192
  <view
153
193
  v-for="menu in filteredMenus"
154
194
  :key="menu.id"
155
- class="w-full flex cursor-pointer items-center gap-3 rounded-xl bg-white p-3 shadow-sm transition-all duration-200 active:scale-[0.98] hover:shadow-md"
195
+ class="flex cursor-pointer items-center gap-3 rounded-xl bg-white p-3 shadow-sm transition-all duration-200 active:scale-[0.98] hover:shadow-md"
156
196
  @click="handleMenuClick(menu)"
157
197
  >
158
198
  <view
159
- :class="menu.color"
199
+ :style="{ background: menu.color }"
160
200
  class="h-10 w-10 flex flex-shrink-0 items-center justify-center rounded-lg"
161
201
  >
162
202
  <!-- <component
@@ -164,14 +204,15 @@ onMounted(() => {
164
204
  :is="iconMap[menu.icon]"
165
205
  class="w-5 h-5 text-white"
166
206
  /> -->
207
+ <wd-icon name="picture" size="22px" color="#FFF" />
167
208
  </view>
168
209
  <view class="flex-1 text-left">
169
210
  <p
170
211
  class="text-base text-slate-800 font-medium"
171
212
  v-html="highlightedLabel(menu)"
172
213
  />
173
- <p v-if="menu.description" class="mt-0.5 text-xs text-slate-400">
174
- {{ menu.description }}
214
+ <p v-if="menu.tip" class="mt-0.5 text-xs text-slate-400">
215
+ {{ menu.tip }}
175
216
  </p>
176
217
  </view>
177
218
  </view>
@@ -0,0 +1,42 @@
1
+ import { enums, listData, pageConfig, pageKey } from '../api/page'
2
+ import { ref } from 'vue'
3
+ import ControlTypeSupportor from '../utils/control-type-supportor'
4
+ import type { Enums } from '../type'
5
+ export function useEnums({ config }: { config: any }) {
6
+ const enumColumn = ref<Enums>({})
7
+ // 获取枚举
8
+ async function getEnums() {
9
+ try {
10
+ const params: string[] = []
11
+ const criterias = config.value?.criterias ?? []
12
+ const columns = config.value.columns ?? []
13
+ const writes = config.value.rowActions?.reduce((acc: any, cur: any) => {
14
+ return [...acc, ...cur.writes]
15
+ }, []) || []
16
+ columns.forEach((item: any) => {
17
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
18
+ params.push(`mstrucIds=${item.mstrucId}`)
19
+ }
20
+ })
21
+ criterias.forEach((item: any) => {
22
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
23
+ params.push(`mstrucIds=${item.mstrucId}`)
24
+ }
25
+ })
26
+ writes.forEach((item: any) => {
27
+ if (ControlTypeSupportor.getControlType(item) === 'select' || ControlTypeSupportor.getControlType(item) === 'multiselect') {
28
+ params.push(`mstrucIds=${item.mstrucId}`)
29
+ }
30
+ })
31
+ if (!params.length)
32
+ return
33
+ const res = await enums(params.join('&'))
34
+ enumColumn.value = res.enumMap || {}
35
+ }
36
+ catch (error) {
37
+ console.log('error:', error)
38
+ }
39
+ }
40
+
41
+ return { getEnums, enumColumn }
42
+ }
@@ -14,10 +14,12 @@ interface Props {
14
14
  load: () => void
15
15
  menuTopType: string
16
16
  }
17
- interface MenuItem {
17
+ export interface MenuItem {
18
18
  id: string
19
19
  title: string
20
20
  icon: string
21
+ color: string
22
+ tip: string
21
23
  pageType: string
22
24
  children?: MenuItem[]
23
25
  }
@@ -31,7 +33,7 @@ export function useMenus(props?: Props, pagingRef?: Ref<any>) {
31
33
  const menuList = ref<MenuItem[]>([])
32
34
  const title = ref('')
33
35
  const navTitle = ref('')
34
- const filtermenu = computed(() => {
36
+ const filtermenu = computed<MenuItem[]>(() => {
35
37
  let arr = []
36
38
  if (currentThemeColor.value.primary) {
37
39
  arr = filterHiddenTree(menuList.value, 'items', true)
@@ -170,7 +172,7 @@ export function useMenus(props?: Props, pagingRef?: Ref<any>) {
170
172
  try {
171
173
  const res = await fastmenu()
172
174
  if (res.fastMenu) {
173
- sectionmenu.value = res.fastMenu.QuickQueryBar || []
175
+ sectionmenu.value = res.fastMenu.QuickQueryBar || []
174
176
  }
175
177
  else {
176
178
  sectionmenu.value = []
package/index.ts CHANGED
@@ -26,7 +26,7 @@ import WuiUser from './components/wui-user/wui-user.vue'
26
26
  import WuiAutoUpdateComponent from './components/wui-auto-update-component/wui-auto-update-component.vue'
27
27
  import iData from './utils/idata-scan'// PAD扫描
28
28
  import wuiSearchHistoryBabbar from './components/wui-search-history-babbar/wui-search-history-babbar.vue'
29
-
29
+ import enumeSelectControl from './components/enume-select-control/enume-select-control.vue'
30
30
  // 组件列表
31
31
  const coms: Array<{ name: string }> = [
32
32
  WuiSystemSettings,
@@ -73,6 +73,7 @@ export {
73
73
  iData, // PAD扫描
74
74
  // nfc, // nfc读取
75
75
  useLanguageStore, // 语言
76
+ enumeSelectControl,// 枚举选择
76
77
  }
77
78
 
78
79
  export default install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wui-components-v2",
3
- "version": "1.1.35",
3
+ "version": "1.1.36",
4
4
  "description": "wui 组件库",
5
5
  "author": "wgxshh",
6
6
  "license": "MIT",
package/type.ts CHANGED
@@ -108,6 +108,7 @@ export interface Groups {
108
108
  readOnly: boolean
109
109
  displayConfig: string[]
110
110
  batchAddFileField?: Fields
111
+ primaryColumn?: Columns
111
112
  }
112
113
 
113
114
  export interface Entity extends Entities {