hookehuyr

✨ feat: 新增axios接口去重、数据持久化测试

...@@ -25,12 +25,14 @@ export const getComponentAPI = (params) => fn(fetch.get(Api.QUERY_COMPONENT, par ...@@ -25,12 +25,14 @@ export const getComponentAPI = (params) => fn(fetch.get(Api.QUERY_COMPONENT, par
25 /** 25 /**
26 * @description: 查询部门列表 26 * @description: 查询部门列表
27 * @param: form_code 表单code 27 * @param: form_code 表单code
28 + * { ...params, headers: { "only-data": true, "keep-data": true } }
28 */ 29 */
29 export const getFlowDeptListAPI = (params) => fn(fetch.get(Api.FLOW_DEPT_LIST, params)); 30 export const getFlowDeptListAPI = (params) => fn(fetch.get(Api.FLOW_DEPT_LIST, params));
30 31
31 /** 32 /**
32 * @description: 查询角色列表 33 * @description: 查询角色列表
33 * @param: form_code 表单code 34 * @param: form_code 表单code
35 + * { ...params, headers: { "only-data": true, "keep-data": true } }
34 */ 36 */
35 export const getFlowRoleListAPI = (params) => fn(fetch.get(Api.FLOW_ROLE_LIST, params)); 37 export const getFlowRoleListAPI = (params) => fn(fetch.get(Api.FLOW_ROLE_LIST, params));
36 38
......
1 <!-- 1 <!--
2 * @Date: 2022-08-29 14:31:20 2 * @Date: 2022-08-29 14:31:20
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-11-21 12:41:40 4 + * @LastEditTime: 2024-11-25 15:34:53
5 * @FilePath: /data-table/src/components/OrgPickerField/MyComponent.vue 5 * @FilePath: /data-table/src/components/OrgPickerField/MyComponent.vue
6 * @Description: 树形组件 6 * @Description: 树形组件
7 --> 7 -->
...@@ -341,6 +341,44 @@ const treeCheckedCount = computed(() => { ...@@ -341,6 +341,44 @@ const treeCheckedCount = computed(() => {
341 }); 341 });
342 342
343 onMounted(async () => { 343 onMounted(async () => {
344 + // 挂载逻辑调整为手动触发,测试持久化保存接口数据
345 + mountedLogic();
346 + // // TAG: 获取后台数据
347 + // const flowDeptList = await getFlowDeptListAPI({ form_code: $route.query.code });
348 + // if (flowDeptList.code) {
349 + // role_list = flowDeptList.data;
350 + // }
351 + // const flowRoleList = await getFlowRoleListAPI({ form_code: $route.query.code });
352 + // if (flowRoleList.code) {
353 + // dept_list = flowRoleList.data;
354 + // }
355 + // // TODO:等待后台数据
356 + // check_type.value = '';
357 + // // 获取已选中数据
358 + // // 如果有默认值处理
359 + // props.value = props.component_props.default;
360 + // //
361 + // if (props.value) {
362 + // props.value.forEach(item => {
363 + // if (item.type === 'dept') {
364 + // emitCheckedGroup.value.dept.push(item);
365 + // } else if (item.type === 'role') {
366 + // emitCheckedGroup.value.role.push(item);
367 + // } else if (item.type === 'user') {
368 + // emitCheckedGroup.value.user.push(item);
369 + // }
370 + // });
371 + // // 发送到表单数据
372 + // tree_select_value.value = [].concat(...Object.values(emitCheckedGroup.value));
373 + // }
374 + // // 获取宽度处理成员角色值可能太长显示问题
375 + // nextTick(() => {
376 + // maxWidth.value = $('.select-tree-box').width();
377 + // })
378 +});
379 +
380 +const mountedLogic = async () => {
381 + await nextTick();
344 // TAG: 获取后台数据 382 // TAG: 获取后台数据
345 const flowDeptList = await getFlowDeptListAPI({ form_code: $route.query.code }); 383 const flowDeptList = await getFlowDeptListAPI({ form_code: $route.query.code });
346 if (flowDeptList.code) { 384 if (flowDeptList.code) {
...@@ -373,13 +411,17 @@ onMounted(async () => { ...@@ -373,13 +411,17 @@ onMounted(async () => {
373 nextTick(() => { 411 nextTick(() => {
374 maxWidth.value = $('.select-tree-box').width(); 412 maxWidth.value = $('.select-tree-box').width();
375 }) 413 })
376 -}); 414 +};
377 415
378 -const openTree = () => { // 点击组件展示框回调 416 +const openTree = async () => { // 点击组件展示框回调
379 if (props.component_props.readonly) return false; // 只读判断 417 if (props.component_props.readonly) return false; // 只读判断
380 // 打开弹窗 418 // 打开弹窗
381 showPopover.value = true; 419 showPopover.value = true;
382 420
421 + if (!role_list.length) {
422 + await mountedLogic();
423 + }
424 +
383 // 获取数据 425 // 获取数据
384 nextTick(() => { 426 nextTick(() => {
385 // 动态判断点击显示的tab,默认点击第一个 427 // 动态判断点击显示的tab,默认点击第一个
...@@ -394,7 +436,6 @@ const openTree = () => { // 点击组件展示框回调 ...@@ -394,7 +436,6 @@ const openTree = () => { // 点击组件展示框回调
394 if (!$('#deptTree').find('.tree-placeholder').length) { 436 if (!$('#deptTree').find('.tree-placeholder').length) {
395 $('#deptTree').find('.ctree-tree__block-area').append('<div class="tree-placeholder" style="height: 10vh;"></div>'); 437 $('#deptTree').find('.ctree-tree__block-area').append('<div class="tree-placeholder" style="height: 10vh;"></div>');
396 } 438 }
397 -
398 }); 439 });
399 } 440 }
400 /** 441 /**
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 * @Author: hookehuyr hookehuyr@gmail.com 2 * @Author: hookehuyr hookehuyr@gmail.com
3 * @Date: 2022-05-28 10:17:40 3 * @Date: 2022-05-28 10:17:40
4 * @LastEditors: hookehuyr hookehuyr@gmail.com 4 * @LastEditors: hookehuyr hookehuyr@gmail.com
5 - * @LastEditTime: 2024-08-12 12:37:11 5 + * @LastEditTime: 2024-11-25 15:56:19
6 * @FilePath: /data-table/src/utils/axios.js 6 * @FilePath: /data-table/src/utils/axios.js
7 * @Description: 7 * @Description:
8 */ 8 */
...@@ -17,6 +17,112 @@ axios.defaults.params = { ...@@ -17,6 +17,112 @@ axios.defaults.params = {
17 f: 'custom_form', 17 f: 'custom_form',
18 }; 18 };
19 19
20 +//去重缓存数据
21 +const onlyDataCache = {
22 + // 缓存列表
23 + list: [],
24 + // 根据请求的信息(请求方式,url,请求get/post数据),产生map的key
25 + getRequestKey(config) {
26 + const fullPath = config.headers["full-path"];
27 + const { method, url, params, data } = config;
28 + var key = [method, url].join("&");
29 + if (fullPath) {
30 + key = [method, url, stringify(params), stringify(data)].join("&");
31 + }
32 + return key;
33 + },
34 + query() {
35 + console.log("onlyData=" + JSON.stringify(this.list));
36 + },
37 + add(config, cancel) {
38 + var key = this.getRequestKey(config);
39 + //console.log("onlyData add key=" + key);
40 + var index = this.list.findIndex(t => t.key === key);
41 + if (index > -1) {
42 + this.list[index].cancel();
43 + this.list[index].cancel = cancel;
44 + } else {
45 + // 添加到缓存列表中
46 + this.list.push({ key, cancel });
47 + }
48 + },
49 + delete(config) {
50 + var targetKey = this.getRequestKey(config);
51 + //console.log("onlyData delete key=" + targetKey);
52 + if (targetKey) {
53 + this.list.forEach((item, index) => {
54 + if (item.key === targetKey) {
55 + item.cancel();
56 + this.list.splice(index, 1);
57 + }
58 + });
59 + }
60 + },
61 + deleteAll() {
62 + this.list.forEach((item, index) => {
63 + item.cancel();
64 + this.list.splice(index, 1);
65 + });
66 + }
67 +};
68 +// 持久化缓存数据
69 +const keepDataCache = {
70 + // 缓存列表
71 + list: [],
72 + // 最大缓存数
73 + MAX_NUM: 100,
74 + // 最大缓存时间
75 + EXPIRED_TIME: 60000,
76 + // 根据请求的信息(请求方式,url,请求get/post数据),产生map的key
77 + getRequestKey(config) {
78 + const { method, url, params, data } = config;
79 + const key = [method, url, JSON.stringify(params), JSON.stringify(data)].join("&");
80 + return key;
81 + },
82 + query() {
83 + console.log("keepData=" + JSON.stringify(this.list));
84 + },
85 + // 添加缓存结果
86 + add({ config, data }) {
87 + if (config.data) config.data = JSON.parse(config.data);
88 + var key = this.getRequestKey(config);
89 + // console.log("keepData add key=" + key);
90 + var index = this.list.findIndex(t => t.key === key);
91 + if (index > -1) {
92 + // 保存请求结果
93 + this.list[index].data = data;
94 + } else {
95 + // 添加到缓存列表中
96 + this.list.push({ time: Date.now(), key, data });
97 + }
98 + },
99 + // 查找缓存结果
100 + find(config) {
101 + // 根据请求信息生成key
102 + var key = this.getRequestKey(config);
103 + // console.log("keepData find key=" + key);
104 + var index = this.list.findIndex(t => t.key === key);
105 + // 判断缓存当中是否有该请求结果
106 + if (index > -1) {
107 + let data = this.list[index];
108 + // 判断是否超出了最大缓存时间
109 + if (Date.now() - data.time > this.EXPIRED_TIME) {
110 + // 清除该缓存
111 + this.list.splice(index, 1);
112 + } else {
113 + // 返回缓存
114 + return data;
115 + }
116 + }
117 + // 判断是否超出了最大缓存数量
118 + if (this.list.length === this.MAX_NUM) {
119 + this.list.shift();
120 + }
121 + // 返回undefined,让请求拦截不执行config.adapter
122 + return undefined;
123 + }
124 +};
125 +
20 /** 126 /**
21 * @description 请求拦截器 127 * @description 请求拦截器
22 */ 128 */
...@@ -30,8 +136,53 @@ axios.interceptors.request.use( ...@@ -30,8 +136,53 @@ axios.interceptors.request.use(
30 * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错 136 * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错
31 */ 137 */
32 // config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data; 138 // config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data;
139 +
140 + // config.params.headers 合并到 config.headers 里面, 适配去重配置
141 + if (config.params.headers) {
142 + config.headers = { ...config.headers, ...config.params.headers };
143 + delete config.params.headers;
144 + }
33 // 绑定默认请求头 145 // 绑定默认请求头
34 - config.params = { ...config.params, timestamp } 146 + // config.params = { ...config.params, timestamp };
147 + // TAG:请求去重和持久化缓存
148 + if (config.headers) {
149 + //判断是否需要去重
150 + const onlyData = config.headers["only-data"];
151 + if (onlyData) {
152 + //console.log("删除接口onlyData缓存数据!");
153 + onlyDataCache.delete(config);
154 +
155 + config.cancelToken = new axios.CancelToken(cancel => {
156 + //console.log("保存接口onlyData缓存数据!");
157 + onlyDataCache.add(config, cancel);
158 + });
159 + }
160 +
161 + //判断是否需要持久化,并判断是否有缓存数据
162 + const keepData = config.headers["keep-data"];
163 + if (keepData) {
164 + // console.log("加载接口keepData缓存数据!");
165 + var cacheData = keepDataCache.find(config);
166 + // 查看缓存当中有没有
167 + if (cacheData) {
168 + // console.log("加载成功过,keepData有缓冲数据!");
169 + // 通过config.adapter,允许自定义处理请求
170 + config.adapter = function (config) {
171 + return new Promise(resolve => {
172 + const res = {
173 + status: 200,
174 + statusText: "",
175 + headers: { "content-type": "text/html; charset=UTF-8" },
176 + config,
177 + request: {}
178 + };
179 + resolve({ ...res, data: cacheData.data });
180 + });
181 + };
182 + }
183 + }
184 + }
185 +
35 return config; 186 return config;
36 }, 187 },
37 error => { 188 error => {
...@@ -56,10 +207,39 @@ axios.interceptors.response.use( ...@@ -56,10 +207,39 @@ axios.interceptors.response.use(
56 } 207 }
57 }) 208 })
58 } 209 }
210 +
211 + // TAG:请求持久化缓存
212 + const config = response.config;
213 + if (response) {
214 + const keepData = config.headers["keep-data"];
215 + if (keepData) {
216 + if (response.status === 200 && response.data.code === 1) {
217 + if (
218 + response.headers["content-type"] &&
219 + response.headers["content-type"].indexOf("text/html; charset=UTF-8") >=
220 + 0 &&
221 + response.request.responseType != "blob"
222 + ) {
223 + // console.log("保存接口keepData缓存数据!");
224 + //缓存结果到缓存中
225 + keepDataCache.add(response);
226 + }
227 + }
228 + }
229 + }
230 +
59 return response; 231 return response;
60 }, 232 },
61 error => { 233 error => {
234 + // TAG: 处理请求去重
235 + if (axios.isCancel(error)) { // 取消请求的情况下,终端Promise调用链
236 + return new Promise(() => {
237 + console.error('取消请求响应', error);
238 + return false;
239 + });
240 + } else { // 其他的错误处理
62 return Promise.reject(error); 241 return Promise.reject(error);
242 + }
63 }); 243 });
64 244
65 export default axios; 245 export default axios;
......