n20-common-lib 1.3.30 → 1.3.33

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": "1.3.30",
3
+ "version": "1.3.33",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,46 +1,22 @@
1
- const name = process.env.VUE_APP_NAME
1
+ import { addTab, closeTab, setTabName, refreshTab } from '../utils/handleTab.js'
2
2
 
3
3
  const PM = {
4
4
  namespaced: true,
5
5
  state: {
6
- data: {}
6
+ data: undefined
7
7
  },
8
8
  mutations: {
9
- set(state, data) {
10
- state.data = Object.assign({}, state.data, data)
9
+ addTab(state, opt) {
10
+ addTab(opt)
11
11
  },
12
- addTab(state, opt = {}) {
13
- window.postMessage({
14
- addTab: opt,
15
- targetName: 'main',
16
- originName: name
17
- })
12
+ closeTab(state, opt) {
13
+ closeTab(opt)
18
14
  },
19
- closeTab(state, opt = {}) {
20
- window.postMessage({
21
- closeTab: opt,
22
- targetName: 'main',
23
- originName: name
24
- })
15
+ setTabName(state, opt) {
16
+ setTabName(opt)
25
17
  },
26
- setTabName(state, opt = {}) {
27
- window.postMessage({
28
- setTabName: opt,
29
- targetName: 'main',
30
- originName: name
31
- })
32
- },
33
- refreshTab(state, opt = {}) {
34
- window.postMessage({
35
- refreshTab: opt,
36
- targetName: 'main',
37
- originName: name
38
- })
39
- }
40
- },
41
- getters: {
42
- get(state) {
43
- return state.data
18
+ refreshTab(state, opt) {
19
+ refreshTab(opt)
44
20
  }
45
21
  }
46
22
  }
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <div>
3
+ <div ref="ad">
4
+ <el-card class="box-card" :header="header">
5
+ <cB />
6
+ <p>这里的传值,是只依赖DOM结构,利用自定义事件/事件冒泡实现值得传递</p>
7
+ </el-card>
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import cB from './b.vue'
14
+ export default {
15
+ components: { cB },
16
+ data() {
17
+ return {
18
+ header: ''
19
+ }
20
+ },
21
+ mounted() {
22
+ this.$refs['ad'].addEventListener('demoEv', (event) => {
23
+ event.stopPropagation()
24
+ const cD = event.target.customData
25
+ this.header = cD.title
26
+ })
27
+ }
28
+ }
29
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div>
3
+ <cC />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ import cC from './c.vue'
9
+ export default {
10
+ components: { cC }
11
+ }
12
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div class="flex-box flex-v">
3
+ <label>标题</label><el-input class="flex-item m-l" v-model="title" />
4
+ <EventBubble :data-custom="{ title: title }" data-event="demoEv" />
5
+ </div>
6
+ </template>
7
+
8
+ <script>
9
+ import EventBubble from '../index.vue'
10
+ export default {
11
+ components: { EventBubble },
12
+ data() {
13
+ return {
14
+ title: '默认标题'
15
+ }
16
+ }
17
+ }
18
+ </script>
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <i data-node="custom-el" style="display: none"></i>
3
+ </template>
4
+
5
+ <script>
6
+ // 触发自定义冒泡事假
7
+ export default {
8
+ name: 'EventBubble',
9
+ props: {
10
+ dataCustom: {
11
+ type: Object,
12
+ default: undefined
13
+ },
14
+ dataEvent: {
15
+ type: String,
16
+ default: 'custom'
17
+ }
18
+ },
19
+ watch: {
20
+ dataCustom: {
21
+ handler(val) {
22
+ this.setData(val)
23
+ },
24
+ deep: true
25
+ }
26
+ },
27
+ mounted() {
28
+ this.$nextTick(() => {
29
+ this.setData(this.dataCustom)
30
+ })
31
+ },
32
+ methods: {
33
+ setData(obj) {
34
+ if (obj) {
35
+ this.$el.customData = JSON.parse(JSON.stringify(obj))
36
+ dispatchEvent(this.$el, this.dataEvent)
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ function dispatchEvent(el, type) {
43
+ var evName = '_on_' + type
44
+ var evEvent = undefined
45
+
46
+ if (!window[evName]) {
47
+ evEvent = new CustomEvent(type, { bubbles: true, cancelable: false })
48
+ window[evName] = evEvent
49
+ }
50
+
51
+ el.dispatchEvent(window[evName])
52
+ // iframe is not target
53
+ // if (el.nodeName !== 'IFRAME' && window.frameElement) {
54
+ // dispatchEvent(window.frameElement, type)
55
+ // }
56
+ }
57
+ </script>
@@ -7,6 +7,25 @@
7
7
  v-bind="item.props"
8
8
  v-on="item.on"
9
9
  />
10
+ <el-input
11
+ v-else-if="item.type === 'search'"
12
+ v-model="form[item.value]"
13
+ :clearable="item | clearableF"
14
+ style="width: 100%"
15
+ readonly
16
+ v-bind="item.props"
17
+ v-on="item.on"
18
+ >
19
+ <i
20
+ slot="suffix"
21
+ class="el-input__icon el-icon-zoom-in"
22
+ @click="
23
+ () => {
24
+ item.on && item.on.focus && item.on.focus()
25
+ }
26
+ "
27
+ ></i>
28
+ </el-input>
10
29
  <el-select
11
30
  v-else-if="item.type === 'select'"
12
31
  v-model="form[item.value]"
@@ -100,6 +119,7 @@
100
119
  </template>
101
120
 
102
121
  <script>
122
+ import axios from '../../utils/axios'
103
123
  import inputNumber from '../InputNumber/index.vue'
104
124
  import inputNumberRange from '../InputNumber/numberRange.vue'
105
125
  import datePickerPor from '../DatePicker/por.vue'
@@ -127,6 +147,39 @@ export default {
127
147
  type: Object,
128
148
  default: undefined
129
149
  }
150
+ },
151
+ created() {
152
+ if (this.item.reqOptions) {
153
+ this.getOptions()
154
+ }
155
+ },
156
+ methods: {
157
+ getOptions() {
158
+ let reqOptions = this.item.reqOptions
159
+ let url = reqOptions.url || ''
160
+ url = url.includes('?')
161
+ ? `${url}r=${Math.random()}`
162
+ : `${url}?r=${Math.random()}`
163
+
164
+ axios({
165
+ ...reqOptions,
166
+ url: url,
167
+ loading: false,
168
+ noMsg: true,
169
+ resList: undefined
170
+ }).then((res) => {
171
+ let resKeys = reqOptions.resList
172
+ ? reqOptions.resList.split('.')
173
+ : ['data', 'list']
174
+
175
+ let list = res
176
+ resKeys.forEach((key) => {
177
+ list = list[key]
178
+ })
179
+
180
+ this.$set(this.item, 'options', list)
181
+ })
182
+ }
130
183
  }
131
184
  }
132
185
  </script>
@@ -6,7 +6,6 @@
6
6
  title="筛选"
7
7
  placement="bottom-end"
8
8
  @show="show"
9
- @after-leave="leave"
10
9
  >
11
10
  <template slot="reference">
12
11
  <el-button
@@ -91,7 +90,7 @@
91
90
  :columns="filterList"
92
91
  :is-filter="true"
93
92
  :auto-save="true"
94
- page-id="filterId"
93
+ :page-id="'filter:' + filterId"
95
94
  @setColumns="setRemoteChange"
96
95
  />
97
96
  </template>
@@ -170,10 +169,6 @@ export default {
170
169
  }
171
170
  })
172
171
  },
173
- leave() {
174
- this.showPopC = false
175
- this.showMore = false
176
- },
177
172
  clear() {
178
173
  this.$emit('clear')
179
174
  },
@@ -20,6 +20,7 @@
20
20
  :value="valueNum"
21
21
  :placeholder="phd"
22
22
  v-on="listeners"
23
+ @input.native="inputFn"
23
24
  @blur="blurFn"
24
25
  @change="changeFn"
25
26
  />
@@ -97,6 +98,7 @@ export default {
97
98
  if (val && typeof val === 'string' && val.includes(',')) {
98
99
  return this.$emit('input', Number(val.replace(/,/g, '')))
99
100
  }
101
+ this.preValue = val
100
102
  this.valueStr = this.num2str(val)
101
103
  },
102
104
  immediate: true
@@ -164,6 +166,13 @@ export default {
164
166
  }
165
167
  break
166
168
  }
169
+ },
170
+ inputFn({ target }) {
171
+ if (target.value !== '-' && isNaN(target.value)) {
172
+ target.value = this.preValue
173
+ } else {
174
+ this.preValue = target.value
175
+ }
167
176
  }
168
177
  }
