vue2-client 1.18.39 → 1.18.40
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/.eslintrc.js +90 -90
- package/Components.md +60 -60
- package/docs/index.md +30 -30
- package/docs//350/257/267/346/261/202/345/267/245/345/205/267/344/275/277/347/224/250/350/257/264/346/230/216.md +353 -0
- package/index.js +31 -31
- package/jest-transform-stub.js +8 -8
- package/jest.setup.js +7 -7
- package/package.json +1 -1
- package/src/assets/img/querySlotDemo.svg +15 -15
- package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
- package/src/base-client/components/common/CitySelect/index.js +3 -3
- package/src/base-client/components/common/CitySelect/index.md +109 -109
- package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
- package/src/base-client/components/common/CreateQuery/index.js +3 -3
- package/src/base-client/components/common/CreateQuery/index.md +42 -42
- package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
- package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
- package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
- package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
- package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
- package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
- package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
- package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
- package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
- package/src/base-client/components/common/PersonSetting/index.js +3 -3
- package/src/base-client/components/common/Tree/Tree.vue +149 -149
- package/src/base-client/components/common/Tree/index.js +2 -2
- package/src/base-client/components/common/Upload/index.js +3 -3
- package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
- package/src/base-client/components/common/XCard/XCard.vue +64 -64
- package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
- package/src/base-client/components/common/XDataDrawer/index.js +3 -3
- package/src/base-client/components/common/XDataDrawer/index.md +41 -41
- package/src/base-client/components/common/XDescriptions/index.js +3 -3
- package/src/base-client/components/common/XDescriptions/index.md +322 -322
- package/src/base-client/components/common/XForm/index.md +178 -178
- package/src/base-client/components/common/XFormTable/demo.vue +2 -4
- package/src/base-client/components/common/XReport/print.js +186 -186
- package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +1 -1
- package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
- package/src/base-client/components/common/XStepView/index.js +3 -3
- package/src/base-client/components/common/XStepView/index.md +31 -31
- package/src/base-client/components/common/XTable/XTable.vue +1715 -1715
- package/src/base-client/components/common/XTable/XTableWrapper.vue +786 -769
- package/src/base-client/components/common/XTable/index.md +255 -255
- package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
- package/src/base-client/plugins/Config.js +19 -19
- package/src/base-client/plugins/tabs-page-plugin.js +39 -39
- package/src/components/Charts/Bar.vue +62 -62
- package/src/components/Charts/ChartCard.vue +134 -134
- package/src/components/Charts/Liquid.vue +67 -67
- package/src/components/Charts/MiniArea.vue +39 -39
- package/src/components/Charts/MiniBar.vue +39 -39
- package/src/components/Charts/MiniProgress.vue +75 -75
- package/src/components/Charts/MiniSmoothArea.vue +40 -40
- package/src/components/Charts/Radar.vue +68 -68
- package/src/components/Charts/RankList.vue +77 -77
- package/src/components/Charts/TagCloud.vue +113 -113
- package/src/components/Charts/TransferBar.vue +64 -64
- package/src/components/Charts/Trend.vue +82 -82
- package/src/components/Charts/chart.less +12 -12
- package/src/components/Charts/smooth.area.less +13 -13
- package/src/components/NumberInfo/NumberInfo.vue +54 -54
- package/src/components/NumberInfo/index.js +3 -3
- package/src/components/NumberInfo/index.less +54 -54
- package/src/components/NumberInfo/index.md +43 -43
- package/src/components/card/ChartCard.vue +79 -79
- package/src/components/chart/Bar.vue +60 -60
- package/src/components/chart/MiniArea.vue +67 -67
- package/src/components/chart/MiniBar.vue +59 -59
- package/src/components/chart/MiniProgress.vue +57 -57
- package/src/components/chart/Radar.vue +80 -80
- package/src/components/chart/RankingList.vue +60 -60
- package/src/components/chart/Trend.vue +79 -79
- package/src/components/chart/index.less +9 -9
- package/src/components/checkbox/ColorCheckbox.vue +157 -157
- package/src/components/input/IInput.vue +66 -66
- package/src/components/menu/SideMenu.vue +75 -75
- package/src/components/menu/menu.js +273 -273
- package/src/components/tool/AStepItem.vue +60 -60
- package/src/composables/demo/UseRequestDemo.vue +175 -0
- package/src/composables/index.js +6 -0
- package/src/composables/useGlobalLoading.js +206 -0
- package/src/composables/usePost.js +221 -0
- package/src/layouts/CommonLayout.vue +56 -56
- package/src/layouts/header/HeaderNotice.vue +177 -177
- package/src/lib.js +1 -1
- package/src/mock/extend/index.js +84 -84
- package/src/mock/goods/index.js +108 -108
- package/src/pages/dashboard/workplace/WorkPlace.vue +141 -141
- package/src/pages/system/dictionary/index.vue +44 -44
- package/src/pages/system/monitor/loginInfor/index.vue +37 -37
- package/src/pages/system/monitor/operLog/index.vue +37 -37
- package/src/services/api/cas.js +79 -79
- package/src/services/api/restTools.js +34 -46
- package/src/store/modules/setting.js +119 -119
- package/src/utils/authority-utils.js +85 -85
- package/src/utils/errorCode.js +6 -6
- package/src/utils/map-utils.js +47 -47
- package/src/utils/request.js +103 -0
- package/vue.config.js +9 -4
- package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a-card title="useRunLogic / usePost 请求工具示例" :bordered="false">
|
|
3
|
+
<a-space direction="vertical" style="width: 100%">
|
|
4
|
+
<!-- 示例1: 基础用法 - 组件级 loading -->
|
|
5
|
+
<a-button
|
|
6
|
+
type="primary"
|
|
7
|
+
:loading="basicRequest.loading"
|
|
8
|
+
@click="handleBasicRequest"
|
|
9
|
+
>
|
|
10
|
+
基础请求 (组件级 loading)
|
|
11
|
+
</a-button>
|
|
12
|
+
|
|
13
|
+
<!-- 示例2: 全局 Loading -->
|
|
14
|
+
<a-button
|
|
15
|
+
type="danger"
|
|
16
|
+
:loading="globalLoadingRequest.loading"
|
|
17
|
+
@click="handleGlobalLoadingRequest"
|
|
18
|
+
>
|
|
19
|
+
全局 Loading 请求
|
|
20
|
+
</a-button>
|
|
21
|
+
|
|
22
|
+
<!-- 示例3: 请求去重 -->
|
|
23
|
+
<a-button
|
|
24
|
+
type="dashed"
|
|
25
|
+
@click="handleDedupeRequest"
|
|
26
|
+
>
|
|
27
|
+
去重请求 (快速点击试试)
|
|
28
|
+
</a-button>
|
|
29
|
+
|
|
30
|
+
<!-- 示例4: 组合使用 -->
|
|
31
|
+
<a-button
|
|
32
|
+
:loading="comboRequest.loading"
|
|
33
|
+
@click="handleComboRequest"
|
|
34
|
+
>
|
|
35
|
+
组合使用 (去重 + 全局 Loading)
|
|
36
|
+
</a-button>
|
|
37
|
+
|
|
38
|
+
<!-- 示例5: usePost 基础用法 -->
|
|
39
|
+
<a-button
|
|
40
|
+
type="primary"
|
|
41
|
+
ghost
|
|
42
|
+
:loading="postRequest.loading"
|
|
43
|
+
@click="handlePostRequest"
|
|
44
|
+
>
|
|
45
|
+
usePost 示例
|
|
46
|
+
</a-button>
|
|
47
|
+
|
|
48
|
+
<!-- 显示请求结果 -->
|
|
49
|
+
<a-card v-if="requestResult" size="small" title="请求结果">
|
|
50
|
+
<pre style="margin: 0; font-size: 12px; max-height: 200px; overflow: auto;">{{ JSON.stringify(requestResult, null, 2) }}</pre>
|
|
51
|
+
</a-card>
|
|
52
|
+
</a-space>
|
|
53
|
+
</a-card>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script>
|
|
57
|
+
import { useRunLogic, usePost } from '@vue2-client/composables'
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
name: 'UseRequestDemo',
|
|
61
|
+
|
|
62
|
+
data () {
|
|
63
|
+
return {
|
|
64
|
+
// 请求结果展示
|
|
65
|
+
requestResult: null,
|
|
66
|
+
|
|
67
|
+
// ========== useRunLogic 实例 ==========
|
|
68
|
+
// 示例1: 基础用法
|
|
69
|
+
basicRequest: useRunLogic('test'),
|
|
70
|
+
|
|
71
|
+
// 示例2: 全局 Loading
|
|
72
|
+
globalLoadingRequest: useRunLogic('test', {
|
|
73
|
+
globalLoading: '正在加载数据...'
|
|
74
|
+
}),
|
|
75
|
+
|
|
76
|
+
// 示例3: 请求去重
|
|
77
|
+
dedupeRequest: useRunLogic('test', {
|
|
78
|
+
dedupe: true
|
|
79
|
+
}),
|
|
80
|
+
|
|
81
|
+
// 示例4: 组合使用
|
|
82
|
+
comboRequest: useRunLogic('test', {
|
|
83
|
+
dedupe: true,
|
|
84
|
+
globalLoading: '处理中,请勿重复操作...'
|
|
85
|
+
}),
|
|
86
|
+
|
|
87
|
+
// ========== usePost 实例 ==========
|
|
88
|
+
postRequest: usePost('/api/af-safecheck/logic/test', {
|
|
89
|
+
globalLoading: '请求中...'
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
methods: {
|
|
95
|
+
// 示例1: 基础请求
|
|
96
|
+
async handleBasicRequest () {
|
|
97
|
+
const { success, data, error } = await this.basicRequest.execute({
|
|
98
|
+
queryParamsName: 'checkPlanListCRUD',
|
|
99
|
+
pageNum: 1,
|
|
100
|
+
pageSize: 5
|
|
101
|
+
})
|
|
102
|
+
if (success) {
|
|
103
|
+
this.requestResult = data
|
|
104
|
+
this.$message.success('基础请求成功')
|
|
105
|
+
} else if (error?.code !== 'ERR_DUPLICATE_REQUEST') {
|
|
106
|
+
this.$message.error('请求失败: ' + error?.message)
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
// 示例2: 全局 Loading 请求
|
|
111
|
+
async handleGlobalLoadingRequest () {
|
|
112
|
+
const { success, data, error } = await this.globalLoadingRequest.execute({
|
|
113
|
+
queryParamsName: 'checkPlanListCRUD',
|
|
114
|
+
pageNum: 1,
|
|
115
|
+
pageSize: 5
|
|
116
|
+
})
|
|
117
|
+
if (success) {
|
|
118
|
+
this.requestResult = data
|
|
119
|
+
this.$message.success('全局 Loading 请求成功')
|
|
120
|
+
} else if (error?.code !== 'ERR_DUPLICATE_REQUEST') {
|
|
121
|
+
this.$message.error('请求失败: ' + error?.message)
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// 示例3: 去重请求
|
|
126
|
+
async handleDedupeRequest () {
|
|
127
|
+
// 快速点击多次,只会发送一次请求
|
|
128
|
+
const { success, data, error } = await this.dedupeRequest.execute({
|
|
129
|
+
queryParamsName: 'checkPlanListCRUD',
|
|
130
|
+
pageNum: 1,
|
|
131
|
+
pageSize: 5
|
|
132
|
+
})
|
|
133
|
+
if (success) {
|
|
134
|
+
this.requestResult = data
|
|
135
|
+
this.$message.success('去重请求成功 (查看控制台是否有去重警告)')
|
|
136
|
+
} else if (error?.code === 'ERR_DUPLICATE_REQUEST') {
|
|
137
|
+
// 重复请求被拦截,静默处理或提示
|
|
138
|
+
console.log('重复请求已被拦截')
|
|
139
|
+
} else {
|
|
140
|
+
this.$message.error('请求失败: ' + error?.message)
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
// 示例4: 组合请求
|
|
145
|
+
async handleComboRequest () {
|
|
146
|
+
const { success, data, error } = await this.comboRequest.execute({
|
|
147
|
+
queryParamsName: 'checkPlanListCRUD',
|
|
148
|
+
pageNum: 1,
|
|
149
|
+
pageSize: 5
|
|
150
|
+
})
|
|
151
|
+
if (success) {
|
|
152
|
+
this.requestResult = data
|
|
153
|
+
this.$message.success('组合请求成功')
|
|
154
|
+
} else if (error?.code !== 'ERR_DUPLICATE_REQUEST') {
|
|
155
|
+
this.$message.error('请求失败: ' + error?.message)
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// 示例5: usePost 请求
|
|
160
|
+
async handlePostRequest () {
|
|
161
|
+
const { success, data, error } = await this.postRequest.execute({
|
|
162
|
+
queryParamsName: 'checkPlanListCRUD',
|
|
163
|
+
pageNum: 1,
|
|
164
|
+
pageSize: 5
|
|
165
|
+
})
|
|
166
|
+
if (success) {
|
|
167
|
+
this.requestResult = data
|
|
168
|
+
this.$message.success('usePost 请求成功')
|
|
169
|
+
} else if (error?.code !== 'ERR_DUPLICATE_REQUEST') {
|
|
170
|
+
this.$message.error('请求失败: ' + error?.message)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
</script>
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局 Loading 管理
|
|
3
|
+
* 纯 JS 实现,直接操作 DOM,不依赖 Vue 组件
|
|
4
|
+
* 支持引用计数,多个并发请求时正确处理显示/隐藏
|
|
5
|
+
* 支持超时自动隐藏保护机制
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// 全局状态
|
|
9
|
+
let isLoading = false
|
|
10
|
+
let loadingElement = null
|
|
11
|
+
let messageText = '加载中...'
|
|
12
|
+
let loadingCount = 0 // 引用计数,支持并发请求
|
|
13
|
+
let autoHideTimer = null // 超时自动隐藏定时器
|
|
14
|
+
|
|
15
|
+
// 配置
|
|
16
|
+
const DEFAULT_TIMEOUT = 30000 // 默认超时时间 30 秒
|
|
17
|
+
const CONTAINER_ID = 'global-loading-container'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 创建 Loading DOM 元素
|
|
21
|
+
*/
|
|
22
|
+
function createLoadingElement (message) {
|
|
23
|
+
const container = document.createElement('div')
|
|
24
|
+
container.id = CONTAINER_ID
|
|
25
|
+
container.innerHTML = `
|
|
26
|
+
<div class="global-loading-mask">
|
|
27
|
+
<div class="global-loading-content">
|
|
28
|
+
<div class="global-loading-spinner">
|
|
29
|
+
<div class="ant-spin ant-spin-lg ant-spin-spinning">
|
|
30
|
+
<span class="ant-spin-dot ant-spin-dot-spin">
|
|
31
|
+
<i class="ant-spin-dot-item"></i>
|
|
32
|
+
<i class="ant-spin-dot-item"></i>
|
|
33
|
+
<i class="ant-spin-dot-item"></i>
|
|
34
|
+
<i class="ant-spin-dot-item"></i>
|
|
35
|
+
</span>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<p class="global-loading-message">${message}</p>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
`
|
|
42
|
+
return container
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 注入全局样式(只注入一次)
|
|
47
|
+
*/
|
|
48
|
+
function injectStyles () {
|
|
49
|
+
if (document.getElementById('global-loading-styles')) return
|
|
50
|
+
|
|
51
|
+
const style = document.createElement('style')
|
|
52
|
+
style.id = 'global-loading-styles'
|
|
53
|
+
style.textContent = `
|
|
54
|
+
.global-loading-mask {
|
|
55
|
+
position: fixed;
|
|
56
|
+
top: 0;
|
|
57
|
+
left: 0;
|
|
58
|
+
right: 0;
|
|
59
|
+
bottom: 0;
|
|
60
|
+
background: rgba(0, 0, 0, 0.45);
|
|
61
|
+
z-index: 99999;
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
}
|
|
66
|
+
.global-loading-content {
|
|
67
|
+
text-align: center;
|
|
68
|
+
}
|
|
69
|
+
.global-loading-message {
|
|
70
|
+
margin-top: 16px;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
color: #fff;
|
|
73
|
+
}
|
|
74
|
+
.global-loading-content .ant-spin-dot-item {
|
|
75
|
+
background-color: #fff !important;
|
|
76
|
+
}
|
|
77
|
+
`
|
|
78
|
+
document.head.appendChild(style)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 清除超时定时器
|
|
83
|
+
*/
|
|
84
|
+
function clearAutoHideTimer () {
|
|
85
|
+
if (autoHideTimer) {
|
|
86
|
+
clearTimeout(autoHideTimer)
|
|
87
|
+
autoHideTimer = null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 设置超时自动隐藏
|
|
93
|
+
* @param {number} timeout - 超时时间(毫秒)
|
|
94
|
+
*/
|
|
95
|
+
function setAutoHideTimer (timeout) {
|
|
96
|
+
clearAutoHideTimer()
|
|
97
|
+
if (timeout > 0) {
|
|
98
|
+
autoHideTimer = setTimeout(() => {
|
|
99
|
+
console.warn(`[GlobalLoading] 超时自动隐藏 (${timeout}ms)`)
|
|
100
|
+
forceHideGlobalLoading()
|
|
101
|
+
}, timeout)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 显示全局 Loading
|
|
107
|
+
* 支持引用计数,多次调用只显示一个 Loading
|
|
108
|
+
* @param {string|boolean} message - 提示信息,传 true 使用默认文字
|
|
109
|
+
* @param {number} timeout - 超时自动隐藏时间(毫秒),默认 30 秒,传 0 禁用
|
|
110
|
+
*/
|
|
111
|
+
export function showGlobalLoading (message = '加载中...', timeout = DEFAULT_TIMEOUT) {
|
|
112
|
+
loadingCount++
|
|
113
|
+
|
|
114
|
+
// 已经在显示,只增加计数,重置超时
|
|
115
|
+
if (isLoading) {
|
|
116
|
+
setAutoHideTimer(timeout)
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
isLoading = true
|
|
121
|
+
messageText = typeof message === 'string' ? message : '加载中...'
|
|
122
|
+
|
|
123
|
+
// 注入样式
|
|
124
|
+
injectStyles()
|
|
125
|
+
|
|
126
|
+
// 创建并插入 DOM
|
|
127
|
+
loadingElement = createLoadingElement(messageText)
|
|
128
|
+
document.body.appendChild(loadingElement)
|
|
129
|
+
|
|
130
|
+
// 设置超时自动隐藏
|
|
131
|
+
setAutoHideTimer(timeout)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 隐藏全局 Loading
|
|
136
|
+
* 只有当所有请求都完成时才真正隐藏
|
|
137
|
+
*/
|
|
138
|
+
export function hideGlobalLoading () {
|
|
139
|
+
loadingCount = Math.max(0, loadingCount - 1)
|
|
140
|
+
|
|
141
|
+
// 还有其他请求在进行中,不隐藏
|
|
142
|
+
if (loadingCount > 0) return
|
|
143
|
+
|
|
144
|
+
doHide()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 强制隐藏全局 Loading(重置计数器)
|
|
149
|
+
* 用于异常情况下的强制重置
|
|
150
|
+
*/
|
|
151
|
+
export function forceHideGlobalLoading () {
|
|
152
|
+
loadingCount = 0
|
|
153
|
+
doHide()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 执行隐藏操作
|
|
158
|
+
*/
|
|
159
|
+
function doHide () {
|
|
160
|
+
if (!isLoading) return
|
|
161
|
+
|
|
162
|
+
isLoading = false
|
|
163
|
+
clearAutoHideTimer()
|
|
164
|
+
|
|
165
|
+
// 移除 DOM
|
|
166
|
+
if (loadingElement && loadingElement.parentNode) {
|
|
167
|
+
loadingElement.parentNode.removeChild(loadingElement)
|
|
168
|
+
}
|
|
169
|
+
loadingElement = null
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 获取当前 Loading 状态
|
|
174
|
+
* @returns {boolean}
|
|
175
|
+
*/
|
|
176
|
+
export function isGlobalLoadingVisible () {
|
|
177
|
+
return isLoading
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 获取当前 Loading 计数
|
|
182
|
+
* @returns {number}
|
|
183
|
+
*/
|
|
184
|
+
export function getLoadingCount () {
|
|
185
|
+
return loadingCount
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* useGlobalLoading Hook(Vue Composition API 风格)
|
|
190
|
+
* @returns {{ show: Function, hide: Function, forceHide: Function, isVisible: Function }}
|
|
191
|
+
*/
|
|
192
|
+
export function useGlobalLoading () {
|
|
193
|
+
return {
|
|
194
|
+
show: showGlobalLoading,
|
|
195
|
+
hide: hideGlobalLoading,
|
|
196
|
+
forceHide: forceHideGlobalLoading,
|
|
197
|
+
isVisible: isGlobalLoadingVisible
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export default {
|
|
202
|
+
show: showGlobalLoading,
|
|
203
|
+
hide: hideGlobalLoading,
|
|
204
|
+
forceHide: forceHideGlobalLoading,
|
|
205
|
+
isVisible: isGlobalLoadingVisible
|
|
206
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import { post } from '@vue2-client/services/api/restTools'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} RequestResult
|
|
6
|
+
* @property {boolean} success - 请求是否成功
|
|
7
|
+
* @property {any} data - 响应数据
|
|
8
|
+
* @property {Error|null} error - 错误信息
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} UsePostReturn
|
|
13
|
+
* @property {boolean} loading - 加载状态
|
|
14
|
+
* @property {Error|null} error - 错误信息
|
|
15
|
+
* @property {any} data - 响应数据
|
|
16
|
+
* @property {(params?: object, config?: object) => Promise<RequestResult>} execute - 执行请求
|
|
17
|
+
* @property {() => void} reset - 重置状态
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Vue Composition API 风格的 POST 请求 Hook
|
|
22
|
+
* 提供响应式的 loading 状态管理,返回统一的结果结构
|
|
23
|
+
*
|
|
24
|
+
* @param {string} url - 请求地址
|
|
25
|
+
* @param {object} defaultConfig - 默认配置
|
|
26
|
+
* @param {boolean|string} defaultConfig.globalLoading - 是否显示全局 Loading
|
|
27
|
+
* @param {boolean} defaultConfig.dedupe - 是否启用请求去重(POST 默认开启,设为 false 可关闭)
|
|
28
|
+
* @returns {UsePostReturn}
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // 基础用法
|
|
32
|
+
* const { loading, execute } = usePost('/api/save')
|
|
33
|
+
* const { success, data, error } = await execute(formData)
|
|
34
|
+
* if (success) {
|
|
35
|
+
* message.success('保存成功')
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // 在模板中绑定 loading 状态
|
|
40
|
+
* // <a-button :loading="loading" @click="handleSave">保存</a-button>
|
|
41
|
+
* const { loading, execute } = usePost('/api/save', { globalLoading: '保存中...' })
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // 获取响应式数据
|
|
45
|
+
* const { loading, data, error, execute } = usePost('/api/query')
|
|
46
|
+
* await execute({ id: 1 })
|
|
47
|
+
* // data 会自动更新,可直接在模板中使用
|
|
48
|
+
*/
|
|
49
|
+
export function usePost (url, defaultConfig = {}) {
|
|
50
|
+
// 响应式状态
|
|
51
|
+
const state = Vue.observable({
|
|
52
|
+
loading: false,
|
|
53
|
+
error: null,
|
|
54
|
+
data: null
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 执行请求
|
|
59
|
+
* @param {object} params - 请求参数
|
|
60
|
+
* @param {object} config - 本次请求的配置(覆盖默认配置)
|
|
61
|
+
* @returns {Promise<RequestResult>} 统一的结果结构
|
|
62
|
+
*/
|
|
63
|
+
async function execute (params = {}, config = {}) {
|
|
64
|
+
state.loading = true
|
|
65
|
+
state.error = null
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const result = await post(url, params, { ...defaultConfig, ...config })
|
|
69
|
+
state.data = result
|
|
70
|
+
return { success: true, data: result, error: null }
|
|
71
|
+
} catch (err) {
|
|
72
|
+
state.error = err
|
|
73
|
+
return { success: false, data: null, error: err }
|
|
74
|
+
} finally {
|
|
75
|
+
state.loading = false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 重置状态
|
|
81
|
+
*/
|
|
82
|
+
function reset () {
|
|
83
|
+
state.loading = false
|
|
84
|
+
state.error = null
|
|
85
|
+
state.data = null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 返回响应式属性的 getter,确保在模板中能正确响应
|
|
89
|
+
return {
|
|
90
|
+
get loading () { return state.loading },
|
|
91
|
+
get error () { return state.error },
|
|
92
|
+
get data () { return state.data },
|
|
93
|
+
execute,
|
|
94
|
+
reset
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default usePost
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @typedef {Object} UseRunLogicReturn
|
|
102
|
+
* @property {boolean} loading - 加载状态
|
|
103
|
+
* @property {Error|null} error - 错误信息
|
|
104
|
+
* @property {any} data - 响应数据
|
|
105
|
+
* @property {(params?: object, overrideOptions?: object) => Promise<RequestResult>} execute - 执行请求
|
|
106
|
+
* @property {() => void} reset - 重置状态
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Vue Composition API 风格的 runLogic Hook
|
|
111
|
+
* 用于调用后端业务逻辑,提供响应式的 loading 状态管理
|
|
112
|
+
*
|
|
113
|
+
* @param {string} logicName - 业务逻辑名称
|
|
114
|
+
* @param {object} options - 配置选项
|
|
115
|
+
* @param {string} options.serviceName - 服务名称,默认为 VUE_APP_SYSTEM_NAME
|
|
116
|
+
* @param {boolean} options.isDev - 是否为开发环境
|
|
117
|
+
* @param {boolean|string} options.globalLoading - 是否显示全局 Loading
|
|
118
|
+
* @param {boolean} options.dedupe - 是否启用请求去重(POST 默认开启,设为 false 可关闭)
|
|
119
|
+
* @returns {UseRunLogicReturn}
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* // 基础用法
|
|
123
|
+
* const { loading, execute, data } = useRunLogic('getUserInfo')
|
|
124
|
+
* const { success, data: result } = await execute({ userId: 1 })
|
|
125
|
+
* if (success) {
|
|
126
|
+
* console.log(result)
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* // 带全局 Loading
|
|
131
|
+
* const { loading, execute } = useRunLogic('saveOrder', {
|
|
132
|
+
* globalLoading: '保存中...',
|
|
133
|
+
* dedupe: true
|
|
134
|
+
* })
|
|
135
|
+
* // 模板: <a-button :loading="loading" @click="handleSave">保存</a-button>
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* // 指定服务名称
|
|
139
|
+
* const { execute } = useRunLogic('queryData', {
|
|
140
|
+
* serviceName: 'af-custom',
|
|
141
|
+
* isDev: false
|
|
142
|
+
* })
|
|
143
|
+
*/
|
|
144
|
+
export function useRunLogic (logicName, options = {}) {
|
|
145
|
+
const {
|
|
146
|
+
serviceName = process.env.VUE_APP_SYSTEM_NAME,
|
|
147
|
+
isDev = false,
|
|
148
|
+
globalLoading = false,
|
|
149
|
+
dedupe = false
|
|
150
|
+
} = options
|
|
151
|
+
|
|
152
|
+
// 响应式状态
|
|
153
|
+
const state = Vue.observable({
|
|
154
|
+
loading: false,
|
|
155
|
+
error: null,
|
|
156
|
+
data: null
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 构建请求 URL
|
|
161
|
+
* @param {string} svcName - 服务名称
|
|
162
|
+
* @param {boolean} dev - 是否开发环境
|
|
163
|
+
* @returns {string}
|
|
164
|
+
*/
|
|
165
|
+
function buildUrl (svcName, dev) {
|
|
166
|
+
const apiPre = dev ? '/devApi/' : '/api/'
|
|
167
|
+
return `${apiPre}${svcName}/logic/${logicName}`
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 执行业务逻辑
|
|
172
|
+
* @param {object} params - 请求参数
|
|
173
|
+
* @param {object} overrideOptions - 本次请求的配置(覆盖默认配置)
|
|
174
|
+
* @returns {Promise<RequestResult>} 统一的结果结构
|
|
175
|
+
*/
|
|
176
|
+
async function execute (params = {}, overrideOptions = {}) {
|
|
177
|
+
state.loading = true
|
|
178
|
+
state.error = null
|
|
179
|
+
|
|
180
|
+
// 合并配置
|
|
181
|
+
const finalServiceName = overrideOptions.serviceName || serviceName
|
|
182
|
+
const finalIsDev = overrideOptions.isDev !== undefined ? overrideOptions.isDev : isDev
|
|
183
|
+
|
|
184
|
+
// 构建请求 URL
|
|
185
|
+
const url = buildUrl(finalServiceName, finalIsDev)
|
|
186
|
+
|
|
187
|
+
// 构建请求配置
|
|
188
|
+
const requestConfig = {
|
|
189
|
+
globalLoading: overrideOptions.globalLoading !== undefined ? overrideOptions.globalLoading : globalLoading,
|
|
190
|
+
dedupe: overrideOptions.dedupe !== undefined ? overrideOptions.dedupe : dedupe
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
const result = await post(url, params, requestConfig)
|
|
195
|
+
state.data = result
|
|
196
|
+
return { success: true, data: result, error: null }
|
|
197
|
+
} catch (err) {
|
|
198
|
+
state.error = err
|
|
199
|
+
return { success: false, data: null, error: err }
|
|
200
|
+
} finally {
|
|
201
|
+
state.loading = false
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 重置状态
|
|
207
|
+
*/
|
|
208
|
+
function reset () {
|
|
209
|
+
state.loading = false
|
|
210
|
+
state.error = null
|
|
211
|
+
state.data = null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
get loading () { return state.loading },
|
|
216
|
+
get error () { return state.error },
|
|
217
|
+
get data () { return state.data },
|
|
218
|
+
execute,
|
|
219
|
+
reset
|
|
220
|
+
}
|
|
221
|
+
}
|