haiwei-ui 1.3.7 → 1.4.0

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": "haiwei-ui",
3
- "version": "1.3.7",
3
+ "version": "1.4.0",
4
4
  "description": "HaiWei前端组件库",
5
5
  "author": "Eric",
6
6
  "license": "ISC",
@@ -68,11 +68,8 @@ export default {
68
68
  /** 提交 */
69
69
  submit() {
70
70
  this.validate(() => {
71
- this.openLoading()
72
- console.log('this.model======>', this.model);
73
- // 使用深拷贝确保获取最新数据
74
- const formData = JSON.parse(JSON.stringify(this.model))
75
- console.log('this.model======>formData', formData);
71
+ this.openLoading()
72
+
76
73
  this.action(this.model)
77
74
  .then(data => {
78
75
  if (this.successMsg === true) {
@@ -150,35 +150,12 @@ export default {
150
150
  }
151
151
  },
152
152
  methods: {
153
- /** 提交 */
154
153
  async submit() {
155
154
  // 设置loading状态
156
- this.loading_ = true
157
-
158
- // 触发 before-submit 钩子
159
- if (this.$listeners['before-submit']) {
160
- try {
161
- // 执行 before-submit 钩子并等待结果
162
- // 注意:这里不传递model参数,父组件应该直接修改this.model
163
- const result = await this.$emit('before-submit')
164
-
165
- // 如果返回false,停止提交
166
- if (result === false) {
167
- this.loading_ = false
168
- return
169
- }
170
- // 返回true或undefined则继续提交
171
- } catch (error) {
172
- this.loading_ = false
173
- this.$emit('error', error)
174
- return
175
- }
176
- }
177
-
178
- console.log('test',this.model)
179
- // 继续原有提交逻辑
155
+ this.loading_ = true
180
156
  this.$refs.form.submit()
181
157
  },
158
+
182
159
  /** 重置 */
183
160
  reset() {
184
161
  this.$nextTick(() => {
@@ -12,6 +12,9 @@
12
12
  <el-dropdown-item>
13
13
  <nm-button type="text" text="修改密码" icon="password" @click="updatePassword.visiable = true" />
14
14
  </el-dropdown-item>
15
+ <el-dropdown-item divided>
16
+ <nm-button type="text" text="清理缓存" icon="delete" @click="clearCache" />
17
+ </el-dropdown-item>
15
18
  </el-dropdown-menu>
16
19
  </el-dropdown>
17
20
 
@@ -38,6 +41,29 @@
38
41
  methods: {
39
42
  openUserInfo() {
40
43
  this.$router.push({ name: this.userPage, query: { tn_: '账户信息' } })
44
+ },
45
+ clearCache() {
46
+ this.$confirm('确定要清理所有枚举缓存吗?清理后所有枚举数据将重新从服务器获取。', '提示', {
47
+ confirmButtonText: '确定',
48
+ cancelButtonText: '取消',
49
+ type: 'warning'
50
+ }).then(() => {
51
+ // 调用全局的缓存清理方法
52
+ if (this.$clearAllEnumCache) {
53
+ this.$clearAllEnumCache()
54
+ this.$message.success('缓存清理成功')
55
+
56
+ // 可以添加统计信息显示
57
+ const stats = this.$getCacheStats ? this.$getCacheStats() : null
58
+ if (stats) {
59
+ console.log('缓存统计:', stats)
60
+ }
61
+ } else {
62
+ this.$message.warning('缓存清理功能未启用')
63
+ }
64
+ }).catch(() => {
65
+ // 用户取消操作
66
+ })
41
67
  }
42
68
  }
43
69
  }
@@ -56,14 +56,27 @@
56
56
  methods: {
57
57
  refresh() {
58
58
  this.loading = true
59
- this.action()
60
- .then(options => {
61
- this.options = options
62
- this.loading = false
63
- })
64
- .catch(() => {
65
- this.loading = false
66
- })
59
+ // 如果是枚举组件,使用缓存方法
60
+ if (this.moduleCode && this.enumName) {
61
+ this.getEnumData(this.moduleCode, this.enumName, this.libName)
62
+ .then(options => {
63
+ this.options = options
64
+ this.loading = false
65
+ })
66
+ .catch(() => {
67
+ this.loading = false
68
+ })
69
+ } else {
70
+ // 非枚举组件,使用原来的action方法
71
+ this.action()
72
+ .then(options => {
73
+ this.options = options
74
+ this.loading = false
75
+ })
76
+ .catch(() => {
77
+ this.loading = false
78
+ })
79
+ }
67
80
  },
68
81
  // 清楚已选项
69
82
  clear() {
@@ -1,4 +1,124 @@
1
+ /* eslint-disable no-undef */
1
2
  import { mapState } from 'vuex'
3
+
4
+ // 枚举数据缓存
5
+ const enumCache = new Map()
6
+ const pendingRequests = new Map()
7
+
8
+ // 缓存统计
9
+ let cacheStats = {
10
+ hits: 0,
11
+ misses: 0,
12
+ size: 0
13
+ }
14
+
15
+ // 更新缓存统计
16
+ function updateCacheStats() {
17
+ cacheStats.size = enumCache.size
18
+ }
19
+
20
+ // 全局缓存管理方法
21
+ const cacheManager = {
22
+ /**
23
+ * 获取枚举数据(带缓存)
24
+ * @param {string} moduleCode 模块编码
25
+ * @param {string} enumName 枚举名称
26
+ * @param {string} libName 库名称
27
+ * @returns {Promise<Array>} 枚举数据
28
+ */
29
+ async getEnumData(moduleCode, enumName, libName = '') {
30
+ const cacheKey = `${moduleCode}_${enumName}_${libName}`
31
+
32
+ // 检查缓存
33
+ if (enumCache.has(cacheKey)) {
34
+ cacheStats.hits++
35
+ updateCacheStats()
36
+ return Promise.resolve(enumCache.get(cacheKey))
37
+ }
38
+
39
+ cacheStats.misses++
40
+
41
+ // 检查正在进行的请求
42
+ if (pendingRequests.has(cacheKey)) {
43
+ return pendingRequests.get(cacheKey)
44
+ }
45
+
46
+ // 发起新请求
47
+ const requestPromise = cacheManager._getEnumApiRequest(moduleCode, enumName, libName)
48
+ .then(result => {
49
+ if (result && Array.isArray(result)) {
50
+ enumCache.set(cacheKey, result)
51
+ updateCacheStats()
52
+ }
53
+ return result || []
54
+ }).finally(() => {
55
+ pendingRequests.delete(cacheKey)
56
+ })
57
+
58
+ pendingRequests.set(cacheKey, requestPromise)
59
+ return requestPromise
60
+ },
61
+
62
+ /**
63
+ * 获取枚举API请求(可被子类重写)
64
+ * @param {string} moduleCode 模块编码
65
+ * @param {string} enumName 枚举名称
66
+ * @param {string} libName 库名称
67
+ * @returns {Promise<Array>} 枚举数据
68
+ */
69
+ _getEnumApiRequest(moduleCode, enumName, libName = '') {
70
+ // 默认使用全局$api,如果不存在则返回空数组
71
+ if (typeof $api !== 'undefined' && $api.admin && $api.admin.tool && $api.admin.tool.enumSelect) {
72
+ return $api.admin.tool.enumSelect({ moduleCode, enumName, libName })
73
+ }
74
+ return Promise.resolve([])
75
+ },
76
+
77
+ /**
78
+ * 清除枚举缓存
79
+ * @param {string} moduleCode 模块编码
80
+ * @param {string} enumName 枚举名称
81
+ * @param {string} libName 库名称
82
+ */
83
+ clearEnumCache(moduleCode, enumName, libName = '') {
84
+ const cacheKey = `${moduleCode}_${enumName}_${libName}`
85
+ enumCache.delete(cacheKey)
86
+ updateCacheStats()
87
+ },
88
+
89
+ /**
90
+ * 清除所有枚举缓存
91
+ */
92
+ clearAllEnumCache() {
93
+ enumCache.clear()
94
+ pendingRequests.clear()
95
+ cacheStats.hits = 0
96
+ cacheStats.misses = 0
97
+ cacheStats.size = 0
98
+ },
99
+
100
+ /**
101
+ * 获取缓存统计信息
102
+ * @returns {Object} 缓存统计
103
+ */
104
+ getCacheStats() {
105
+ return {
106
+ ...cacheStats,
107
+ hitRate: cacheStats.hits + cacheStats.misses > 0
108
+ ? (cacheStats.hits / (cacheStats.hits + cacheStats.misses) * 100).toFixed(2) + '%'
109
+ : '0%'
110
+ }
111
+ },
112
+
113
+ /**
114
+ * 获取所有缓存键
115
+ * @returns {Array} 缓存键列表
116
+ */
117
+ getCacheKeys() {
118
+ return Array.from(enumCache.keys())
119
+ }
120
+ }
121
+
2
122
  export default {
3
123
  computed: {
4
124
  ...mapState('app/loading', {
@@ -15,6 +135,54 @@ export default {
15
135
  spinner: this.loadingSpinner,
16
136
  background: this.loadingBackground
17
137
  })
138
+ },
139
+
140
+ /**
141
+ * 获取枚举数据(带缓存)
142
+ * @param {string} moduleCode 模块编码
143
+ * @param {string} enumName 枚举名称
144
+ * @param {string} libName 库名称
145
+ * @returns {Promise<Array>} 枚举数据
146
+ */
147
+ async getEnumData(moduleCode, enumName, libName = '') {
148
+ return cacheManager.getEnumData(moduleCode, enumName, libName)
149
+ },
150
+
151
+ /**
152
+ * 清除枚举缓存
153
+ * @param {string} moduleCode 模块编码
154
+ * @param {string} enumName 枚举名称
155
+ * @param {string} libName 库名称
156
+ */
157
+ clearEnumCache(moduleCode, enumName, libName = '') {
158
+ cacheManager.clearEnumCache(moduleCode, enumName, libName)
159
+ },
160
+
161
+ /**
162
+ * 清除所有枚举缓存
163
+ */
164
+ clearAllEnumCache() {
165
+ cacheManager.clearAllEnumCache()
166
+ },
167
+
168
+ /**
169
+ * 获取缓存统计信息
170
+ * @returns {Object} 缓存统计
171
+ */
172
+ getCacheStats() {
173
+ return cacheManager.getCacheStats()
18
174
  }
19
175
  }
20
176
  }
177
+
178
+ // 安装全局缓存管理方法
179
+ export function installCacheManager(Vue) {
180
+ // 将缓存管理方法添加到Vue原型
181
+ Vue.prototype.$clearAllEnumCache = cacheManager.clearAllEnumCache
182
+ Vue.prototype.$clearEnumCache = cacheManager.clearEnumCache
183
+ Vue.prototype.$getCacheStats = cacheManager.getCacheStats
184
+ Vue.prototype.$getCacheKeys = cacheManager.getCacheKeys
185
+
186
+ // 将缓存管理器暴露给全局
187
+ window.$enumCacheManager = cacheManager
188
+ }
@@ -44,17 +44,33 @@
44
44
  methods: {
45
45
  refresh() {
46
46
  this.loading = true
47
- this.action()
48
- .then(data => {
49
- this.options = data
50
- if (data.length > 0 && this.checkedFirst) {
51
- this.onChange(data[0].value)
52
- }
53
- this.loading = false
54
- })
55
- .catch(() => {
56
- this.loading = false
57
- })
47
+ // 如果是枚举组件,使用缓存方法
48
+ if (this.moduleCode && this.enumName) {
49
+ this.getEnumData(this.moduleCode, this.enumName, this.libName)
50
+ .then(data => {
51
+ this.options = data
52
+ if (data.length > 0 && this.checkedFirst) {
53
+ this.onChange(data[0].value)
54
+ }
55
+ this.loading = false
56
+ })
57
+ .catch(() => {
58
+ this.loading = false
59
+ })
60
+ } else {
61
+ // 非枚举组件,使用原来的action方法
62
+ this.action()
63
+ .then(data => {
64
+ this.options = data
65
+ if (data.length > 0 && this.checkedFirst) {
66
+ this.onChange(data[0].value)
67
+ }
68
+ this.loading = false
69
+ })
70
+ .catch(() => {
71
+ this.loading = false
72
+ })
73
+ }
58
74
  },
59
75
  onChange(val) {
60
76
  this.value_ = val
@@ -100,25 +100,54 @@ export default {
100
100
  if (this.filterable && this.remote) return
101
101
 
102
102
  this.loading = true
103
- this.action().then(options => {
104
- this.options = options
105
- this.loading = false
103
+
104
+ // 如果是枚举组件,使用缓存方法
105
+ if (this.moduleCode && this.enumName) {
106
+ this.getEnumData(this.moduleCode, this.enumName, this.libName)
107
+ .then(options => {
108
+ this.options = options
109
+ this.loading = false
106
110
 
107
- // 检查当前值是否在新加载的选项中
108
- if (this.value_ && options.length > 0) {
109
- const found = this.findOptionByValue(this.value_)
110
- if (found) {
111
- console.log('【nm-select】refresh后找到匹配选项:', found.label, '->', found.value)
112
- } else {
113
- console.warn('【nm-select】refresh后未找到匹配选项,当前值:', this.value_)
111
+ // 检查当前值是否在新加载的选项中
112
+ if (this.value_ && options.length > 0) {
113
+ const found = this.findOptionByValue(this.value_)
114
+ if (found) {
115
+ console.log('【nm-select】refresh后找到匹配选项:', found.label, '->', found.value)
116
+ } else {
117
+ console.warn('【nm-select】refresh后未找到匹配选项,当前值:', this.value_)
118
+ }
119
+ }
120
+
121
+ if (this.checkedFirst && !this.hasInit && options.length > 0) {
122
+ this.onChange(options[0].value)
123
+ this.hasInit = true
124
+ }
125
+ })
126
+ .catch(() => {
127
+ this.loading = false
128
+ })
129
+ } else {
130
+ // 非枚举组件,使用原来的action方法
131
+ this.action().then(options => {
132
+ this.options = options
133
+ this.loading = false
134
+
135
+ // 检查当前值是否在新加载的选项中
136
+ if (this.value_ && options.length > 0) {
137
+ const found = this.findOptionByValue(this.value_)
138
+ if (found) {
139
+ console.log('【nm-select】refresh后找到匹配选项:', found.label, '->', found.value)
140
+ } else {
141
+ console.warn('【nm-select】refresh后未找到匹配选项,当前值:', this.value_)
142
+ }
114
143
  }
115
- }
116
144
 
117
- if (this.checkedFirst && !this.hasInit && options.length > 0) {
118
- this.onChange(options[0].value)
119
- this.hasInit = true
120
- }
121
- })
145
+ if (this.checkedFirst && !this.hasInit && options.length > 0) {
146
+ this.onChange(options[0].value)
147
+ this.hasInit = true
148
+ }
149
+ })
150
+ }
122
151
  },
123
152
  // 根据值查找选项
124
153
  findOptionByValue(value) {
@@ -0,0 +1,82 @@
1
+ import loading from './loading'
2
+
3
+ export default {
4
+ mixins: [loading],
5
+ data() {
6
+ return {
7
+ value_: this.value,
8
+ options: [],
9
+ action: null,
10
+ loading: false
11
+ }
12
+ },
13
+ props: {
14
+ value: {
15
+ type: [String, Number],
16
+ default: ''
17
+ },
18
+ // 是否显示为标签形式
19
+ tag: Boolean,
20
+ // 标签类型
21
+ type: {
22
+ type: String,
23
+ default: ''
24
+ },
25
+ // 标签大小
26
+ size: String,
27
+ // 是否禁用
28
+ disabled: Boolean,
29
+ // 是否可点击
30
+ clickable: Boolean,
31
+ // 点击事件
32
+ onClick: Function
33
+ },
34
+ methods: {
35
+ refresh() {
36
+ this.loading = true
37
+ // 如果是枚举组件,使用缓存方法
38
+ if (this.moduleCode && this.enumName) {
39
+ this.getEnumData(this.moduleCode, this.enumName, this.libName)
40
+ .then(options => {
41
+ this.options = options
42
+ this.loading = false
43
+ })
44
+ .catch(() => {
45
+ this.loading = false
46
+ })
47
+ } else {
48
+ // 非枚举组件,使用原来的action方法
49
+ this.action()
50
+ .then(options => {
51
+ this.options = options
52
+ this.loading = false
53
+ })
54
+ .catch(() => {
55
+ this.loading = false
56
+ })
57
+ }
58
+ },
59
+ getLabelByValue(value) {
60
+ if (!value || !this.options.length) return value
61
+
62
+ for (let i = 0; i < this.options.length; i++) {
63
+ const opt = this.options[i]
64
+ if (opt.value === value) return opt.label
65
+ }
66
+ return value
67
+ },
68
+ handleClick(value) {
69
+ if (this.clickable && this.onClick) {
70
+ this.onClick(value)
71
+ }
72
+ }
73
+ },
74
+ created() {
75
+ this.refresh()
76
+ },
77
+ watch: {
78
+ value(val) {
79
+ if (val !== this.value_) this.value_ = val
80
+ }
81
+ }
82
+ }
@@ -8,7 +8,7 @@ import setTabName from './global/setTabName'
8
8
  import dialog from './components/dialog'
9
9
  import select from './components/select'
10
10
  import drawer from './components/drawer'
11
- import loading from './components/loading'
11
+ import loading, { installCacheManager } from './components/loading'
12
12
  import formDialogEdit from './components/form-dialog-edit'
13
13
  import formSave from './components/form-save'
14
14
  import formReadonly from './components/form-readonly'
@@ -18,6 +18,7 @@ import treeSelect from '../../packages/components/tree-select/mixins.vue'
18
18
  import button from './components/button'
19
19
  import radio from './components/radio.vue'
20
20
  import checkbox from './components/checkbox.vue'
21
+ import text from './components/text'
21
22
 
22
23
  export default {
23
24
  global(Vue) {
@@ -32,6 +33,9 @@ export default {
32
33
 
33
34
  //设置标签导航名称
34
35
  Vue.mixin(setTabName)
36
+
37
+ // 安装缓存管理器
38
+ installCacheManager(Vue)
35
39
  },
36
40
  components: {
37
41
  dialog,
@@ -46,6 +50,7 @@ export default {
46
50
  treeSelect,
47
51
  button,
48
52
  radio,
49
- checkbox
53
+ checkbox,
54
+ text
50
55
  }
51
56
  }
@@ -2,8 +2,8 @@
2
2
  <nm-container>
3
3
  <nm-box page>
4
4
  <div class="nm-default">
5
- <nm-icon name="work" class="nm-size-100" />
6
- <h1 class="nm-m-20 nm-size-20">欢迎使用{{ title }}管理平台</h1>
5
+ <nm-icon name="group" class="nm-size-100" />
6
+ <h1 class="nm-m-20 nm-size-20">欢迎使用{{ title }}平台</h1>
7
7
  <p class="nm-description">
8
8
  本系统采用前后端分离架构:<br>
9
9
  前端基于 Vue.js + Element UI 构建<br>
Binary file
Binary file
package/src/api/config.js CHANGED
@@ -3,7 +3,7 @@ const getUI = () => {
3
3
  resolve({
4
4
  system: {
5
5
  /** 标题 */
6
- title: 'UI',
6
+ title: '模块化框架件UI组件',
7
7
  /** logo */
8
8
  logo: '',
9
9
  /** 用户信息页(路由名称) */
package/vue.config.js CHANGED
@@ -9,7 +9,8 @@ module.exports = {
9
9
  devServer: {
10
10
  port: 6220
11
11
  },
12
- publicPath: '/ui',
12
+ // publicPath: '/ui',
13
+ publicPath: '',
13
14
  transpileDependencies: ['haiwei-ui.*', 'element-ui'],
14
15
  configureWebpack() {
15
16
  let config = {