169
178
  }
@@ -179,6 +179,7 @@
179
179
  </template>
180
180
 
181
181
  <script>
182
+ import Cookies from 'js-cookie'
182
183
  import { themeList } from '../../../utils/theme.config.js'
183
184
 
184
185
  import dialogWrap from '../../Dialog/index.vue'
@@ -229,7 +230,7 @@ const i18n = {
229
230
  en: ':'
230
231
  },
231
232
  秒: {
232
- en: ':'
233
+ en: ''
233
234
  },
234
235
  '确定退出,将清除未提交的临时操作,是否继续?': {
235
236
  en: 'Are you sure to exit? Uncommitted temporary operations will be cleared. Do you want to continue?'
@@ -299,23 +300,35 @@ export default {
299
300
  },
300
301
  setUserVisible(v) {
301
302
  if (v) {
302
- let loginTime = sessionStorage.getItem('loginTime')
303
- if (loginTime) {
304
- this.durationTime = dayjs.duration(Date.now() - loginTime).format(
305
- `HH${this.$l('小时', this.i18n)}
306
- mm${this.$l('分', this.i18n)}
307
- ss${this.$l('秒', this.i18n)}`
308
- )
309
- }
310
-
311
303
  let userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}')
312
304
  this.userInfo = {
313
305
  userName: userInfo.uname,
314
306
  companyName: userInfo.cltName
315
307
  }
316
308
  this.rolesList = userInfo.roles || []
309
+
310
+ let loginTime = sessionStorage.getItem('loginTime')
311
+ if (loginTime) {
312
+ this.setDurationTime(loginTime)
313
+ this.durationTime_timeout = setInterval(
314
+ () => this.setDurationTime(loginTime),
315
+ 500
316
+ )
317
+ }
318
+ } else {
319
+ clearInterval(this.durationTime_timeout)
317
320
  }
318
321
  },
