n20-common-lib 3.1.1 → 3.1.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -0,0 +1,152 @@
1
+ import bus from './eventBus'
2
+
3
+ // 事件名常量
4
+ const MAIN_STATE_CHANGE = 'MAIN_STATE_CHANGE'
5
+ const CHILD_MESSAGE = 'CHILD_MESSAGE'
6
+
7
+ // 子应用间通讯的通道标记
8
+ const CHILD_CHANNEL = 'child-to-child'
9
+
10
+ // 模块级状态
11
+ let qiankunProps = null
12
+ let unsubscribe = null
13
+ let latestMainState = null
14
+
15
+ /**
16
+ * 初始化 qiankun 通讯,应在 mount() 中调用
17
+ * @param {Object} props qiankun mount 阶段传入的 props
18
+ */
19
+ export function initCommunication(props) {
20
+ // 防止重复初始化累积监听器
21
+ destroyCommunication()
22
+
23
+ qiankunProps = props || null
24
+
25
+ if (props && typeof props.onGlobalStateChange === 'function') {
26
+ unsubscribe = props.onGlobalStateChange((state, prev) => {
27
+ if (state && state._channel === CHILD_CHANNEL) {
28
+ // 子应用间消息,走独立通道
29
+ bus.$emit(CHILD_MESSAGE, {
30
+ type: state._type,
31
+ data: state._data,
32
+ from: state._from,
33
+ target: state._target
34
+ })
35
+ return
36
+ }
37
+ latestMainState = state
38
+ bus.$emit(MAIN_STATE_CHANGE, state, prev)
39
+ }, true)
40
+ }
41
+ }
42
+
43
+ /**
44
+ * 销毁通讯,清理监听器和缓存引用,应在 unmount() 中调用
45
+ */
46
+ export function destroyCommunication() {
47
+ if (typeof unsubscribe === 'function') {
48
+ unsubscribe()
49
+ }
50
+ unsubscribe = null
51
+ qiankunProps = null
52
+ latestMainState = null
53
+ }
54
+
55
+ /**
56
+ * 通过 qiankun GlobalState 向主应用发送状态
57
+ * @param {Object} state 要发送的状态对象
58
+ * @returns {boolean} 是否发送成功
59
+ */
60
+ export function setGlobalState(state) {
61
+ if (qiankunProps && typeof qiankunProps.setGlobalState === 'function') {
62
+ qiankunProps.setGlobalState(state)
63
+ return true
64
+ }
65
+ return false
66
+ }
67
+
68
+ /**
69
+ * 监听主应用全局状态变化
70
+ * @param {Function} callback 回调函数 (state) => void
71
+ */
72
+ export function onMainStateChange(callback) {
73
+ bus.$on(MAIN_STATE_CHANGE, callback)
74
+ // 已有缓存状态时立即同步回调
75
+ if (latestMainState !== null) {
76
+ callback(latestMainState)
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 注销主应用状态变化监听
82
+ * @param {Function} callback 要注销的回调
83
+ */
84
+ export function offMainStateChange(callback) {
85
+ bus.$off(MAIN_STATE_CHANGE, callback)
86
+ }
87
+
88
+ /**
89
+ * 获取缓存的主应用最新状态
90
+ * @returns {Object|null}
91
+ */
92
+ export function getMainState() {
93
+ return latestMainState
94
+ }
95
+
96
+ /**
97
+ * 通过 window.postMessage 向主应用发送结构化消息
98
+ * 格式兼容现有 handleTab.js 的 postMessage 协议
99
+ * @param {string} type 消息类型
100
+ * @param {*} data 消息数据
101
+ */
102
+ export function postToMain(type, data) {
103
+ const originName = process.env.VUE_APP_NAME
104
+ window.postMessage({
105
+ [type]: data,
106
+ targetName: 'main',
107
+ originName
108
+ })
109
+ }
110
+
111
+ /**
112
+ * 通过主应用中转向另一个子应用发送消息
113
+ * @param {string} childAppName 目标子应用名称
114
+ * @param {string} type 消息类型
115
+ * @param {*} data 消息数据
116
+ * @returns {boolean} 是否发送成功
117
+ */
118
+ export function sendToChild(childAppName, type, data) {
119
+ if (qiankunProps && typeof qiankunProps.setGlobalState === 'function') {
120
+ qiankunProps.setGlobalState({
121
+ _channel: CHILD_CHANNEL,
122
+ _target: childAppName,
123
+ _from: process.env.VUE_APP_NAME,
124
+ _type: type,
125
+ _data: data
126
+ })
127
+ return true
128
+ }
129
+ return false
130
+ }
131
+
132
+ /**
133
+ * 监听其他子应用发来的消息
134
+ * @param {Function} callback 回调函数 ({ type, data, from, target }) => void
135
+ */
136
+ export function onChildMessage(callback) {
137
+ bus.$on(CHILD_MESSAGE, callback)
138
+ }
139
+
140
+ /**
141
+ * 检测当前是否在 qiankun 环境中运行
142
+ * @returns {boolean}
143
+ */
144
+ export function isQiankunEnvironment() {
145
+ return !!window.__POWERED_BY_QIANKUN__
146
+ }
147
+
148
+ // 透传 EventBus 方法
149
+ export const $on = bus.$on.bind(bus)
150
+ export const $off = bus.$off.bind(bus)
151
+ export const $emit = bus.$emit.bind(bus)
152
+ export const $once = bus.$once.bind(bus)
@@ -0,0 +1,55 @@
1
+ /**
2
+ * 轻量级发布/订阅事件总线,供 qiankun 通信模块内部使用,同时对外暴露
3
+ */
4
+ class EventBus {
5
+ constructor() {
6
+ this._events = Object.create(null)
7
+ }
8
+
9
+ $on(event, fn) {
10
+ if (Array.isArray(event)) {
11
+ event.forEach((e) => this.$on(e, fn))
12
+ return
13
+ }
14
+ ;(this._events[event] || (this._events[event] = [])).push(fn)
15
+ }
16
+
17
+ $off(event, fn) {
18
+ if (!event) {
19
+ this._events = Object.create(null)
20
+ return
21
+ }
22
+ const cbs = this._events[event]
23
+ if (!cbs) return
24
+ if (!fn) {
25
+ this._events[event] = null
26
+ return
27
+ }
28
+ for (let i = cbs.length - 1; i >= 0; i--) {
29
+ if (cbs[i] === fn || cbs[i].__onceFn__ === fn) {
30
+ cbs.splice(i, 1)
31
+ }
32
+ }
33
+ }
34
+
35
+ $emit(event, ...args) {
36
+ const cbs = this._events[event]
37
+ if (!cbs || !cbs.length) return
38
+ // 快照避免边触发边注销导致的遍历问题
39
+ const snapshot = cbs.slice()
40
+ for (let i = 0; i < snapshot.length; i++) {
41
+ snapshot[i](...args)
42
+ }
43
+ }
44
+
45
+ $once(event, fn) {
46
+ const wrapper = (...args) => {
47
+ this.$off(event, wrapper)
48
+ fn(...args)
49
+ }
50
+ wrapper.__onceFn__ = fn
51
+ this.$on(event, wrapper)
52
+ }
53
+ }
54
+
55
+ export default new EventBus()
@@ -1,4 +1,5 @@
1
1
  import Vue from 'vue'
2
+ import { initCommunication, onMainStateChange, destroyCommunication } from './communicator'
2
3
 
3
4
  const vuePar = {
4
5
  render: undefined,
@@ -112,16 +113,17 @@ export async function bootstrap() {
112
113
  // console.log('[vue] vue app bootstraped')
113
114
  }
114
115
  export async function mount(props) {
115
- // console.log('[vue] props from main framework', props)
116
- props?.onGlobalStateChange((state) => {
117
- // state: 变更后的状态; prev 变更前的状态
118
- // console.log('onGlobalStateChange111', state, prev)
116
+ // 监听主应用状态变化 -> 提交到 Vuex(在 initCommunication 前注册,避免初始状态丢失)
117
+ onMainStateChange((state) => {
119
118
  vuePar?.store?.commit('MP/setGlobalState', state)
120
- }, true)
119
+ })
120
+ // 初始化统一通信层
121
+ initCommunication(props)
121
122
  /* 从其他子运用再切回这个运用,是否保持之前的状态 */
122
123
  KEEP_ALIVE && !props.router ? _mountKeep(props) : _mount(props)
123
124
  }
124
125
  export async function unmount(props) {
126
+ destroyCommunication()
125
127
  /* 从其他子运用再切回这个运用,是否保持之前的状态 */
126
128
  KEEP_ALIVE && !props.router ? _unmountKeep() : _unmount()
127
129
  }
@@ -190,7 +190,7 @@ $--checkbox-disabled-checked-input-border-color: $--border-color-base !default;
190
190
  $--checkbox-disabled-checked-icon-color: $--color-text-placeholder !default;
191
191
 
192
192
  /// color||Color|0
193
- $--checkbox-checked-font-color: #e5e6eb;
193
+ $--checkbox-checked-font-color: #1d2129;
194
194
  $--checkbox-checked-input-border-color: $--color-primary !default;
195
195
  /// color||Color|0
196
196
  $--checkbox-checked-background-color: $--color-primary !default;
@@ -143,7 +143,7 @@
143
143
  </div>
144
144
  <cl-advanced-filter
145
145
  v-if="form.viewType === VIEW_TYPE.ADVANCED"
146
- ref="filter"
146
+ ref="filter_box"
147
147
  :key="dialogFilterKey"
148
148
  class="filter"
149
149
  :visible="visible"
@@ -362,6 +362,13 @@ export default {
362
362
  this.searchValue = { ...this.getInitialSearchValue, ...this.initialValue }
363
363
  },
364
364
  methods: {
365
+ /**
366
+ * 供外部调用更新 GroupData
367
+ * @param {Array} data - 筛选条件数据
368
+ */
369
+ setGroupData(data) {
370
+ this.$refs.filter.mackData(data || [])
371
+ },
365
372
  // 处理 slot 类型字段的输入事件,同时更新 searchValue 和 initialValue
366
373
  handleSlotInput(fieldName, val) {
367
374
  // 防御性检查:如果 fieldName 无效,不执行任何操作
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="v2-table-pro-wrapper" style="height: 100%; position: relative">
2
+ <div class="v2-table-pro-wrapper" style="height: 100%; position: relative; overflow: hidden">
3
3
  <vxe-table
4
4
  ref="vxeTable"
5
5
  :key="colsKey"
@@ -1,9 +1,16 @@
1
1
  <template>
2
2
  <div class="flex-box flex-v flex-c table-operate-btns__wrapper">
3
3
  <childrenOperateBtn :btn-list="dfBtns" :row="row" @command="(c) => $emit('command', c)" />
4
- <el-dropdown v-if="moreBtns.length" class="m-l-b" @command="(c) => $emit('command', c)">
4
+ <!-- 更多操作下拉菜单:静态 moreBtns + 异步动态按钮 -->
5
+ <el-dropdown
6
+ v-if="showMoreBtn"
7
+ class="m-l-b"
8
+ @command="(c) => $emit('command', c)"
9
+ @visible-change="handleDropdownVisibleChange"
10
+ >
5
11
  <el-button class="n20-icon-moren" size="mini" type="text" />
6
12
  <el-dropdown-menu slot="dropdown" class="text-c">
13
+ <!-- 静态更多按钮 -->
7
14
  <template v-for="(item, i) in moreBtns">
8
15
  <el-dropdown-item v-if="item.children && item.children.length" :key="i">
9
16
  <template>{{ item.label }}</template>
@@ -39,12 +46,39 @@
39
46
  </template>
40
47
  </el-dropdown-item>
41
48
  </template>
49
+ <!-- 动态按钮加载中 -->
50
+ <el-dropdown-item v-if="dynamicLoading" disabled class="table-operate-loading">
51
+ <i class="el-icon-loading" /> {{ $lc('加载中') }}
52
+ </el-dropdown-item>
53
+ <!-- 动态按钮加载失败 -->
54
+ <el-dropdown-item v-else-if="dynamicError" disabled class="table-operate-error">
55
+ <i class="el-icon-warning" /> {{ $lc('加载失败') }}
56
+ </el-dropdown-item>
57
+ <!-- 动态按钮列表 -->
58
+ <template v-else>
59
+ <el-dropdown-item
60
+ v-for="(item, i) in dynamicBtns"
61
+ :key="'dynamic-' + i"
62
+ :command="item.command"
63
+ :disabled="item.disabled | dbdBtn(row)"
64
+ >
65
+ <el-badge v-if="resolveBadge(item)" :value="resolveBadge(item)" :max="item.badgeMax || 99">
66
+ <el-link v-if="item.type" :type="item.type" :underline="false">{{ item.label }}</el-link>
67
+ <template v-else>{{ item.label }}</template>
68
+ </el-badge>
69
+ <template v-else>
70
+ <el-link v-if="item.type" :type="item.type" :underline="false">{{ item.label }}</el-link>
71
+ <template v-else>{{ item.label }}</template>
72
+ </template>
73
+ </el-dropdown-item>
74
+ </template>
42
75
  </el-dropdown-menu>
43
76
  </el-dropdown>
44
77
  </div>
45
78
  </template>
46
79
  <script>
47
80
  import childrenOperateBtn from './childrenOperateBtn.vue'
81
+ import { $lc } from '../../utils/i18n/index.js'
48
82
 
49
83
  export default {
50
84
  name: 'TableOperate',
@@ -70,10 +104,19 @@ export default {
70
104
  row: {
71
105
  type: Object,
72
106
  default: () => ({})
107
+ },
108
+ // 异步获取操作按钮函数,(row) => Promise<Array<BtnItem>>
109
+ getOperateBtns: {
110
+ type: Function,
111
+ default: null
73
112
  }
74
113
  },
75
114
  data() {
76
- return {}
115
+ return {
116
+ dynamicBtns: [], // 异步加载的按钮列表
117
+ dynamicLoading: false, // 加载中状态
118
+ dynamicError: false // 加载失败状态
119
+ }
77
120
  },
78
121
  computed: {
79
122
  hasBtns() {
@@ -92,9 +135,14 @@ export default {
92
135
  } else {
93
136
  return []
94
137
  }
138
+ },
139
+ // 是否显示"更多"下拉按钮(静态 moreBtns 或异步 getOperateBtns 存在时)
140
+ showMoreBtn() {
141
+ return this.moreBtns.length > 0 || !!this.getOperateBtns
95
142
  }
96
143
  },
97
144
  methods: {
145
+ $lc,
98
146
  resolveBadge(item) {
99
147
  if (!item.badge) return null
100
148
  if (typeof item.badge === 'function') {
@@ -113,6 +161,24 @@ export default {
113
161
  } else if (typeof isHas === 'function') {
114
162
  return isHas(row)
115
163
  }
164
+ },
165
+ // 下拉菜单展开/收起时触发异步加载
166
+ async handleDropdownVisibleChange(visible) {
167
+ if (!visible || !this.getOperateBtns) return
168
+ this.dynamicBtns = []
169
+ this.dynamicError = false
170
+ this.dynamicLoading = true
171
+ try {
172
+ const btns = await this.getOperateBtns(this.row)
173
+ // 按 isHas 过滤动态按钮
174
+ this.dynamicBtns = Array.isArray(btns) ? btns.filter((btn) => this.hasBtn(btn.isHas, this.row)) : []
175
+ } catch (e) {
176
+ console.warn('[TablePro] getOperateBtns failed:', e)
177
+ this.dynamicError = true
178
+ this.dynamicBtns = []
179
+ } finally {
180
+ this.dynamicLoading = false
181
+ }
116
182
  }
117
183
  }
118
184
  }
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <div class="n20-view-toggle" :class="{ disabled }">
3
- <div class="n20-toggle-container">
3
+ <div class="n20-toggle-container" ref="container">
4
4
  <div
5
5
  v-for="(item, index) in options"
6
6
  :key="item.value"
7
+ ref="items"
7
8
  class="n20-toggle-item"
8
9
  :class="{ active: value === item.value, 'is-disabled': item.disabled }"
9
10
  :style="itemStyle"
@@ -33,7 +34,7 @@ export default {
33
34
  },
34
35
  itemWidth: {
35
36
  type: [Number, String],
36
- default: 80
37
+ default: ''
37
38
  },
38
39
  itemHeight: {
39
40
  type: [Number, String],
@@ -44,31 +45,90 @@ export default {
44
45
  default: false
45
46
  }
46
47
  },
48
+ data() {
49
+ return {
50
+ // 自适应模式下指示器的测量数据
51
+ measuredIndicator: { width: 0, height: 0, translateX: 0 }
52
+ }
53
+ },
47
54
  computed: {
55
+ // 是否为固定宽度模式
56
+ isFixedWidth() {
57
+ return this.itemWidth !== '' && this.itemWidth !== undefined && this.itemWidth !== null
58
+ },
48
59
  itemStyle() {
49
- const width = typeof this.itemWidth === 'number' ? `${this.itemWidth}px` : (isNaN(this.itemWidth) ? this.itemWidth : `${this.itemWidth}px`)
50
- const height = typeof this.itemHeight === 'number' ? `${this.itemHeight}px` : (isNaN(this.itemHeight) ? this.itemHeight : `${this.itemHeight}px`)
51
- return {
52
- width,
53
- height
60
+ const style = {}
61
+ if (this.isFixedWidth) {
62
+ style.width = this.normalizeSize(this.itemWidth)
63
+ } else {
64
+ // 自适应模式:用 padding 撑开宽度
65
+ style.padding = '0 12px'
54
66
  }
67
+ style.height = this.normalizeSize(this.itemHeight)
68
+ return style
55
69
  },
56
70
  indicatorStyle() {
57
- const itemW = typeof this.itemWidth === 'number' ? this.itemWidth : parseInt(this.itemWidth)
58
- const itemH = typeof this.itemHeight === 'number' ? this.itemHeight : parseInt(this.itemHeight)
59
71
  const gap = 2
60
- const activeIndex = this.options.findIndex((item) => item.value === this.value)
61
- const translateX = activeIndex >= 0 ? activeIndex * itemW : 0
72
+ const itemH = typeof this.itemHeight === 'number' ? this.itemHeight : parseInt(this.itemHeight) || 30
73
+ if (this.isFixedWidth) {
74
+ const itemW = typeof this.itemWidth === 'number' ? this.itemWidth : parseInt(this.itemWidth) || 80
75
+ const activeIndex = this.options.findIndex((item) => item.value === this.value)
76
+ const translateX = activeIndex >= 0 ? activeIndex * itemW : 0
77
+ return {
78
+ width: `${itemW - 2 * gap}px`,
79
+ height: `${itemH - 2 * gap}px`,
80
+ top: `${gap}px`,
81
+ left: `${gap}px`,
82
+ transform: `translateX(${translateX}px)`
83
+ }
84
+ }
85
+ // 自适应模式:基于 DOM 测量定位
86
+ const { width, height, translateX } = this.measuredIndicator
62
87
  return {
63
- width: `${itemW - 2 * gap}px`,
64
- height: `${itemH - 2 * gap}px`,
88
+ width: `${width - 2 * gap}px`,
89
+ height: `${height - 2 * gap}px`,
65
90
  top: `${gap}px`,
66
91
  left: `${gap}px`,
67
92
  transform: `translateX(${translateX}px)`
68
93
  }
69
94
  }
70
95
  },
96
+ watch: {
97
+ value() {
98
+ if (!this.isFixedWidth) this.$nextTick(this.updateIndicator)
99
+ },
100
+ options: {
101
+ deep: true,
102
+ handler() {
103
+ if (!this.isFixedWidth) this.$nextTick(this.updateIndicator)
104
+ }
105
+ }
106
+ },
107
+ mounted() {
108
+ if (!this.isFixedWidth) this.updateIndicator()
109
+ },
71
110
  methods: {
111
+ // 统一尺寸格式化
112
+ normalizeSize(val) {
113
+ if (typeof val === 'number') return `${val}px`
114
+ return isNaN(val) ? val : `${val}px`
115
+ },
116
+ // 自适应模式下测量激活项的位置
117
+ updateIndicator() {
118
+ const items = this.$refs.items
119
+ if (!items || !items.length) return
120
+ const activeIndex = this.options.findIndex((item) => item.value === this.value)
121
+ if (activeIndex < 0) {
122
+ this.measuredIndicator = { width: 0, height: 0, translateX: 0 }
123
+ return
124
+ }
125
+ const activeEl = items[activeIndex]
126
+ this.measuredIndicator = {
127
+ width: activeEl.offsetWidth,
128
+ height: activeEl.offsetHeight,
129
+ translateX: activeEl.offsetLeft
130
+ }
131
+ },
72
132
  handleChange(val) {
73
133
  if (this.disabled) return
74
134
  const item = this.options.find((item) => item.value === val)
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="v3-table-pro-wrapper" style="height: 100%; position: relative">
2
+ <div class="v3-table-pro-wrapper" style="height: 100%; position: relative; overflow: hidden">
3
3
  <!-- 骨架屏 - 仅覆盖内容区域,不覆盖表头 -->
4
4
  <div v-if="loading" class="table-pro-skeleton">
5
5
  <div v-for="n in skeletonRows" :key="'skeleton-' + n" class="skeleton-row">
@@ -35,7 +35,7 @@
35
35
  ...$attrs.columnConfig,
36
36
  ...$attrs['column-config']
37
37
  }"
38
- :scroll-y="scrollY"
38
+ :virtual-y-config="scrollY"
39
39
  :sort-config="{
40
40
  multiple: false,
41
41
  remote: true,
@@ -281,7 +281,7 @@
281
281
  </div>
282
282
  </template>
283
283
  <template #default="{ row, $rowIndex }">
284
- <OperateBtns :btn-list="btnList" :row="row" @command="(c) => handleOperateCommand(c, row, $rowIndex)" />
284
+ <OperateBtns :btn-list="btnList" :row="row" :get-operate-btns="getOperateBtns" @command="(c) => handleOperateCommand(c, row, $rowIndex)" />
285
285
  </template>
286
286
  </vxe-column>
287
287
  <template #empty>
@@ -420,7 +420,7 @@ export default {
420
420
  scrollY: {
421
421
  type: Object,
422
422
  default: () => {
423
- return { enabled: true, oSize: 20, gt: 30 }
423
+ return { enabled: true, gt: 0, model: 'wheel' }
424
424
  }
425
425
  },
426
426
  data: {
@@ -567,6 +567,11 @@ export default {
567
567
  operateColumnWidth: {
568
568
  type: Number,
569
569
  default: 180
570
+ },
571
+ // 异步获取操作按钮函数,(row) => Promise<Array<BtnItem>>
572
+ getOperateBtns: {
573
+ type: Function,
574
+ default: null
570
575
  }
571
576
  },
572
577
  data() {
@@ -728,6 +733,8 @@ export default {
728
733
  this.checkColumns = columns
729
734
  // 将 remote: true 的远程列同步写入 this.columns,保持位置一致
730
735
  this.syncRemoteColumns(columns)
736
+ // 强制 vxe-table 重建,确保固定列图标、颜色等表头状态正确回显
737
+ this.colsKey++
731
738
  } else {
732
739
  this.checkColumns = this.filterDefaultHidden(this.columns)
733
740
  }
@@ -740,8 +747,6 @@ export default {
740
747
  async refreshColumns() {
741
748
  if (this.showColumn && this.pageId) {
742
749
  await this.getColumns()
743
- // 强制重建 vxe-table,确保列变更后视图正确刷新
744
- this.colsKey++
745
750
  }
746
751
  },
747
752
  // 将 API 返回中标记 remote: true 的列同步到 this.columns,保持对应位置一致
package/src/index.js CHANGED
@@ -160,6 +160,26 @@ import fitlers from './fitlers'
160
160
  /** 修正ElementUI的问题 */
161
161
  import monitor from './utils/monitor.js'
162
162
  import repairEl from './utils/repairElementUI'
163
+
164
+ /** qiankun 微前端通讯 */
165
+ import {
166
+ initCommunication,
167
+ destroyCommunication,
168
+ setGlobalState,
169
+ postToMain,
170
+ onMainStateChange,
171
+ offMainStateChange,
172
+ getMainState,
173
+ sendToChild,
174
+ onChildMessage,
175
+ isQiankunEnvironment,
176
+ $on,
177
+ $off,
178
+ $emit,
179
+ $once
180
+ } from './_qiankun/communicator'
181
+ import PM from './_qiankun/postMessage.js'
182
+
163
183
  const components = [
164
184
  ProFilterView,
165
185
  DynamicFieldTable,
@@ -440,5 +460,23 @@ export {
440
460
  type,
441
461
  version,
442
462
  watermark,
443
- accountFormat
463
+ accountFormat,
464
+ // qiankun Vuex module
465
+ PM,
466
+ // qiankun 通讯函数
467
+ initCommunication,
468
+ destroyCommunication,
469
+ setGlobalState,
470
+ postToMain,
471
+ onMainStateChange,
472
+ offMainStateChange,
473
+ getMainState,
474
+ sendToChild,
475
+ onChildMessage,
476
+ isQiankunEnvironment,
477
+ // 事件总线
478
+ $on,
479
+ $off,
480
+ $emit,
481
+ $once
444
482
  }