322
+ setDurationTime(loginTime) {
323
+ this.durationTime = dayjs
324
+ .duration(Date.now() - loginTime)
325
+ .format(
326
+ `HH${this.$l('小时', this.i18n)}mm${this.$l(
327
+ '分',
328
+ this.i18n
329
+ )}ss${this.$l('秒', this.i18n)}`
330
+ )
331
+ },
319
332
  // 打开帮助文档
320
333
  openHelp() {
321
334
  axios
@@ -357,6 +370,10 @@ export default {
357
370
  setLang() {
358
371
  this.langV = false
359
372
  window.localStorage.setItem('pageLang', this.langVal)
373
+ Cookies.set(
374
+ 'language',
375
+ ['zh-cn', 'zh-hk'].includes(this.langVal) ? 'zh' : this.langVal
376
+ )
360
377
  window.location.reload()
361
378
  },
362
379
  setTheme({ value }) {
@@ -68,8 +68,8 @@ export default {
68
68
  },
69
69
  methods: {
70
70
  watchMessage(ev) {
71
- const { targetName, originName } = ev.data
72
- if (targetName === '*' && originName === 'main') {
71
+ const { updateCache, originName, targetName } = ev.data
72
+ if (updateCache && originName === 'main' && targetName === '*') {
73
73
  this.pendingRemoveCaches()
74
74
  }
75
75
  },
@@ -1,8 +1,9 @@
1
- .page-header {
1
+ .n20-page-header {
2
2
  display: flex;
3
3
  line-height: 20px;
4
4
  padding-bottom: 2px;
5
5
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
6
+
6
7
  .page-header__left {
7
8
  display: flex;
8
9
  align-items: center;
@@ -10,12 +11,15 @@
10
11
  margin-right: 16px;
11
12
  position: relative;
12
13
  }
14
+
13
15
  .page-header__left:hover {
14
16
  color: var(--color-primary);
17
+
15
18
  .page-header__title {
16
19
  color: var(--color-primary);
17
20
  }
18
21
  }
22
+
19
23
  .page-header__left:after {
20
24
  content: '';
21
25
  position: absolute;
@@ -26,14 +30,16 @@
26
30
  transform: translateY(-50%);
27
31
  background-color: #dcdfe6;
28
32
  }
33
+
29
34
  .page-header__title {
30
35
  font-size: 14px;
31
36
  line-height: 20px;
32
37
  color: #3d4a57;
33
38
  }
39
+
34
40
  .page-header__content {
35
41
  font-size: 14px;
36
42
  line-height: 20px;
37
43
  color: #3d4a57;
38
44
  }
39
- }
45
+ }
@@ -0,0 +1,60 @@
1
+ import numerify from 'numerify'
2
+ import dayjs from 'dayjs'
3
+
4
+ function tplFn(row, sc, mck, map = {}) {
5
+ let str = ''
6
+ sc.forEach((s, i) => {
7
+ str += s
8
+ let kA = mck[i]
9
+ if (kA && kA.length) {
10
+ let key = kA[0]
11
+ if (kA.length === 1) {
12
+ str += row[key]
13
+ } else {
14
+ let type = kA[1]
15
+ switch (type) {
16
+ case 'money':
17
+ str += numerify(row[key], '0,0.00')
18
+ break
19
+ case 'rate':
20
+ str += numerify(row[key], '0.000000')
21
+ break
22
+ case 'map':
23
+ str += map[row[key]]
24
+ break
25
+ case 'date':
26
+ str += dayjs(row[key]).format('YYYY-MM-DD')
27
+ break
28
+ case 'datetime':
29
+ str += dayjs(row[key]).format('YYYY-MM-DD HH:mm:ss')
30
+ break
31
+ case 'time':
32
+ str += dayjs(row[key]).format('HH:mm:ss')
33
+ break
34
+ default:
35
+ str += row[key]
36
+ break
37
+ }
38
+ }
39
+ }
40
+ })
41
+ return str
42
+ }
43
+
44
+ export function colfF(colf, map) {
45
+ if (typeof colf !== 'string') return colf
46
+ let sc = colf.split(/{.+?}/g) || []
47
+ let mc = colf.match(/{.+?}/g) || []
48
+ let mck = []
49
+ mc.forEach((t) => {
50
+ t = t.replace(/^{|\s+|}$/g, '').split('|')
51
+ mck.push(t)
52
+ })
53
+
54
+ return (row) => tplFn(row, sc, mck, map)
55
+ }
56
+
57
+ export function colftF(colft, fMap) {
58
+ if (typeof colft !== 'string') return colft
59
+ return fMap[colft]
60
+ }
@@ -39,9 +39,22 @@
39
39
  </template>
40
40
 
41
41
  <script>
42
- import numerify from 'numerify'
43
- import dayjs from 'dayjs'
44
42
  import thSelectHeader from './ThSelectHeader.vue'
43
+ import { colfF, colftF } from './filters'
44
+
45
+ const columnRender = {
46
+ props: {
47
+ cRender: {
48
+ type: Function
49
+ },
50
+ row: {
51
+ type: Object
52
+ }
53
+ },
54
+ render(h) {
55
+ return this.cRender(h, this.row)
56
+ }
57
+ }
45
58
 
46
59
  export default {
47
60
  name: 'Table',
@@ -120,75 +133,4 @@ export default {
120
133
  }
121
134
  }
122
135
  }
123
-
124
- const columnRender = {
125
- props: {
126
- cRender: {
127
- type: Function
128
- },
129
- row: {
130
- type: Object
131
- }
132
- },
133
- render(h) {
134
- return this.cRender(h, this.row)
135
- }
136
- }
137
-
138
- function colfF(colf, map) {
139
- if (typeof colf !== 'string') return colf
140
- let sc = colf.split(/{.+?}/g) || []
141
- let mc = colf.match(/{.+?}/g) || []
142
- let mck = []
143
- mc.forEach((t) => {
144
- t = t.replace(/^{|\s+|}$/g, '').split('|')
145
- mck.push(t)
146
- })
147
-
148
- return (row) => tplFn(row, sc, mck, map)
149
- }
150
- function tplFn(row, sc, mck, map = {}) {
151
- let str = ''
152
- sc.forEach((s, i) => {
153
- str += s
154
- let kA = mck[i]
155
- if (kA && kA.length) {
156
- let key = kA[0]
157
- if (kA.length === 1) {
158
- str += row[key]
159
- } else {
160
- let type = kA[1]
161
- switch (type) {
162
- case 'money':
163
- str += numerify(row[key], '0,0.00')
164
- break
165
- case 'rate':
166
- str += numerify(row[key], '0.000000')
167
- break
168
- case 'map':
169
- str += map[row[key]]
170
- break
171
- case 'date':
172
- str += dayjs(row[key]).format('YYYY-MM-DD')
173
- break
174
- case 'datetime':
175
- str += dayjs(row[key]).format('YYYY-MM-DD HH:mm:ss')
176
- break
177
- case 'time':
178
- str += dayjs(row[key]).format('HH:mm:ss')
179
- break
180
- default:
181
- str += row[key]
182
- break
183
- }
184
- }
185
- }
186
- })
187
- return str
188
- }
189
-
190
- function colftF(colft, fMap) {
191
- if (typeof colft !== 'string') return colft
192
- return fMap[colft]
193
- }
194
136
  </script>
@@ -1,3 +1,5 @@
1
+ import { Popover as elPopover } from 'element-ui'
2
+
1
3
  let timer = undefined
2
4
  const popClass = 'at-title-pop-' + Date.now()
3
5
 
@@ -44,6 +46,9 @@ TitleDirective.install = (Vue) => {
44
46
  if (Vue.prototype.$isServer) return
45
47
  const tooltip = new Vue({
46
48
  el: document.createElement('div'),
49
+ components: {
50
+ elPopover
51
+ },
47
52
  data() {
48
53
  return {
49
54
  visible: false
package/src/index.js CHANGED
@@ -48,10 +48,11 @@ import FlowStep from './components/FlowStep/index.vue'
48
48
  import CascaderArea from './components/CascaderArea/index.vue'
49
49
  import FileExportAsync from './components/FileExportAsync/index.vue'
50
50
  import FlowDialog from './components/ApprovalRecord/flowDialog.vue'
51
- import ChildRange from './components/ChildRange/index'
52
- import FileImport from './components/FileImport/index'
53
- import PageHeader from './components/PageHeader/index'
54
- import Descriptions from './components/Descriptions'
51
+ import ChildRange from './components/ChildRange/index.vue'
52
+ import FileImport from './components/FileImport/index.vue'
53
+ import PageHeader from './components/PageHeader/index.vue'
54
+ import Descriptions from './components/Descriptions/index.vue'
55
+ import EventBubble from './components/EventBubble/index.vue'
55
56
  // ECharts 不要打包进来
56
57
  // import Search from './components/Search/index.vue'
57
58
  import Stamp from './components/Stamp/index.vue'
@@ -142,6 +143,7 @@ const components = [
142
143
  FileImport,
143
144
  PageHeader,
144
145
  Descriptions,
146
+ EventBubble,
145
147
  // Search,
146
148
  approvalImg,
147
149
  Stamp,
@@ -154,6 +156,8 @@ const components = [
154
156
  const install = function (Vue, opts = { prefix: 'Cl', i18nConfig: {} }) {
155
157
  components.forEach((component) => {
156
158
  let name = component.name
159
+ if (!name) return console.error('Component name is required:', component)
160
+
157
161
  name = opts.prefix + name.replace(name[0], name[0].toUpperCase())
158
162
  Vue.component(name, component)
159
163
  })
@@ -251,6 +255,7 @@ export {
251
255
  FileImport,
252
256
  PageHeader,
253
257
  Descriptions,
258
+ EventBubble,
254
259
  // Search,
255
260
  approvalImg,
256
261
  Stamp
@@ -1,57 +1,11 @@
1
+ import { setTabs, closeTag } from '../../utils/handleTab.js'
2
+
1
3
  // 老系统子应用调用函数,新增页签的函数接口
2
4
  export function setTabsForSub(baseUrl, to, tab = true) {
3
- let { path, name, meta = {}, query } = to
4
- let _path = baseUrl + path
5
- _path = _path.replace('//', '/')
6
- let _i18n
7
- let _title
8
-
9
- let { title, i18n } = meta
10
- if (i18n && typeof i18n === 'object') {
11
- _i18n = i18n
12
- } else if (title && typeof title === 'object') {
13
- _i18n = title
14
- } else if (name && typeof name === 'object') {
15
- _i18n = name
16
- }
17
- if (_i18n && _i18n.zh) {
18
- _title = _i18n.zh
19
- } else {
20
- _title = title
21
- }
22
-
23
- if (tab) {
24
- window.postMessage({
25
- addTabO: {
26
- path: _path,
27
- title: _title,
28
- i18n: _i18n,
29
- query: query
30
- },
31
- targetName: 'main',
32
- originName: name
33
- })
34
- } else {
35
- window.postMessage({
36
- replaceTab: {
37
- path: _path,
38
- title: _title,
39
- i18n: _i18n,
40
- query: query
41
- },
42
- targetName: 'main',
43
- originName: name
44
- })
45
- }
5
+ setTabs(baseUrl, to, tab)
46
6
  }
47
7
 
48
8
  // 老系统子应用调用函数,关闭页签的函数接口
49
9
  export function closeTagsForBackPage(url) {
50
- window.postMessage({
51
- closeTab: {
52
- path: url || window.location.pathname
53
- },
54
- targetName: 'main',
55
- originName: '*'
56
- })
10
+ closeTag(url)
57
11
  }
package/src/utils/auth.js CHANGED
@@ -29,6 +29,7 @@ const auth = {
29
29
  },
30
30
  setLoginPath(router) {
31
31
  let { base = '/', mode = 'history' } = router.options
32
+ ;/\/$/.test(base) || (base += '/')
32
33
  if (mode === 'hash') {
33
34
  ownLoginPath = window.location.origin + base + '#/login'
34
35
  } else {
@@ -0,0 +1,109 @@
1
+ // 操作切换路由生成的页签
2
+ const dN = process.env.VUE_APP_NAME
3
+ /** 打开页签,push对应路由 */
4
+ export function addTab(opt = {}, name) {
5
+ window.postMessage({
6
+ addTab: opt,
7
+ targetName: 'main',
8
+ originName: name || dN
9
+ })
10
+ }
11
+ /** 子打开页签,不再push对应路由 */
12
+ export function addTabO(opt = {}, name) {
13
+ window.postMessage({
14
+ addTabO: opt,
15
+ targetName: 'main',
16
+ originName: name || dN
17
+ })
18
+ }
19
+
20
+ export function closeTab(opt = {}, name) {
21
+ window.postMessage({
22
+ closeTab: opt,
23
+ targetName: 'main',
24
+ originName: name || dN
25
+ })
26
+ }
27
+
28
+ export function setTabName(opt = {}, name) {
29
+ window.postMessage({
30
+ setTabName: opt,
31
+ targetName: 'main',
32
+ originName: name || dN
33
+ })
34
+ }
35
+
36
+ export function refreshTab(opt = {}, name) {
37
+ window.postMessage({
38
+ refreshTab: opt,
39
+ targetName: 'main',
40
+ originName: name || dN
41
+ })
42
+ }
43
+ /** 不打开页签,替换当前页签保存的路由信息 */
44
+ export function replaceTab(opt = {}, name) {
45
+ window.postMessage({
46
+ replaceTab: opt,
47
+ targetName: 'main',
48
+ originName: name || dN
49
+ })
50
+ }
51
+
52
+ /* 业务应用 */
53
+ // 获取页签名称
54
+ function getI18n(meta = {}, name) {
55
+ let _i18n = undefined
56
+ let { title, i18n } = meta
57
+
58
+ if (i18n && typeof i18n === 'object') {
59
+ _i18n = i18n
60
+ } else if (title && typeof title === 'object') {
61
+ _i18n = title
62
+ } else if (name && typeof name === 'object') {
63
+ _i18n = name
64
+ }
65
+ return {
66
+ i18n: _i18n,
67
+ title: _i18n && _i18n.zh ? _i18n.zh : title
68
+ }
69
+ }
70
+ // 获取绝对路径
71
+ function getPath(baseUrl, path) {
72
+ return (baseUrl + path).replace('//', '/')
73
+ }
74
+ // 获取模块名称
75
+ function getName(baseUrl) {
76
+ return dN || baseUrl.replace('/', '')
77
+ }
78
+ /** 子模块在门户中打开页签 */
79
+ export function setTabs(baseUrl, to, tab = true) {
80
+ let { path, name, meta = {}, query } = to
81
+ let { i18n, title } = getI18n(meta, name)
82
+ let route = getPath(baseUrl, path)
83
+
84
+ if (tab) {
85
+ addTabO(
86
+ {
87
+ path: route,
88
+ title: title,
89
+ i18n: i18n,
90
+ query: query
91
+ },
92
+ getName(baseUrl)
93
+ )
94
+ } else {
95
+ replaceTab(
96
+ {
97
+ path: route,
98
+ title: title,
99
+ i18n: i18n,
100
+ query: query
101
+ },
102
+ getName(baseUrl)
103
+ )
104
+ }
105
+ }
106
+ /** 子模块关闭在门户中的页签 */
107
+ export function closeTag(url, name) {
108
+ closeTab({ path: url || window.location.pathname }, name || '*')
109
+ }
@@ -17,7 +17,7 @@ export function $l(zh, map = {}) {
17
17
  } else {
18
18
  let key = pageLang
19
19
  let valMap = map[zh] || $i18n_map_root[zh] || {}
20
- let val = valMap[key] || zh
20
+ let val = valMap[key] !== undefined ? valMap[key] : zh
21
21
 
22
22
  return val
23
23
  }
@@ -0,0 +1,115 @@
1
+ import ExcelJS from 'exceljs'
2
+
3
+ function toExcel({ columns = [], rows = [], name = 'sheet01' }) {
4
+ let cols = []
5
+ columns.forEach((col) => {
6
+ if (!col.static) {
7
+ let _col = {
8
+ header: col.label,
9
+ key: col.prop,
10
+ style: col.style || {}
11
+ }
12
+
13
+ let width = col.width || col.minWidth || col['min-width'] || 0
14
+ width = Math.max(width / 8, col.label.length * 2.2 + 2)
15
+ width > 9 && (_col.width = width)
16
+
17
+ if (col.numFmt) {
18
+ _col.style.numFmt = col.numFmt
19
+ } else if (col.formatter && typeof col.formatter === 'string') {
20
+ if (/\|\s?money/.test(col.formatter)) {
21
+ _col.style.numFmt = '#,##0.00'
22
+ }
23
+ if (/\|\s?rate/.test(col.formatter)) {
24
+ _col.style.numFmt = '0.000000'
25
+ }
26
+ }
27
+
28
+ cols.push(_col)
29
+ }
30
+ })
31
+
32
+ let cL = cols.length
33
+ let rL = rows.length
34
+
35
+ const workbook = new ExcelJS.Workbook()
36
+ const worksheet = workbook.addWorksheet(name)
37
+
38
+ worksheet.columns = cols
39
+ worksheet.addRows(rows)
40
+
41
+ worksheet.views = [
42
+ {
43
+ state: 'frozen',
44
+ // xSplit: 1,
45
+ ySplit: 1
46
+ }
47
+ ]
48
+
49
+ for (let i = 0; i < cL; i++) {
50
+ worksheet.getCell(1, i + 1).style = {
51
+ fill: {
52
+ type: 'pattern',
53
+ pattern: 'solid',
54
+ fgColor: { argb: 'FFE1E1E1' }
55
+ },
56
+ alignment: {
57
+ vertical: 'middle',
58
+ horizontal: 'center'
59
+ },
60
+ font: {
61
+ bold: true
62
+ }
63
+ }
64
+ }
65
+
66
+ for (let i = 0; i < cL; i++) {
67
+ for (let j = 0; j < rL + 1; j++) {
68
+ worksheet.getCell(j + 1, i + 1).border = {
69
+ top: { style: 'thin' },
70
+ left: { style: 'thin' },
71
+ bottom: { style: 'thin' },
72
+ right: { style: 'thin' }
73
+ }
74
+ }
75
+ }
76
+
77
+ // worksheet.getColumn(1).numFmt = '#,##0.00"%"'
78
+ // worksheet.getColumn(1).numFmt = '#,##0.00'
79
+ // worksheet.getColumn(2).width = 32
80
+
81
+ return new Promise((resolve, reject) => {
82
+ workbook.xlsx
83
+ .writeBuffer()
84
+ .then((buffer) => {
85
+ resolve(buffer)
86
+ })
87
+ .catch((err) => {
88
+ reject(err)
89
+ })
90
+ })
91
+ }
92
+ export default toExcel
93
+
94
+ export function toJson(file, name) {
95
+ const workbook = new ExcelJS.Workbook()
96
+ return new Promise((resolve, reject) => {
97
+ workbook.xlsx
98
+ .load(file)
99
+ .then(() => {
100
+ const worksheet = workbook.getWorksheet(name || 1)
101
+ let rows = []
102
+ worksheet.eachRow((r) => {
103
+ let row = []
104
+ r.eachCell((c) => {
105
+ row.push(c.value)
106
+ })
107
+ rows.push(row)
108
+ })
109
+ resolve(rows)
110
+ })
111
+ .catch((err) => {
112
+ reject(err)
113
+ })
114
+ })
115
+ }